smbconnect.c 9.3 KB

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