smbconnect.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #include "headers.h"
  2. SmbClient *
  3. smbconnect(char *to, char *share, char **errmsgp)
  4. {
  5. NbSession *nbs;
  6. SmbBuffer *b;
  7. SmbHeader h, rh;
  8. long n;
  9. ushort bytecountfixupoffset;
  10. ushort andxfixupoffset;
  11. uchar *pdata;
  12. SmbPeerInfo peerinfo;
  13. ushort index;
  14. vlong utcintenthsofaus;
  15. ulong secssince1970;
  16. ushort bytecount;
  17. int x;
  18. MSchapreply mschapreply;
  19. NbName nbto;
  20. SmbClient *c;
  21. char namebuf[100];
  22. ushort ipctid, sharetid;
  23. nbmknamefromstringandtype(nbto, to, 0x20);
  24. peerinfo.encryptionkey = nil;
  25. peerinfo.oemdomainname = nil;
  26. assert(smbglobals.nbname[0] != 0);
  27. nbs = nbssconnect(nbto, smbglobals.nbname);
  28. if (nbs == nil)
  29. return nil;
  30. print("netbios session established\n");
  31. b = smbbuffernew(65535);
  32. memset(&h, 0, sizeof(h));
  33. h.command = SMB_COM_NEGOTIATE;
  34. h.flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES | SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_UNICODE;
  35. h.wordcount = 0;
  36. h.pid = 42;
  37. smbbufferputheader(b, &h, &peerinfo);
  38. bytecountfixupoffset = smbbufferwriteoffset(b);
  39. smbbufferputbytes(b, nil, 2);
  40. smbbufferputb(b, 2);
  41. smbbufferputstring(b, nil, SMB_STRING_ASCII, "NT LM 0.12");
  42. smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
  43. nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
  44. nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
  45. /*
  46. * now receive a reply
  47. */
  48. smbbufferreset(b);
  49. n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
  50. if (n < 0) {
  51. smbstringprint(errmsgp, "smbconnect: read error: %r");
  52. goto fail;
  53. }
  54. smbbuffersetreadlen(b, n);
  55. nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
  56. if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp))
  57. goto fail;
  58. if (!smbsuccess(&rh, errmsgp))
  59. goto fail;
  60. if (rh.wordcount == 0) {
  61. smbstringprint(errmsgp, "no parameters in negotiate response");
  62. goto fail;
  63. }
  64. index = smbnhgets(pdata); pdata += 2;
  65. if (index != 0) {
  66. smbstringprint(errmsgp, "no agreement on protocol");
  67. goto fail;
  68. }
  69. if (rh.wordcount != 17) {
  70. smbstringprint(errmsgp, "wrong number of parameters for negotiate response");
  71. goto fail;
  72. }
  73. peerinfo.securitymode = *pdata++;
  74. peerinfo.maxmpxcount = smbnhgets(pdata); pdata += 2;
  75. peerinfo.maxnumbervcs = smbnhgets(pdata); pdata += 2;
  76. peerinfo.maxbuffersize = smbnhgetl(pdata); pdata += 4;
  77. peerinfo.maxrawsize = smbnhgetl(pdata); pdata += 4;
  78. peerinfo.sessionkey = smbnhgets(pdata); pdata += 4;
  79. peerinfo.capabilities = smbnhgets(pdata); pdata += 4;
  80. utcintenthsofaus = smbnhgetv(pdata); pdata += 8;
  81. secssince1970 = utcintenthsofaus / 10000000 - 11644473600LL;
  82. peerinfo.utc = (vlong)secssince1970 * (vlong)1000000000 + (utcintenthsofaus % 10000000) * 100;
  83. peerinfo.tzoff = -smbnhgets(pdata) * 60; pdata += 2;
  84. peerinfo.encryptionkeylength = *pdata++;
  85. print("securitymode: 0x%.2ux\n", peerinfo.securitymode);
  86. print("maxmpxcount: 0x%.4ux\n", peerinfo.maxmpxcount);
  87. print("maxnumbervcs: 0x%.4ux\n", peerinfo.maxnumbervcs);
  88. print("maxbuffersize: 0x%.8lux\n", peerinfo.maxbuffersize);
  89. print("maxrawsize: 0x%.8lux\n", peerinfo.maxrawsize);
  90. print("sessionkey: 0x%.8lux\n", peerinfo.sessionkey);
  91. print("capabilities: 0x%.8lux\n", peerinfo.capabilities);
  92. print("utc: %s(and %lld μs)\n", asctime(gmtime(peerinfo.utc / 1000000000)), peerinfo.utc % 1000000000);
  93. print("tzoff: %d\n", peerinfo.tzoff);
  94. print("encryptionkeylength: %d\n", peerinfo.encryptionkeylength);
  95. smberealloc(&peerinfo.encryptionkey, peerinfo.encryptionkeylength);
  96. if (!smbbuffergetbytes(b, peerinfo.encryptionkey, peerinfo.encryptionkeylength)) {
  97. smbstringprint(errmsgp, "not enough data for encryption key");
  98. goto fail;
  99. }
  100. print("encryptionkey: ");
  101. for (x = 0; x < peerinfo.encryptionkeylength; x++)
  102. print("%.2ux", peerinfo.encryptionkey[x]);
  103. print("\n");
  104. if (!smbbuffergetucs2(b, 0, &peerinfo.oemdomainname)) {
  105. smbstringprint(errmsgp, "not enough data for oemdomainname");
  106. goto fail;
  107. }
  108. print("oemdomainname: %s\n", peerinfo.oemdomainname);
  109. if (peerinfo.capabilities & CAP_EXTENDED_SECURITY) {
  110. smbstringprint(errmsgp, "server wants extended security");
  111. goto fail;
  112. }
  113. /*
  114. * ok - now send SMB_COM_SESSION_SETUP_ANDX
  115. * fix the flags to reflect what the peer can do
  116. */
  117. smbbufferreset(b);
  118. h.command = SMB_COM_SESSION_SETUP_ANDX;
  119. h.wordcount = 13;
  120. h.flags2 &= ~SMB_FLAGS2_UNICODE;
  121. if (smbsendunicode(&peerinfo))
  122. h.flags2 |= SMB_FLAGS2_UNICODE;
  123. smbbufferputheader(b, &h, &peerinfo);
  124. smbbufferputb(b, SMB_COM_TREE_CONNECT_ANDX);
  125. smbbufferputb(b, 0);
  126. andxfixupoffset = smbbufferwriteoffset(b);
  127. smbbufferputs(b, 0);
  128. smbbufferputs(b, 0xffff);
  129. smbbufferputs(b, 1);
  130. smbbufferputs(b, 0);
  131. smbbufferputl(b, peerinfo.sessionkey);
  132. smbbufferputs(b, sizeof(mschapreply.LMresp));
  133. smbbufferputs(b, sizeof(mschapreply.NTresp));
  134. smbbufferputl(b, 0);
  135. smbbufferputl(b, CAP_UNICODE | CAP_LARGE_FILES);
  136. bytecountfixupoffset = smbbufferwriteoffset(b);
  137. smbbufferputs(b, 0);
  138. if (auth_respond(peerinfo.encryptionkey, peerinfo.encryptionkeylength,
  139. nil, 0,
  140. &mschapreply, sizeof(mschapreply), auth_getkey,
  141. "proto=mschap role=client server=%s", "cher") != sizeof(mschapreply)) {
  142. print("auth_respond failed: %r\n");
  143. goto fail;
  144. }
  145. smbbufferputbytes(b, &mschapreply, sizeof(mschapreply));
  146. smbbufferputstring(b, &peerinfo, 0, smbglobals.accountname);
  147. smbbufferputstring(b, &peerinfo, 0, smbglobals.primarydomain);
  148. smbbufferputstring(b, &peerinfo, 0, smbglobals.nativeos);
  149. smbbufferputstring(b, &peerinfo, 0, "");
  150. smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
  151. smbbufferalignl2(b, 2);
  152. smbbufferoffsetputs(b, andxfixupoffset, smbbufferwriteoffset(b));
  153. smbbufferputb(b, 4);
  154. smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND);
  155. smbbufferputb(b, 0);
  156. smbbufferputs(b, 0);
  157. smbbufferputs(b, 0);
  158. smbbufferputs(b, 0);
  159. bytecountfixupoffset = smbbufferwriteoffset(b);
  160. smbbufferputs(b, 0);
  161. strcpy(namebuf, "\\\\");
  162. strcat(namebuf, to);
  163. strcat(namebuf, "\\IPC$");
  164. smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf);
  165. smbbufferputstring(b, nil, SMB_STRING_ASCII, "?????");
  166. smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
  167. nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
  168. nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
  169. smbbufferreset(b);
  170. n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
  171. if (n < 0) {
  172. smbstringprint(errmsgp, "read error: %r");
  173. goto fail;
  174. }
  175. smbbuffersetreadlen(b, n);
  176. nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
  177. if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp))
  178. goto fail;
  179. if (!smbsuccess(&rh, errmsgp))
  180. goto fail;
  181. h.uid = rh.uid;
  182. ipctid = rh.tid;
  183. /*
  184. * now do another TREE_CONNECT if needed
  185. */
  186. if (share) {
  187. smbbufferreset(b);
  188. h.command = SMB_COM_TREE_CONNECT_ANDX;
  189. h.wordcount = 4;
  190. h.tid = 0;
  191. smbbufferputheader(b, &h, &peerinfo);
  192. smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND);
  193. smbbufferputb(b, 0);
  194. smbbufferputs(b, 0);
  195. smbbufferputs(b, 0);
  196. smbbufferputs(b, 0);
  197. bytecountfixupoffset = smbbufferwriteoffset(b);
  198. smbbufferputs(b, 0);
  199. strcpy(namebuf, "\\\\");
  200. strcat(namebuf, to);
  201. strcat(namebuf, "\\");
  202. strcat(namebuf, share);
  203. smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf);
  204. smbbufferputstring(b, nil, SMB_STRING_ASCII, "A:");
  205. smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
  206. nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
  207. nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
  208. smbbufferreset(b);
  209. n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
  210. if (n < 0) {
  211. smbstringprint(errmsgp, "read error: %r");
  212. goto fail;
  213. }
  214. smbbuffersetreadlen(b, n);
  215. nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
  216. if (!smbbuffergetandcheckheader(b, &rh, h.command, 3, &pdata, &bytecount, errmsgp))
  217. goto fail;
  218. if (!smbsuccess(&rh, errmsgp))
  219. goto fail;
  220. sharetid = rh.tid;
  221. }
  222. else
  223. sharetid = -2;
  224. c = smbemalloc(sizeof(*c));
  225. c->peerinfo = peerinfo;
  226. c->ipctid = ipctid;
  227. c->sharetid = sharetid;
  228. c->b = b;
  229. c->protoh = h;
  230. c->nbss = nbs;
  231. return c;
  232. fail:
  233. smbbufferfree(&b);
  234. free(peerinfo.encryptionkey);
  235. free(peerinfo.oemdomainname);
  236. return nil;
  237. }
  238. void
  239. smbclientfree(SmbClient *c)
  240. {
  241. if (c) {
  242. free(c->peerinfo.encryptionkey);
  243. free(c->peerinfo.oemdomainname);
  244. free(c);
  245. smbbufferfree(&c->b);
  246. }
  247. }
  248. int
  249. smbtransactionclientsend(void *magic, SmbBuffer *ob, char **)
  250. {
  251. SmbClient *c = magic;
  252. smblogprint(-1, "sending:\n");
  253. smblogdata(-1, smblogprint, smbbufferreadpointer(ob), smbbufferwriteoffset(ob), 256);
  254. return nbsswrite(c->nbss, smbbufferreadpointer(ob), smbbufferwriteoffset(ob)) == 0;
  255. }
  256. int
  257. smbtransactionclientreceive(void *magic, SmbBuffer *ib, char **)
  258. {
  259. long n;
  260. SmbClient *c = magic;
  261. smbbufferreset(ib);
  262. n = nbssread(c->nbss, smbbufferwritepointer(ib), smbbufferwritespace(ib));
  263. if (n >= 0) {
  264. assert(smbbufferputbytes(ib, nil, n));
  265. return 1;
  266. }
  267. return 0;
  268. }