smbtransaction.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  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 Args Args;
  11. struct Args {
  12. uint32_t pcount;
  13. uint32_t poffset;
  14. uint32_t pdisplacement;
  15. uint32_t dcount;
  16. uint32_t doffset;
  17. uint32_t ddisplacement;
  18. uint8_t scount;
  19. };
  20. int
  21. _smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
  22. SmbBuffer *b, int hasname, char **errmsgp)
  23. {
  24. uint16_t poffset, doffset;
  25. if (h->wordcount < 14) {
  26. smbstringprint(errmsgp, "word count less than 14");
  27. return -1;
  28. }
  29. t->in.scount = pdata[13 * 2];
  30. if (h->wordcount != 14 + t->in.scount) {
  31. smbstringprint(errmsgp, "smbcomtransaction: word count invalid\n");
  32. return -1;
  33. }
  34. t->in.tpcount = smbnhgets(pdata); pdata += 2;
  35. t->in.tdcount = smbnhgets(pdata); pdata += 2;
  36. t->in.maxpcount = smbnhgets(pdata); pdata += 2;
  37. t->in.maxdcount = smbnhgets(pdata); pdata += 2;
  38. t->in.maxscount = *pdata++;
  39. pdata++;
  40. t->in.flags = smbnhgets(pdata); pdata += 2;
  41. pdata += 4; /* timeout */
  42. pdata += 2;
  43. t->in.pcount = smbnhgets(pdata); pdata += 2;
  44. poffset = smbnhgets(pdata); pdata += 2;
  45. t->in.dcount = smbnhgets(pdata); pdata += 2;
  46. doffset = smbnhgets(pdata); pdata += 2;
  47. pdata++; /* scount */
  48. pdata++; /* reserved */
  49. smbfree(&t->in.setup);
  50. if (t->in.scount) {
  51. int x;
  52. t->in.setup = smbemalloc(t->in.scount * sizeof(uint16_t));
  53. for (x = 0; x < t->in.scount; x++) {
  54. t->in.setup[x] = smbnhgets(pdata);
  55. pdata += 2;
  56. }
  57. }
  58. smbfree(&t->in.name);
  59. if (hasname && !smbbuffergetstring(b, h, SMB_STRING_PATH, &t->in.name)) {
  60. smbstringprint(errmsgp, "not enough bdata for name");
  61. return -1;
  62. }
  63. if (poffset + t->in.pcount > smbbufferwriteoffset(b)) {
  64. smbstringprint(errmsgp, "not enough bdata for parameters");
  65. return -1;
  66. }
  67. if (t->in.pcount > t->in.tpcount) {
  68. smbstringprint(errmsgp, "too many parameters");
  69. return -1;
  70. }
  71. smbfree(&t->in.parameters);
  72. t->in.parameters = smbemalloc(t->in.tpcount);
  73. memcpy(t->in.parameters, smbbufferpointer(b, poffset), t->in.pcount);
  74. if (doffset + t->in.dcount > smbbufferwriteoffset(b)) {
  75. smbstringprint(errmsgp, "not enough bdata for data");
  76. return -1;
  77. }
  78. if (t->in.dcount > t->in.tdcount) {
  79. smbstringprint(errmsgp, "too much data");
  80. return -1;
  81. }
  82. smbfree(&t->in.data);
  83. t->in.data = smbemalloc(t->in.tdcount);
  84. memcpy(t->in.data, smbbufferpointer(b, doffset), t->in.dcount);
  85. if (t->in.dcount < t->in.tdcount || t->in.pcount < t->in.tpcount)
  86. return 0;
  87. return 1;
  88. }
  89. int
  90. decoderesponse(SmbTransaction *t, Args *a, SmbBuffer *b, char **errmsgp)
  91. {
  92. if (t->out.tpcount > smbbufferwritemaxoffset(t->out.parameters)) {
  93. smbstringprint(errmsgp, "decoderesponse: too many parameters for buffer");
  94. return 0;
  95. }
  96. if (t->out.tdcount > smbbufferwritemaxoffset(t->out.data)) {
  97. smbstringprint(errmsgp, "decoderesponse: too much data for buffer");
  98. return 0;
  99. }
  100. if (a->pdisplacement + a->pcount > t->out.tpcount) {
  101. smbstringprint(errmsgp, "decoderesponse: more parameters than tpcount");
  102. return 0;
  103. }
  104. if (a->pdisplacement != smbbufferwriteoffset(t->out.parameters)) {
  105. smbstringprint(errmsgp, "decoderesponse: parameter displacement inconsistent");
  106. return 0;
  107. }
  108. if (a->ddisplacement + a->dcount > t->out.tdcount) {
  109. smbstringprint(errmsgp, "decoderesponse: more data than tdcount");
  110. return 0;
  111. }
  112. if (a->ddisplacement != smbbufferwriteoffset(t->out.data)) {
  113. smbstringprint(errmsgp, "decoderesponse: data displacement inconsistent");
  114. return 0;
  115. }
  116. assert(a->scount == 0);
  117. if (a->pcount) {
  118. if (!smbbufferreadskipto(b, a->poffset)) {
  119. smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid parameter offset");
  120. return 0;
  121. }
  122. if (!smbbuffercopy(t->out.parameters, b, a->pcount)) {
  123. smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for parameters");
  124. return 0;
  125. }
  126. }
  127. if (a->dcount) {
  128. if (!smbbufferreadskipto(b, a->doffset)) {
  129. smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid data offset");
  130. return 0;
  131. }
  132. if (!smbbuffercopy(t->out.data, b, a->dcount)) {
  133. smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for data");
  134. return 0;
  135. }
  136. }
  137. return 1;
  138. }
  139. int
  140. smbtransactiondecoderesponse(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
  141. SmbBuffer *b, char **errmsgp)
  142. {
  143. Args a;
  144. if (h->command != SMB_COM_TRANSACTION) {
  145. smbstringprint(errmsgp, "smbtransactiondecoderesponse: not an SMB_COM_TRANSACTION");
  146. return 0;
  147. }
  148. if (h->wordcount < 10) {
  149. smbstringprint(errmsgp, "smbtransactiondecoderesponse: word count less than 10");
  150. return -1;
  151. }
  152. t->out.tpcount = smbnhgets(pdata); pdata += 2;
  153. t->out.tdcount = smbnhgets(pdata); pdata += 2;
  154. pdata += 2;
  155. a.pcount = smbnhgets(pdata); pdata += 2;
  156. a.poffset = smbnhgets(pdata); pdata += 2;
  157. a.pdisplacement = smbnhgets(pdata); pdata += 2;
  158. a.dcount = smbnhgets(pdata); pdata += 2;
  159. a.doffset = smbnhgets(pdata); pdata += 2;
  160. a.ddisplacement = smbnhgets(pdata); pdata += 2;
  161. a.scount = *pdata;
  162. if (a.scount != h->wordcount - 10) {
  163. smbstringprint(errmsgp, "smbtransactiondecoderesponse: scount inconsistent");
  164. return 0;
  165. }
  166. return decoderesponse(t, &a, b, errmsgp);
  167. }
  168. int
  169. smbtransactiondecoderesponse2(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
  170. SmbBuffer *b, char **errmsgp)
  171. {
  172. Args a;
  173. if (h->command != SMB_COM_TRANSACTION2) {
  174. smbstringprint(errmsgp, "smbtransactiondecoderesponse2: not an SMB_COM_TRANSACTION2");
  175. return 0;
  176. }
  177. if (h->wordcount < 10) {
  178. smbstringprint(errmsgp, "smbtransactiondecoderesponse2: word count less than 10");
  179. return -1;
  180. }
  181. t->out.tpcount = smbnhgets(pdata); pdata += 2;
  182. t->out.tdcount = smbnhgets(pdata); pdata += 2;
  183. pdata += 2;
  184. a.pcount = smbnhgets(pdata); pdata += 2;
  185. a.poffset = smbnhgets(pdata); pdata += 2;
  186. a.pdisplacement = smbnhgets(pdata); pdata += 2;
  187. a.dcount = smbnhgets(pdata); pdata += 2;
  188. a.doffset = smbnhgets(pdata); pdata += 2;
  189. a.ddisplacement = smbnhgets(pdata); pdata += 2;
  190. a.scount = *pdata;
  191. if (a.scount != h->wordcount - 10) {
  192. smbstringprint(errmsgp, "smbtransactiondecoderesponse2: scount inconsistent");
  193. return 0;
  194. }
  195. return decoderesponse(t, &a, b, errmsgp);
  196. }
  197. int
  198. smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
  199. SmbBuffer *b, char **errmsgp)
  200. {
  201. return _smbtransactiondecodeprimary(t, h, pdata, b, 1, errmsgp);
  202. }
  203. int
  204. smbtransactiondecodeprimary2(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
  205. SmbBuffer *b, char **errmsgp)
  206. {
  207. return _smbtransactiondecodeprimary(t, h, pdata, b, 0, errmsgp);
  208. }
  209. void
  210. smbtransactionfree(SmbTransaction *t)
  211. {
  212. free(t->in.parameters);
  213. free(t->in.data);
  214. free(t->in.setup);
  215. free(t->in.name);
  216. smbbufferfree(&t->out.parameters);
  217. smbbufferfree(&t->out.data);
  218. }
  219. static int
  220. _transactionencodeprimary(SmbTransaction *t, uint8_t cmd, SmbHeader *h,
  221. SmbPeerInfo *p, SmbBuffer *ob,
  222. uint8_t *wordcountp, uint16_t *bytecountp, char **errmsgp)
  223. {
  224. SmbHeader mh;
  225. uint32_t countsfixupoffset, bytecountfixupoffset;
  226. int x;
  227. mh = *h;
  228. *wordcountp = mh.wordcount = 14 + t->in.scount;
  229. mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
  230. mh.command = cmd;
  231. if (!smbbufferputheader(ob, &mh, p)) {
  232. toosmall:
  233. smbstringprint(errmsgp, "output buffer too small");
  234. return 0;
  235. }
  236. if (t->in.tpcount > 65535 || t->in.tdcount > 65535 || t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
  237. smbstringprint(errmsgp, "counts too big");
  238. return 0;
  239. }
  240. if (!smbbufferputs(ob, t->in.tpcount)
  241. || !smbbufferputs(ob, t->in.tdcount)
  242. || !smbbufferputs(ob, t->in.maxpcount)
  243. || !smbbufferputs(ob, t->in.maxdcount)
  244. || !smbbufferputb(ob, t->in.maxscount)
  245. || !smbbufferputb(ob, 0)
  246. || !smbbufferputs(ob, t->in.flags)
  247. || !smbbufferputl(ob, 0)
  248. || !smbbufferputs(ob, 0))
  249. goto toosmall;
  250. countsfixupoffset = smbbufferwriteoffset(ob);
  251. if (!smbbufferputs(ob, 0)
  252. || !smbbufferputs(ob, 0)
  253. || !smbbufferputs(ob, 0)
  254. || !smbbufferputs(ob, 0))
  255. goto toosmall;
  256. if (!smbbufferputb(ob, t->in.scount)
  257. || !smbbufferputb(ob, 0))
  258. goto toosmall;
  259. for (x = 0; x < t->in.scount; x++)
  260. if (!smbbufferputs(ob, t->in.setup[x]))
  261. goto toosmall;
  262. bytecountfixupoffset = smbbufferwriteoffset(ob);
  263. if (!smbbufferputs(ob, 0))
  264. goto toosmall;
  265. smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
  266. if (!smbbufferputstring(ob, p, SMB_STRING_UPCASE, t->in.name))
  267. goto toosmall;
  268. if (t->in.pcount < t->in.tpcount) {
  269. uint32_t align = smbbufferwriteoffset(ob) & 1;
  270. uint32_t pthistime;
  271. pthistime = smbbufferwritespace(ob) - align;
  272. if (pthistime > t->in.tpcount - t->in.pcount)
  273. pthistime = t->in.tpcount - t->in.pcount;
  274. if (pthistime > 65535)
  275. pthistime = 65535;
  276. if (smbbufferwriteoffset(ob) > 65535)
  277. pthistime = 0;
  278. if (pthistime) {
  279. assert(smbbufferalignl2(ob, 0));
  280. assert(smbbufferoffsetputs(ob, countsfixupoffset, pthistime));
  281. assert(smbbufferoffsetputs(ob, countsfixupoffset + 2, smbbufferwriteoffset(ob)));
  282. assert(smbbufferputbytes(ob, t->in.parameters + t->in.pcount, pthistime));
  283. }
  284. t->in.pcount += pthistime;
  285. }
  286. if (t->in.dcount < t->in.tdcount) {
  287. uint32_t align = smbbufferwriteoffset(ob) & 1;
  288. uint32_t dthistime;
  289. dthistime = smbbufferwritespace(ob) - align;
  290. if (dthistime > t->in.tdcount - t->in.dcount)
  291. dthistime = t->in.tdcount - t->in.dcount;
  292. if (dthistime > 65535)
  293. dthistime = 65535;
  294. if (smbbufferwriteoffset(ob) > 65535)
  295. dthistime = 0;
  296. if (dthistime) {
  297. assert(smbbufferalignl2(ob, 0));
  298. assert(smbbufferoffsetputs(ob, countsfixupoffset + 4, dthistime));
  299. assert(smbbufferoffsetputs(ob, countsfixupoffset + 6, smbbufferwriteoffset(ob)));
  300. assert(smbbufferputbytes(ob, t->in.data + t->in.dcount, dthistime));
  301. }
  302. t->in.dcount += dthistime;
  303. }
  304. *bytecountp = smbbufferwriteoffset(ob) - bytecountfixupoffset - 2;
  305. assert(smbbufferoffsetputs(ob, bytecountfixupoffset, *bytecountp));
  306. return 1;
  307. }
  308. int
  309. smbtransactionencodeprimary(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
  310. uint8_t *wordcountp, uint16_t *bytecountp, char **errmsgp)
  311. {
  312. return _transactionencodeprimary(t, SMB_COM_TRANSACTION, h, p,ob, wordcountp, bytecountp, errmsgp);
  313. };
  314. int
  315. smbtransactionencodeprimary2(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
  316. uint8_t *wordcountp, uint16_t *bytecountp, char **errmsgp)
  317. {
  318. return _transactionencodeprimary(t, SMB_COM_TRANSACTION2, h, p,ob, wordcountp, bytecountp, errmsgp);
  319. };
  320. int
  321. _transactionencoderesponse(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
  322. uint8_t cmd,
  323. char **errmsgp)
  324. {
  325. SmbHeader mh;
  326. uint32_t countsfixupoffset, bytecountfixupoffset;
  327. int palign, dalign;
  328. uint32_t pbytecount, dbytecount;
  329. uint32_t poffset, doffset;
  330. if (t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
  331. smbstringprint(errmsgp, "counts too big");
  332. return 0;
  333. }
  334. mh = *h;
  335. mh.wordcount = 10;
  336. mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
  337. mh.command = cmd;
  338. mh.errclass = SUCCESS;
  339. mh.error = SUCCESS;
  340. if (!smbbufferputheader(ob, &mh, p)
  341. || !smbbufferputs(ob, smbbufferwriteoffset(t->out.parameters))
  342. || !smbbufferputs(ob, smbbufferwriteoffset(t->out.data))
  343. || !smbbufferputs(ob, 0)) {
  344. toosmall:
  345. smbstringprint(errmsgp, "output buffer too small");
  346. goto toosmall;
  347. }
  348. countsfixupoffset = smbbufferwriteoffset(ob);
  349. if (!smbbufferputbytes(ob, nil, 6 * sizeof(uint16_t))
  350. || !smbbufferputb(ob, 0) // scount == 0
  351. || !smbbufferputb(ob, 0)) // reserved2
  352. goto toosmall;
  353. /* now the byte count */
  354. bytecountfixupoffset = smbbufferwriteoffset(ob);
  355. if (!smbbufferputs(ob, 0))
  356. goto toosmall;
  357. smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
  358. palign = bytecountfixupoffset & 1;
  359. if (palign && !smbbufferputb(ob, 0))
  360. goto toosmall;
  361. pbytecount = smbbufferreadspace(t->out.parameters);
  362. if (pbytecount > smbbufferwritespace(ob))
  363. pbytecount = smbbufferwritespace(ob);
  364. poffset = smbbufferwriteoffset(ob);
  365. if (poffset > 65535)
  366. goto toosmall;
  367. if (!smbbufferputbytes(ob, smbbufferreadpointer(t->out.parameters), pbytecount))
  368. goto toosmall;
  369. dalign = smbbufferwritespace(ob) > 0 && (smbbufferwriteoffset(ob) & 1) != 0;
  370. if (dalign && !smbbufferputb(ob, 0))
  371. goto toosmall;
  372. dbytecount = smbbufferreadspace(t->out.data);
  373. if (dbytecount > smbbufferwritespace(ob))
  374. dbytecount = smbbufferwritespace(ob);
  375. doffset = smbbufferwriteoffset(ob);
  376. if (doffset > 65535)
  377. goto toosmall;
  378. if (!smbbufferputbytes(ob, smbbufferreadpointer(t->out.data), dbytecount))
  379. goto toosmall;
  380. if (!smbbufferoffsetputs(ob, bytecountfixupoffset, palign + pbytecount + dalign + dbytecount)
  381. || !smbbufferoffsetputs(ob, countsfixupoffset, pbytecount)
  382. || !smbbufferoffsetputs(ob, countsfixupoffset + 2, poffset)
  383. || !smbbufferoffsetputs(ob, countsfixupoffset + 4, smbbufferreadoffset(t->out.parameters))
  384. || !smbbufferoffsetputs(ob, countsfixupoffset + 6, dbytecount)
  385. || !smbbufferoffsetputs(ob, countsfixupoffset + 8, doffset)
  386. || !smbbufferoffsetputs(ob, countsfixupoffset + 10, smbbufferreadoffset(t->out.data)))
  387. goto toosmall;
  388. assert(smbbufferoffsetputs(ob, bytecountfixupoffset, smbbufferwriteoffset(ob) - bytecountfixupoffset - 2));
  389. smbbuffergetbytes(t->out.parameters, nil, pbytecount);
  390. smbbuffergetbytes(t->out.data, nil, dbytecount);
  391. return 1;
  392. }
  393. int
  394. smbtransactionencoderesponse(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
  395. char **errmsgp)
  396. {
  397. return _transactionencoderesponse(t, h, p, ob, SMB_COM_TRANSACTION, errmsgp);
  398. }
  399. int
  400. smbtransactionencoderesponse2(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
  401. char **errmsgp)
  402. {
  403. return _transactionencoderesponse(t, h, p, ob, SMB_COM_TRANSACTION2, errmsgp);
  404. }
  405. int
  406. smbtransactionrespond(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob, SmbTransactionMethod *method, void *magic,
  407. char **errmsgp)
  408. {
  409. /* generate one or more responses */
  410. while (smbbufferreadspace(t->out.parameters) || smbbufferreadspace(t->out.data)) {
  411. assert(method->encoderesponse);
  412. if (!(*method->encoderesponse)(t, h, p, ob, errmsgp))
  413. return 0;
  414. assert(method->sendresponse);
  415. if (!(*method->sendresponse)(magic, ob, errmsgp))
  416. return 0;
  417. }
  418. return 1;
  419. }
  420. int
  421. smbtransactionnbdgramsend(void *magic, SmbBuffer *ob, char **errmsgp)
  422. {
  423. NbDgramSendParameters *p = magic;
  424. //print("sending to %B\n", p->to);
  425. //nbdumpdata(smbbufferreadpointer(ob), smbbufferreadspace(ob));
  426. if (!nbdgramsend(p, smbbufferreadpointer(ob), smbbufferreadspace(ob))) {
  427. smbstringprint(errmsgp, "dgram send failed");
  428. return 0;
  429. }
  430. return 1;
  431. }
  432. SmbTransactionMethod smbtransactionmethoddgram = {
  433. .encodeprimary = smbtransactionencodeprimary,
  434. .sendrequest = smbtransactionnbdgramsend,
  435. .encoderesponse = smbtransactionencoderesponse,
  436. };
  437. int
  438. smbtransactionexecute(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *iob, SmbTransactionMethod *method, void *magic, SmbHeader *rhp,
  439. char **errmsgp)
  440. {
  441. uint8_t sentwordcount;
  442. uint16_t sentbytecount;
  443. SmbHeader rh;
  444. smbbufferreset(iob);
  445. if (!(*method->encodeprimary)(t, h, p, iob, &sentwordcount, &sentbytecount, errmsgp))
  446. return 0;
  447. // smblogprint(-1, "sent...\n");
  448. // smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
  449. if (!(*method->sendrequest)(magic, iob, errmsgp))
  450. return 0;
  451. if (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount) {
  452. uint8_t wordcount;
  453. uint16_t bytecount;
  454. /* secondary needed */
  455. if (method->encodesecondary == nil || method->receiveintermediate == nil) {
  456. smbstringprint(errmsgp, "buffer too small and secondaries not allowed");
  457. return 0;
  458. }
  459. if (!(*method->receiveintermediate)(magic, &wordcount, &bytecount, errmsgp))
  460. return 0;
  461. if (sentwordcount != wordcount || sentbytecount != bytecount) {
  462. smbstringprint(errmsgp, "server intermediate reply counts differ");
  463. return 0;
  464. }
  465. do {
  466. if (!(*method->encodesecondary)(t, h, iob, errmsgp))
  467. return 0;
  468. if (!(*method->sendrequest)(magic, iob, errmsgp))
  469. return 0;
  470. } while (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount);
  471. }
  472. if (method->receiveresponse == nil || method->decoderesponse == nil)
  473. return 1;
  474. do {
  475. uint8_t *pdata;
  476. uint16_t bytecount;
  477. if (!(*method->receiveresponse)(magic, iob, errmsgp))
  478. return 0;
  479. if (!smbbuffergetheader(iob, &rh, &pdata, &bytecount)) {
  480. smbstringprint(errmsgp, "smbtransactionexecute: invalid response header");
  481. return 0;
  482. }
  483. if (!smbcheckheaderdirection(&rh, 1, errmsgp))
  484. return 0;
  485. if (rh.errclass != SUCCESS) {
  486. smbstringprint(errmsgp, "smbtransactionexecute: remote error %d/%d", rh.errclass, rh.error);
  487. return 0;
  488. }
  489. if (!smbbuffertrimreadlen(iob, bytecount)) {
  490. smbstringprint(errmsgp, "smbtransactionexecute: invalid bytecount");
  491. return 0;
  492. }
  493. // smblogprint(-1, "received...\n");
  494. // smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
  495. if (!(*method->decoderesponse)(t, &rh, pdata, iob, errmsgp))
  496. return 0;
  497. } while (smbbufferwriteoffset(t->out.parameters) < t->out.tpcount || smbbufferwriteoffset(t->out.data) < t->out.tdcount);
  498. if (rhp)
  499. *rhp = rh;
  500. return 1;
  501. }