Пример #1
0
SmbProcessResult
smbcomflush(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *)
{
	SmbTree *t;
	SmbFile *f;
	ushort fid;
	Dir nulldir;
	if (h->wordcount != 1)
		return SmbProcessResultFormat;
	fid = smbnhgets(pdata);
	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(&nulldir, 0xff, sizeof(nulldir));
	nulldir.name = nulldir.uid = nulldir.gid = nulldir.muid = nil;
	dirfwstat(f->fd, &nulldir);
	return smbbufferputack(s->response, h, &s->peerinfo);
}
Пример #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
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #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
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;
}
Пример #8
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);
}
Пример #9
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;
}
Пример #10
0
void
smbsearchclosebyid(SmbSession *s, ushort sid)
{
	smbsearchclose(s,  smbidmapfind(s->sidmap, sid));
}
Пример #11
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;
}
Пример #12
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;
}