cifs: merge with steve simons latest version. thank you very much!

This commit is contained in:
cinap_lenrek 2019-02-05 23:10:03 +01:00
parent a2abe177e4
commit 01b6aa0f9f
11 changed files with 303 additions and 171 deletions

View file

@ -9,3 +9,8 @@ is just a matter of creating a new registry entry, see:
-Steve
Tue Sep 21 17:05:48 BST 2010
---------------------------------
FYI This hot-fix also works for Windows 2k8
Mon Jun 25 10:38:57 BST 2012

View file

@ -39,7 +39,7 @@ cifsdial(char *host, char *called, char *sysname)
s->seq = 0;
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->flags2 = FL2_KNOWS_LONG_NAMES | FL2_HAS_LONG_NAMES | FL2_PAGEING_IO | FL2_UNICODE;
s->macidx = -1;
@ -125,6 +125,20 @@ pbytes(Pkt *p)
p->bytebase = pl16(p, 0); /* filled in by cifsrpc() */
}
static void
dmp(int seq, uchar *buf)
{
int i;
if(seq == 99)
print("\n ");
else
print("%+2d ", seq);
for(i = 0; i < 8; i++)
print("%02x ", buf[i] & 0xff);
print("\n");
}
int
cifsrpc(Pkt *p)
{
@ -233,32 +247,10 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
{
int d, i;
char *ispeak = "NT LM 0.12";
static char *dialects[] = {
// { "PC NETWORK PROGRAM 1.0"},
// { "MICROSOFT NETWORKS 1.03"},
// { "MICROSOFT NETWORKS 3.0"},
// { "LANMAN1.0"},
// { "LM1.2X002"},
// { "NT LANMAN 1.0"},
{ "NT LM 0.12" },
};
static char *dialects[] = { { "NT LM 0.12" } };
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++){
@ -284,25 +276,28 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
return -1;
}
s->secmode = g8(p); /* Security mode */
s->secmode = g8(p); /* Security mode */
gl16(p); /* Max outstanding requests */
gl16(p); /* Max VCs */
s->mtu = gl32(p); /* Max buffer size */
gl32(p); /* Max raw buffer size (depricated) */
gl32(p); /* Session key */
s->caps = gl32(p); /* Server capabilities */
gl16(p); /* Max outstanding requests */
gl16(p); /* Max VCs */
s->mtu = gl32(p); /* Max buffer size */
gl32(p); /* Max raw buffer size (depricated) */
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->challen = g8(p); /* Encryption key length */
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 */
gstr(p, domain, domlen); /* source domain */
gmem(p, s->chal, s->challen); /* Get the challenge */
{ /* NetApp Filer seem not to report its called name */
/*
* for some weird reason the following two string always seem to be in unicode,
* however they are NOT byte aligned, every other packet is correctly aligned
*/
gstr_noalign(p, domain, domlen); /* source domain */
{ /* NetApp Filer seem not to report its called name */
char *cn = emalloc9p(cnamlen);
gstr(p, cn, cnamlen); /* their name */
gstr_noalign(p, cn, cnamlen); /* their name */
if(strlen(cn) > 0)
memcpy(cname, cn, cnamlen);
free(cn);
@ -310,6 +305,8 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
if(s->caps & CAP_UNICODE)
s->flags2 |= FL2_UNICODE;
else
s->flags2 &= ~FL2_UNICODE;
free(p);
return 0;
@ -329,37 +326,49 @@ CIFSsession(Session *s)
s->seqrun = 1; /* activate the sequence number generation/checking */
p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX);
p8(p, 0xFF); /* No secondary command */
p8(p, 0); /* Reserved (must be zero) */
pl16(p, 0); /* Offset to next command */
pl16(p, MTU); /* my max buffer size */
pl16(p, 1); /* my max multiplexed pending requests */
pl16(p, 0); /* Virtual connection # */
pl32(p, 0); /* Session key (if vc != 0) */
p8(p, 0xFF); /* No secondary command */
p8(p, 0); /* Reserved (must be zero) */
pl16(p, 0); /* Offset to next command */
pl16(p, MTU); /* my max buffer size */
pl16(p, 1); /* my max multiplexed pending requests */
pl16(p, 0); /* Virtual connection # */
pl32(p, 0); /* Session key (if vc != 0) */
if(Debug && strstr(Debug, "auth") != nil)
fprint(2, "mycaps=%x\n", mycaps);
if((s->secmode & SECMODE_PW_ENCRYPT) == 0) {
if(Debug && strstr(Debug, "auth") != nil)
fprint(2, "user=%d %q\npass=%d %q\n", Sess->auth->len[0], Sess->auth->resp[0], Sess->auth->len[1], Sess->auth->resp[1]);
pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size */
pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */
pl32(p, 0); /* Reserved */
pl32(p, 0); /* Reserved */
pl32(p, mycaps);
pbytes(p);
for(q = Sess->auth->resp[0]; *q; ){
q += chartorune(&r, q);
if(r > Bits16)
sysfatal("CIFSsession: '%C' utf too wide for windows\n", r);
pl16(p, toupperrune(r));
}
pl16(p, 0);
for(q = Sess->auth->resp[0]; *q; ){
q += chartorune(&r, q);
if(r > Bits16)
sysfatal("CIFSsession: '%C' utf too wide for windows\n", r);
pl16(p, r);
}
pl16(p, 0);
}else{
if(Debug && strstr(Debug, "auth") != nil)
fprint(2, "encrypted len=%d,%d\n", Sess->auth->len[0], Sess->auth->len[1]);
pl16(p, Sess->auth->len[0]); /* LM passwd size */
pl16(p, Sess->auth->len[1]); /* NTLM passwd size */
pl32(p, 0); /* Reserved */
pl32(p, 0); /* Reserved */
pl32(p, mycaps);
pbytes(p);
@ -367,18 +376,21 @@ CIFSsession(Session *s)
pmem(p, Sess->auth->resp[1], Sess->auth->len[1]);
}
pstr(p, Sess->auth->user); /* Account name */
if(Debug && strstr(Debug, "auth") != nil)
fprint(2, "user=%q\nwindom=%q\nos=%s\nmanager=%s\n", Sess->auth->user, Sess->auth->windom, "plan9", argv0);
pstr(p, Sess->auth->user); /* Account name */
pstr(p, Sess->auth->windom); /* Primary domain */
pstr(p, "plan9"); /* Client OS */
pstr(p, argv0); /* Client LAN Manager type */
pstr(p, "plan9"); /* Client OS */
pstr(p, argv0); /* Client LAN Manager type */
if(cifsrpc(p) == -1){
free(p);
return -1;
}
g8(p); /* Reserved (0) */
gl16(p); /* Offset to next command wordcount */
g8(p); /* Reserved (0) */
gl16(p); /* Offset to next command wordcount */
Sess->isguest = gl16(p) & 1; /* logged in as guest */
gl16(p);

View file

@ -18,6 +18,7 @@ enum {
MAX_SHARES = 4096, /* static table of shares attached */
RAP_ERR_MOREINFO= 234, /* non-error code, more info to be fetched */
MAX_DFS_PATH = 512, /* MS says never more than 250 chars... */
Bits16 = 0xFFFF, /* max Unicode value Windows supports */
};
enum {
@ -451,7 +452,6 @@ typedef struct {
int type; /* o=unknown, 1=CIFS, 2=netware 3=domain */
int flags; /* 1 == strip off consumed chars before resubmitting */
int ttl; /* time to live of this info in secs */
int prox; /* lower value is preferred */
char *path; /* new path */
char *addr; /* new server */
} Refer;
@ -584,6 +584,7 @@ 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 gstr_noalign(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);
@ -629,6 +630,7 @@ 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);
extern int T2fsdeviceinfo(Session *s, Share *sp, int *type, int *flags);
/* transnt.c */
extern int TNTquerysecurity(Session *s, Share *sp, int fh, char **usid, char **gsid);

View file

@ -18,9 +18,8 @@
* this is not a problem for me and I think it hides a load
* of problems of its own wrt plan9's private namespaces.
*
* The proximity of my test server (AD enabled) is always 0 but some
* systems may report more meaningful values. The expiry time is
* similarly zero, so I guess at 5 mins.
* The expiry of my test server (AD enabled) is always 0 but some
* systems may report more meaningful values.
*
* If the redirection points to a "hidden" share (i.e., its name
* ends in a $) then the type of the redirection is 0 (unknown) even
@ -70,7 +69,6 @@ struct Dfscache {
char *path;
long expiry; /* expiry time in sec */
long rtt; /* round trip time, nsec */
int prox; /* proximity, lower = closer */
};
Dfscache *Cache;
@ -85,8 +83,8 @@ dfscacheinfo(Fmt *f)
ex = cp->expiry - time(nil);
if(ex < 0)
ex = -1;
fmtprint(f, "%-42s %6ld %8.1f %4d %-16s %-24s %s\n",
cp->src, ex, (double)cp->rtt/1000.0L, cp->prox,
fmtprint(f, "%-42s %6ld %8.1f %-16s %-24s %s\n",
cp->src, ex, (double)cp->rtt/1000.0L,
cp->host, cp->share, cp->path);
}
return 0;
@ -239,11 +237,6 @@ remap(Dfscache *cp, Refer *re)
if(*p == '\\')
*p = '/';
if(cp->prox < re->prox){
if(Debug && strstr(Debug, "dfs") != nil)
print(" remap %d < %d\n", cp->prox, re->prox);
return -1;
}
if((n = getfields(re->addr, a, sizeof(a), 0, "/")) < 3){
if(Debug && strstr(Debug, "dfs") != nil)
print(" remap nfields=%d\n", n);
@ -270,14 +263,13 @@ remap(Dfscache *cp, Refer *re)
free(cp->share);
free(cp->path);
cp->rtt = rtt;
cp->prox = re->prox;
cp->expiry = time(nil)+re->ttl;
cp->host = estrdup9p(a[Hostname]);
cp->share = estrdup9p(trimshare(a[Sharename]));
cp->path = estrdup9p(a[Pathname]);
if(Debug && strstr(Debug, "dfs") != nil)
print(" remap ping OK prox=%d host=%s share=%s path=%s\n",
cp->prox, cp->host, cp->share, cp->path);
print(" remap ping OK host=%s share=%s path=%s\n",
cp->host, cp->share, cp->path);
return 0;
}
@ -286,8 +278,7 @@ redir1(Session *s, char *path, Dfscache *cp, int level)
{
Refer retab[16], *re;
int n, gflags, used, found;
if(level > 8)
if(level > 16)
return -1;
if((n = T2getdfsreferral(s, &Ipc, path, &gflags, &used, retab,
@ -295,14 +286,20 @@ redir1(Session *s, char *path, Dfscache *cp, int level)
return -1;
if(! (gflags & DFS_HEADER_ROOT))
used = SINT_MAX;
used = 9999;
found = 0;
for(re = retab; re < retab+n; re++){
if(Debug && strstr(Debug, "dfs") != nil)
print("referal level=%d prox=%d path=%q addr=%q\n",
level, re->prox, re->path, re->addr);
print("referal level=%d path=%q addr=%q\n",
level, re->path, re->addr);
if(*re->path == 0 || *re->addr == 0){
free(re->addr);
free(re->path);
continue;
}
if(gflags & DFS_HEADER_STORAGE){
if(remap(cp, re) == 0)
found = 1;
@ -350,7 +347,6 @@ redirect(Session *s, Share *sp, char *path)
} else{ /* cache hit, but entry stale */
cp->rtt = SINT_MAX;
cp->prox = SINT_MAX;
unc = smprint("//%s/%s/%s%s%s", s->auth->windom,
cp->share, cp->path, *cp->path? "/": "",
@ -385,7 +381,6 @@ redirect(Session *s, Share *sp, char *path)
cp = emalloc9p(sizeof(Dfscache));
memset(cp, 0, sizeof(Dfscache));
cp->rtt = SINT_MAX;
cp->prox = SINT_MAX;
if(redir1(s, unc, cp, 1) == -1){
if(Debug && strstr(Debug, "dfs") != nil)

View file

@ -8,44 +8,40 @@
static char *period(long sec);
static char *devtypes[] = {
"beep", "cd", "cdfs", "datalink", "dfs", "disk", "diskfs", "fs", "inport",
"kbd", "mailslot", "midi-in", "midi-out", "mouse", "unc", "named-pipe", "net", "net",
"browser", "netfs", "null", "lpt", "nic", "lpr", "scanner", "eia-mouse",
"eia", "screen", "sound", "streams", "tape", "tapefs", "transport", "unknown",
"video", "virt-disk", "wav-in", "wav-out", "8042", "battery", "bus-exp", "modem", "vdm"
};
static double
togb(uvlong n)
{
return (double)n / (1024.0 * 1024.0 * 1024.0);
}
int
shareinfo(Fmt *f)
{
int i, j, n;
char *type;
int type;
Share *sp;
Shareinfo2 si2;
Share *sp, *sip;
uvlong total, unused;
if((n = RAPshareenum(Sess, &Ipc, &sip)) < 1){
fmtprint(f, "can't enumerate shares: %r\n");
return 0;
}
for(sp = Shares; sp < &Shares[Nshares]; sp++){
fmtprint(f, "%-24q ", sp->name);
for(i = 0; i < n; i++){
fmtprint(f, "%-13q ", sip[i].name);
if(T2fsdeviceinfo(Sess, sp, &type, nil) != -1)
fmtprint(f, "%-16s ", devtypes[type]);
sp = &sip[i];
for(j = 0; j < Nshares; j++)
if(strcmp(Shares[j].name, sip[i].name) == 0){
sp = &Shares[j];
break;
}
if(j >= Nshares)
sp->tid = Ipc.tid;
if(T2fssizeinfo(Sess, sp, &total, &unused) != -1)
fmtprint(f, "%6.1f/%-6.1f ", togb(total-unused), togb(total));
if(RAPshareinfo(Sess, sp, sp->name, &si2) != -1){
switch(si2.type){
case STYPE_DISKTREE: type = "disk"; break;
case STYPE_PRINTQ: type = "printq"; break;
case STYPE_DEVICE: type = "device"; break;
case STYPE_IPC: type = "ipc"; break;
case STYPE_SPECIAL: type = "special"; break;
case STYPE_TEMP: type = "temp"; break;
default: type = "unknown"; break;
}
fmtprint(f, "%-8s %5d/%-5d %s", type,
si2.activeusrs, si2.maxusrs, si2.comment);
fmtprint(f, "%5d/%-5d %s", si2.activeusrs, si2.maxusrs, si2.comment);
free(si2.name);
free(si2.comment);
free(si2.path);
@ -54,7 +50,6 @@ shareinfo(Fmt *f)
fmtprint(f, "\n");
}
free(sip);
return 0;
}
@ -359,7 +354,7 @@ period(long sec)
min = sec / 60L;
sec -= min * 60L;
if(days)
snprint(when, sizeof(when), "%d %d:%d:%ld ", days, hrs, min, sec);
snprint(when, sizeof(when), "%d,%d:%d:%ld ", days, hrs, min, sec);
else
snprint(when, sizeof(when), "%d:%d:%ld ", hrs, min, sec);
return when;

View file

@ -18,6 +18,7 @@ struct Aux {
long expire; /* expiration time of cache */
long off; /* file pos of start of cache */
long end; /* file pos of end of cache */
long mtime; /* last modification time - windows updates it only on close */
char *cache;
int fh; /* file handle */
int sh; /* search handle */
@ -38,7 +39,7 @@ int Active = IDLE_TIME; /* secs until next keepalive is sent */
static int Keeppid; /* process ID of keepalive thread */
Share Shares[MAX_SHARES]; /* table of connected shares */
int Nshares = 0; /* number of Shares connected */
Aux *Auxroot = nil; /* linked list of Aux structs */
Aux *Openfiles = nil; /* linked list of Aux structs */
char *Host = nil; /* host we are connected to */
static char *Ipcname = "IPC$";
@ -73,7 +74,7 @@ filetableinfo(Fmt *f)
Aux *ap;
char *type;
if((ap = Auxroot) != nil)
if((ap = Openfiles) != nil)
do{
type = "walked";
if(ap->sh != -1)
@ -82,7 +83,7 @@ filetableinfo(Fmt *f)
type = "openfile";
fmtprint(f, "%-9s %s\n", type, ap->path);
ap = ap->next;
}while(ap != Auxroot);
}while(ap != Openfiles);
return 0;
}
@ -129,7 +130,7 @@ V2D(Dir *d, Qid qid, char *name)
}
static void
I2D(Dir *d, Share *sp, char *path, FInfo *fi)
I2D(Dir *d, Share *sp, char *path, long mtime, FInfo *fi)
{
char *name;
@ -144,7 +145,10 @@ I2D(Dir *d, Share *sp, char *path, FInfo *fi)
d->gid = estrdup9p("trog");
d->muid = estrdup9p("boyd");
d->atime = fi->accessed;
d->mtime = fi->written;
if(mtime > fi->written)
d->mtime = mtime;
else
d->mtime = fi->written;
if(fi->attribs & ATTR_READONLY)
d->mode = 0444;
@ -189,6 +193,27 @@ newpath(char *path, char *name)
return smprint("%s/%s", path, name);
}
/*
* get the last write time if the file is open -
* windows only updates mtime when the file is closed
* which is not good enough for acme.
*/
static long
realmtime(char *path)
{
Aux *a;
if((a = Openfiles) == nil)
return 0;
do{
if(a->fh != -1 && cistrcmp(path, a->path) == 0)
return a->mtime;
a = a->next;
}while(a != Openfiles);
return 0;
}
/* remove "." and ".." from the cache */
static int
rmdots(Aux *a, int got)
@ -282,7 +307,7 @@ from_cache:
fi = (FInfo *)(a->cache + (off - a->off));
npath = smprint("%s/%s", mapfile(a->path), fi->name);
I2D(d, a->sp, npath, fi);
I2D(d, a->sp, npath, realmtime(npath), fi);
if(Billtrog == 0)
upd_names(Sess, a->sp, npath, d);
free(npath);
@ -314,13 +339,13 @@ fsattach(Req *r)
a->fh = -1;
a->sh = -1;
if(Auxroot){
a->prev = Auxroot;
a->next = Auxroot->next;
Auxroot->next->prev = a;
Auxroot->next = a;
if(Openfiles){
a->prev = Openfiles;
a->next = Openfiles->next;
Openfiles->next->prev = a;
Openfiles->next = a;
} else {
Auxroot = a;
Openfiles = a;
a->next = a;
a->prev = a;
}
@ -341,13 +366,13 @@ fsclone(Fid *ofid, Fid *fid)
a->sp = oa->sp;
a->path = estrdup9p(oa->path);
if(Auxroot){
a->prev = Auxroot;
a->next = Auxroot->next;
Auxroot->next->prev = a;
Auxroot->next = a;
if(Openfiles){
a->prev = Openfiles;
a->next = Openfiles->next;
Openfiles->next->prev = a;
Openfiles->next = a;
} else {
Auxroot = a;
Openfiles = a;
a->next = a;
a->prev = a;
}
@ -483,6 +508,8 @@ again:
}
*qid = mkqid(npath, fi.attribs & ATTR_DIRECTORY, fi.changed, 0, 0);
a->mtime = realmtime(npath);
free(a->path);
a->path = npath;
fid->qid = *qid;
@ -512,7 +539,7 @@ fsstat(Req *r)
responderrstr(r);
return;
}
I2D(&r->d, a->sp, a->path, &fi);
I2D(&r->d, a->sp, a->path, a->mtime, &fi);
if(Billtrog == 0)
upd_names(Sess, a->sp, mapfile(a->path), &r->d);
}
@ -767,6 +794,8 @@ fswrite(Req *r)
} while(got < len && m >= n);
r->ofcall.count = got;
a->mtime = time(nil);
if(m == -1)
responderrstr(r);
else
@ -834,12 +863,12 @@ fsdestroyfid(Fid *f)
if(a->cache)
free(a->cache);
if(a == Auxroot)
Auxroot = a->next;
if(a == Openfiles)
Openfiles = a->next;
a->prev->next = a->next;
a->next->prev = a->prev;
if(a->next == a->prev)
Auxroot = nil;
Openfiles = nil;
if(a)
free(a);
}
@ -881,7 +910,7 @@ fsremove(Req *r)
}
/* close all instences of this file/dir */
if((ap = Auxroot) != nil)
if((ap = Openfiles) != nil)
do{
if(strcmp(ap->path, a->path) == 0){
if(ap->sh != -1)
@ -892,7 +921,7 @@ fsremove(Req *r)
ap->fh = -1;
}
ap = ap->next;
}while(ap != Auxroot);
}while(ap != Openfiles);
try = 0;
again:
if(r->fid->qid.type & QTDIR)
@ -1158,11 +1187,13 @@ dmpkey(char *s, void *v, int n)
void
main(int argc, char **argv)
{
int i, n;
int i, n, local;
long svrtime;
char windom[64], cname[64];
char *method, *sysname, *keyp, *mtpt, *svs;
char *p, *method, *sysname, *keyp, *mtpt, *svs;
static char *sh[1024];
local = 0;
*cname = 0;
keyp = "";
method = nil;
@ -1190,6 +1221,9 @@ main(int argc, char **argv)
case 'k':
keyp = EARGF(usage());
break;
case 'l':
local++;
break;
case 'm':
mtpt = EARGF(usage());
break;
@ -1213,8 +1247,12 @@ main(int argc, char **argv)
Host = argv[0];
if(mtpt == nil && svs == nil)
mtpt = smprint("/n/%s", Host);
if(mtpt == nil && svs == nil){
if((p = strchr(Host, '!')) != nil)
mtpt = smprint("/n/%s", p+1);
else
mtpt = smprint("/n/%s", Host);
}
if((sysname = getenv("sysname")) == nil)
sysname = "unknown";
@ -1227,7 +1265,10 @@ main(int argc, char **argv)
goto connected;
strcpy(cname, Host);
if((Sess = cifsdial(Host, Host, sysname)) != nil ||
if((p = strchr(cname, '!')) != nil)
strcpy(cname, p+1);
if((Sess = cifsdial(Host, cname, sysname)) != nil ||
(Sess = cifsdial(Host, "*SMBSERVER", sysname)) != nil)
goto connected;
@ -1240,6 +1281,9 @@ connected:
Sess->secmode &= ~SECMODE_SIGN_ENABLED;
#endif
if(local)
strcpy(windom, ".");
Sess->auth = getauth(method, windom, keyp, Sess->secmode, Sess->chal,
Sess->challen);

View file

@ -68,6 +68,19 @@ Gmem(uchar **p, void *v, int n)
*str++ = *(*p)++;
}
static ulong
GB32(uchar **p)
{
ulong n;
n = *(*p)++ << 24;
n |= *(*p)++ << 16;
n |= *(*p)++ << 8;
n |= *(*p)++;
return n;
}
static ushort
GB16(uchar **p)
{

View file

@ -32,6 +32,8 @@ ppath(Pkt *p, char *str)
p8(p, 0);
while(*str){
str += chartorune(&r, str);
if(r > Bits16)
sysfatal("ppath: %C/%x utf too wide for windows\n", r, r);
if(r == L'/')
r = L'\\';
pl16(p, r);
@ -62,6 +64,8 @@ pstr(Pkt *p, char *str)
p8(p, 0); /* pad to even offset */
while(*str){
str += chartorune(&r, str);
if(r > Bits16)
sysfatal("pstr: %C/%x utf too wide for windows\n", r, r);
pl16(p, r);
}
pl16(p, 0);
@ -229,8 +233,8 @@ gmem(Pkt *p, void *v, int n)
* in runes or bytes, in ASCII mode this is also the size
* of the output buffer but this is not so in Unicode mode!
*/
void
gstr(Pkt *p, char *str, int n)
static void
_gstr(Pkt *p, char *str, int n, int align)
{
int i;
Rune r;
@ -239,9 +243,10 @@ gstr(Pkt *p, char *str, int n)
return;
if(p->flags2 & FL2_UNICODE){
if(((p->pos - p->buf) % 2) != 0)
g8(p); /* strip padding to even offset */
if(((p->pos - p->buf) % 2) != 0){
if(align)
abort();
}
i = 0;
while(*p->pos && n && p->pos < p->eop){
r = gl16(p);
@ -249,7 +254,6 @@ gstr(Pkt *p, char *str, int n)
n -= 2;
}
*(str + i) = 0;
while(*p->pos && p->pos < p->eop)
gl16(p);
/*
@ -269,6 +273,40 @@ gstr(Pkt *p, char *str, int n)
}
}
void
gstr(Pkt *p, char *str, int n)
{
_gstr(p, str, n, 1);
}
void
gstr_noalign(Pkt *p, char *str, int n)
{
_gstr(p, str, n, 0);
}
/*
* Because DFS uses a string heap rather than strings embedded in the
* data packet, experience (rather than any spec) tells, us we must
* turn off the 16bit alignment for unicode strings.
*/
void
goff(Pkt *p, uchar *base, char *str, int n)
{
int off;
uchar *pos;
off = gl16(p);
if(off == 0 || base + off > p->eop){
memset(str, 0, n);
return;
}
pos = p->pos;
p->pos = base + off;
gstr_noalign(p, str, n);
p->pos = pos;
}
void
gascii(Pkt *p, char *str, int n)
{
@ -401,17 +439,17 @@ gdatetime(Pkt *p)
d = gl16(p);
}
memset(&tm, 0, sizeof(tm));
tm.year = 80 + (d >> 9);
tm.mon = ((d >> 5) & 017) - 1;
tm.mday = d & 037;
tm.zone[0] = 0;
tm.tzoff = p->s->tz;
tm.hour = t >> 11;
tm.min = (t >> 5) & 63;
tm.sec = (t & 31) << 1;
strcpy(tm.zone, "GMT");
return tm2sec(&tm) + p->s->tz;
return tm2sec(&tm);
}
long
@ -448,19 +486,3 @@ gconv(Pkt *p, int conv, char *str, int n)
p->pos = pos;
}
void
goff(Pkt *p, uchar *base, char *str, int n)
{
int off;
uchar *pos;
off = gl16(p);
if(off == 0 || base + off > p->eop){
memset(str, 0, n);
return;
}
pos = p->pos;
p->pos = base + off;
gstr(p, str, n);
p->pos = pos;
}

View file

@ -103,6 +103,13 @@ gtparam(Pkt *p)
p->pos = p->tparam;
}
static void
gtdata(Pkt *p)
{
p->pos = p->tdata;
}
int
RAPshareenum(Session *s, Share *sp, Share **ent)
{
@ -281,8 +288,8 @@ RAPsessionenum(Session *s, Share *sp, Sessinfo **sip)
ngot++;
q++;
}
if(ngot < navail)
fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
// if(ngot < navail)
// fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
free(p);
return ngot;
}

View file

@ -402,8 +402,8 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno,
ct = gvtime(p); /* creation time */
sn = gl32(p); /* serial number */
n = gl32(p); /* label name length */
g8(p); /* reserved */
g8(p); /* reserved */
g8(p); /* reserved */
g8(p); /* reserved */
memset(label, 0, labellen);
if(n < labellen && n > 0)
@ -417,6 +417,35 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno,
return 0;
}
int
T2fsdeviceinfo(Session *s, Share *sp, int *type, int *flags)
{
Pkt *p;
long t, f;
p = t2hdr(s, sp, TRANS2_QUERY_FS_INFORMATION);
pt2param(p);
pl16(p, SMB_QUERY_FS_DEVICE_INFO); /* Information level */
pt2data(p);
if(t2rpc(p) == -1){
free(p);
return -1;
}
gt2data(p);
t = gl32(p); /* device type */
f = gl32(p); /* device characteristics */
if(type)
*type = t;
if(flags)
*flags = f;
free(p);
return 0;
}
int
T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused)
{
@ -485,15 +514,15 @@ T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used,
re[i].flags = gl16(p); /* referal flags */
switch(vers){
case 1:
re[i].prox = 0; /* nearby */
re[i].ttl = 5*60; /* 5 mins */
re[i].ttl = 300; /* 30 mins */
gstr(p, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp);
re[i].path = estrdup9p(tmp);
break;
case 2:
re[i].prox = gl32(p); /* not implemented in v2 */
re[i].ttl = gl32(p);
if(re[i].ttl == 0)
re[i].ttl = 1800;
goff(p, base, re[i].path, sizeof tmp);
re[i].path = estrdup9p(tmp);
goff(p, base, re[i].path, sizeof tmp);/* spurious 8.3 path */
@ -501,24 +530,26 @@ T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used,
re[i].addr = estrdup9p(tmp);
break;
case 3:
if(re[i].flags & DFS_REFERAL_LIST){
re[i].prox = 0;
if(re[i].flags & DFS_REFERAL_LIST){ /* normal referal */
re[i].ttl = gl32(p);
if(re[i].ttl == 0)
re[i].ttl = 1800;
goff(p, base, tmp, sizeof tmp);
re[i].path = estrdup9p(tmp);
gl16(p);
goff(p, base, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp);
}
else{
re[i].prox = 0;
else{ /* domain root */
re[i].ttl = gl32(p);
if(re[i].ttl == 0)
re[i].ttl = 300;
goff(p, base, tmp, sizeof tmp);
re[i].path = estrdup9p(tmp);
gl16(p); /* spurious 8.3 path */
goff(p, base, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp);
gl16(p); /* GUID (historic) */
/* GUID (historic) here, skipped below as we know the record length */
}
break;
default:

View file

@ -95,6 +95,12 @@ tntrpc(Pkt *p)
return got;
}
static void
gtntparam(Pkt *p)
{
p->pos = p->tparam;
}
static void
gtntdata(Pkt *p)
{