Esempio n. 1
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;
}
Esempio n. 2
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);
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}