diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aquarela/smbconnect.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aquarela/smbconnect.c')
-rwxr-xr-x | sys/src/cmd/aquarela/smbconnect.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/sys/src/cmd/aquarela/smbconnect.c b/sys/src/cmd/aquarela/smbconnect.c new file mode 100755 index 000000000..6e6ce3550 --- /dev/null +++ b/sys/src/cmd/aquarela/smbconnect.c @@ -0,0 +1,275 @@ +#include "headers.h" + +SmbClient * +smbconnect(char *to, char *share, char **errmsgp) +{ + NbSession *nbs; + SmbBuffer *b; + SmbHeader h, rh; + long n; + ushort bytecountfixupoffset; + ushort andxfixupoffset; + uchar *pdata; + SmbPeerInfo peerinfo; + ushort index; + vlong utcintenthsofaus; + ulong secssince1970; + ushort bytecount; + int x; + MSchapreply mschapreply; + NbName nbto; + SmbClient *c; + char namebuf[100]; + ushort ipctid, sharetid; + + nbmknamefromstringandtype(nbto, to, 0x20); + + peerinfo.encryptionkey = nil; + peerinfo.oemdomainname = nil; + assert(smbglobals.nbname[0] != 0); + nbs = nbssconnect(nbto, smbglobals.nbname); + if (nbs == nil) + return nil; +print("netbios session established\n"); + b = smbbuffernew(65535); + memset(&h, 0, sizeof(h)); + h.command = SMB_COM_NEGOTIATE; + h.flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES | SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_UNICODE; + h.wordcount = 0; + h.pid = 42; + smbbufferputheader(b, &h, &peerinfo); + bytecountfixupoffset = smbbufferwriteoffset(b); + smbbufferputbytes(b, nil, 2); + smbbufferputb(b, 2); + smbbufferputstring(b, nil, SMB_STRING_ASCII, "NT LM 0.12"); + smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2); + nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b)); + nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b)); + /* + * now receive a reply + */ + smbbufferreset(b); + n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b)); + if (n < 0) { + smbstringprint(errmsgp, "smbconnect: read error: %r"); + goto fail; + } + smbbuffersetreadlen(b, n); + nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b)); + if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp)) + goto fail; + if (!smbsuccess(&rh, errmsgp)) + goto fail; + if (rh.wordcount == 0) { + smbstringprint(errmsgp, "no parameters in negotiate response"); + goto fail; + } + index = smbnhgets(pdata); pdata += 2; + if (index != 0) { + smbstringprint(errmsgp, "no agreement on protocol"); + goto fail; + } + if (rh.wordcount != 17) { + smbstringprint(errmsgp, "wrong number of parameters for negotiate response"); + goto fail; + } + peerinfo.securitymode = *pdata++; + peerinfo.maxmpxcount = smbnhgets(pdata); pdata += 2; + peerinfo.maxnumbervcs = smbnhgets(pdata); pdata += 2; + peerinfo.maxbuffersize = smbnhgetl(pdata); pdata += 4; + peerinfo.maxrawsize = smbnhgetl(pdata); pdata += 4; + peerinfo.sessionkey = smbnhgets(pdata); pdata += 4; + peerinfo.capabilities = smbnhgets(pdata); pdata += 4; + utcintenthsofaus = smbnhgetv(pdata); pdata += 8; + secssince1970 = utcintenthsofaus / 10000000 - 11644473600LL; + peerinfo.utc = (vlong)secssince1970 * (vlong)1000000000 + (utcintenthsofaus % 10000000) * 100; + peerinfo.tzoff = -smbnhgets(pdata) * 60; pdata += 2; + peerinfo.encryptionkeylength = *pdata++; + print("securitymode: 0x%.2ux\n", peerinfo.securitymode); + print("maxmpxcount: 0x%.4ux\n", peerinfo.maxmpxcount); + print("maxnumbervcs: 0x%.4ux\n", peerinfo.maxnumbervcs); + print("maxbuffersize: 0x%.8lux\n", peerinfo.maxbuffersize); + print("maxrawsize: 0x%.8lux\n", peerinfo.maxrawsize); + print("sessionkey: 0x%.8lux\n", peerinfo.sessionkey); + print("capabilities: 0x%.8lux\n", peerinfo.capabilities); + print("utc: %s(and %lld μs)\n", asctime(gmtime(peerinfo.utc / 1000000000)), peerinfo.utc % 1000000000); + print("tzoff: %d\n", peerinfo.tzoff); + print("encryptionkeylength: %d\n", peerinfo.encryptionkeylength); + smberealloc(&peerinfo.encryptionkey, peerinfo.encryptionkeylength); + if (!smbbuffergetbytes(b, peerinfo.encryptionkey, peerinfo.encryptionkeylength)) { + smbstringprint(errmsgp, "not enough data for encryption key"); + goto fail; + } + print("encryptionkey: "); + for (x = 0; x < peerinfo.encryptionkeylength; x++) + print("%.2ux", peerinfo.encryptionkey[x]); + print("\n"); + if (!smbbuffergetucs2(b, 0, &peerinfo.oemdomainname)) { + smbstringprint(errmsgp, "not enough data for oemdomainname"); + goto fail; + } + print("oemdomainname: %s\n", peerinfo.oemdomainname); + if (peerinfo.capabilities & CAP_EXTENDED_SECURITY) { + smbstringprint(errmsgp, "server wants extended security"); + goto fail; + } + /* + * ok - now send SMB_COM_SESSION_SETUP_ANDX + * fix the flags to reflect what the peer can do + */ + smbbufferreset(b); + h.command = SMB_COM_SESSION_SETUP_ANDX; + h.wordcount = 13; + h.flags2 &= ~SMB_FLAGS2_UNICODE; + if (smbsendunicode(&peerinfo)) + h.flags2 |= SMB_FLAGS2_UNICODE; + smbbufferputheader(b, &h, &peerinfo); + smbbufferputb(b, SMB_COM_TREE_CONNECT_ANDX); + smbbufferputb(b, 0); + andxfixupoffset = smbbufferwriteoffset(b); + smbbufferputs(b, 0); + smbbufferputs(b, 0xffff); + smbbufferputs(b, 1); + smbbufferputs(b, 0); + smbbufferputl(b, peerinfo.sessionkey); + smbbufferputs(b, sizeof(mschapreply.LMresp)); + smbbufferputs(b, sizeof(mschapreply.NTresp)); + smbbufferputl(b, 0); + smbbufferputl(b, CAP_UNICODE | CAP_LARGE_FILES); + bytecountfixupoffset = smbbufferwriteoffset(b); + smbbufferputs(b, 0); + if (auth_respond(peerinfo.encryptionkey, peerinfo.encryptionkeylength, + nil, 0, + &mschapreply, sizeof(mschapreply), auth_getkey, + "proto=mschap role=client server=%s", "cher") != sizeof(mschapreply)) { + print("auth_respond failed: %r\n"); + goto fail; + } + smbbufferputbytes(b, &mschapreply, sizeof(mschapreply)); + smbbufferputstring(b, &peerinfo, 0, smbglobals.accountname); + smbbufferputstring(b, &peerinfo, 0, smbglobals.primarydomain); + smbbufferputstring(b, &peerinfo, 0, smbglobals.nativeos); + smbbufferputstring(b, &peerinfo, 0, ""); + smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2); + smbbufferalignl2(b, 2); + smbbufferoffsetputs(b, andxfixupoffset, smbbufferwriteoffset(b)); + smbbufferputb(b, 4); + smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND); + smbbufferputb(b, 0); + smbbufferputs(b, 0); + smbbufferputs(b, 0); + smbbufferputs(b, 0); + bytecountfixupoffset = smbbufferwriteoffset(b); + smbbufferputs(b, 0); + strcpy(namebuf, "\\\\"); + strcat(namebuf, to); + strcat(namebuf, "\\IPC$"); + smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf); + smbbufferputstring(b, nil, SMB_STRING_ASCII, "?????"); + smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2); + nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b)); + nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b)); + smbbufferreset(b); + n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b)); + if (n < 0) { + smbstringprint(errmsgp, "read error: %r"); + goto fail; + } + smbbuffersetreadlen(b, n); + nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b)); + if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp)) + goto fail; + if (!smbsuccess(&rh, errmsgp)) + goto fail; + h.uid = rh.uid; + ipctid = rh.tid; + /* + * now do another TREE_CONNECT if needed + */ + if (share) { + smbbufferreset(b); + h.command = SMB_COM_TREE_CONNECT_ANDX; + h.wordcount = 4; + h.tid = 0; + smbbufferputheader(b, &h, &peerinfo); + smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND); + smbbufferputb(b, 0); + smbbufferputs(b, 0); + smbbufferputs(b, 0); + smbbufferputs(b, 0); + bytecountfixupoffset = smbbufferwriteoffset(b); + smbbufferputs(b, 0); + strcpy(namebuf, "\\\\"); + strcat(namebuf, to); + strcat(namebuf, "\\"); + strcat(namebuf, share); + smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf); + smbbufferputstring(b, nil, SMB_STRING_ASCII, "A:"); + smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2); + nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b)); + nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b)); + smbbufferreset(b); + n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b)); + if (n < 0) { + smbstringprint(errmsgp, "read error: %r"); + goto fail; + } + smbbuffersetreadlen(b, n); + nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b)); + if (!smbbuffergetandcheckheader(b, &rh, h.command, 3, &pdata, &bytecount, errmsgp)) + goto fail; + if (!smbsuccess(&rh, errmsgp)) + goto fail; + sharetid = rh.tid; + } + else + sharetid = -2; + c = smbemalloc(sizeof(*c)); + c->peerinfo = peerinfo; + c->ipctid = ipctid; + c->sharetid = sharetid; + c->b = b; + c->protoh = h; + c->nbss = nbs; + return c; +fail: + smbbufferfree(&b); + free(peerinfo.encryptionkey); + free(peerinfo.oemdomainname); + return nil; +} + +void +smbclientfree(SmbClient *c) +{ + if (c) { + free(c->peerinfo.encryptionkey); + free(c->peerinfo.oemdomainname); + free(c); + smbbufferfree(&c->b); + } +} + +int +smbtransactionclientsend(void *magic, SmbBuffer *ob, char **) +{ + SmbClient *c = magic; +smblogprint(-1, "sending:\n"); +smblogdata(-1, smblogprint, smbbufferreadpointer(ob), smbbufferwriteoffset(ob), 256); + return nbsswrite(c->nbss, smbbufferreadpointer(ob), smbbufferwriteoffset(ob)) == 0; +} + +int +smbtransactionclientreceive(void *magic, SmbBuffer *ib, char **) +{ + long n; + SmbClient *c = magic; + smbbufferreset(ib); + n = nbssread(c->nbss, smbbufferwritepointer(ib), smbbufferwritespace(ib)); + if (n >= 0) { + assert(smbbufferputbytes(ib, nil, n)); + return 1; + } + return 0; +} + |