smbrap2.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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.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 *v, 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. /* uint16_t sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, uint16_t *pcTotalAvail */
  220. if (!smbbuffergets(inparam, &level))
  221. return SmbProcessResultFormat;
  222. smblogprintif(smbglobals.log.rap2, "netshareenum(%lu, %lu)\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. * uint16_t sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, uint16_t *pcTotalAvail,
  240. * uint32_t fServerType, char *pszDomain
  241. */
  242. domain = malloc(sizeof(domain));
  243. if (!smbbuffergets(inparam, &level)
  244. || !smbbuffergets(inparam, &rbl)
  245. || !smbbuffergetl(inparam, &servertype)
  246. || !smbbuffergetstr(inparam, 0, &domain)) {
  247. fmtfail:
  248. pr = SmbProcessResultFormat;
  249. goto done;
  250. }
  251. smblogprintif(smbglobals.log.rap2, "netserverenum2(%lu, %lu, 0x%.8lux, %s)\n",
  252. level, smbbufferwritespace(outdata), servertype, domain);
  253. if (level > 1)
  254. goto fmtfail;
  255. if (servertype == 0xffffffff)
  256. servertype &= ~(SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY);
  257. if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0 && (servertype & SV_TYPE_DOMAIN_ENUM) == 0)
  258. servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
  259. entries = 0;
  260. if ((servertype & SV_TYPE_SERVER) != 0
  261. && (domain[0] == 0 || cistrcmp(domain, smbglobals.primarydomain) == 0)) {
  262. si[entries++] = &smbglobals.serverinfo;
  263. }
  264. if ((servertype & SV_TYPE_DOMAIN_ENUM) != 0) {
  265. /* there's only one that I know about */
  266. memset(&domainsi, 0, sizeof(domainsi));
  267. domainsi.name = smbglobals.primarydomain;
  268. domainsi.stype = SV_TYPE_DOMAIN_ENUM;
  269. si[entries++] = &domainsi;
  270. }
  271. si[entries] = 0;
  272. pr = thingfill(outparam, outdata, &serverinfo, level, si);
  273. done:
  274. free(domain);
  275. return pr;
  276. }
  277. static SmbProcessResult
  278. netsharegetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  279. {
  280. char *netname;
  281. uint16_t level;
  282. SmbProcessResult pr;
  283. SmbService *serv;
  284. /*
  285. * zWrLh
  286. * char *pszNetName, uint16_t sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, uint16_t *pcbTotalAvail
  287. */
  288. if (!smbbuffergetstrinline(inparam, &netname)
  289. || !smbbuffergets(inparam, &level)) {
  290. fmtfail:
  291. pr = SmbProcessResultFormat;
  292. goto done;
  293. }
  294. smblogprintif(smbglobals.log.rap2, "netsharegetinfo(%s, %lu, %lu)\n",
  295. netname, level, smbbufferwritespace(outdata));
  296. if (level > 2)
  297. goto fmtfail;
  298. for (serv = smbservices; serv; serv = serv->next)
  299. if (cistrcmp(serv->name, netname) == 0)
  300. break;
  301. if (serv == nil) {
  302. smblogprint(-1, "netsharegetinfo: service %s unimplemented\n", netname);
  303. pr = SmbProcessResultUnimp;
  304. goto done;
  305. }
  306. pr = onethingfill(outparam, outdata, &shareinfo, level, serv);
  307. done:
  308. return pr;
  309. }
  310. static SmbProcessResult
  311. netservergetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  312. {
  313. uint16_t level;
  314. SmbProcessResult pr;
  315. /* WrLh
  316. * uint16_t sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, uint16_t *pcbTotalAvail
  317. */
  318. if (!smbbuffergets(inparam, &level)) {
  319. fmtfail:
  320. pr = SmbProcessResultFormat;
  321. goto done;
  322. }
  323. smblogprintif(smbglobals.log.rap2, "netservergetinfo(%lu, %lu)\n",
  324. level, smbbufferwritespace(outdata));
  325. if (level > 1)
  326. goto fmtfail;
  327. pr = onethingfill(outparam, outdata, &shareinfo, level, &smbglobals.serverinfo);
  328. done:
  329. return pr;
  330. }
  331. static SmbProcessResult
  332. netwkstagetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
  333. {
  334. uint16_t level;
  335. uint16_t usefulbytes;
  336. SmbProcessResult pr;
  337. int moredata;
  338. /* WrLh
  339. * uint16_t sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, uint16_t *pcbTotalAvail
  340. */
  341. if (!smbbuffergets(inparam, &level)) {
  342. fmtfail:
  343. pr = SmbProcessResultFormat;
  344. goto done;
  345. }
  346. smblogprintif(smbglobals.log.rap2, "netwkstagetinfo(%lu, %lu)\n",
  347. level, smbbufferwritespace(outdata));
  348. if (level != 10)
  349. goto fmtfail;
  350. usefulbytes = 22 + smbstrlen(smbglobals.serverinfo.name) + smbstrlen(getuser())
  351. + 3 * smbstrlen(smbglobals.primarydomain);
  352. moredata = usefulbytes > smbbufferwritespace(outdata);
  353. assert(smbbufferputl(outdata, 0));
  354. assert(smbbufferputl(outdata, 0));
  355. assert(smbbufferputl(outdata, 0));
  356. assert(smbbufferputb(outdata, smbglobals.serverinfo.vmaj));
  357. assert(smbbufferputb(outdata, smbglobals.serverinfo.vmin));
  358. assert(smbbufferputl(outdata, 0));
  359. assert(smbbufferputl(outdata, 0));
  360. assert(smbbufferfixupabsolutel(outdata, 0));
  361. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.serverinfo.name));
  362. assert(smbbufferfixupabsolutel(outdata, 4));
  363. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, getuser()));
  364. assert(smbbufferfixupabsolutel(outdata, 8));
  365. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
  366. assert(smbbufferfixupabsolutel(outdata, 14));
  367. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
  368. assert(smbbufferfixupabsolutel(outdata, 18));
  369. assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain));
  370. if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS)
  371. || !smbbufferputs(outparam, 0)
  372. || !smbbufferputs(outparam, usefulbytes)) {
  373. pr = SmbProcessResultFormat;
  374. goto done;
  375. }
  376. pr = SmbProcessResultReply;
  377. done:
  378. return pr;
  379. }
  380. static RapTableEntry raptable[] = {
  381. [RapNetShareGetInfo] = { "NetShareGetInfo", netsharegetinfo },
  382. [RapNetShareEnum] = { "NetShareEnum", netshareenum },
  383. [RapNetServerGetInfo] = {"NetServerGetInfo", netservergetinfo },
  384. [RapNetWkstaGetInfo] = { "NetWkstaGetInfo", netwkstagetinfo },
  385. [RapNetServerEnum2] = { "NetServerEnum2", netserverenum2 },
  386. };
  387. int
  388. smbrap2(SmbSession *s)
  389. {
  390. char *pstring;
  391. char *dstring;
  392. uint16_t pno;
  393. RapTableEntry *e;
  394. SmbProcessResult pr;
  395. SmbBuffer *inparam;
  396. inparam = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
  397. if (!smbbuffergets(inparam, &pno)
  398. || !smbbuffergetstrinline(inparam, &pstring)
  399. || !smbbuffergetstrinline(inparam, &dstring)) {
  400. smblogprintif(smbglobals.log.rap2, "smbrap2: not enough parameters\n");
  401. pr = SmbProcessResultFormat;
  402. goto done;
  403. }
  404. if (pno > nelem(raptable) || raptable[pno].name == nil) {
  405. smblogprint(-1, "smbrap2: unsupported procedure %u\n", pno);
  406. pr = SmbProcessResultUnimp;
  407. goto done;
  408. }
  409. e = raptable + pno;
  410. pr = (*e->procedure)(inparam, s->transaction.out.parameters, s->transaction.out.data);
  411. done:
  412. smbbufferfree(&inparam);
  413. return pr;
  414. }