From 8f5375fa61acb4da83e855e40402d12be01a8c68 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 16 Jan 2012 18:42:16 +0100 Subject: [PATCH] cifs: updated cifs/smb client to quintiles latest version --- sys/man/4/cifs | 74 ++++++--- sys/src/cmd/cifs/auth-testcase.c | 78 ++++----- sys/src/cmd/cifs/auth.c | 115 +++++++------- sys/src/cmd/cifs/cifs.c | 58 +++++-- sys/src/cmd/cifs/cifs.h | 262 +++++++++++++++---------------- sys/src/cmd/cifs/info.c | 40 ++--- sys/src/cmd/cifs/main.c | 9 +- sys/src/cmd/cifs/mkfile | 7 - sys/src/cmd/cifs/nterrstr.c | 23 ++- sys/src/cmd/cifs/pack.c | 9 +- sys/src/cmd/cifs/remsmb.h | 28 ++-- sys/src/cmd/cifs/trans.c | 24 +-- sys/src/cmd/cifs/trans2.c | 2 +- 13 files changed, 388 insertions(+), 341 deletions(-) diff --git a/sys/man/4/cifs b/sys/man/4/cifs index 9481df6c5..cdb1c89c2 100644 --- a/sys/man/4/cifs +++ b/sys/man/4/cifs @@ -20,6 +20,9 @@ cifs - Microsoft™ Windows network filesystem client ] [ .B -m .I mntpnt +] [ +.B -t +.I dfs-timeout ] .I host [ @@ -32,8 +35,7 @@ translates between Microsoft's file-sharing protocol (shares or trees in MS terminology) published by such servers. .PP The root of the mounted directory contains one subdirectory per share, -always named in lower case, and a few virtual files of mixed case which -give additional server, session, share, and user information. +and a few virtual files give additional information. The arguments are: .TF "-a\fI auth-method" .PD @@ -71,6 +73,14 @@ CIFS packet debug. .B -D 9P request debug. .TP +.B -i +By default +.I cifs(4) +attempts to enforce case significance file and directory names, though objects +which differ only in their case still cannot co-exist in the same directory. The +.B -i +option disables this behaveiour. +.TP .BI -k " keyparam" lists extra parameters which will be passed to .IR factotum (4) @@ -112,6 +122,11 @@ and finally it will try the name post the service as .BI /srv/ srvname. .TP +.BI -t " dfs-timeout" +sets the timeout in for DFS redirections - it defaults to 100ms. +This is a reasonable minimum, it should have a value just greater than +the RTT to the most distant server being accessed. +.TP .I host The address of the remote server to connect to. .TP @@ -126,7 +141,7 @@ Several synthetic files appear in the root of the mounted filesystem: .TP .B Shares Contains a list of the currently attached shares, -with fields giving the share name, disk free space / capacity, the share type, +with fields giving the share name, the share type, disk free space / capacity, and a descriptive comment from the server. .TP .B Connection @@ -161,27 +176,48 @@ the version number of the OS it is running, and comma-separated list of flags giving the features of that OS. .TP .B Dfsroot -Top level DFS routing giving the DFS link type, time to live of the data, -proximity of the server, the Netbios or DNS name and -a physical path or a machine that this maps to. -.IP -DNS paths are usually assigned dynamicially as a form of load balancing. +Lists the top level DFS domains and the servers that +provision them. +.TP +.B Dfscache +Contents of the DFS referal cache, giving the path prefix, +the expiry time (or -1 for never), the measured RTT to the server +in milliseconds, the server proximity (0 is local), the server name, +and the share name on that server. +.SH COMPATIBILITY +.I Cifs +has been tested against +.IR aquarela (8), +Windows 95, NT4.0sp6, +Windows server 2003, Windows server 2003, WinXP pro, +Samba 2.0 (Pluto VideoSpace), and Samba 3.0. +.LP +Windows Vista require a hotfix (registry change) +to support NTLMv2 without GSSAPI, see http://support.microsoft.com/kb/957441. +Alternatively the +.B -a +option can be used to force +.I cifs +to use one of the less secure authentication mechnisms. +.LP +Windows 7 has dropped support for RAP, which is used to generate +the synthetic files offered by +.IR cifs . +RAP is also used to enumerate the shares offered by the remote host so +remote share names must always be specified on the command line. +.LP +The NetApp Filer was supported by earlier releases, however recent +attempts to mount one have failed. Should a server be available it is +likely that this could be easily fixed. +.PP .SH SOURCE .B /sys/src/cmd/cifs .SH SEE ALSO .IR factotum (4), -.IR cifsd (8) +.IR aquarela (8) .SH BUGS -NetApp Filer compatibility has not yet been tested; there may not be any. +DFS support is unfinished, it will not follow referals that span servers. .PP -DFS support is unfinished. -.PP -Kerberos authentication is unfinished. +Kerberos authentication is not supported. .PP NetBios name resolution is not supported, though it is now rarely used. -.PP -.I Cifs -has only been tested against -aquarela, Windows 95, NT4.0sp6, -Windows server 2003, WinXP pro, Samba 3.0, and Samba 2.0 (Pluto VideoSpace). -No support is attempted for servers predating NT 4.0. diff --git a/sys/src/cmd/cifs/auth-testcase.c b/sys/src/cmd/cifs/auth-testcase.c index 0bc74a773..ae932a319 100644 --- a/sys/src/cmd/cifs/auth-testcase.c +++ b/sys/src/cmd/cifs/auth-testcase.c @@ -137,30 +137,28 @@ hmac_t64(uchar *data, ulong dlen, uchar *key, ulong klen, uchar *digest, static int ntv2_blob(uchar *blob, int len, char *windom) { - int n; - uvlong nttime; - Rune r; - char *d; + uvlong t; uchar *p; enum { /* name types */ Beof, /* end of name list */ - Bnetbios, /* Netbios machine name */ + Bhost, /* Netbios host name */ Bdomain, /* Windows Domain name (NT) */ - Bdnsfqdn, /* DNS Fully Qualified Domain Name */ - Bdnsname, /* DNS machine name (win2k) */ + Bdnshost, /* DNS host name */ + Bdnsdomain, /* DNS domain name */ }; p = blob; - *p++ = 1; /* response type */ - *p++ = 1; /* max response type understood by client */ + *p++ = 1; /* 8bit: response type */ + *p++ = 1; /* 8bit: max response type understood by client */ + *p++ = 0; /* 16bit: reserved */ *p++ = 0; - *p++ = 0; /* 2 bytes reserved */ + *p++ = 0; /* 32bit: unknown */ *p++ = 0; *p++ = 0; *p++ = 0; - *p++ = 0; /* 4 bytes unknown */ + #ifdef NTLMV2_TEST *p++ = 0xf0; @@ -172,18 +170,19 @@ ntv2_blob(uchar *blob, int len, char *windom) *p++ = 0xbe; *p++ = 0x01; #else - nttime = time(nil); /* nt time now */ - nttime = nttime + 11644473600LL; - nttime = nttime * 10000000LL; - *p++ = nttime & 0xff; - *p++ = (nttime >> 8) & 0xff; - *p++ = (nttime >> 16) & 0xff; - *p++ = (nttime >> 24) & 0xff; - *p++ = (nttime >> 32) & 0xff; - *p++ = (nttime >> 40) & 0xff; - *p++ = (nttime >> 48) & 0xff; - *p++ = (nttime >> 56) & 0xff; + t = time(nil); /* 64bit: time in NT format */ + t += 11644473600LL; + t *= 10000000LL; + *p++ = t; + *p++ = t >> 8; + *p++ = t >> 16; + *p++ = t >> 24; + *p++ = t >> 32; + *p++ = t >> 40; + *p++ = t >> 48; + *p++ = t >> 56; #endif + #ifdef NTLMV2_TEST *p++ = 0x05; *p++ = 0x83; @@ -195,38 +194,17 @@ ntv2_blob(uchar *blob, int len, char *windom) *p++ = 0x6d; #else genrandom(p, 8); - p += 8; /* client nonce */ + p += 8; /* 64bit: client nonce */ #endif - *p++ = 0x6f; - *p++ = 0; - *p++ = 0x6e; - *p++ = 0; /* unknown data */ - *p++ = Bdomain; - *p++ = 0; /* name type */ - - n = utflen(windom) * 2; - *p++ = n; - *p++ = n >> 8; /* name length */ - - d = windom; - while(*d && p - blob < len - 8){ - d += chartorune(&r, d); - r = toupperrune(r); - *p++ = r; - *p++ = r >> 8; - } - - *p++ = 0; - *p++ = Beof; /* name type */ - - *p++ = 0; - *p++ = 0; /* name length */ - - *p++ = 0x65; + *p++ = 0; /* 32bit: unknown data */ *p++ = 0; *p++ = 0; - *p++ = 0; /* unknown data */ + *p++ = 0; + + p += putname(p, len - (p-blob), windom, Bdomain); + p += putname(p, len - (p-blob), "", Beof); + return p - blob; } diff --git a/sys/src/cmd/cifs/auth.c b/sys/src/cmd/cifs/auth.c index f72c03d2d..5bf2433f9 100644 --- a/sys/src/cmd/cifs/auth.c +++ b/sys/src/cmd/cifs/auth.c @@ -135,77 +135,80 @@ hmac_t64(uchar *data, ulong dlen, uchar *key, ulong klen, uchar *digest, static int -ntv2_blob(uchar *blob, int len, char *windom) +putname(uchar *buf, int len, char *name, int type) { int n; - uvlong nttime; Rune r; char *d; - uchar *p; - enum { /* name types */ - Beof, /* end of name list */ - Bnetbios, /* Netbios machine name */ - Bdomain, /* Windows Domain name (NT) */ - Bdnsfqdn, /* DNS Fully Qualified Domain Name */ - Bdnsname, /* DNS machine name (win2k) */ - }; + uchar *p = buf; - p = blob; - *p++ = 1; /* response type */ - *p++ = 1; /* max response type understood by client */ + *p++ = type; + *p++ = 0; /* 16bit: name type */ - *p++ = 0; - *p++ = 0; /* 2 bytes reserved */ - - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = 0; /* 4 bytes unknown */ - - nttime = time(nil); /* nt time now */ - nttime += 11644473600LL; - nttime *= 10000000LL; - *p++ = nttime; - *p++ = nttime >> 8; - *p++ = nttime >> 16; - *p++ = nttime >> 24; - *p++ = nttime >> 32; - *p++ = nttime >> 40; - *p++ = nttime >> 48; - *p++ = nttime >> 56; - - genrandom(p, 8); - p += 8; /* client nonce */ - *p++ = 0x6f; - *p++ = 0; - *p++ = 0x6e; - *p++ = 0; /* unknown data */ - - *p++ = Bdomain; - *p++ = 0; /* name type */ - - n = utflen(windom) * 2; + n = utflen(name) * 2; *p++ = n; - *p++ = n >> 8; /* name length */ + *p++ = n >> 8; /* 16bit: name length */ - d = windom; - while(*d && p-blob < (len-8)){ + d = name; + while(*d != 0 && p-buf < len-8){ d += chartorune(&r, d); r = toupperrune(r); *p++ = r; - *p++ = r >> 8; - } + *p++ = r >> 8; + } /* var: actual name */ - *p++ = 0; - *p++ = Beof; /* name type */ + return p - buf; +} - *p++ = 0; - *p++ = 0; /* name length */ +static int +ntv2_blob(uchar *blob, int len, char *windom) +{ + uvlong t; + uchar *p; + enum { /* name types */ + Beof, /* end of name list */ + Bhost, /* Netbios host name */ + Bdomain, /* Windows Domain name (NT) */ + Bdnshost, /* DNS host name */ + Bdnsdomain, /* DNS domain name */ + }; - *p++ = 0x65; + p = blob; + *p++ = 1; /* 8bit: response type */ + *p++ = 1; /* 8bit: max response type understood by client */ + + *p++ = 0; /* 16bit: reserved */ + *p++ = 0; + + *p++ = 0; /* 32bit: unknown */ *p++ = 0; *p++ = 0; - *p++ = 0; /* unknown data */ + *p++ = 0; + + t = time(nil); + t += 11644473600LL; + t *= 10000000LL; + + *p++ = t; /* 64bit: time in NT format */ + *p++ = t >> 8; + *p++ = t >> 16; + *p++ = t >> 24; + *p++ = t >> 32; + *p++ = t >> 40; + *p++ = t >> 48; + *p++ = t >> 56; + + genrandom(p, 8); + p += 8; /* 64bit: client nonce */ + + *p++ = 0; /* 32bit: unknown data */ + *p++ = 0; + *p++ = 0; + *p++ = 0; + + p += putname(p, len - (p-blob), windom, Bdomain); + p += putname(p, len - (p-blob), "", Beof); + return p - blob; } @@ -293,7 +296,7 @@ auth_ntlmv2(char *windom, char *keyp, uchar *chal, int len) memcpy(ap->mackey[0]+MD5dlen, ap->resp[0], MACkeylen-MD5dlen); /* NTLM v2 */ - n = ntv2_blob(blob, sizeof(blob), windom); + n = ntv2_blob(blob, sizeof blob, windom); ds = hmac_t64(chal, len, v2hash, MD5dlen, nil, nil); hmac_t64(blob, n, v2hash, MD5dlen, nt_hmac, ds); ap->len[1] = MD5dlen+n; diff --git a/sys/src/cmd/cifs/cifs.c b/sys/src/cmd/cifs/cifs.c index 68b6a636c..7b667951e 100644 --- a/sys/src/cmd/cifs/cifs.c +++ b/sys/src/cmd/cifs/cifs.c @@ -40,8 +40,12 @@ cifsdial(char *host, char *called, char *sysname) s->seqrun = 0; s->secmode = SECMODE_SIGN_ENABLED; /* hope for the best */ s->flags2 = FL2_KNOWS_LONG_NAMES | FL2_HAS_LONG_NAMES | FL2_PAGEING_IO; + s->macidx = -1; + if(s->mtu > MTU) + s->mtu = MTU; + return s; } @@ -76,6 +80,7 @@ cifshdr(Session *s, Share *sp, int cmd) p->buf = (uchar *)p + sizeof(Pkt); p->s = s; + p->request = cmd; /* for debug */ qlock(&s->seqlock); if(s->seqrun){ @@ -137,11 +142,12 @@ dmp(int seq, uchar *buf) int cifsrpc(Pkt *p) { - int flags2, got, err; + int reply, got, err; uint tid, uid, seq; uchar *pos; char m[nelem(magic)]; + pos = p->pos; if(p->bytebase){ p->pos = p->bytebase; @@ -155,20 +161,23 @@ cifsrpc(Pkt *p) qlock(&p->s->rpclock); got = nbtrpc(p); qunlock(&p->s->rpclock); - if(got == -1) + + if(got < 32+NBHDRLEN){ + werrstr("cifs packet too small (%d < %d)\n", got, 32+NBHDRLEN); return -1; + } gmem(p, m, nelem(magic)); if(memcmp(m, magic, nelem(magic)) != 0){ - werrstr("cifsrpc: bad magic number in packet %20ux%02ux%02ux%02ux", + werrstr("cifsrpc: bad magic number in packet 0x%02ux%02ux%02ux%02ux", m[0], m[1], m[2], m[3]); return -1; } - g8(p); /* cmd */ + reply = g8(p); /* cmd */ err = gl32(p); /* errcode */ g8(p); /* flags */ - flags2 = gl16(p); /* flags2 */ + p->flags2 = gl16(p); /* flags2 */ gl16(p); /* PID MS bits */ seq = gl32(p); /* reserved */ gl32(p); /* MAC (if in use) */ @@ -179,6 +188,12 @@ cifsrpc(Pkt *p) gl16(p); /* mid */ g8(p); /* word count */ + if(reply != p->request){ + fprint(2, "unexpected reply (cmd=%x/%x seq=%d/%d)\n", + reply, p->request, seq, p->seq); + return -1; + } + if(p->s->secmode & SECMODE_SIGN_ENABLED){ if(macsign(p, p->seq+1) != 0 && p->s->seqrun){ werrstr("cifsrpc: invalid packet signature"); @@ -196,7 +211,7 @@ print("MAC signature bad\n"); * catch that too. */ if(p->s->seqrun && seq != p->seq && seq != 0){ - print("%ux != %ux bad sequence number\n", seq, p->seq); + werrstr("bad sequence number (%d != %d)\n", p->seq, seq); return -1; } } @@ -205,7 +220,7 @@ print("MAC signature bad\n"); if(p->s->uid == NO_UID) p->s->uid = uid; - if(flags2 & FL2_NT_ERRCODES){ + if(p->flags2 & FL2_NT_ERRCODES){ /* is it a real error rather than info/warning/chatter? */ if((err & 0xF0000000) == 0xC0000000){ werrstr("%s", nterrstr(err)); @@ -243,11 +258,26 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, }; Pkt *p; + /* + * This should not be necessary, however the XP seems to use + * Unicode strings in its Negoiate response, but not set the + * Flags2 UNICODE flag. + * + * It does however echo back the FL_UNICODE flag we set in the + * flags2 negoiate request. + * + * The bodge is to force FL_UNICODE for this single request, + * clearing it after. Later we set FL2_UNICODE if the server + * agrees to CAP_UNICODE as it "should" be done. + */ + s->flags2 |= FL2_UNICODE; p = cifshdr(s, nil, SMB_COM_NEGOTIATE); + s->flags2 &= ~FL2_UNICODE; + pbytes(p); for(i = 0; i < nelem(dialects); i++){ p8(p, STR_DIALECT); - pstr(p, dialects[i]); + pascii(p, dialects[i]); } if(cifsrpc(p) == -1){ @@ -277,7 +307,7 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, gl32(p); /* Session key */ s->caps = gl32(p); /* Server capabilities */ *svrtime = gvtime(p); /* fileserver time */ - s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */ + s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */ s->challen = g8(p); /* Encryption key length */ gl16(p); gmem(p, s->chal, s->challen); /* Get the challenge */ @@ -368,7 +398,7 @@ CIFSsession(Session *s) gl16(p); gl16(p); /* no security blob here - we don't understand extended security anyway */ - gstr(p, os, sizeof(os)); + gstr(p, os, sizeof os); s->remos = estrdup9p(os); free(p); @@ -386,9 +416,9 @@ CIFStreeconnect(Session *s, char *cname, char *tree, Share *sp) resp = Sess->auth->resp[0]; len = Sess->auth->len[0]; if((s->secmode & SECMODE_USER) != SECMODE_USER){ - memset(zeros, 0, sizeof(zeros)); + memset(zeros, 0, sizeof zeros); resp = zeros; - len = sizeof(zeros); + len = sizeof zeros; } p = cifshdr(s, nil, SMB_COM_TREE_CONNECT_ANDX); @@ -408,11 +438,11 @@ CIFStreeconnect(Session *s, char *cname, char *tree, Share *sp) } path = smprint("//%s/%s", cname, tree); - strupr(path); + ppath(p, path); /* path */ free(path); - pascii(p, "?????"); /* service type any (so we can do RAP calls) */ + pascii(p, "?????"); /* service type any (so we can do RAP calls) */ if(cifsrpc(p) == -1){ free(p); diff --git a/sys/src/cmd/cifs/cifs.h b/sys/src/cmd/cifs/cifs.h index a600ed7d4..8acf1b350 100644 --- a/sys/src/cmd/cifs/cifs.h +++ b/sys/src/cmd/cifs/cifs.h @@ -350,10 +350,10 @@ typedef struct { int uid; /* user (authentication) ID */ int seq; /* sequence number */ int seqrun; /* sequence numbering active */ - int caps; /* server capabilities */ + int caps; /* server's capabilities */ int support; /* support bits */ - int flags; /* SMB flags */ - int flags2; /* SMB flags 2 */ + int flags; /* SMB flags that we will send in the next packet */ + int flags2; /* SMB flags 2 that we will send in the next packet */ int nocache; /* disable write behind caching in server */ int pid; /* process ID */ int mid; /* multiplex ID */ @@ -378,6 +378,8 @@ typedef struct { int tid; /* tree ID received from server */ int seq; /* sequence number expected in reply */ + int request; /* request cmd no (for debug) */ + int flags2; /* flags2 received with this packet */ uchar *seqbase; /* cifs: pos of sequence number in packet */ uchar *wordbase; /* cifs: base of words section of data */ @@ -483,156 +485,150 @@ extern Share Ipc; extern Share Shares[MAX_SHARES]; extern int Nshares; -/* main.c */ -Qid mkqid(char *, int, long, int, long); - /* auth.c */ -Auth *getauth(char *, char *, char *, int, uchar *, int); -void autherr(void); -int macsign(Pkt *, int); +extern void autherr(void); +extern Auth *getauth(char *name, char *windom, char *keyp, int secmode, uchar *chal, int len); +extern int macsign(Pkt *p, int seq); /* cifs.c */ -Session *cifsdial(char *, char *, char *); -void cifsclose(Session *); -Pkt *cifshdr(Session *, Share *, int); -void pbytes(Pkt *); -int cifsrpc(Pkt *); -int CIFSnegotiate(Session *, long *, char *, int, char *, int); -int CIFSsession(Session *); -int CIFStreeconnect(Session *, char *, char *, Share *); -int CIFSlogoff(Session *); -int CIFStreedisconnect(Session *, Share *); -int CIFSdeletefile(Session *, Share *, char *); -int CIFSdeletedirectory(Session *, Share *, char *); -int CIFScreatedirectory(Session *, Share *, char *); -int CIFSrename(Session *, Share *, char *, char *); -int CIFS_NT_opencreate(Session *, Share *, char *, int, int, int, int, int, int, int *, FInfo *); -int CIFS_SMB_opencreate(Session *, Share *, char *, int, int, int, int *); -vlong CIFSwrite(Session *, Share *, int, uvlong, void *, vlong); -vlong CIFSread(Session *, Share *, int, uvlong, void *, vlong, vlong); -int CIFSflush(Session *, Share *, int); -int CIFSclose(Session *, Share *, int); -int CIFSfindclose2(Session *, Share *, int); -int CIFSecho(Session *); -int CIFSsetinfo(Session *, Share *, char *, FInfo *); -void goff(Pkt *, uchar *, char *, int); +extern Session *cifsdial(char *host, char *called, char *sysname); +extern void cifsclose(Session *s); +extern Pkt *cifshdr(Session *s, Share *sp, int cmd); +extern void pbytes(Pkt *p); +extern int cifsrpc(Pkt *p); +extern int CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, int cnamlen); +extern int CIFSsession(Session *s); +extern int CIFStreeconnect(Session *s, char *cname, char *tree, Share *sp); +extern int CIFSlogoff(Session *s); +extern int CIFStreedisconnect(Session *s, Share *sp); +extern int CIFSdeletefile(Session *s, Share *sp, char *name); +extern int CIFSdeletedirectory(Session *s, Share *sp, char *name); +extern int CIFScreatedirectory(Session *s, Share *sp, char *name); +extern int CIFSrename(Session *s, Share *sp, char *old, char *new); +extern int CIFS_NT_opencreate(Session *s, Share *sp, char *name, int flags, int options, int attrs, int access, int share, int action, int *result, FInfo *fi); +extern int CIFS_SMB_opencreate(Session *s, Share *sp, char *name, int access, int attrs, int action, int *result); +extern vlong CIFSwrite(Session *s, Share *sp, int fh, uvlong off, void *buf, vlong n); +extern vlong CIFSread(Session *s, Share *sp, int fh, uvlong off, void *buf, vlong n, vlong minlen); +extern int CIFSflush(Session *s, Share *sp, int fh); +extern int CIFSclose(Session *s, Share *sp, int fh); +extern int CIFSfindclose2(Session *s, Share *sp, int sh); +extern int CIFSecho(Session *s); +extern int CIFSsetinfo(Session *s, Share *sp, char *path, FInfo *fip); /* dfs.c */ -char *mapfile(char *); -int mapshare(char *, Share **); -int redirect(Session *, Share *s, char *); -int dfscacheinfo(Fmt *); -char *trimshare(char *); +extern int dfscacheinfo(Fmt *f); +extern char *trimshare(char *s); +extern char *mapfile(char *opath); +extern int mapshare(char *path, Share **osp); +extern int redirect(Session *s, Share *sp, char *path); /* doserrstr.c */ -char *doserrstr(uint); +extern char *doserrstr(uint err); /* fs.c */ -int shareinfo(Fmt *); -int conninfo(Fmt *); -int sessioninfo(Fmt *); -int userinfo(Fmt *); -int groupinfo(Fmt *); -int domaininfo(Fmt *); -int workstationinfo(Fmt *); -int dfsrootinfo(Fmt *); -int openfileinfo(Fmt *); -int dfsrootinfo(Fmt *); -int filetableinfo(Fmt *); /* is in main.c due to C scope */ +extern int shareinfo(Fmt *f); +extern int openfileinfo(Fmt *f); +extern int conninfo(Fmt *f); +extern int sessioninfo(Fmt *f); +extern int dfsrootinfo(Fmt *f); +extern int userinfo(Fmt *f); +extern int groupinfo(Fmt *f); +extern int domaininfo(Fmt *f); +extern int workstationinfo(Fmt *f); /* info.c */ -int walkinfo(char *); -int numinfo(void); -int dirgeninfo(int, Dir *); -int makeinfo(int); -int readinfo(int, char *, int, int); -void freeinfo(int); +extern int walkinfo(char *name); +extern int numinfo(void); +extern int dirgeninfo(int slot, Dir *d); +extern int makeinfo(int path); +extern int readinfo(int path, char *buf, int len, int off); +extern void freeinfo(int path); /* main.c */ -void usage(void); -void dmpkey(char *, void *, int); -void main(int, char **); +extern void setup(void); +extern int filetableinfo(Fmt *f); +extern Qid mkqid(char *s, int is_dir, long vers, int subtype, long path); +extern int rdonly(Session *s, Share *sp, char *path, int rdonly); +extern void usage(void); +extern void dmpkey(char *s, void *v, int n); +extern void main(int argc, char **argv); /* misc.c */ -char *strupr(char *); -char *strlwr(char *); +extern char *strupr(char *s); +extern char *strlwr(char *s); /* netbios.c */ -void Gmem(uchar **, void *, int); -int calledname(char *, char *); -int nbtdial(char *, char *, char *); -void nbthdr(Pkt *); -int nbtrpc(Pkt *); -void xd(char *, void *, int); +extern void Gmem(uchar **p, void *v, int n); +extern int calledname(char *host, char *name); +extern int nbtdial(char *addr, char *called, char *sysname); +extern void nbthdr(Pkt *p); +extern int nbtrpc(Pkt *p); +extern void xd(char *str, void *buf, int n); /* nterrstr.c */ -char *nterrstr(uint); +extern char *nterrstr(uint err); /* pack.c */ -void *pmem(Pkt *, void *, int); -void *ppath(Pkt *, char *); -void *pstr(Pkt *, char *); -void *pascii(Pkt *, char *); -void *pl64(Pkt *, uvlong); -void *pb32(Pkt *, uint); -void *pl32(Pkt *, uint); -void *pb16(Pkt *, uint); -void *pl16(Pkt *, uint); -void *p8(Pkt *, uint); -void *pname(Pkt *, char *, char); -void *pvtime(Pkt *, uvlong); -void *pdatetime(Pkt *, long); -void gmem(Pkt *, void *, int); -void gstr(Pkt *, char *, int); -void gascii(Pkt *, char *, int); -uvlong gl64(Pkt *); -uvlong gb48(Pkt *); -uint gb32(Pkt *); -uint gl32(Pkt *); -uint gb16(Pkt *); -uint gl16(Pkt *); -uint g8(Pkt *); -long gdatetime(Pkt *); -long gvtime(Pkt *); -void gconv(Pkt *, int, char *, int); - -/* raperrstr.c */ -char *raperrstr(uint); - -/* sid2name.c */ -void upd_names(Session *, Share *, char *, Dir *); - -/* trans.c */ -int RAPshareenum(Session *, Share *, Share **); -int RAPshareinfo(Session *, Share *, char *, Shareinfo2 *); - -int RAPsessionenum(Session *, Share *, Sessinfo **); - -int RAPgroupenum(Session *, Share *, Namelist **); -int RAPgroupusers(Session *, Share *, char *, Namelist **); - -int RAPuserenum(Session *, Share *, Namelist **); -int RAPuserenum2(Session *, Share *, Namelist **); -int RAPuserinfo(Session *, Share *, char *, Userinfo *); - -int RAPServerenum2(Session *, Share *, char *, int, int *, Serverinfo **); -int RAPServerenum3(Session *, Share *, char *, int, int, Serverinfo *); - -int RAPFileenum2(Session *, Share *, char *, char *, Fileinfo **); - -/* trans2.c */ -int T2findfirst(Session *, Share *, int, char *, int *, long *, FInfo *); -int T2findnext(Session *, Share *, int, char *, int *, long *, FInfo *, int); -int T2queryall(Session *, Share *, char *, FInfo *); -int T2querystandard(Session *, Share *, char *, FInfo *); -int T2setpathinfo(Session *, Share *, char *, FInfo *); -int T2setfilelength(Session *, Share *, int, FInfo *); -int T2fsvolumeinfo(Session *, Share *, long *, long *, char *, int); -int T2fssizeinfo(Session *, Share *, uvlong *, uvlong *); -int T2getdfsreferral(Session *, Share *, char *, int *, int *, Refer *, int); - -/* transnt.c */ -int TNTquerysecurity(Session *, Share *, int, char **, char **); +extern void *pmem(Pkt *p, void *v, int len); +extern void *ppath(Pkt *p, char *str); +extern void *pstr(Pkt *p, char *str); +extern void *pascii(Pkt *p, char *str); +extern void *pl64(Pkt *p, uvlong n); +extern void *pb32(Pkt *p, uint n); +extern void *pl32(Pkt *p, uint n); +extern void *pb16(Pkt *p, uint n); +extern void *pl16(Pkt *p, uint n); +extern void *p8(Pkt *p, uint n); +extern void *pname(Pkt *p, char *name, char pad); +extern void *pvtime(Pkt *p, uvlong n); +extern void *pdatetime(Pkt *p, long utc); +extern void gmem(Pkt *p, void *v, int n); +extern void gstr(Pkt *p, char *str, int n); +extern void gascii(Pkt *p, char *str, int n); +extern uvlong gl64(Pkt *p); +extern uvlong gb48(Pkt *p); +extern uint gb32(Pkt *p); +extern uint gl32(Pkt *p); +extern uint gb16(Pkt *p); +extern uint gl16(Pkt *p); +extern uint g8(Pkt *p); +extern long gdatetime(Pkt *p); +extern long gvtime(Pkt *p); +extern void gconv(Pkt *p, int conv, char *str, int n); +extern void goff(Pkt *p, uchar *base, char *str, int n); /* ping.c */ -int ping(char *, int); +extern int ping(char *host, int timeout); + +/* raperrstr.c */ +extern char *raperrstr(uint err); + +/* sid2name.c */ +extern void upd_names(Session *s, Share *sp, char *path, Dir *d); + +/* trans.c */ +extern int RAPshareenum(Session *s, Share *sp, Share **ent); +extern int RAPshareinfo(Session *s, Share *sp, char *share, Shareinfo2 *si2p); +extern int RAPsessionenum(Session *s, Share *sp, Sessinfo **sip); +extern int RAPgroupenum(Session *s, Share *sp, Namelist **nlp); +extern int RAPgroupusers(Session *s, Share *sp, char *group, Namelist **nlp); +extern int RAPuserenum(Session *s, Share *sp, Namelist **nlp); +extern int RAPuserenum2(Session *s, Share *sp, Namelist **nlp); +extern int RAPuserinfo(Session *s, Share *sp, char *user, Userinfo *uip); +extern int RAPServerenum2(Session *s, Share *sp, char *workgroup, int type, int *more, Serverinfo **si); +extern int RAPServerenum3(Session *s, Share *sp, char *workgroup, int type, int last, Serverinfo *si); +extern int RAPFileenum2(Session *s, Share *sp, char *user, char *path, Fileinfo **fip); + +/* trans2.c */ +extern int T2findfirst(Session *s, Share *sp, int slots, char *path, int *got, long *resume, FInfo *fip); +extern int T2findnext(Session *s, Share *sp, int slots, char *path, int *got, long *resume, FInfo *fip, int sh); +extern int T2queryall(Session *s, Share *sp, char *path, FInfo *fip); +extern int T2querystandard(Session *s, Share *sp, char *path, FInfo *fip); +extern int T2setpathinfo(Session *s, Share *sp, char *path, FInfo *fip); +extern int T2setfilelength(Session *s, Share *sp, int fh, FInfo *fip); +extern int T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno, char *label, int labellen); +extern int T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused); +extern int T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used, Refer *re, int nent); + +/* transnt.c */ +extern int TNTquerysecurity(Session *s, Share *sp, int fh, char **usid, char **gsid); diff --git a/sys/src/cmd/cifs/info.c b/sys/src/cmd/cifs/info.c index f6feb5f3b..fd432a87d 100644 --- a/sys/src/cmd/cifs/info.c +++ b/sys/src/cmd/cifs/info.c @@ -8,22 +8,22 @@ struct { - char *name; - int (*func)(Fmt *f); - char *buf; - int len; + char *name; + int (*func)(Fmt *f); + char *buf; + int len; } Infdir[] = { - { "Users", userinfo }, - { "Groups", groupinfo }, - { "Shares", shareinfo }, - { "Connection", conninfo }, - { "Sessions", sessioninfo }, - { "Dfsroot", dfsrootinfo }, - { "Dfscache", dfscacheinfo }, - { "Domains", domaininfo }, - { "Openfiles", openfileinfo }, - { "Workstations", workstationinfo }, - { "Filetable", filetableinfo }, + { "Users" , userinfo }, + { "Groups" , groupinfo }, + { "Shares" , shareinfo }, + { "Connection" , conninfo }, + { "Sessions" , sessioninfo }, + { "Dfsroot" , dfsrootinfo }, + { "Dfscache" , dfscacheinfo }, + { "Domains" , domaininfo }, + { "Openfiles" , openfileinfo }, + { "Workstations" , workstationinfo }, + { "Filetable" , filetableinfo }, }; int @@ -63,6 +63,7 @@ dirgeninfo(int slot, Dir *d) d->qid.vers = 1; d->qid.path = slot; d->qid.type = 0; + return 0; } @@ -76,10 +77,12 @@ makeinfo(int path) if(Infdir[path].buf != nil) return 0; fmtstrinit(&f); - if((*Infdir[path].func)(&f) == -1l) + if((*Infdir[path].func)(&f) == -1) + return -1; + if((Infdir[path].buf = fmtstrflush(&f)) == nil) + return -1; + if((Infdir[path].len = strlen(Infdir[path].buf)) <= 0) return -1; - Infdir[path].buf = fmtstrflush(&f); - Infdir[path].len = strlen(Infdir[path].buf); return 0; } @@ -104,3 +107,4 @@ freeinfo(int path) free(Infdir[path].buf); Infdir[path].buf = nil; } + diff --git a/sys/src/cmd/cifs/main.c b/sys/src/cmd/cifs/main.c index 4849c5495..78f9dcb9a 100644 --- a/sys/src/cmd/cifs/main.c +++ b/sys/src/cmd/cifs/main.c @@ -198,7 +198,9 @@ dirgen(int slot, Dir *d, void *aux) Aux *a = aux; char *npath; int numinf = numinfo(); - int slots = min(Sess->mtu, MTU) / sizeof(FInfo); + int slots; + + slots = 128; /* number of dir entries to fetch at one time */ if(strcmp(a->path, "/") == 0){ if(slot < numinf){ @@ -1103,6 +1105,7 @@ keepalive(void) sleep(6000); if(Active-- != 0) continue; + for(i = 0; i < Nshares; i++){ if((rc = T2fssizeinfo(Sess, &Shares[slot], &tot, &fre)) == 0) break; @@ -1253,6 +1256,8 @@ connected: memcpy(Shares+Nshares, sip+i, sizeof(Share)); if(CIFStreeconnect(Sess, Sess->cname, Shares[Nshares].name, Shares+Nshares) == -1){ + fprint(2, "%s: %s %q - can't connect to share" + ", %r\n", argv0, Host, Shares[Nshares].name); free(Shares[Nshares].name); continue; } @@ -1263,7 +1268,7 @@ connected: for(i = 1; i < argc; i++){ if(CIFStreeconnect(Sess, Sess->cname, argv[i], Shares+Nshares) == -1){ - fprint(2, "%s: %s %q - can't connect to share" + fprint(2, "%s: %s %q - can't connect to share" ", %r\n", argv0, Host, argv[i]); continue; } diff --git a/sys/src/cmd/cifs/mkfile b/sys/src/cmd/cifs/mkfile index b53660103..683e616ea 100644 --- a/sys/src/cmd/cifs/mkfile +++ b/sys/src/cmd/cifs/mkfile @@ -11,10 +11,3 @@ OFILES= main.$O transnt.$O trans2.$O trans.$O cifs.$O \ auth.$O dfs.$O ping.$O s->caps & CAP_UNICODE){ + if(p->s->flags2 & FL2_UNICODE){ if(((p->pos - p->buf) % 2) != 0) /* pad to even offset */ p8(p, 0); while(*str){ @@ -57,7 +57,7 @@ pstr(Pkt *p, char *str) if(!str) return s; - if(p->s->caps & CAP_UNICODE){ + if(p->s->flags2 & FL2_UNICODE){ if(((p->pos - p->buf) % 2) != 0) p8(p, 0); /* pad to even offset */ while(*str){ @@ -238,7 +238,10 @@ gstr(Pkt *p, char *str, int n) if(!n || !str) return; - if(p->s->caps & CAP_UNICODE){ + if(p->flags2 & FL2_UNICODE){ + if(((p->pos - p->buf) % 2) != 0) + g8(p); /* strip padding to even offset */ + i = 0; while(*p->pos && n && p->pos < p->eop){ r = gl16(p); diff --git a/sys/src/cmd/cifs/remsmb.h b/sys/src/cmd/cifs/remsmb.h index ee01f4b9c..c243dabb3 100644 --- a/sys/src/cmd/cifs/remsmb.h +++ b/sys/src/cmd/cifs/remsmb.h @@ -48,11 +48,11 @@ Revision History: #ifndef _REMDEF_ #define _REMDEF_ -/* - * ==================================================================== - * SMB XACT message descriptors. - * ==================================================================== - */ +//==================================================================== +// +/* SMB XACT message descriptors. */ +// +//==================================================================== #define REMSmb_share_info_0 "B13" #define REMSmb_share_info_1 "B13BWz" @@ -402,11 +402,11 @@ Revision History: #define REMSmb_LocalOnlyCall "" -/* - * The following definitions exist for DOS LANMAN--Windows 3.0. - * Normally, there is a const char far * servername - * as the first parameter, but this will be ignored (sort of). - */ +// +/* The following definitions exist for DOS LANMAN--Windows 3.0 */ +/* Normally, there is a const char far * servername */ +/* as the first parameter, but this will be ignored (sort of) */ +// #define REMSmb_DosPrintJobGetId_P "WrL" #define REMSmb_GetPrintId "WB16B13B" #define REMSmb_NetRemoteCopy_P "zzzzWWrL" @@ -458,9 +458,9 @@ Revision History: #define REMSmb_NetAccountConfirmUpd_P "b12g12D" #define REMSmb_update_info_0 "K" -/* - * SamrOemChangePasswordUser2 api support - */ -#define REMSmb_SamOEMChgPasswordUser2 "B516B16" /* data that is passed */ +// +/* SamrOemChangePasswordUser2 api support */ +// +#define REMSmb_SamOEMChgPasswordUser2 "B516B16" /* data that is passed */ #endif /* ndef _REMDEF_ */ diff --git a/sys/src/cmd/cifs/trans.c b/sys/src/cmd/cifs/trans.c index d6daa2857..f88935aba 100644 --- a/sys/src/cmd/cifs/trans.c +++ b/sys/src/cmd/cifs/trans.c @@ -16,7 +16,7 @@ thdr(Session *s, Share *sp) p->tbase = pl16(p, 0); /* 0 Total parameter bytes to be sent, filled later */ pl16(p, 0); /* 2 Total data bytes to be sent, filled later */ pl16(p, 64); /* 4 Max parameter to return */ - pl16(p, MTU - T2HDRLEN - 128); /* 6 Max data to return */ + pl16(p, s->mtu - T2HDRLEN - 128); /* 6 Max data to return */ pl16(p, 1); /* 8 Max setup count to return */ pl16(p, 0); /* 10 Flags */ pl32(p, 1000); /* 12 Timeout (ms) */ @@ -126,7 +126,7 @@ RAPshareenum(Session *s, Share *sp, Share **ent) pascii(p, REMSmb_NetShareEnum_P); /* request descriptor */ pascii(p, REMSmb_share_info_0); /* reply descriptor */ pl16(p, 0); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); if(trpc(p) == -1){ @@ -183,7 +183,7 @@ RAPshareinfo(Session *s, Share *sp, char *share, Shareinfo2 *si2p) pascii(p, REMSmb_share_info_2); /* reply descriptor */ pascii(p, share); pl16(p, 1); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); @@ -252,7 +252,7 @@ RAPsessionenum(Session *s, Share *sp, Sessinfo **sip) pascii(p, REMSmb_NetSessionEnum_P); /* request descriptor */ pascii(p, REMSmb_session_info_10); /* reply descriptor */ pl16(p, 10); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); if(trpc(p) == -1){ @@ -312,7 +312,7 @@ RAPgroupenum(Session *s, Share *sp, Namelist **nlp) pascii(p, REMSmb_NetGroupEnum_P); /* request descriptor */ pascii(p, REMSmb_group_info_0); /* reply descriptor */ pl16(p, 0); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); if(trpc(p) == -1){ @@ -368,7 +368,7 @@ RAPgroupusers(Session *s, Share *sp, char *group, Namelist **nlp) pascii(p, REMSmb_user_info_0); /* reply descriptor */ pascii(p, group); /* group name for list */ pl16(p, 0); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); if(trpc(p) == -1){ @@ -422,7 +422,7 @@ RAPuserenum(Session *s, Share *sp, Namelist **nlp) pascii(p, REMSmb_NetUserEnum_P); /* request descriptor */ pascii(p, REMSmb_user_info_0); /* reply descriptor */ pl16(p, 0); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); if(trpc(p) == -1){ @@ -478,7 +478,7 @@ more: pascii(p, REMSmb_NetUserEnum2_P); /* request descriptor */ pascii(p, REMSmb_user_info_0); /* reply descriptor */ pl16(p, 0); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ pl32(p, resume); /* resume key to allow multiple fetches */ ptdata(p); @@ -536,7 +536,7 @@ RAPuserinfo(Session *s, Share *sp, char *user, Userinfo *uip) pascii(p, REMSmb_user_info_10); /* reply descriptor */ pascii(p, user); /* username */ pl16(p, 10); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ ptdata(p); if(trpc(p) == -1){ @@ -592,7 +592,7 @@ RAPServerenum2(Session *s, Share *sp, char *workgroup, int type, int *more, pascii(p, REMSmb_NetServerEnum2_P); /* request descriptor */ pascii(p, REMSmb_server_info_1); /* reply descriptor */ pl16(p, 1); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ pl32(p, type); pascii(p, workgroup); @@ -655,7 +655,7 @@ more: pascii(p, REMSmb_NetServerEnum3_P); /* request descriptor */ pascii(p, REMSmb_server_info_1); /* reply descriptor */ pl16(p, 1); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ pl32(p, type); pascii(p, workgroup); pascii(p, first); @@ -731,7 +731,7 @@ more: pascii(p, path); pascii(p, user); pl16(p, 1); /* detail level */ - pl16(p, MTU - 200); /* receive buffer length */ + pl16(p, s->mtu - 1024); /* receive buffer length */ pl32(p, resume); /* resume key */ /* FIXME: maybe the padding and resume key are the wrong way around? */ pl32(p, 0); /* padding ? */ diff --git a/sys/src/cmd/cifs/trans2.c b/sys/src/cmd/cifs/trans2.c index 090054096..321f157ee 100644 --- a/sys/src/cmd/cifs/trans2.c +++ b/sys/src/cmd/cifs/trans2.c @@ -15,7 +15,7 @@ t2hdr(Session *s, Share *sp, int cmd) p->tbase = pl16(p, 0); /* 0 Total parameter bytes to be sent, filled later */ pl16(p, 0); /* 2 Total data bytes to be sent, filled later */ pl16(p, 64); /* 4 Max parameter to return */ - pl16(p, (MTU - T2HDRLEN)-64); /* 6 Max data to return */ + pl16(p, (s->mtu - T2HDRLEN)-64); /* 6 Max data to return */ p8(p, 0); /* 8 Max setup count to return */ p8(p, 0); /* 9 Reserved */ pl16(p, 0); /* 10 Flags */