smbrap2.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "headers.h"
  10. typedef struct RapTableEntry RapTableEntry;
  11. struct RapTableEntry {
  12. char *name;
  13. SmbProcessResult (*procedure)(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata);
  14. };
  15. typedef int INFOSIZEFN(uint16_t level, void *data);
  16. typedef int INFOPUTFN(SmbBuffer *b, uint16_t level, void *data);
  17. typedef int INFOPUTSTRINGSFN(SmbBuffer *b, uint16_t level, int instance,
  18. void *data);
  19. typedef void *INFOENUMERATEFN(void *magic, int i);
  20. typedef struct InfoMethod {
  21. INFOSIZEFN *size;
  22. INFOPUTFN *put;
  23. INFOPUTSTRINGSFN *putstrings;
  24. INFOENUMERATEFN *enumerate;
  25. } InfoMethod;
  26. static int
  27. serverinfosize(uint16_t level, void *data)
  28. {
  29. SmbServerInfo *si = data;
  30. switch (level) {
  31. case 0:
  32. return 16;
  33. case 1:
  34. return 26 + smbstrlen(si->remark);
  35. default:
  36. return 0;
  37. }
  38. }
  39. static int
  40. serverinfoput(SmbBuffer *b, uint16_t level, void *data)
  41. {
  42. SmbServerInfo *si = data;
  43. if (!smbbufferputstrn(b, si->name, 16, 1))
  44. return 0;
  45. if (level > 0) {
  46. if (!smbbufferputb(b, si->vmaj)
  47. || !smbbufferputb(b, si->vmin)
  48. || !smbbufferputl(b, si->stype)
  49. || !smbbufferputl(b, 0))
  50. return 0;
  51. }
  52. if (level > 1)
  53. return 0;
  54. return 1;
  55. }
  56. static int
  57. serverinfoputstrings(SmbBuffer *b, uint16_t level, int instance, void *data)
  58. {
  59. SmbServerInfo *si = data;
  60. if (level == 1) {
  61. if (!smbbufferfixupabsolutel(b, instance * 26 + 22)
  62. || !smbbufferputstring(b, nil, SMB_STRING_ASCII, si->remark))
  63. return 0;
  64. }
  65. return 1;
  66. }
  67. static void *
  68. serverinfoenumerate(void *magic, int i)
  69. {
  70. if (magic) {
  71. SmbServerInfo **si = magic;
  72. return si[i];
  73. }
  74. if (i == 0)
  75. return &smbglobals.serverinfo;
  76. return nil;
  77. }
  78. InfoMethod serverinfo = {
  79. serverinfosize,
  80. serverinfoput,
  81. serverinfoputstrings,
  82. serverinfoenumerate,
  83. };
  84. static int
  85. shareinfosize(uint16_t level, void *data)
  86. {
  87. SmbService *serv = data;
  88. switch (level) {
  89. case 0:
  90. return 13;
  91. case 1:
  92. return 20 + smbstrlen(serv->remark);
  93. case 2:
  94. return 40 + smbstrlen(serv->remark) + smbstrlen(serv->path);
  95. default:
  96. return 0;
  97. }
  98. }
  99. static int
  100. shareinfoput(SmbBuffer *b, uint16_t level, void *data)
  101. {
  102. SmbService *serv = data;
  103. if (!smbbufferputstrn(b, serv->name, 13, 0))
  104. return 0;
  105. if (level > 0) {
  106. if (!smbbufferputb(b, 0)
  107. || !smbbufferputs(b, serv->stype)
  108. || !smbbufferputl(b, 0))
  109. return 0;
  110. }
  111. if (level > 1) {
  112. if (!smbbufferputs(b, 7)
  113. || !smbbufferputs(b, -1)
  114. || !smbbufferputs(b, serv->ref)
  115. || !smbbufferputl(b, 0)
  116. || !smbbufferfill(b, 0, 10))
  117. return 0;
  118. }
  119. if (level > 2)
  120. return 0;
  121. return 1;
  122. }
  123. static int
  124. shareinfoputstrings(SmbBuffer *b, uint16_t level, int instance, void *data)
  125. {
  126. SmbService *serv = data;
  127. switch (level) {
  128. case 0:
  129. break;
  130. case 1:
  131. if (!smbbufferfixupabsolutel(b, instance * 20 + 16)
  132. || !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->remark))
  133. return 0;
  134. break;
  135. case 2:
  136. if (!smbbufferfixupabsolutel(b, instance * 40 + 16)
  137. || !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->remark)
  138. || !smbbufferfixupabsolutel(b, instance * 40 + 26)
  139. || !smbbufferputstring(b, nil, SMB_STRING_ASCII, serv->path))
  140. return 0;
  141. break;
  142. default:
  143. return 0;
  144. }
  145. return 1;
  146. }
  147. static void *
  148. shareinfoenumerate(void *, int i)
  149. {
  150. SmbService *serv;
  151. for (serv = smbservices; i-- > 0 && serv; serv = serv->next)
  152. ;
  153. return serv;
  154. }
  155. static InfoMethod shareinfo = {
  156. shareinfosize,
  157. shareinfoput,
  158. shareinfoputstrings,
  159. shareinfoenumerate,
  160. };
  161. static SmbProcessResult
  162. thingfill(SmbBuffer *outparam, SmbBuffer *outdata, InfoMethod *m,
  163. uint16_t level, void *magic)
  164. {
  165. int sentthings, totalthings;
  166. int i;
  167. int totalbytes;
  168. sentthings = 0;
  169. totalbytes = 0;
  170. for (i = 0; ; i++) {
  171. int len;
  172. void *thing = (*m->enumerate)(magic, i);
  173. if (thing == nil)
  174. break;
  175. len = (*m->size)(level, thing);
  176. if (totalbytes + len <= smbbufferspace(outdata)) {
  177. assert((*m->put)(outdata, level, thing));
  178. sentthings++;
  179. }
  180. totalbytes += len;
  181. }
  182. totalthings = i;
  183. for (i = 0; i < sentthings; i++) {
  184. void *thing = (*m->enumerate)(magic, i);
  185. assert(thing);
  186. assert((*m->putstrings)(outdata, level, i, thing));
  187. }
  188. if (!smbbufferputs(outparam, sentthings < totalthings ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
  189. || !smbbufferputs(outparam, 0)
  190. || !smbbufferputs(outparam, totalthings)
  191. || !smbbufferputs(outparam, sentthings))
  192. return SmbProcessResultFormat;
  193. return SmbProcessResultReply;
  194. }
  195. static SmbProcessResult
  196. onethingfill(SmbBuffer *outparam, SmbBuffer *outdata, InfoMethod *m,
  197. uint16_t level, void *thing)
  198. {
  199. int moredata;
  200. int totalbytes = (*m->size)(level, thing);
  201. if (totalbytes <= smbbufferspace(outdata)) {
  202. assert((*m->put)(outdata, level, thing));
  203. assert((*m->putstrings)(outdata, level, 0, thing));
  204. moredata = 0;
  205. }
  206. else
  207. moredata = 1;
  208. if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
  209. || !smbbufferputs(outparam, 0)
  210. || !smbbufferputs(outparam, totalbytes))
  211. return SmbProcessResultFormat;
  212. return SmbProcessResultReply;
  213. }
  214. static SmbProcessResult
  215. netshareenum(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  216. {
  217. uint16_t level;
  218. /* WrLeh */
  219. /* ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail */
  220. if (!smbbuffergets(inparam, &level))
  221. return SmbProcessResultFormat;
  222. smblogprintif(smbglobals.log.rap2, "netshareenum(%lud, %lud)\n",
  223. level, smbbufferwritespace(outdata));
  224. if (level != 1)
  225. return SmbProcessResultFormat;
  226. return thingfill(outparam, outdata, &shareinfo, level, nil);
  227. }
  228. static SmbProcessResult
  229. netserverenum2(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  230. {
  231. uint16_t level, rbl;
  232. char *domain;
  233. uint32_t servertype;
  234. SmbProcessResult pr;
  235. SmbServerInfo *si[3];
  236. SmbServerInfo domainsi;
  237. int entries;
  238. /* WrLehDz
  239. * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail,
  240. * ulong fServerType, char *pszDomain
  241. */
  242. if (!smbbuffergets(inparam, &level)
  243. || !smbbuffergets(inparam, &rbl)
  244. || !smbbuffergetl(inparam, &servertype)
  245. || !smbbuffergetstr(inparam, 0, &domain)) {
  246. fmtfail:
  247. pr = SmbProcessResultFormat;
  248. goto done;
  249. }
  250. smblogprintif(smbglobals.log.rap2, "netserverenum2(%lud, %lud, 0x%.8lux, %s)\n",
  251. level, smbbufferwritespace(outdata), servertype, domain);
  252. if (level > 1)
  253. goto fmtfail;
  254. if (servertype == 0xffffffff)
  255. servertype &= ~(SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY);
  256. if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0 && (servertype & SV_TYPE_DOMAIN_ENUM) == 0)
  257. servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
  258. entries = 0;
  259. if ((servertype & SV_TYPE_SERVER) != 0
  260. && (domain[0] == 0 || cistrcmp(domain, smbglobals.primarydomain) == 0)) {
  261. si[entries++] = &smbglobals.serverinfo;
  262. }
  263. if ((servertype & SV_TYPE_DOMAIN_ENUM) != 0) {
  264. /* there's only one that I know about */
  265. memset(&domainsi, 0, sizeof(domainsi));
  266. domainsi.name = smbglobals.primarydomain;
  267. domainsi.stype = SV_TYPE_DOMAIN_ENUM;
  268. si[entries++] = &domainsi;
  269. }
  270. si[entries] = 0;
  271. pr = thingfill(outparam, outdata, &serverinfo, level, si);
  272. done:
  273. free(domain);
  274. return pr;
  275. }
  276. static SmbProcessResult
  277. netsharegetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  278. {
  279. char *netname;
  280. uint16_t level;
  281. SmbProcessResult pr;
  282. SmbService *serv;
  283. /*
  284. * zWrLh
  285. * char *pszNetName, ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
  286. */
  287. if (!smbbuffergetstrinline(inparam, &netname)
  288. || !smbbuffergets(inparam, &level)) {
  289. fmtfail:
  290. pr = SmbProcessResultFormat;
  291. goto done;
  292. }
  293. smblogprintif(smbglobals.log.rap2, "netsharegetinfo(%s, %lud, %lud)\n",
  294. netname, level, smbbufferwritespace(outdata));
  295. if (level > 2)
  296. goto fmtfail;
  297. for (serv = smbservices; serv; serv = serv->next)
  298. if (cistrcmp(serv->name, netname) == 0)
  299. break;
  300. if (serv == nil) {
  301. smblogprint(-1, "netsharegetinfo: service %s unimplemented\n", netname);
  302. pr = SmbProcessResultUnimp;
  303. goto done;
  304. }
  305. pr = onethingfill(outparam, outdata, &shareinfo, level, serv);
  306. done:
  307. return pr;
  308. }
  309. static SmbProcessResult
  310. netservergetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  311. {
  312. uint16_t level;
  313. SmbProcessResult pr;
  314. /* WrLh
  315. * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
  316. */
  317. if (!smbbuffergets(inparam, &level)) {
  318. fmtfail:
  319. pr = SmbProcessResultFormat;
  320. goto done;
  321. }
  322. smblogprintif(smbglobals.log.rap2, "netservergetinfo(%lud, %lud)\n",
  323. level, smbbufferwritespace(outdata));
  324. if (level > 1)
  325. goto fmtfail;
  326. pr = onethingfill(outparam, outdata, &shareinfo, level, &smbglobals.serverinfo);
  327. done:
  328. return pr;
  329. }
  330. static SmbProcessResult
  331. netwkstagetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  332. {
  333. uint16_t level;
  334. uint16_t usefulbytes;
  335. SmbProcessResult pr;
  336. int moredata;
  337. /* WrLh
  338. * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
  339. */
  340. if (!smbbuffergets(inparam, &level)) {
  341. fmtfail:
  342. pr = SmbProcessResultFormat;
  343. goto done;
  344. }
  345. smblogprintif(smbglobals.log.rap2, "netwkstagetinfo(%lud, %lud)\n",
  346. level, smbbufferwritespace(outdata));
  347. if (level != 10)
  348. goto fmtfail;
  349. usefulbytes = 22 + smbstrlen(smbglobals.serverinfo.name) + smbstrlen(getuser())
  350. + 3 * smbstrlen(smbglobals.primarydomain);
  351. moredata = usefulbytes > smbbufferwritespace(outdata);
  352. assert(smbbufferputl(outdata, 0));
  353. assert(smbbufferputl(outdata, 0));
  354. assert(smbbufferputl(outdata, 0));
  355. assert(smbbufferputb(outdata, smbglobals.serverinfo.vmaj));
  356. assert(smbbufferputb(outdata, smbglobals.serverinfo.vmin));
  357. assert(smbbufferputl(outdata, 0));
  358. assert(smbbufferputl(outdata, 0));
  359. assert(smbbufferfixupabsolutel(outdata, 0));
  360. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.serverinfo.name));
  361. assert(smbbufferfixupabsolutel(outdata, 4));
  362. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, getuser()));
  363. assert(smbbufferfixupabsolutel(outdata, 8));
  364. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
  365. assert(smbbufferfixupabsolutel(outdata, 14));
  366. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
  367. assert(smbbufferfixupabsolutel(outdata, 18));
  368. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
  369. if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
  370. || !smbbufferputs(outparam, 0)
  371. || !smbbufferputs(outparam, usefulbytes)) {
  372. pr = SmbProcessResultFormat;
  373. goto done;
  374. }
  375. pr = SmbProcessResultReply;
  376. done:
  377. return pr;
  378. }
  379. static RapTableEntry raptable[] = {
  380. [RapNetShareGetInfo] { "NetShareGetInfo", netsharegetinfo },
  381. [RapNetShareEnum] { "NetShareEnum", netshareenum },
  382. [RapNetServerGetInfo] {"NetServerGetInfo", netservergetinfo },
  383. [RapNetWkstaGetInfo] { "NetWkstaGetInfo", netwkstagetinfo },
  384. [RapNetServerEnum2] { "NetServerEnum2", netserverenum2 },
  385. };
  386. SmbProcessResult
  387. smbrap2(SmbSession *s)
  388. {
  389. char *pstring;
  390. char *dstring;
  391. uint16_t pno;
  392. RapTableEntry *e;
  393. SmbProcessResult pr;
  394. SmbBuffer *inparam;
  395. inparam = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  396. if (!smbbuffergets(inparam, &pno)
  397. || !smbbuffergetstrinline(inparam, &pstring)
  398. || !smbbuffergetstrinline(inparam, &dstring)) {
  399. smblogprintif(smbglobals.log.rap2, "smbrap2: not enough parameters\n");
  400. pr = SmbProcessResultFormat;
  401. goto done;
  402. }
  403. if (pno > nelem(raptable) || raptable[pno].name == nil) {
  404. smblogprint(-1, "smbrap2: unsupported procedure %ud\n", pno);
  405. pr = SmbProcessResultUnimp;
  406. goto done;
  407. }
  408. e = raptable + pno;
  409. pr = (*e->procedure)(inparam, s->transaction.out.parameters, s->transaction.out.data);
  410. done:
  411. smbbufferfree(&inparam);
  412. return pr;
  413. }