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