Пример #1
0
int
smbtransactiondecoderesponse2(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
			      SmbBuffer *b, char **errmsgp)
{
	Args a;

	if (h->command != SMB_COM_TRANSACTION2) {
		smbstringprint(errmsgp, "smbtransactiondecoderesponse2: not an SMB_COM_TRANSACTION2");
		return 0;
	}
	if (h->wordcount < 10) {
		smbstringprint(errmsgp, "smbtransactiondecoderesponse2: word count less than 10");
		return -1;
	}
	t->out.tpcount = smbnhgets(pdata); pdata += 2;
	t->out.tdcount = smbnhgets(pdata); pdata += 2;
	pdata += 2;
	a.pcount = smbnhgets(pdata); pdata += 2;
	a.poffset =  smbnhgets(pdata); pdata += 2;
	a.pdisplacement = smbnhgets(pdata); pdata += 2;
	a.dcount = smbnhgets(pdata); pdata += 2;
	a.doffset =  smbnhgets(pdata); pdata += 2;
	a.ddisplacement = smbnhgets(pdata); pdata += 2;
	a.scount = *pdata;
	if (a.scount != h->wordcount - 10) {
		smbstringprint(errmsgp, "smbtransactiondecoderesponse2: scount inconsistent");
		return 0;
	}
	return decoderesponse(t, &a, b, errmsgp);
}
Пример #2
0
int
decoderesponse(SmbTransaction *t, Args *a, SmbBuffer *b, char **errmsgp)
{
	if (t->out.tpcount > smbbufferwritemaxoffset(t->out.parameters)) {
		smbstringprint(errmsgp, "decoderesponse: too many parameters for buffer");
		return 0;
	}
	if (t->out.tdcount > smbbufferwritemaxoffset(t->out.data)) {
		smbstringprint(errmsgp, "decoderesponse: too much data for buffer");
		return 0;
	}
	if (a->pdisplacement + a->pcount > t->out.tpcount) {
		smbstringprint(errmsgp, "decoderesponse: more parameters than tpcount");
		return 0;
	}
	if (a->pdisplacement != smbbufferwriteoffset(t->out.parameters)) {
		smbstringprint(errmsgp, "decoderesponse: parameter displacement inconsistent");
		return 0;
	}
	if (a->ddisplacement + a->dcount > t->out.tdcount) {
		smbstringprint(errmsgp, "decoderesponse: more data than tdcount");
		return 0;
	}
	if (a->ddisplacement != smbbufferwriteoffset(t->out.data)) {
		smbstringprint(errmsgp, "decoderesponse: data displacement inconsistent");
		return 0;
	}
	assert(a->scount == 0);
	if (a->pcount) {
		if (!smbbufferreadskipto(b, a->poffset)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid parameter offset");
			return 0;
		}
		if (!smbbuffercopy(t->out.parameters, b, a->pcount)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for parameters");
			return 0;
		}
	}
	if (a->dcount) {
		if (!smbbufferreadskipto(b, a->doffset)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid data offset");
			return 0;
		}
		if (!smbbuffercopy(t->out.data, b, a->dcount)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for data");
			return 0;
		}
	}
	return 1;
}
Пример #3
0
SmbService *
smbservicefind(SmbSession *s, char *uncpath, char *servicetype,
	       uint8_t *errclassp,
	       uint16_t *errorp)
{
	char *p, *q;
	if ((uncpath[0] == '/' && uncpath[1] == '/')
	||  (uncpath[0] == '\\' && uncpath[1] == '\\')) {
		/* check that the server name matches mine */
		p = uncpath + 2;
		q = strchr(p, uncpath[0]);
		if (q == nil)
			goto bad;
		*q++ = 0;
//		if (cistrcmp(p, smbglobals.serverinfo.name) != 0)
//			goto bad;
	}
	else
		q = uncpath + 1;
	if (strcmp(servicetype, "?????") == 0 && strcmp(q, "IPC$") == 0)
		return &ipc;
	if ((strcmp(servicetype, "?????") == 0 || strcmp(servicetype, "A:") == 0)) {
		SmbService *serv;
		if (cistrcmp(q, local.name) == 0)
			return &local;
		/* try the session specific list */
		for (serv = s->serv; serv; serv = serv->next)
			if (cistrcmp(q, serv->name) == 0)
				return serv;
		/* exec "9fs q" in case it invents /n/q */
		for (p = q; *p; p++)
			if (*p >= 'A' && *p <= 'Z')
				*p = tolower(*p);
		if (run9fs(q) >= 0) {
			serv = smbemallocz(sizeof(*serv), 1);
			serv->name = smbestrdup(q);
			serv->type = smbestrdup("A:");
			serv->stype = STYPE_DISKTREE;
			smbstringprint(&serv->remark, "9fs %s", q);
			smbstringprint(&serv->path, "/n/%s", q);
			serv->next = s->serv;
			s->serv = serv;
			return serv;
		}
	}
bad:
	*errclassp = ERRDOS;
	*errorp = ERRbadpath;
	return nil;
}
Пример #4
0
SmbProcessResult
smbcomcreatedirectory(SmbSession *s, SmbHeader *h, uint8_t *, SmbBuffer *b)
{
	int fd;
	char *path;
	char *fullpath = nil;
	SmbTree *t;
	uint8_t fmt;

	if (h->wordcount != 0)
		return SmbProcessResultFormat;
	if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path))
		return SmbProcessResultFormat;
	smblogprint(h->command, "smbcomcreatedirectory: %s\n", path);
	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		return SmbProcessResultError;
	}
	smbstringprint(&fullpath, "%s%s", t->serv->path, path);
	fd = create(fullpath, OREAD, DMDIR | 0775);
	if (fd < 0) {
		smblogprint(h->command, "smbcomcreatedirectory failed: %r\n");
		smbseterror(s, ERRDOS, ERRnoaccess);
		free(path);
		return SmbProcessResultError;
	}
	close(fd);
	free(fullpath);
	free(path);
	return smbbufferputack(s->response, h, &s->peerinfo);
}
Пример #5
0
int
smbbuffergetandcheckheader(SmbBuffer *b, SmbHeader *h, uchar command, int response, uchar **pdatap, ushort *bytecountp, char **errmsgp)
{
	if (!smbbuffergetheader(b, h, pdatap, bytecountp)) {
		smbstringprint(errmsgp, "smbbuffergetandcheckheader: not enough data for header");
		return 0;
	}
	return smbcheckheader(h, command, response, errmsgp);
}
Пример #6
0
int
smbcheckheaderdirection(SmbHeader *h, int response, char **errmsgp)
{
	if (((h->flags & SMB_FLAGS_SERVER_TO_REDIR) == 0) == response) {
		smbstringprint(errmsgp, "unexpected %s", response ? "request" : "response");
		return 0;
	}
	return 1;
}
Пример #7
0
int
smbsuccess(SmbHeader *h, char **errmsgp)
{
	if (h->errclass != SUCCESS) {
		smbstringprint(errmsgp, "%s returned error %d/%d", smboptable[h->command].name, h->errclass, h->error);
		return 0;
	}
	return 1;
}
Пример #8
0
int
smbcheckheader(SmbHeader *h, uint8_t command, int response, char **errmsgp)
{
	if (response && h->command != command) {
		smbstringprint(errmsgp, "sent %.2uc request, got %.2ux response", command, h->command);
		return 0;
	}
	if (!smbcheckheaderdirection(h, response, errmsgp))
		return 0;
	return 1;
}
Пример #9
0
int
smbtransactionnbdgramsend(void *magic, SmbBuffer *ob, char **errmsgp)
{
	NbDgramSendParameters *p = magic;
//print("sending to %B\n", p->to);
//nbdumpdata(smbbufferreadpointer(ob), smbbufferreadspace(ob));
	if (!nbdgramsend(p, smbbufferreadpointer(ob), smbbufferreadspace(ob))) {
		smbstringprint(errmsgp, "dgram send failed");
		return 0;
	}
	return 1;
}
Пример #10
0
static int
sendresponse(void *magic, SmbBuffer *, char **errmsgp)
{
	int rv;
	SmbSession *s = magic;
	rv = smbresponsesend(s);
	if (rv < 0) {
		smbstringprint(errmsgp, "sendresponse failed");
		return 0;
	}
	return 1;
}
Пример #11
0
int
smbclientopen(SmbClient *c, uint16_t mode, char *name, uint8_t *errclassp,
	      uint16_t *errorp,
	uint16_t *fidp, uint16_t *attrp, uint32_t *mtimep, uint32_t *sizep,
	      uint16_t *accessallowedp, char **errmsgp)
{
	SmbBuffer *b;
	SmbHeader h;
	uint32_t bytecountfixup;
	int32_t n;
	uint8_t *pdata;
	uint16_t bytecount;

	b = smbbuffernew(65535);
	h = c->protoh;
	h.tid = c->sharetid;
	h.command = SMB_COM_OPEN;
	h.wordcount = 2;
	smbbufferputheader(b, &h, &c->peerinfo);
	smbbufferputs(b, mode);
	smbbufferputs(b, 0);
	bytecountfixup = smbbufferwriteoffset(b);
	smbbufferputs(b, 0);
	smbbufferputb(b, 4);
	smbbufferputstring(b, &c->peerinfo, SMB_STRING_REVPATH, name);
	smbbufferfixuprelatives(b, bytecountfixup);
	nbsswrite(c->nbss, smbbufferreadpointer(b), smbbufferwriteoffset(b));
	smbbufferreset(b);
	n = nbssread(c->nbss, smbbufferwritepointer(b), smbbufferwritespace(b));
	if (n < 0) {
		smbstringprint(errmsgp, "read error: %r");
		smbbufferfree(&b);
		return 0;
	}
	smbbuffersetreadlen(b, n);
	if (!smbbuffergetandcheckheader(b, &h, h.command, 7, &pdata, &bytecount, errmsgp)) {
		smbbufferfree(&b);
		return 0;
	}
	if (h.errclass) {
		*errclassp = h.errclass;
		*errorp = h.error;
		smbbufferfree(&b);
		return 0;
	}
	*fidp = smbnhgets(pdata); pdata += 2;
	*attrp = smbnhgets(pdata); pdata += 2;
	*mtimep = smbnhgetl(pdata); pdata += 4;
	*sizep = smbnhgets(pdata); pdata += 4;
	*accessallowedp = smbnhgets(pdata);
	return 1;
}
Пример #12
0
SmbProcessResult
smbtruncatefile(SmbSession *s, SmbFile *f, vlong offset)
{
	Dir *d;
	ulong o;
	uchar *db = nil;
	vlong length;
	int rv;
	SmbProcessResult pr;

	d = dirfstat(f->fd);
	assert(d);
	length = d->length;
	free(d);

	if (length == offset)
		return SmbProcessResultReply;

	rv = dirfwstatlength(f->fd, offset);
	if (rv == 0) {
		pr = SmbProcessResultReply;
		goto done;
	}
//smblogprint(-1, "dirfwstatlength failed: %r\n");
	if (length > offset) {
		int nfd;
		char *fullpath;
		if (offset > INMEMORYTRUNCTHRESH) {
			smblogprint(-1, "smbcomwrite: truncation beyond %lud not supported\n", offset);
			pr = SmbProcessResultUnimp;
			goto done;
		}
		db = smbemalloc(offset);
		if (pread(f->fd, db, offset, 0) != offset) {
			pr = SmbProcessResultMisc;
			goto done;
		}
		fullpath = nil;
		smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name);
		nfd = open(fullpath, f->p9mode | OTRUNC);
		free(fullpath);
		if (nfd < 0) {
			smbseterror(s, ERRDOS, ERRnoaccess);
			pr = SmbProcessResultError;
			goto done;
		}
		close(nfd);
		if (pwrite(f->fd, db, offset, 0) != offset) {
			pr = SmbProcessResultMisc;
			goto done;
		}
		pr = SmbProcessResultReply;
	}
	else {
		db = smbemalloc(16384);
		memset(db, 0, 16384);
		o = length;
		while (o < offset) {
			long tt = 16384;
			if (tt > offset - o)
				tt = offset - o;
			if (pwrite(f->fd, db, tt, o) != tt) {
				smbseterror(s, ERRDOS, ERRnoaccess);
				pr = SmbProcessResultError;
				goto done;
			}
			o += tt;
		}
		pr = SmbProcessResultReply;
	}
done:
	free(db);
	return pr;
}
Пример #13
0
int
_smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
			     SmbBuffer *b, int hasname, char **errmsgp)
{
	uint16_t poffset, doffset;

	if (h->wordcount < 14) {
		smbstringprint(errmsgp, "word count less than 14");
		return -1;
	}
	t->in.scount = pdata[13 * 2];
	if (h->wordcount != 14 + t->in.scount) {
		smbstringprint(errmsgp, "smbcomtransaction: word count invalid\n");
		return -1;
	}
	t->in.tpcount = smbnhgets(pdata); pdata += 2;
	t->in.tdcount = smbnhgets(pdata); pdata += 2;
	t->in.maxpcount = smbnhgets(pdata); pdata += 2;
	t->in.maxdcount = smbnhgets(pdata); pdata += 2;
	t->in.maxscount = *pdata++;
	pdata++;
	t->in.flags = smbnhgets(pdata); pdata += 2;
	pdata += 4; /* timeout */
	pdata += 2;
	t->in.pcount = smbnhgets(pdata); pdata += 2;
	poffset = smbnhgets(pdata); pdata += 2;
	t->in.dcount = smbnhgets(pdata); pdata += 2;
	doffset = smbnhgets(pdata); pdata += 2;
	pdata++; /* scount */
	pdata++; /* reserved */
	smbfree(&t->in.setup);
	if (t->in.scount) {
		int x;
		t->in.setup = smbemalloc(t->in.scount * sizeof(uint16_t));
		for (x = 0; x < t->in.scount; x++) {
			t->in.setup[x] = smbnhgets(pdata);
			pdata += 2;
		}
	}
	smbfree(&t->in.name);
	if (hasname && !smbbuffergetstring(b, h, SMB_STRING_PATH, &t->in.name)) {
		smbstringprint(errmsgp, "not enough bdata for name");
		return -1;
	}
	if (poffset + t->in.pcount > smbbufferwriteoffset(b)) {
		smbstringprint(errmsgp, "not enough bdata for parameters");
		return -1;
	}
	if (t->in.pcount > t->in.tpcount) {
		smbstringprint(errmsgp, "too many parameters");
		return -1;
	}
	smbfree(&t->in.parameters);
	t->in.parameters = smbemalloc(t->in.tpcount);
	memcpy(t->in.parameters, smbbufferpointer(b, poffset), t->in.pcount);
	if (doffset + t->in.dcount > smbbufferwriteoffset(b)) {
		smbstringprint(errmsgp, "not enough bdata for data");
		return -1;
	}
	if (t->in.dcount > t->in.tdcount) {
		smbstringprint(errmsgp, "too much data");
		return -1;
	}
	smbfree(&t->in.data);
	t->in.data = smbemalloc(t->in.tdcount);
	memcpy(t->in.data, smbbufferpointer(b, doffset), t->in.dcount);
	if (t->in.dcount < t->in.tdcount || t->in.pcount < t->in.tpcount)
		return 0;
	return 1;
}
Пример #14
0
static int
_transactionencodeprimary(SmbTransaction *t, uint8_t cmd, SmbHeader *h,
			  SmbPeerInfo *p, SmbBuffer *ob,
	uint8_t *wordcountp, uint16_t *bytecountp, char **errmsgp)
{
	SmbHeader mh;
	uint32_t countsfixupoffset, bytecountfixupoffset;
	int x;
	mh = *h;
	*wordcountp = mh.wordcount = 14 + t->in.scount;
	mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
	mh.command = cmd;
	if (!smbbufferputheader(ob, &mh, p)) {
	toosmall:
		smbstringprint(errmsgp, "output buffer too small");
		return 0;
	}
	if (t->in.tpcount > 65535 || t->in.tdcount > 65535 || t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
		smbstringprint(errmsgp, "counts too big");
		return 0;
	}
	if (!smbbufferputs(ob, t->in.tpcount)
		|| !smbbufferputs(ob, t->in.tdcount)
		|| !smbbufferputs(ob, t->in.maxpcount)
		|| !smbbufferputs(ob, t->in.maxdcount)
		|| !smbbufferputb(ob, t->in.maxscount)
		|| !smbbufferputb(ob, 0)
		|| !smbbufferputs(ob, t->in.flags)
		|| !smbbufferputl(ob, 0)
		|| !smbbufferputs(ob, 0))
		goto toosmall;
	countsfixupoffset = smbbufferwriteoffset(ob);
	if (!smbbufferputs(ob, 0)
		|| !smbbufferputs(ob, 0)
		|| !smbbufferputs(ob, 0)
		|| !smbbufferputs(ob, 0))
		goto toosmall;
	if (!smbbufferputb(ob, t->in.scount)
		|| !smbbufferputb(ob, 0))
		goto toosmall;
	for (x = 0; x < t->in.scount; x++)
		if (!smbbufferputs(ob, t->in.setup[x]))
			goto toosmall;
	bytecountfixupoffset = smbbufferwriteoffset(ob);
	if (!smbbufferputs(ob, 0))
		goto toosmall;
	smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
	if (!smbbufferputstring(ob, p, SMB_STRING_UPCASE, t->in.name))
		goto toosmall;
	if (t->in.pcount < t->in.tpcount) {
		uint32_t align = smbbufferwriteoffset(ob) & 1;
		uint32_t pthistime;
		pthistime = smbbufferwritespace(ob) - align;
		if (pthistime > t->in.tpcount - t->in.pcount)
			pthistime = t->in.tpcount - t->in.pcount;
		if (pthistime > 65535)
			pthistime = 65535;
		if (smbbufferwriteoffset(ob) > 65535)
			pthistime = 0;
		if (pthistime) {
			assert(smbbufferalignl2(ob, 0));
			assert(smbbufferoffsetputs(ob, countsfixupoffset, pthistime));
			assert(smbbufferoffsetputs(ob, countsfixupoffset + 2, smbbufferwriteoffset(ob)));
			assert(smbbufferputbytes(ob, t->in.parameters + t->in.pcount, pthistime));
		}
		t->in.pcount += pthistime;
	}
	if (t->in.dcount < t->in.tdcount) {
		uint32_t align = smbbufferwriteoffset(ob) & 1;
		uint32_t dthistime;
		dthistime = smbbufferwritespace(ob) - align;
		if (dthistime > t->in.tdcount - t->in.dcount)
			dthistime = t->in.tdcount - t->in.dcount;
		if (dthistime > 65535)
			dthistime = 65535;
		if (smbbufferwriteoffset(ob) > 65535)
			dthistime = 0;
		if (dthistime) {
			assert(smbbufferalignl2(ob, 0));
			assert(smbbufferoffsetputs(ob, countsfixupoffset + 4, dthistime));
			assert(smbbufferoffsetputs(ob, countsfixupoffset + 6, smbbufferwriteoffset(ob)));
			assert(smbbufferputbytes(ob, t->in.data + t->in.dcount, dthistime));
		}
		t->in.dcount += dthistime;
	}
	*bytecountp = smbbufferwriteoffset(ob) - bytecountfixupoffset - 2;
	assert(smbbufferoffsetputs(ob, bytecountfixupoffset, *bytecountp));
	return 1;
}
Пример #15
0
int
_transactionencoderesponse(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *ob,
			   uint8_t cmd,
	char **errmsgp)
{
	SmbHeader mh;
	uint32_t countsfixupoffset, bytecountfixupoffset;
	int palign, dalign;
	uint32_t pbytecount, dbytecount;
	uint32_t poffset, doffset;

	if (t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
		smbstringprint(errmsgp, "counts too big");
		return 0;
	}
	mh = *h;
	mh.wordcount = 10;
	mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
	mh.command = cmd;
	mh.errclass = SUCCESS;
	mh.error = SUCCESS;
	if (!smbbufferputheader(ob, &mh, p)
		|| !smbbufferputs(ob, smbbufferwriteoffset(t->out.parameters))
		|| !smbbufferputs(ob, smbbufferwriteoffset(t->out.data))
		|| !smbbufferputs(ob, 0)) {
	toosmall:
		smbstringprint(errmsgp, "output buffer too small");
		goto toosmall;
	}
	countsfixupoffset = smbbufferwriteoffset(ob);
	if (!smbbufferputbytes(ob, nil, 6 * sizeof(uint16_t))
		|| !smbbufferputb(ob, 0)	// scount == 0
		|| !smbbufferputb(ob, 0))	// reserved2
		goto toosmall;
	/* now the byte count */
	bytecountfixupoffset = smbbufferwriteoffset(ob);
	if (!smbbufferputs(ob, 0))
		goto toosmall;
	smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
	palign = bytecountfixupoffset & 1;
	if (palign && !smbbufferputb(ob, 0))
		goto toosmall;
	pbytecount = smbbufferreadspace(t->out.parameters);
	if (pbytecount > smbbufferwritespace(ob))
		pbytecount = smbbufferwritespace(ob);
	poffset = smbbufferwriteoffset(ob);
	if (poffset > 65535)
		goto toosmall;
	if (!smbbufferputbytes(ob, smbbufferreadpointer(t->out.parameters), pbytecount))
		goto toosmall;
	dalign = smbbufferwritespace(ob) > 0 && (smbbufferwriteoffset(ob) & 1) != 0;
	if (dalign && !smbbufferputb(ob, 0))
		goto toosmall;
	dbytecount = smbbufferreadspace(t->out.data);
	if (dbytecount > smbbufferwritespace(ob))
		dbytecount = smbbufferwritespace(ob);
	doffset = smbbufferwriteoffset(ob);
	if (doffset > 65535)
		goto toosmall;
	if (!smbbufferputbytes(ob, smbbufferreadpointer(t->out.data), dbytecount))
		goto toosmall;
	if (!smbbufferoffsetputs(ob, bytecountfixupoffset, palign + pbytecount + dalign + dbytecount)
		|| !smbbufferoffsetputs(ob, countsfixupoffset, pbytecount)
		|| !smbbufferoffsetputs(ob, countsfixupoffset + 2, poffset)
		|| !smbbufferoffsetputs(ob, countsfixupoffset + 4, smbbufferreadoffset(t->out.parameters))
		|| !smbbufferoffsetputs(ob, countsfixupoffset + 6, dbytecount)
		|| !smbbufferoffsetputs(ob, countsfixupoffset + 8, doffset)
		|| !smbbufferoffsetputs(ob, countsfixupoffset + 10, smbbufferreadoffset(t->out.data)))
		goto toosmall;
	assert(smbbufferoffsetputs(ob, bytecountfixupoffset, smbbufferwriteoffset(ob) - bytecountfixupoffset - 2));
	smbbuffergetbytes(t->out.parameters, nil, pbytecount);
	smbbuffergetbytes(t->out.data, nil, dbytecount);
	return 1;
}
Пример #16
0
int
smbclienttrans2findfirst2(SmbClient *c, ushort searchcount, char *filename,
	ushort *sidp, ushort *searchcountp, ushort *endofsearchp,SmbFindFileBothDirectoryInfo *ip, char **errmsgp)
{
	int rv;
	ushort setup;
	SmbBuffer *inparam;
	SmbBuffer *outparam;
	SmbBuffer *outdata;
	SmbHeader rh;
	setup = SMB_TRANS2_FIND_FIRST2;
	inparam = smbbuffernew(512);
	smbbufferputs(inparam, 0x16);
	smbbufferputs(inparam, searchcount);
	smbbufferputs(inparam, 7);
	smbbufferputs(inparam, SMB_FIND_FILE_BOTH_DIRECTORY_INFO);
	smbbufferputl(inparam, 0);
	smbbufferputstring(inparam, &c->peerinfo, 0, filename);
	outparam = smbbuffernew(10);
	outdata = smbbuffernew(65535);
	rv = smbclienttrans2(c, 1, &setup, inparam, outparam, outdata, &rh, errmsgp);
	smbbufferfree(&inparam);
	if (rv) {
		ushort eaerroroffset, lastnameoffset;
		ulong nextentry;
		int i;

		if (!smbbuffergets(outparam, sidp)
			|| !smbbuffergets(outparam, searchcountp)
			|| !smbbuffergets(outparam, endofsearchp)
			|| !smbbuffergets(outparam, &eaerroroffset)
			|| !smbbuffergets(outparam, &lastnameoffset)) {
			smbstringprint(errmsgp, "smbclienttrans2findfirst2: not enough parameters returned");
			rv = 0;
			goto done;
		}
		nextentry = 0;
smblogprint(-1, "returned data:\n");
smblogdata(-1, smblogprint, smbbufferreadpointer(outdata), smbbufferreadspace(outdata), 256);
		for (i = 0; i < *searchcountp; i++) {
			SmbFindFileBothDirectoryInfo *info = ip + i;
			ulong neo, filenamelength, easize;
			uchar shortnamelength;
			if (i && !smbbufferreadskipto(outdata, nextentry)) {
			underflow:
				smbstringprint(errmsgp, "smbclientrans2findfirst2: not enough data returned");
				rv = 0;
				goto done;
			}
			if (!smbbuffergetl(outdata, &neo))
				goto underflow;
			nextentry = smbbufferreadoffset(outdata) + neo - 4;
print("neo 0x%.8lux\n", neo);
			if (!smbbuffergetl(outdata, &info->fileindex)
				|| !smbbuffergetv(outdata, &info->creationtime)
				|| !smbbuffergetv(outdata, &info->lastaccesstime)
				|| !smbbuffergetv(outdata, &info->lastwritetime)
				|| !smbbuffergetv(outdata, &info->changetime)
				|| !smbbuffergetv(outdata, &info->endoffile)
				|| !smbbuffergetv(outdata, &info->allocationsize))
				goto underflow;
print("got here\n");
			if (!smbbuffergetl(outdata, &info->extfileattributes)
				|| !smbbuffergetl(outdata, &filenamelength)
				|| !smbbuffergetl(outdata, &easize)
				|| !smbbuffergetb(outdata, &shortnamelength)
				|| !smbbuffergetbytes(outdata, nil, 1)
				|| !smbbuffergetbytes(outdata, nil, 24)
				|| !smbbuffergetstring(outdata, &rh, SMB_STRING_REVPATH, &info->filename))
				goto underflow;
print("got here as well\n");
		}
	}
done:
	smbbufferfree(&outparam);
	smbbufferfree(&outdata);
	return rv;
}
Пример #17
0
int
smbtransactionexecute(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *iob, SmbTransactionMethod *method, void *magic, SmbHeader *rhp,
		      char **errmsgp)
{
	uint8_t sentwordcount;
	uint16_t sentbytecount;
	SmbHeader rh;
	smbbufferreset(iob);
	if (!(*method->encodeprimary)(t, h, p, iob, &sentwordcount, &sentbytecount, errmsgp))
		return 0;
//	smblogprint(-1, "sent...\n");
//	smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
	if (!(*method->sendrequest)(magic, iob, errmsgp))
		return 0;
	if (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount) {
		uint8_t wordcount;
		uint16_t bytecount;
		/* secondary needed */
		if (method->encodesecondary == nil || method->receiveintermediate == nil) {
			smbstringprint(errmsgp, "buffer too small and secondaries not allowed");
			return 0;
		}
		if (!(*method->receiveintermediate)(magic, &wordcount, &bytecount, errmsgp))
			return 0;
		if (sentwordcount != wordcount || sentbytecount != bytecount) {
			smbstringprint(errmsgp, "server intermediate reply counts differ");
			return 0;
		}
		do {
			if (!(*method->encodesecondary)(t, h, iob, errmsgp))
				return 0;
			if (!(*method->sendrequest)(magic, iob, errmsgp))
				return 0;
		} while (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount);
	}
	if (method->receiveresponse == nil || method->decoderesponse == nil)
		return 1;
	do {
		uint8_t *pdata;
		uint16_t bytecount;

		if (!(*method->receiveresponse)(magic, iob, errmsgp))
			return 0;
		if (!smbbuffergetheader(iob, &rh, &pdata, &bytecount)) {
			smbstringprint(errmsgp, "smbtransactionexecute: invalid response header");
			return 0;
		}
		if (!smbcheckheaderdirection(&rh, 1, errmsgp))
			return 0;
		if (rh.errclass != SUCCESS) {
			smbstringprint(errmsgp, "smbtransactionexecute: remote error %d/%d", rh.errclass, rh.error);
			return 0;
		}
		if (!smbbuffertrimreadlen(iob, bytecount)) {
			smbstringprint(errmsgp, "smbtransactionexecute: invalid bytecount");
			return 0;
		}
//		smblogprint(-1, "received...\n");
//		smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
		if (!(*method->decoderesponse)(t, &rh, pdata, iob, errmsgp))
			return 0;
	} while (smbbufferwriteoffset(t->out.parameters) < t->out.tpcount || smbbufferwriteoffset(t->out.data) < t->out.tdcount);
	if (rhp)
		*rhp = rh;
	return 1;
}
Пример #18
0
int
smbnetserverenum2(SmbClient *c, uint32_t stype, char *domain,
		  int *entriesp,
		  SmbRapServerInfo1 **sip, char **errmsgp)
{
	int rv;
	uint16_t ec, entries, total, converter;
	SmbRapServerInfo1 *si = nil;
	SmbBuffer *ipb = smbbuffernew(512);
	SmbBuffer *odb = smbbuffernew(65535);
	SmbBuffer *opb = smbbuffernew(8);
	smbbufferputs(ipb, 104);
	smbbufferputstring(ipb, nil, SMB_STRING_ASCII, "WrLehDz");
	smbbufferputstring(ipb, nil, SMB_STRING_ASCII, "B16BBDz");
	smbbufferputs(ipb, 1);
	smbbufferputs(ipb, smbbufferwritespace(odb));
	smbbufferputl(ipb, stype);
	smbbufferputstring(ipb, nil, SMB_STRING_ASCII, domain);
	rv = !smbclientrap(c, ipb, opb, odb, errmsgp);
	smbbufferfree(&ipb);
	if (rv == 0) {
		char *remark, *eremark;
		int remarkspace;
		int i;
		if (!smbbuffergets(opb, &ec)
			|| !smbbuffergets(opb, &converter)
			|| !smbbuffergets(opb, &entries)
			|| !smbbuffergets(opb, &total)) {
			smbstringprint(errmsgp, "smbnetserverenum2: not enough return parameters");
			rv = -1;
			goto done;
		}
		if (ec != 0) {
			rv = ec;
			goto done;
		}
		if (smbbufferreadspace(odb) < entries * 26) {
			smbstringprint(errmsgp, "smbnetserverenum2: not enough return data");
			rv = -1;
			goto done;
		}
		remarkspace = smbbufferreadspace(odb) - entries * 26;
		si = smbemalloc(entries * sizeof(SmbRapServerInfo1) + remarkspace);
		remark = (char *)&si[entries];
		eremark = remark + remarkspace;
		for (i = 0; i < entries; i++) {
			uint32_t offset;
			int remarklen;
			assert(smbbuffergetbytes(odb, si[i].name, 16));
			assert(smbbuffergetb(odb, &si[i].vmaj));
			assert(smbbuffergetb(odb, &si[i].vmin));
			assert(smbbuffergetl(odb, &si[i].type));
			assert(smbbuffergetl(odb, &offset));
			offset -= converter;
			if (!smbbufferoffsetcopystr(odb, offset, remark, eremark - remark, &remarklen)) {
				smbstringprint(errmsgp, "smbnetserverenum2: invalid string offset");
				rv = -1;
				goto done;
			}
			si[i].remark = remark;
			remark += remarklen;
		}
		*sip = si;
		si = nil;
		*entriesp = entries;
	}
	else
		rv = -1;	
done:
	free(si);
	smbbufferfree(&opb);
	smbbufferfree(&odb);
	return rv;
}
Пример #19
0
SmbProcessResult
smbtrans2setpathinformation(SmbSession *s, SmbHeader *h)
{
	char *fullpath, *path;
	SmbTree *t;
	ushort infolevel;
	SmbBuffer *b;
	SmbProcessResult pr;
	ushort atime, adate, mtime, mdate;
	ulong attr;
	ulong mode;
	ulong size;
//	uvlong length;

	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		pr = SmbProcessResultError;
		goto done;
	}
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
	path = nil;
	if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
	misc:
		pr = SmbProcessResultMisc;
		goto done;
	}

	fullpath = nil;
	smbstringprint(&fullpath, "%s%s", t->serv->path, path);

	translogprint(s->transaction.in.setup[0], "path %s\n", path);
	translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
	translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);

	switch (infolevel) {
	case SMB_INFO_STANDARD:
		if (s->transaction.in.tdcount < 6 * 4 + 2 * 2)
			goto misc;
		adate = smbnhgets(s->transaction.in.data + 6);
		atime = smbnhgets(s->transaction.in.data + 4);
		mdate = smbnhgets(s->transaction.in.data + 10);
		mtime = smbnhgets(s->transaction.in.data + 8);
		size = smbnhgetl(s->transaction.in.data + 12);
		attr = smbnhgets(s->transaction.in.data + 20);
		if (attr) {
			Dir *od = dirstat(fullpath);
			if (od == nil)
				goto noaccess;
			mode = smbdosattr2plan9wstatmode(od->mode, attr);
			free(od);
		}
		else
			mode = 0xffffffff;
		translogprint(s->transaction.in.setup[0], "mode 0%od\n", mode);

//		if (size)
//			length = size;
//		else
//			length = ~0LL;
	
		translogprint(s->transaction.in.setup[0], "size %lld\n", size);
		translogprint(s->transaction.in.setup[0], "adate %d atime %d", adate, atime);
		translogprint(s->transaction.in.setup[0], "mdate %d mtime %d\n", mdate, mtime);

		if (size || adate || atime || mdate || mtime || mode != 0xffffffff) {
			Dir d;
			memset(&d, 0xff, sizeof(d));
			d.name = d.uid = d.gid = d.muid = nil;
			if (adate || atime)
				d.atime = smbdatetime2plan9time(adate, atime, s->tzoff);
			if (mdate || mtime)
				d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff);
			d.mode = mode;
			d.length = size;
			if (dirwstat(fullpath, &d) < 0) {
			noaccess:
				smbseterror(s, ERRDOS, ERRnoaccess);
				pr = SmbProcessResultError;
				goto done;
			}
		}
		if (!smbbufferputs(s->transaction.out.parameters, 0))
			goto misc;
		pr = SmbProcessResultReply;
		break;

	default:
		smblogprint(-1, "smbtrans2setpathinformation: infolevel 0x%.4ux not implemented\n", infolevel);
		smbseterror(s, ERRDOS, ERRunknownlevel);
		pr = SmbProcessResultError;
		break;
	}
done:
	smbbufferfree(&b);
	return pr;
}