Пример #1
0
static int
run9fs(char *arg)
{
	int rv;
	Waitmsg *w;

	rv = fork();
	if (rv < 0)
		return -1;
	if (rv == 0) {
		char *argv[3];
		argv[0] = "/rc/bin/9fs";
		argv[1] = arg;
		argv[2] = 0;
		exec(argv[0], argv);
		exits("failed to exec 9fs");
	}
	for (;;) {
		w = wait();
		if (w == nil)
			return -1;
		if (w->pid == rv)
			break;
		free(w);
	}
	if (w->msg[0]) {
		smblogprint(SMB_COM_TREE_CONNECT_ANDX, "smbservicefind: %s\n", w->msg);
		free(w);
		return -1;
	}
	free(w);
	smblogprint(SMB_COM_TREE_CONNECT_ANDX, "smbservicefind: 9fs %s executed successfully\n", arg);
	return 0;
}
Пример #2
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);
}
Пример #3
0
int
smbcomtransaction2(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b)
{
	int rv;
	char *errmsg;
	SmbProcessResult pr = SmbProcessResultDie;
	uint16_t op;

	errmsg = nil;
	rv = smbtransactiondecodeprimary2(&s->transaction, h, pdata, b, &errmsg);
	if (rv < 0) {
	fmtfail:
		pr = SmbProcessResultFormat;
		goto done;
	}
	if (rv == 0) {
		h->wordcount = 0;
		if (smbbufferputack(s->response, h, &s->peerinfo)) {
			pr = SmbProcessResultReply;
			s->nextcommand = SMB_COM_TRANSACTION2_SECONDARY;
		}
		goto done;
	}
	smblogprint(h->command, "smbcomtransaction2: scount %ud tpcount %lud tdcount %lud maxscount %lud maxpcount %lud maxdcount %lud\n",
		s->transaction.in.scount, s->transaction.in.tpcount, s->transaction.in.tdcount,
		s->transaction.in.maxscount, s->transaction.in.maxpcount, s->transaction.in.maxdcount);
	smbbufferfree(&s->transaction.out.parameters);
	smbbufferfree(&s->transaction.out.data);
	s->transaction.out.parameters = smbbuffernew(s->transaction.in.maxpcount);
	s->transaction.out.data = smbbuffernew(s->transaction.in.maxdcount);
	if (s->transaction.in.scount != 1)
		goto fmtfail;
	op = s->transaction.in.setup[0];
	if (op >= smbtrans2optablesize || smbtrans2optable[op].name == nil) {
		smblogprint(-1, "smbcomtransaction2: function %d unknown\n", op);
		pr = SmbProcessResultUnimp;
		goto done;
	}
	if (smbtrans2optable[op].process == nil) {
		smblogprint(-1, "smbcomtransaction2: %s unimplemented\n", smbtrans2optable[op].name);
		pr = SmbProcessResultUnimp;
		goto done;
	}
	pr = (*smbtrans2optable[op].process)(s, h);
	if (pr == SmbProcessResultReply) {
		char *errmsg;
		errmsg = nil;
		rv = smbtransactionrespond(&s->transaction, h, &s->peerinfo, s->response, &smbtransactionmethod2, s, &errmsg);
		if (!rv) {
			smblogprint(h->command, "smbcomtransaction2: failed: %s\n", errmsg);
			pr = SmbProcessResultMisc;
		}
		else
			pr = SmbProcessResultOk;
	}
done:
	free(errmsg);
	return pr;
}
Пример #4
0
int
smbcomtransaction(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b)
{
	int rv;
	char *errmsg;
	SmbProcessResult pr = SmbProcessResultDie;
	errmsg = nil;
	rv = smbtransactiondecodeprimary(&s->transaction, h, pdata, b, &errmsg);
	if (rv < 0) {
		pr = SmbProcessResultFormat;
		goto done;
	}
	if (rv == 0) {
		h->wordcount = 0;
		if (smbbufferputack(s->response, h, &s->peerinfo)) {
			pr = SmbProcessResultReply;
			s->nextcommand = SMB_COM_TRANSACTION_SECONDARY;
		}
		goto done;
	}
	smblogprint(h->command, "smbcomtransaction: %s scount %ud tpcount %lud tdcount %lud maxscount %lud maxpcount %lud maxdcount %lud\n",
		s->transaction.in.name, s->transaction.in.scount, s->transaction.in.tpcount, s->transaction.in.tdcount,
		s->transaction.in.maxscount, s->transaction.in.maxpcount, s->transaction.in.maxdcount);
	smbbufferfree(&s->transaction.out.parameters);
	smbbufferfree(&s->transaction.out.data);
	s->transaction.out.parameters = smbbuffernew(s->transaction.in.maxpcount);
	s->transaction.out.data = smbbuffernew(s->transaction.in.maxdcount);
	if (strcmp(s->transaction.in.name, smbglobals.pipelanman) == 0)
		pr = smbrap2(s);
	else {
		smbseterror(s, ERRDOS, ERRbadpath);
		pr = SmbProcessResultError;
		goto done;
	}
	if (pr == SmbProcessResultReply) {
		char *errmsg;
		errmsg = nil;
		rv = smbtransactionrespond(&s->transaction, h, &s->peerinfo, s->response, &smbtransactionmethod, s, &errmsg);
		if (!rv) {
			smblogprint(h->command, "smbcomtransaction: failed: %s\n", errmsg);
			pr = SmbProcessResultMisc;
		}
		else
			pr = SmbProcessResultOk;
	}
done:
	free(errmsg);
	return pr;
}
Пример #5
0
SmbProcessResult
smbcomsetinformation(SmbSession *s, SmbHeader *h, uint8_t *pdata,
		     SmbBuffer *b)
{
	uint16_t attr;
	uint32_t utime;
	char *name;
	if (h->wordcount != 8)
		return SmbProcessResultFormat;
	attr = smbnhgets(pdata); pdata += 2;
	utime = smbnhgetl(pdata);
	if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &name))
		return SmbProcessResultFormat;
	smblogprint(h->command,
		"smbcomsetinformation: attr 0x%.4ux utime %lud path %s\n",
		attr, utime, name);
	if (utime) {
		Dir d;
		memset(&d, 0xff, sizeof(d));
		d.name = d.uid = d.gid = d.muid = nil;
		d.mtime = smbutime2plan9time(utime, s->tzoff);
		if (dirwstat(name, &d) < 0) {
			smbseterror(s, ERRDOS, ERRnoaccess);
			free(name);
			return SmbProcessResultError;
		}
	}
	free(name);		
	return smbbufferputack(s->response, h, &s->peerinfo);
}
Пример #6
0
SmbProcessResult
smbrap2(SmbSession *s)
{
	char *pstring;
	char *dstring;
	uint16_t pno;
	RapTableEntry *e;
	SmbProcessResult pr;
	SmbBuffer *inparam;

	inparam = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
	if (!smbbuffergets(inparam, &pno)
		|| !smbbuffergetstrinline(inparam, &pstring)
		|| !smbbuffergetstrinline(inparam, &dstring)) {
		smblogprintif(smbglobals.log.rap2, "smbrap2: not enough parameters\n");
		pr = SmbProcessResultFormat;
		goto done;
	}
	if (pno > nelem(raptable) || raptable[pno].name == nil) {
		smblogprint(-1, "smbrap2: unsupported procedure %ud\n", pno);
		pr = SmbProcessResultUnimp;
		goto done;
	}
	e = raptable + pno;
	pr = (*e->procedure)(inparam, s->transaction.out.parameters, s->transaction.out.data);
done:
	smbbufferfree(&inparam);
	return pr;
}
Пример #7
0
SmbProcessResult
smbresponsesend(SmbSession *s)
{
	uchar cmd;
	SmbProcessResult pr;

	assert(smbbufferoffsetgetb(s->response, 4, &cmd));
smbloglock();
smblogprint(cmd, "sending:\n");
smblogdata(cmd, smblogprint, smbbufferreadpointer(s->response), smbbufferreadspace(s->response), 256);
smblogunlock();
	if (s->nbss) {
		NbScatterGather a[2];
		a[0].p = smbbufferreadpointer(s->response);
		a[0].l = smbbufferreadspace(s->response);
		a[1].p = nil;
		nbssgatherwrite(s->nbss, a);
		pr = SmbProcessResultOk;
	}
	else if (s->cifss) {
		ulong l = smbbufferreadspace(s->response);
		uchar nl[4];
		hnputl(nl, l);
		write(s->cifss->fd, nl, 4);
		write(s->cifss->fd, smbbufferreadpointer(s->response), l);
		pr = SmbProcessResultOk;
	}
	else
		pr = SmbProcessResultDie;
	smbbufferreset(s->response);
	return pr;
}
Пример #8
0
void
threadmain(int argc, char **argv)
{
	NbName from, to;
	char *e = nil;
	int netbios = 0;
	ARGBEGIN {
	case 'u':
		smbglobals.unicode = strtol(ARGF(), 0, 0) != 0;
		break;
	case 'p':
		smbglobals.log.print = 1;
		break;
	case 'd':
		logset(ARGF());
		break;
	case 'w':
		smbglobals.primarydomain = ARGF();
		break;
	case 'n':
		netbios = 1;
		break;
	default:
		usage();
	} ARGEND;
	smbglobalsguess(0);
	smblistencifs(cifsaccept);
	if (netbios) {
		nbinit();
		nbmknamefromstring(from, "*");
		nbmknamefromstring(to, "*smbserver\\x20");
		nbsslisten(to, from, nbssaccept, nil);
		nbmknamefromstringandtype(to, smbglobals.serverinfo.name, 0x20);
		nbsslisten(to, from, nbssaccept, nil);
	}
	smblogprint(-1, "Aquarela %d.%d running\n", smbglobals.serverinfo.vmaj, smbglobals.serverinfo.vmin);
	for (;;) {
		if (netbios&& !smbbrowsesendhostannouncement(smbglobals.serverinfo.name, 60 * 1000,
			SV_TYPE_SERVER,
			smbglobals.serverinfo.remark, &e)) {
			smblogprint(-1, "hostannounce failed: %s\n", e);
		}
		if (sleep(60 * 1000) < 0)
			break;
	}
}
Пример #9
0
int
smbcheckwordcount(char *name, SmbHeader *h, uint16_t wordcount)
{
	if (h->wordcount != wordcount) {
		smblogprint(-1, "smb%s: word count not %ud\n", name, wordcount);
		return 0;
	}
	return 1;
}
Пример #10
0
SmbProcessResult
smbcomdelete(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b)
{
	SmbProcessResult pr;
	uint16_t sattr;
	uint8_t fmt;
	char *pattern = nil;
	char *dir = nil;
	char *name = nil;
	Reprog *r = nil;
	SmbTree *t;
	int x, count;
	SmbDirCache *dc = nil;

	if (h->wordcount != 1)
		return SmbProcessResultFormat;
	sattr = smbnhgets(pdata);
	if (!smbbuffergetb(b, &fmt) || fmt != 0x04
		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern))
		return SmbProcessResultFormat;
	smblogprint(SMB_COM_DELETE, "searchattributes: 0x%.4x\npattern:%s\n", sattr, pattern);
	smbpathsplit(pattern, &dir, &name);
	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		pr = SmbProcessResultError;
		goto done;
	}
	dc = smbmkdircache(t, dir);
	if (dc == nil) {
		pr = SmbProcessResultMisc;
		goto done;
	}
	r = smbmkrep(name);
	count = 0;
	for (x = 0; x < dc->n; x++) {
		if (!smbmatch(dc->buf[x].name, r))
			continue;
		if (smbremovefile(t, dir, dc->buf[x].name) == 0)
			count++;
	}
	if (count == 0) {
		smbseterror(s, ERRDOS, ERRnoaccess);
		pr = SmbProcessResultError;
	}
	else
		pr = smbbufferputack(s->response,h, &s->peerinfo);
done:
	free(pattern);
	free(dir);
	free(name);
	smbdircachefree(&dc);
	free(r);
	return pr;
}
Пример #11
0
int
smbcheckwordandbytecount(char *name, SmbHeader *h, ushort wordcount, uchar **bdatap, uchar **edatap)
{
	ushort bytecount;
	uchar *bdata;
	if (h->wordcount != wordcount) {
		smblogprint(-1, "smb%s: word count not %ud\n", name, wordcount);
		return 0;
	}
	bdata = *bdatap;
	if (bdata + 2 > *edatap) {
		smblogprint(-1, "smb%s: not enough data for byte count\n", name);
		return 0;
	}
	bytecount = smbnhgets(bdata); bdata += 2;
	if (bdata + bytecount > *edatap) {
		smblogprint(-1, "smb%s: not enough data for bytes\n", name);
		return 0;
	}
	*edatap = bdata + bytecount;
	*bdatap = bdata;
	return 1;
}
Пример #12
0
static SmbProcessResult
netsharegetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata)
{
	char *netname;
	uint16_t level;
	SmbProcessResult pr;
	SmbService *serv;

	/*
	 * zWrLh
	 * char *pszNetName, ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail
	*/

	if (!smbbuffergetstrinline(inparam, &netname)
		|| !smbbuffergets(inparam, &level)) {
	fmtfail:
		pr = SmbProcessResultFormat;
		goto done;
	}
	
	smblogprintif(smbglobals.log.rap2, "netsharegetinfo(%s, %lud, %lud)\n",
		netname, level, smbbufferwritespace(outdata));

	if (level > 2)
		goto fmtfail;

	for (serv = smbservices; serv; serv = serv->next)
		if (cistrcmp(serv->name, netname) == 0)
			break;

	if (serv == nil) {
		smblogprint(-1, "netsharegetinfo: service %s unimplemented\n", netname);
		pr = SmbProcessResultUnimp;
		goto done;
	}

	pr = onethingfill(outparam, outdata, &shareinfo, level, serv);

done:
	return pr;
}
Пример #13
0
int
smbbuffergetheader(SmbBuffer *b, SmbHeader *h, uint8_t **parametersp,
		   uint16_t *bytecountp)
{
	SmbOpTableEntry *ote;
	SmbRawHeader *rh;
	rh = (SmbRawHeader *)smbbufferreadpointer(b);
	if (!smbbuffergetbytes(b, nil, (int32_t)offsetof(SmbRawHeader, parameterwords[0]))) {
		smblogprint(-1, "smbgetheader: short packet\n");
		return 0;
	}
	if (rh->protocol[0] != 0xff || memcmp(rh->protocol + 1, "SMB", 3) != 0) {
		smblogprint(-1, "smbgetheader: invalid protocol\n");
		return 0;
	}
	h->command = rh->command;
	ote = smboptable + h->command;
	if (ote->name == nil) {
		smblogprint(-1, "smbgetheader: illegal opcode 0x%.2ux\n", h->command);
		return 0;
	}
	h->errclass = rh->status[0];
	h->error = smbnhgets(rh->status + 2);
	h->flags = rh->flags;
	h->flags2 = smbnhgets(rh->flags2);
	if (h->flags & ~(SmbHeaderFlagCaseless | SMB_FLAGS_SERVER_TO_REDIR | SmbHeaderFlagReserved | SmbHeaderFlagServerIgnore))
		smblogprint(-1, "smbgetheader: warning: unexpected flags 0x%.2ux\n", h->flags);
	h->wordcount = rh->wordcount;
	if (parametersp)
		*parametersp = smbbufferreadpointer(b);
	if (!smbbuffergetbytes(b, nil, h->wordcount * 2)) {
		smblogprint(-1, "smbgetheader: not enough data for parameter words\n");
		return 0;
	}
	h->tid = smbnhgets(rh->tid);
	h->pid = smbnhgets(rh->pid);
	h->uid = smbnhgets(rh->uid);
	h->mid = smbnhgets(rh->mid);
	if (!smbbuffergets(b, bytecountp))
		*bytecountp = 0;
	if (!smbbufferpushreadlimit(b, smbbufferreadoffset(b) + *bytecountp))
		return 0;

smblogprint(h->command, "%s %s: tid 0x%.4ux pid 0x%.4ux uid 0x%.4ux mid 0x%.4ux\n", ote->name,
	(h->flags & SMB_FLAGS_SERVER_TO_REDIR) ? "response" : "request", h->tid, h->pid, h->uid, h->mid);
	return 1;
}
Пример #14
0
SmbProcessResult
smbchaincommand(SmbSession *s, SmbHeader *h, uint32_t andxoffsetfixup,
		uint8_t cmd, uint16_t offset, SmbBuffer *b)
{
	SmbOpTableEntry *ote;
	uint8_t *pdata;
	uint16_t bytecount;

	h->command = cmd;
	ote = smboptable + cmd;
	if (ote->process == nil) {
		smblogprint(-1, "smbchaincommand: %s (0x%.2ux) not implemented\n", ote->name, cmd);
		return SmbProcessResultUnimp;
	}
	if (!smbresponsealignl2(s, 2)
		|| !smbresponseoffsetputs(s, andxoffsetfixup, smbresponseoffset(s))
		|| !smbbufferpopreadlimit(b))
		return SmbProcessResultMisc;
	if (!smbbufferreadskipto(b, offset)) {
		smblogprint(-1, "smbchaincommand: illegal offset\n");
		return SmbProcessResultFormat;
	}
	if (!smbbuffergetb(b, &h->wordcount)) {
		smblogprint(-1, "smbchaincommand: not enough space for wordcount\n");
		return SmbProcessResultFormat;
	}
	pdata = smbbufferreadpointer(b);
	if (!smbbuffergetbytes(b, nil, h->wordcount * 2)) {
		smblogprint(-1, "smbchaincommand: not enough space for parameters\n");
		return SmbProcessResultFormat;
	}
	if (!smbbuffergets(b, &bytecount)) {
		smblogprint(-1, "smbchaincommand: not enough space for bytecount\n");
		return SmbProcessResultFormat;
	}
	if (!smbbufferpushreadlimit(b, smbbufferreadoffset(b) + bytecount)) {
		smblogprint(-1, "smbchaincommand: not enough space for bytes\n");
		return SmbProcessResultFormat;
	}
smblogprint(cmd, "chaining to %s\n", ote->name);
	return (*ote->process)(s, h, pdata, b);
}
Пример #15
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;
}
Пример #16
0
SmbProcessResult
smbcomwriteandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
	uchar andxcommand;
	ushort andxoffset;
	ulong andxoffsetfixup;
	SmbTree *t;
	SmbFile *f;
	ushort dataoff, fid, count;
	vlong offset;
	long nb;

	if (h->wordcount != 12 && h->wordcount != 14)
		return SmbProcessResultFormat;

	andxcommand = *pdata++;				// andx command
	pdata++;					// reserved 
	andxoffset = smbnhgets(pdata); pdata += 2;	// andx offset
	fid = smbnhgets(pdata); pdata += 2;		// fid
	offset = smbnhgetl(pdata); pdata += 4;		// offset in file
	pdata += 4;					// timeout
	pdata += 2;					// write mode
	pdata += 2;					// (Remaining) bytes waiting to be written
	pdata += 2;					// Reserved
	count = smbnhgets(pdata); pdata += 2;		// LSBs of length
	dataoff = smbnhgets(pdata); pdata += 2;		// offset to data in packet
	if (dataoff + count > smbbufferwriteoffset(b))
		return SmbProcessResultFormat;
	if(h->wordcount == 14)
		offset |= (vlong)smbnhgetl(pdata)<<32;

	smblogprint(SMB_COM_WRITE_ANDX, "smbcomwriteandx: fid 0x%.4ux count 0x%.4ux offset 0x%.llux\n",
		fid, count, offset);


	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		return SmbProcessResultError;
	}
	f = smbidmapfind(s->fidmap, fid);
	if (f == nil) {
		smbseterror(s, ERRDOS, ERRbadfid);
		return SmbProcessResultError;
	}

	if (!f->ioallowed) {
		smbseterror(s, ERRDOS, ERRbadaccess);
		return SmbProcessResultError;
	}

	seek(f->fd, offset, 0);
	nb = write(f->fd, smbbufferpointer(b, dataoff), count);
	if (nb < 0) {
		smbseterror(s, ERRDOS, ERRnoaccess);
		return SmbProcessResultError;
	}

	h->wordcount = 6;
	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
		return SmbProcessResultMisc;

	if (!smbbufferputs(s->response, nb)			// Count
		|| !smbbufferputs(s->response, 0)		// Available
		|| !smbbufferputl(s->response, 0)		// Reserved
		|| !smbbufferputs(s->response, 0))		// byte count in reply
		return SmbProcessResultMisc;

	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
		return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);

	return SmbProcessResultReply;
}
Пример #17
0
SmbProcessResult
smbcomwrite(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
	SmbTree *t;
	SmbFile *f;
	ushort fid;
	ushort count;
	ulong offset;
	long nb;
	ushort yacount;
	uchar fmt;

	if (h->wordcount != 5)
		return SmbProcessResultFormat;

	fid = smbnhgets(pdata); pdata += 2;
	count = smbnhgets(pdata); pdata += 2;
	offset = smbnhgetl(pdata);

	smblogprint(SMB_COM_WRITE, "smbcomwrite: fid 0x%.4ux count 0x%.4ux offset 0x%.8lux\n",
		fid, count, offset);

	if (!smbbuffergetb(b, &fmt)
		|| fmt != 1
		|| !smbbuffergets(b, &yacount)
		|| yacount != count
		|| smbbufferreadspace(b) < count)
		return SmbProcessResultFormat;
	
	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		return SmbProcessResultError;
	}
	f = smbidmapfind(s->fidmap, fid);
	if (f == nil) {
		smbseterror(s, ERRDOS, ERRbadfid);
		return SmbProcessResultError;
	}
	
	if (!f->ioallowed) {
		smbseterror(s, ERRDOS, ERRbadaccess);
		return SmbProcessResultError;
	}

	if (count == 0) {
		SmbProcessResult pr = smbtruncatefile(s, f, offset);
		if (pr != SmbProcessResultReply)
			return pr;
		nb = 0;
	}
	else {
		seek(f->fd, offset, 0);
		nb = write(f->fd, smbbufferreadpointer(b), count);
		if (nb < 0) {
			smbseterror(s, ERRDOS, ERRnoaccess);
			return SmbProcessResultError;
		}
	}
	h->wordcount = 1;
	if (!smbbufferputheader(s->response, h, &s->peerinfo)
		|| !smbbufferputs(s->response, nb)
		|| !smbbufferputs(s->response, 0))
		return SmbProcessResultMisc;
	return SmbProcessResultReply;
}
Пример #18
0
SmbProcessResult
smbcomlockingandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
	uchar andxcommand;
	ushort andxoffset;
	ulong andxoffsetfixup;
	ushort fid;
	uchar locktype;
	uchar oplocklevel;
	ulong timeout;
	ushort numberofunlocks;
	ushort numberoflocks;
	SmbTree *t;
	SmbFile *f;
	int l;
	SmbProcessResult pr;
	ulong backupoffset;
	int large;

	if (!smbcheckwordcount("comlockingandx", h, 8))
		return SmbProcessResultFormat;

	andxcommand = *pdata++;
	pdata++;
	andxoffset = smbnhgets(pdata); pdata += 2;
	fid = smbnhgets(pdata); pdata += 2;
	locktype = *pdata++;
	oplocklevel = *pdata++;
	timeout = smbnhgetl(pdata); pdata += 4;
	numberofunlocks = smbnhgets(pdata); pdata += 2;
	numberoflocks = smbnhgets(pdata);
	smblogprint(h->command, "smbcomlockingandx: fid 0x%.4ux locktype 0x%.2ux oplocklevel 0x%.2ux timeout %lud numberofunlocks %d numberoflocks %ud\n",
		fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks);
	large = locktype & 0x10;
	locktype &= ~0x10;
	if (locktype != 0 || oplocklevel != 0) {
		smblogprint(-1, "smbcomlockingandx: locktype 0x%.2ux unimplemented\n", locktype);
		return SmbProcessResultUnimp;
	}
	if (oplocklevel != 0) {
		smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2ux unimplemented\n", oplocklevel);
		return SmbProcessResultUnimp;
	}
	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
	error:
		return SmbProcessResultError;
	}
	f = smbidmapfind(s->fidmap, fid);
	if (f == nil) {
		smbseterror(s, ERRDOS, ERRbadfid);
		goto error;
	}
	backupoffset = smbbufferreadoffset(b);
	for (l = 0; l < numberofunlocks; l++) {
		ushort pid;
		uvlong offset;
		uvlong length;
		if (!getlock(b, large, &pid, &offset, &length)) {
			pr = SmbProcessResultFormat;
			goto done;
		}
		smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4ux offset %llud length %llud\n",
			pid, offset, length);
		smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
	}
	for (l = 0; l < numberoflocks; l++) {
		ushort pid;
		uvlong offset;
		uvlong length;
		if (!getlock(b, large, &pid, &offset, &length)) {
			pr = SmbProcessResultFormat;
			goto done;
		}
		smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4ux offset %llud length %llud\n",
			pid, offset, length);
		if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length))
			break;
	}
	if (l < numberoflocks) {
		ushort i;
		ushort pid;
		uvlong offset;
		uvlong length;
		smbbufferreadbackup(b, backupoffset);
		for (i  = 0; i < l; i++) {
			assert(getlock(b, large, &pid, &offset, &length));
			smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length);
		}
		smbseterror(s, ERRDOS, ERRlock);
		goto error;
	}
	h->wordcount = 2;
	if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup)
		|| !smbbufferputs(s->response, 0)) {	// bytecount 0
		pr = SmbProcessResultMisc;
		goto done;
	}
	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
		pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
	else
		pr = SmbProcessResultReply;
done:
	return pr;
}
Пример #19
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;
}
Пример #20
0
SmbProcessResult
smbcomsessionsetupandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
	uchar andxcommand;
	ushort andxoffset;
	ulong andxfixupoffset;
	ushort vcnumber;
	ulong sessionkey;
	ushort caseinsensitivepasswordlength;
	ushort casesensitivepasswordlength;
	ushort bytecountfixup, offset;
	uchar *mschapreply;
	AuthInfo *ai;
	char *sp;
	SmbProcessResult pr;
	char *accountname = nil;
	char *primarydomain = nil;
	char *nativeos = nil;
	char *nativelanman = nil;

	if (!smbcheckwordcount("comsessionsetupandx", h, 13)) {
	fmtfail:
		pr = SmbProcessResultFormat;
		goto done;
	}

	andxcommand = *pdata++;
	switch (andxcommand) {
	case SMB_COM_TREE_CONNECT_ANDX:
	case SMB_COM_OPEN_ANDX:
	case SMB_COM_CREATE_NEW:
	case SMB_COM_DELETE:
	case SMB_COM_FIND:
	case SMB_COM_COPY:
	case SMB_COM_NT_RENAME:
	case SMB_COM_QUERY_INFORMATION:
	case SMB_COM_NO_ANDX_COMMAND:
	case SMB_COM_OPEN:
	case SMB_COM_CREATE:
	case SMB_COM_CREATE_DIRECTORY:
	case SMB_COM_DELETE_DIRECTORY:
	case SMB_COM_FIND_UNIQUE:
	case SMB_COM_RENAME:
	case SMB_COM_CHECK_DIRECTORY:
	case SMB_COM_SET_INFORMATION:
	case SMB_COM_OPEN_PRINT_FILE:
		break;
	default:
		smblogprint(h->command, "smbcomsessionsetupandx: invalid andxcommand %s (0x%.2ux)\n",
			smboptable[andxcommand].name, andxcommand);
		goto fmtfail;
	}
	pdata++;
	andxoffset = smbnhgets(pdata); pdata += 2;
	s->peerinfo.maxlen = smbnhgets(pdata); pdata += 2;
	smbresponseinit(s, s->peerinfo.maxlen);
	s->client.maxmpxcount = smbnhgets(pdata); pdata += 2;
	vcnumber = smbnhgets(pdata); pdata += 2;
	sessionkey = smbnhgetl(pdata); pdata += 4;
	caseinsensitivepasswordlength = smbnhgets(pdata); pdata += 2;
	casesensitivepasswordlength = smbnhgets(pdata); pdata += 2;
	pdata += 4;
	s->peerinfo.capabilities = smbnhgetl(pdata); /*pdata += 4;*/
smbloglock();
smblogprint(h->command, "andxcommand: %s offset %ud\n", smboptable[andxcommand].name, andxoffset);
smblogprint(h->command, "client.maxbuffersize: %ud\n", s->peerinfo.maxlen);
smblogprint(h->command, "client.maxmpxcount: %ud\n", s->client.maxmpxcount);
smblogprint(h->command, "vcnumber: %ud\n", vcnumber);
smblogprint(h->command, "sessionkey: 0x%.8lux\n", sessionkey);
smblogprint(h->command, "caseinsensitivepasswordlength: %ud\n", caseinsensitivepasswordlength);
smblogprint(h->command, "casesensitivepasswordlength: %ud\n", casesensitivepasswordlength);
smblogprint(h->command, "clientcapabilities: 0x%.8lux\n", s->peerinfo.capabilities);
smblogunlock();

	mschapreply = smbbufferreadpointer(b);

	if (!smbbuffergetbytes(b, nil, caseinsensitivepasswordlength + casesensitivepasswordlength)) {
		smblogprint(h->command, "smbcomsessionsetupandx: not enough bdata for passwords\n");
		goto fmtfail;
	}
	if (!smbbuffergetstring(b, h, 0, &accountname)
		|| !smbbuffergetstring(b, h, 0, &primarydomain)
		|| !smbbuffergetstring(b, h, 0, &nativeos)
		|| !smbbuffergetstring(b, h, 0, &nativelanman)) {
		smblogprint(h->command, "smbcomsessionsetupandx: not enough bytes for strings\n");
		goto fmtfail;
	}

	for (sp = accountname; *sp; sp++)
		*sp = tolower(*sp);

smblogprint(h->command, "account: %s\n", accountname);
smblogprint(h->command, "primarydomain: %s\n", primarydomain);
smblogprint(h->command, "nativeos: %s\n", nativeos);
smblogprint(h->command, "nativelanman: %s\n", nativelanman);

	if (s->client.accountname && accountname[0] && strcmp(s->client.accountname, accountname) != 0) {
		smblogprint(h->command, "smbcomsessionsetupandx: more than one user on VC (before %s, now %s)\n",
			s->client.accountname, accountname);
		smbseterror(s, ERRSRV, ERRtoomanyuids);
	errordone:
		pr = SmbProcessResultError;
		goto done;
	}

	if (s->client.accountname == nil) {
		/* first time */
		if (accountname[0] == 0) {
			smbseterror(s, ERRSRV, ERRbaduid);
			goto errordone;
		}
		if ((casesensitivepasswordlength != 24 || caseinsensitivepasswordlength != 24)) {
			smblogprint(h->command,
				"smbcomsessionsetupandx: case sensitive/insensitive password length not 24\n");
			smbseterror(s, ERRSRV, ERRbadpw);
			goto errordone;
		}
		memcpy(&s->client.mschapreply, mschapreply, sizeof(s->client.mschapreply));
		if(s->cs == nil){
			smbseterror(s, ERRSRV, ERRerror);
			goto errordone;
		}
		s->cs->user = accountname;
		s->cs->resp = &s->client.mschapreply;
		s->cs->nresp = sizeof(MSchapreply);
		ai = auth_response(s->cs);
		if (ai == nil) {
			smblogprint(h->command, "authentication failed\n");
			smbseterror(s, ERRSRV, ERRbadpw);
			goto errordone;
		}
		smblogprint(h->command, "authentication succeeded\n");
		if (auth_chuid(ai, nil) < 0) {
			smblogprint(h->command, "smbcomsessionsetupandx: chuid failed: %r\n");
			auth_freeAI(ai);
		miscerror:
			pr = SmbProcessResultMisc;
			goto done;
		}
		auth_freeAI(ai);
		h->uid = 1;
		s->client.accountname = accountname;
		s->client.primarydomain = primarydomain;
		s->client.nativeos = nativeos;
		s->client.nativelanman = nativelanman;
		accountname = nil;
		primarydomain = nil;
		nativeos = nil;
		nativelanman = nil;
	}
	else {
		if (caseinsensitivepasswordlength == 24 && casesensitivepasswordlength == 24
			&& memcmp(&s->client.mschapreply, mschapreply, sizeof(MSchapreply)) != 0) {
			smblogprint(h->command, "second time authentication failed\n");
			smbseterror(s, ERRSRV, ERRbadpw);
			goto errordone;
		}
	}

	/* CIFS says 4 with or without extended security, samba/ms says 3 without */
	h->wordcount = 3;
	if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset))
		goto miscerror;
	if (!smbresponseputs(s, 0))
		goto miscerror;
	bytecountfixup = smbresponseoffset(s);
	if (!smbresponseputs(s, 0))
		goto miscerror;
	if (!smbresponseputstring(s, 1, smbglobals.nativeos)
		|| !smbresponseputstring(s, 1, smbglobals.serverinfo.nativelanman)
		|| !smbresponseputstring(s, 1, smbglobals.primarydomain))
		goto miscerror;
	offset = smbresponseoffset(s);
	smbresponseoffsetputs(s, bytecountfixup, offset - bytecountfixup - 2);
	s->state = SmbSessionEstablished;
	if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
		pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
	else
		pr = SmbProcessResultReply;
done:
	free(accountname);
	free(primarydomain);
	free(nativeos);
	free(nativelanman);
	return pr;
}
Пример #21
0
int
smbsessionwrite(SmbSession *smbs, void *p, int32_t n)
{
	SmbHeader h;
	SmbOpTableEntry *ote;
	uint8_t *pdata;
	int rv;
	SmbBuffer *b = nil;
	uint16_t bytecount;
	SmbProcessResult pr;

	if (smbs->response == nil)
		smbs->response = smbbuffernew(576);
	else
		smbresponsereset(smbs);
	smbs->errclass = SUCCESS;
	smbs->error = SUCCESS;
//	print("received %ld bytes\n", n);
	if (n <= 0)
		goto closedown;
	b = smbbufferinit(p, p, n);
	if (!smbbuffergetheader(b, &h, &pdata, &bytecount)) {
		smblogprint(-1, "smb: invalid header\n");
		goto closedown;
	}
smbloglock();
smblogprint(h.command, "received:\n");
smblogdata(h.command, smblogprint, p, n, 0x1000);
smblogunlock();
	ote = smboptable + h.command;
	if (ote->name == nil) {
		smblogprint(-1, "smb: illegal opcode 0x%.2x\n", h.command);
		goto unimp;
	}
	if (ote->process == nil) {
		smblogprint(-1, "smb: opcode %s unimplemented\n", ote->name);
		goto unimp;
	}
	if (smbs->nextcommand != SMB_COM_NO_ANDX_COMMAND
		&& smbs->nextcommand != h.command) {
		smblogprint(-1, "smb: wrong command - expected %.2x\n", smbs->nextcommand);
		goto misc;
	}
	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
	switch (h.command) {
	case SMB_COM_NEGOTIATE:
	case SMB_COM_SESSION_SETUP_ANDX:
	case SMB_COM_TREE_CONNECT_ANDX:
	case SMB_COM_ECHO:
		break;
	default:
		if (smbs->state != SmbSessionEstablished) {
			smblogprint(-1, "aquarela: command %.2x unexpected\n", h.command);
			goto unimp;
		}
	}
	pr = (*ote->process)(smbs, &h, pdata, b);
	switch (pr) {
	case SmbProcessResultUnimp:
	unimp:
		smbseterror(smbs, ERRDOS, ERRunsup);
		pr = SmbProcessResultError;
		break;
	case SmbProcessResultFormat:
		smbseterror(smbs, ERRSRV, ERRsmbcmd);
		pr = SmbProcessResultError;
		break;
	case SmbProcessResultMisc:
	misc:
		smbseterror(smbs, ERRSRV, ERRerror);
		pr = SmbProcessResultError;
		break;
	case SmbProcessResultOk:
	case SmbProcessResultError:
	case SmbProcessResultReply:
	case SmbProcessResultDie:
		break;
	}
	if (pr == SmbProcessResultError) {
		smblogprint(h.command, "reply: error %d/%d\n", smbs->errclass, smbs->error);
		if (!smbresponseputerror(smbs, &h, smbs->errclass, smbs->error))
			pr = SmbProcessResultDie;
		else
			pr = SmbProcessResultReply;
	}
	else
		smblogprint(h.command, "reply: ok\n");
	if (pr == SmbProcessResultReply)
		rv = smbresponsesend(smbs) == SmbProcessResultOk ? 0 : -1;
	else if (pr == SmbProcessResultDie)
		rv = -1;
	else
		rv = 0;
	goto done;
closedown:
	rv = -1;
done:
	if (rv < 0) {
		smblogprintif(smbglobals.log.sessions, "shutting down\n");
		smbsessionfree(smbs);
	}
	smbbufferfree(&b);
	if (smbglobals.log.poolparanoia)
		poolcheck(mainmem);
	return rv;
}
Пример #22
0
SmbProcessResult
smbcomtreeconnectandx(SmbSession *s, SmbHeader *h, uint8_t *pdata,
                      SmbBuffer *b)
{
    uint8_t andxcommand;
    uint16_t andxoffset;
    char *path = nil;
    char *service = nil;
    uint16_t flags;
    uint16_t passwordlength;
//	ushort bytecount;
    uint8_t errclass;
    uint16_t error;
    SmbService *serv;
    SmbTree *tree;
    uint32_t andxfixupoffset, bytecountfixup;
    SmbProcessResult pr;

    if (!smbcheckwordcount("comtreeconnectandx", h, 4)) {
fmtfail:
        pr = SmbProcessResultFormat;
        goto done;
    }

    switch (s->state) {
    case SmbSessionNeedNegotiate:
        smblogprint(-1, "smbcomtreeconnectandx: called when negotiate expected\n");
        return SmbProcessResultUnimp;
    case SmbSessionNeedSetup:
        smbseterror(s, ERRDOS, ERRbadpw);
        return SmbProcessResultError;
    }

    andxcommand = *pdata++;
    switch (andxcommand) {
    case SMB_COM_OPEN:
    case SMB_COM_CREATE_NEW:
    case SMB_COM_DELETE_DIRECTORY:
    case SMB_COM_FIND_UNIQUE:
    case SMB_COM_CHECK_DIRECTORY:
    case SMB_COM_GET_PRINT_QUEUE:
    case SMB_COM_TRANSACTION:
    case SMB_COM_SET_INFORMATION:
    case SMB_COM_OPEN_ANDX:
    case SMB_COM_CREATE_DIRECTORY:
    case SMB_COM_FIND:
    case SMB_COM_RENAME:
    case SMB_COM_QUERY_INFORMATION:
    case SMB_COM_OPEN_PRINT_FILE:
    case SMB_COM_NO_ANDX_COMMAND:
    case SMB_COM_NT_RENAME:
    case SMB_COM_CREATE:
    case SMB_COM_DELETE:
    case SMB_COM_COPY:
        break;
    default:
        smblogprint(h->command, "smbcomtreeconnectandx: invalid andxcommand %s (0x%.2ux)\n",
                    smboptable[andxcommand].name, andxcommand);
        goto fmtfail;
    }
    pdata++;
    andxoffset = smbnhgets(pdata);
    pdata += 2;
    flags = smbnhgets(pdata);
    pdata += 2;
    passwordlength = smbnhgets(pdata); //pdata += 2;
//	bytecount = smbnhgets(pdata); pdata += 2;
    smblogprint(h->command, "passwordlength: %ud\n", passwordlength);
    smblogprint(h->command, "flags: 0x%.4ux\n", flags);
    if (!smbbuffergetbytes(b, nil, passwordlength)) {
        smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for password\n");
        goto fmtfail;
    }
    smblogprint(h->command, "offset %lud limit %lud\n", smbbufferreadoffset(b), smbbufferwriteoffset(b));
    if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path)
            || !smbbuffergetstr(b, 0, &service)) {
        smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for strings\n");
        goto fmtfail;
    }
    smblogprint(h->command, "path: %s\n", path);
    smblogprint(h->command, "service: %s\n", service);
    if (flags & 1)
        smbtreedisconnectbyid(s, h->tid);
    serv = smbservicefind(s, path, service, &errclass, &error);
    if (serv == nil) {
        pr = SmbProcessResultError;
        smbseterror(s, errclass, error);
        goto done;
    }
    tree = smbtreeconnect(s, serv);
    h->tid = tree->id;
    h->wordcount = 3;
    if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset)
            || !smbresponseputs(s, 1)) {
misc:
        pr = SmbProcessResultMisc;
        goto done;
    }
    bytecountfixup = smbresponseoffset(s);
    if (!smbresponseputs(s, 0)
            || !smbresponseputstr(s, serv->type)
            || !smbresponseputstring(s, 1, s9p2000))
        goto misc;
    if (!smbbufferfixuprelatives(s->response, bytecountfixup))
        goto misc;
    if (andxcommand != SMB_COM_NO_ANDX_COMMAND) {
        pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b);
    }
    else
        pr = SmbProcessResultReply;
done:
    free(path);
    free(service);
    return pr;
}
Пример #23
0
SmbProcessResult
smbtrans2setfileinformation(SmbSession *s, SmbHeader *h)
{
	SmbTree *t;
	ushort infolevel;
	SmbBuffer *b;
	SmbProcessResult pr;
	ushort fid;
	SmbFile *f;
	vlong newsize;
	uvlong atime, mtime;
	ulong attr;
	ulong mode;

	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);
	if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
	misc:
		pr = SmbProcessResultMisc;
		goto done;
	}

	f = smbidmapfind(s->fidmap, fid);
	if (f == nil) {
		smbseterror(s, ERRDOS, ERRbadfid);
		pr = SmbProcessResultError;
		goto done;
	}

	switch (infolevel) {
	case SMB_SET_FILE_ALLOCATION_INFO:
	case SMB_SET_FILE_END_OF_FILE_INFO:
		if (s->transaction.in.tdcount < 8)
			goto misc;
		newsize = smbnhgetv(s->transaction.in.data);
		pr = smbtruncatefile(s, f, newsize);
		if (pr == SmbProcessResultReply && !smbbufferputs(s->transaction.out.parameters, 0))
			goto misc;
		break;

	case SMB_SET_FILE_BASIC_INFO:
		if (s->transaction.in.tdcount < 4 * 8 + 4)
			goto misc;
		atime = smbnhgetv(s->transaction.in.data + 8);
		mtime = smbnhgetv(s->transaction.in.data + 24);
		attr = smbnhgetv(s->transaction.in.data + 32);
		if (attr) {
			Dir *od = dirfstat(f->fd);
			if (od == nil)
				goto noaccess;
			mode = smbdosattr2plan9wstatmode(od->mode, attr);
			free(od);
		}
		else
			mode = 0xffffffff;
		if (atime || mtime || mode != 0xffffffff) {
			Dir d;
			memset(&d, 0xff, sizeof(d));
			d.name = d.uid = d.gid = d.muid = nil;
			if (atime)
				d.atime = smbtime2plan9time(atime);
			if (mtime)
				d.mtime = smbtime2plan9time(mtime);
			d.mode = mode;
			if (dirfwstat(f->fd, &d) < 0) {
			noaccess:
				smbseterror(s, ERRDOS, ERRnoaccess);
				pr = SmbProcessResultError;
				goto done;
			}
		}
		if (!smbbufferputs(s->transaction.out.parameters, 0))
			goto misc;
		pr = SmbProcessResultReply;
		break;

	case SMB_SET_FILE_DISPOSITION_INFO:
		if (s->transaction.in.tdcount < 1)
			goto misc;
		f->sf->deleteonclose = *s->transaction.in.data;
		if (!smbbufferputs(s->transaction.out.parameters, 0))
			goto misc;
		pr = SmbProcessResultReply;
		break;

	default:
		smblogprint(-1, "smbtrans2setfileinformation: infolevel 0x%.4ux not implemented\n", infolevel);
		smbseterror(s, ERRDOS, ERRunknownlevel);
		pr = SmbProcessResultError;
		break;
	}
done:
	smbbufferfree(&b);
	return pr;
}
Пример #24
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;
}
Пример #25
0
SmbProcessResult
smbnegotiate(SmbSession *s, SmbHeader *h, uchar *, SmbBuffer *b)
{
	ushort index;
	int i;
	uchar bufferformat;

	if (!smbcheckwordcount("negotiate", h, 0))
		return SmbProcessResultFormat;
	if (s->state != SmbSessionNeedNegotiate) {
		/* this acts as a complete session reset */
		smblogprint(-1, "smbnegotiate: called when already negotiated\n");
		return SmbProcessResultUnimp;
	}
	i = 0;
	index = 0xffff;
	while (smbbuffergetb(b, &bufferformat)) {
		char *s;
		if (bufferformat != 0x02) {
			smblogprint(-1, "smbnegotiate: unrecognised buffer format 0x%.2ux\n", bufferformat);
			return SmbProcessResultFormat;
		}
		if (!smbbuffergetstr(b, 0, &s)) {
			smblogprint(-1, "smbnegotiate: no null found\n");
			return SmbProcessResultFormat;
		}
		smblogprint(h->command, "smbnegotiate: '%s'\n", s);
		if (index == 0xffff && strcmp(s, "NT LM 0.12") == 0)
			index = i;
		i++;
		free(s);
	}
	if (index != 0xffff) {
		Tm *tm;
		ulong capabilities;
		ulong bytecountfixupoffset;

		h->wordcount = 17;
		if (!smbbufferputheader(s->response, h, nil)
			|| !smbbufferputs(s->response, index)
			|| !smbbufferputb(s->response, 3)			/* user security, encrypted */
			|| !smbbufferputs(s->response, 1)			/* max mux */
			|| !smbbufferputs(s->response, 1)			/* max vc */
			|| !smbbufferputl(s->response, smbglobals.maxreceive)		/* max buffer size */
			|| !smbbufferputl(s->response, 0x10000)		/* max raw */
			|| !smbbufferputl(s->response, threadid()))	/* session key */
			goto die;
		/* <= Win2k insist upon this being set to ensure that they observe the prototol (!) */
		capabilities = CAP_NT_SMBS;
		if (smbglobals.unicode)
			capabilities |= CAP_UNICODE;
		tm = localtime(time(nil));
		s->tzoff = tm->tzoff;
		if (!smbbufferputl(s->response, capabilities)
			|| !smbbufferputv(s->response, nsec() / 100 + (vlong)10000000 * 11644473600LL)
			|| !smbbufferputs(s->response, -s->tzoff / 60)
			|| !smbbufferputb(s->response, 8))	/* crypt len */
			goto die;
		bytecountfixupoffset = smbbufferwriteoffset(s->response);
		if (!smbbufferputs(s->response, 0))
			goto die;
		s->cs = auth_challenge("proto=mschap role=server");
		if (s->cs == nil) {
			smblogprint(h->command, "smbnegotiate: couldn't get mschap challenge\n");
			return SmbProcessResultMisc;
		}
		if (s->cs->nchal != 8) {
			smblogprint(h->command, "smbnegotiate: nchal %d\n", s->cs->nchal);
			return SmbProcessResultMisc;
		}
		if (!smbbufferputbytes(s->response, s->cs->chal, s->cs->nchal)
			|| !smbbufferputstring(s->response, nil, SMB_STRING_UNICODE, smbglobals.primarydomain)
			|| !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
			goto die;
	}
	else {
		h->wordcount = 1;
		if (!smbbufferputheader(s->response, h, nil)
			|| !smbbufferputs(s->response, index)
			|| !smbbufferputs(s->response, 0))
			goto die;
	}
	s->state = SmbSessionNeedSetup;
	return SmbProcessResultReply;
die:
	return SmbProcessResultDie;
}
Пример #26
0
SmbProcessResult
smbtrans2findnext2(SmbSession *s, SmbHeader *h)
{
	SmbBuffer *b;
	int debug;
	ushort sid, scount, infolevel;
	ulong resumekey;
	ushort flags;
	char *filename = nil;
	SmbProcessResult pr;
	ushort e;
	ulong nameoffset;
	ushort eos;
	SmbTree *t;
	SmbSearch *search;

	debug = smboptable[h->command].debug
		|| smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug
		|| smbglobals.log.find;
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
	if (!smbbuffergets(b, &sid)
		|| !smbbuffergets(b, &scount)
		|| !smbbuffergets(b, &infolevel)
		|| !smbbuffergetl(b, &resumekey)
		|| !smbbuffergets(b, &flags)
		|| !smbbuffergetstring(b, h, 0, &filename)) {
		pr = SmbProcessResultFormat;
		goto done;
	}
	smblogprintif(debug,
		"smbtrans2findnext2: sid %d scount %d infolevel 0x%.4ux resumekey %lud flags 0x%.4ux filename %s\n",
		sid, scount, infolevel, resumekey, flags, filename);

	if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
		smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4ux not implemented\n", infolevel);
		smbseterror(s, ERRDOS, ERRunknownlevel);
		pr = SmbProcessResultError;
		goto done;
	}

	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		pr = SmbProcessResultError;
		goto done;
	}

	search = smbidmapfind(s->sidmap, sid);
	if (search == nil) {
		smbseterror(s, ERRDOS, ERRnofiles);
		pr = SmbProcessResultError;
		goto done;
	}

	if (search->t != t) {
		smbseterror(s, ERRSRV, ERRinvtid);
		pr = SmbProcessResultError;
		goto done;
	}

	if ((flags & (1 << 3)) == 0) {
		long i;
		if (filename == nil) {
			smbseterror(s, ERRDOS, ERRnofiles);
			pr = SmbProcessResultError;
			goto done;
		}
		for (i = 0; i < search->dc->n; i++)
			if (strcmp(search->dc->buf[i].name, filename) == 0) {
				search->dc->i = i + 1;
				break;
			}
	}

	populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset);
	
	eos = search->dc->i >= search->dc->n;
	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
		smbsearchclose(s, search);
	smbbufferputs(s->transaction.out.parameters, e);
	smbbufferputs(s->transaction.out.parameters, eos);
	smbbufferputs(s->transaction.out.parameters, 0);
	smbbufferputs(s->transaction.out.parameters, nameoffset);
	pr = SmbProcessResultReply;
done:
	smbbufferfree(&b);
	free(filename);
	return pr;
}
Пример #27
0
SmbProcessResult
smbtrans2findfirst2(SmbSession *s, SmbHeader *h)
{
	SmbBuffer *b;
	char *pattern = nil;
	char *dir = nil;
	char *name = nil;
	ushort searchattributes, searchcount, flags, informationlevel;
	ulong searchstoragetype;
	SmbDirCache *dc = nil;
	ushort e;
	ulong nameoffset;
	ushort eos;
	SmbSearch *search;
	SmbProcessResult pr;
	Reprog *r = nil;
	SmbTree *t;
	int debug;

	debug = smboptable[h->command].debug
		|| smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug
		|| smbglobals.log.find;
poolcheck(mainmem);
	b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
	if (!smbbuffergets(b, &searchattributes)
		|| !smbbuffergets(b, &searchcount)
		|| !smbbuffergets(b, &flags)
		|| !smbbuffergets(b, &informationlevel)
		|| !smbbuffergetl(b, &searchstoragetype)
		|| !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) {
		pr = SmbProcessResultFormat;
		goto done;
	}
	smbloglock();
	smblogprintif(debug, "searchattributes: 0x%.4ux\n", searchattributes);
	smblogprintif(debug, "searchcount: 0x%.4ux\n", searchcount);
	smblogprintif(debug, "flags: 0x%.4ux\n", flags);
	smblogprintif(debug, "informationlevel: 0x%.4ux\n", informationlevel);
	smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype);
	smblogprintif(debug, "pattern: %s\n", pattern);
	smblogunlock();
	smbpathsplit(pattern, &dir, &name);
	if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
		smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4ux not implemented\n", informationlevel);
		smbseterror(s, ERRDOS, ERRunknownlevel);
		pr = SmbProcessResultError;
		goto done;
	}

	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		pr = SmbProcessResultError;
		goto done;
	}

	dc = smbmkdircache(t, dir);
	if (dc == nil) {
		smbseterror(s, ERRDOS, ERRnoaccess);
		pr = SmbProcessResultError;
		goto done;
	}
poolcheck(mainmem);
	r = smbmkrep(name);
	populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset);
poolcheck(mainmem);
	eos = dc->i >= dc->n;
	if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos))
		smbdircachefree(&dc);
poolcheck(mainmem);
	if (dc) {
		/* create a search handle */
		search = smbsearchnew(s, dc, r, t);
		r = nil;
		dc = nil;
	}
	else
		search = nil;
	smbbufferputs(s->transaction.out.parameters, search ? search->id : 0);
	smbbufferputs(s->transaction.out.parameters, e);
	smbbufferputs(s->transaction.out.parameters, eos);
	smbbufferputs(s->transaction.out.parameters, 0);
	smbbufferputs(s->transaction.out.parameters, nameoffset);
	pr = SmbProcessResultReply;
done:
	smbbufferfree(&b);
	free(pattern);
	free(dir);
	free(name);
	smbdircachefree(&dc);
	free(r);
	return pr;
}
Пример #28
0
SmbProcessResult
smbcomsetinformation2(SmbSession *s, SmbHeader *h, uint8_t *pdata,
		      SmbBuffer *)
{
	uint16_t fid, adate, atime, mdate, mtime;
	SmbTree *t;
	SmbFile *f;
	Dir d;

	if (h->wordcount != 7)
		return SmbProcessResultFormat;
	fid = smbnhgets(pdata);
	adate = smbnhgets(pdata + 6);
	atime = smbnhgets(pdata + 8);
	mdate = smbnhgets(pdata + 10);
	mtime = smbnhgets(pdata + 12);
	smblogprint(h->command,
		"smbcomsetinformation2: fid 0x%.4ux adate 0x%.4ux atime 0x%.4ux mdate 0x%.4ux mtime 0x%.4ux\n",
		fid, adate, atime, mdate, mtime);
	t = smbidmapfind(s->tidmap, h->tid);
	if (t == nil) {
		smbseterror(s, ERRSRV, ERRinvtid);
		return SmbProcessResultError;
	}
	f = smbidmapfind(s->fidmap, fid);
	if (f == nil) {
		smbseterror(s, ERRDOS, ERRbadfid);
		return SmbProcessResultError;
	}
	memset(&d, 0xff, sizeof(d));
	d.name = d.uid = d.gid = d.muid = nil;
	if (adate || atime || mdate || mtime) {
//smblogprint(-1, "smbcomsetinformation2: changing times not implemented\n");
//		return SmbProcessResultUnimp;
		/* something to change */
		if (!(adate && atime && mdate && mtime)) {
			/* some null entries */
			uint16_t odate, otime;
			Dir *od = dirfstat(f->fd);
			if (od == nil) {
				smbseterror(s, ERRDOS, ERRnoaccess);
				return SmbProcessResultError;
			}
			if (adate || atime) {
				/* something changed in access time */
				if (!(adate && atime)) {
					/* some nulls in access time */
					smbplan9time2datetime(d.atime, s->tzoff, &odate, &otime);
					if (adate == 0)
						adate = odate;
					if (atime == 0)
						atime = otime;
				}
				d.atime = smbdatetime2plan9time(adate, atime, s->tzoff);
			}
			if (mdate || mtime) {
				/* something changed in modify time */
				if (!(mdate && mtime)) {
					/* some nulls in modify time */
					smbplan9time2datetime(d.mtime, s->tzoff, &odate, &otime);
					if (mdate == 0)
						mdate = odate;
					if (mtime == 0)
						mtime = otime;
				}
				d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff);
			}
			free(od);
		}
		if (dirfwstat(f->fd, &d) < 0) {
			smbseterror(s, ERRDOS, ERRnoaccess);
			return SmbProcessResultError;
		}
	}
	return smbbufferputack(s->response, h, &s->peerinfo);
}