Пример #1
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);
}
Пример #2
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;
}
Пример #3
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);
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
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;
}