summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aquarela/smbconnect.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/aquarela/smbconnect.c275
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;
+}
+