Пример #1
0
static int
findbothflatten(SmbBuffer *b, SmbPeerInfo *p, Dir *d, ulong resumekey, ulong *nameoffsetp)
{
	vlong mtime, atime;
	ulong fixup;

	fixup = smbbufferwriteoffset(b);
	mtime = smbplan9time2time(d->mtime);
	atime = smbplan9time2time(d->atime);
poolcheck(mainmem);
	if (!smbbufferputl(b, 0)
		|| !smbbufferputl(b, resumekey)
		|| !smbbufferputv(b, mtime)
		|| !smbbufferputv(b, atime)
		|| !smbbufferputv(b, mtime)
		|| !smbbufferputv(b, mtime)
		|| !smbbufferputv(b, d->length)
		|| !smbbufferputv(b, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))			// ha
		|| !smbbufferputl(b, (d->qid.type & QTDIR) ? 0x10 : 0x80)
		|| !smbbufferputl(b, smbstringlen(p, d->name))
		|| !smbbufferputl(b, 0)
		|| !smbbufferputb(b, 0)
		|| !smbbufferputb(b, 0)
		|| !smbbufferfill(b, 0, 24))
		return 0;
poolcheck(mainmem);
	*nameoffsetp = smbbufferwriteoffset(b);
	if (!smbbufferputstring(b, p, 0, d->name) || !smbbufferalignl2(b, 2))
		return 0;
poolcheck(mainmem);
	return smbbufferfixuprelativeinclusivel(b, fixup);
}
Пример #2
0
static int
standardflatten(SmbSession *s, SmbBuffer *b, Dir *d, ulong *nameoffsetp)
{
	ushort mdate, mtime;
	ushort adate, atime;
	ushort fnlfixupoffset;

	smbplan9time2datetime(d->mtime, s->tzoff, &mdate, &mtime);
	smbplan9time2datetime(d->atime, s->tzoff, &adate, &atime);
	if (!smbbufferputs(b, mdate)
		|| !smbbufferputs(b, mtime)
		|| !smbbufferputs(b, adate)
		|| !smbbufferputs(b, atime)
		|| !smbbufferputs(b, mdate)
		|| !smbbufferputs(b, mtime)
		|| !smbbufferputl(b, d->length)
		|| !smbbufferputl(b, 512)			// ha
		|| !smbbufferputs(b, (d->qid.type & QTDIR) ? 0x10 : 0))
		return 0;
	fnlfixupoffset = smbbufferwriteoffset(b);
	if (!smbbufferputs(b, 0))
		return 0;
	*nameoffsetp = smbbufferwriteoffset(b);
	if (!smbbufferputstring(b, &s->peerinfo, 0, d->name))
		return 0;
	return smbbufferfixuprelatives(b, fnlfixupoffset);
}
Пример #3
0
int
smbclientopen(SmbClient *c, uint16_t mode, char *name, uint8_t *errclassp,
	      uint16_t *errorp,
	uint16_t *fidp, uint16_t *attrp, uint32_t *mtimep, uint32_t *sizep,
	      uint16_t *accessallowedp, char **errmsgp)
{
	SmbBuffer *b;
	SmbHeader h;
	uint32_t bytecountfixup;
	int32_t n;
	uint8_t *pdata;
	uint16_t bytecount;

	b = smbbuffernew(65535);
	h = c->protoh;
	h.tid = c->sharetid;
	h.command = SMB_COM_OPEN;
	h.wordcount = 2;
	smbbufferputheader(b, &h, &c->peerinfo);
	smbbufferputs(b, mode);
	smbbufferputs(b, 0);
	bytecountfixup = smbbufferwriteoffset(b);
	smbbufferputs(b, 0);
	smbbufferputb(b, 4);
	smbbufferputstring(b, &c->peerinfo, SMB_STRING_REVPATH, name);
	smbbufferfixuprelatives(b, bytecountfixup);
	nbsswrite(c->nbss, smbbufferreadpointer(b), smbbufferwriteoffset(b));
	smbbufferreset(b);
	n = nbssread(c->nbss, smbbufferwritepointer(b), smbbufferwritespace(b));
	if (n < 0) {
		smbstringprint(errmsgp, "read error: %r");
		smbbufferfree(&b);
		return 0;
	}
	smbbuffersetreadlen(b, n);
	if (!smbbuffergetandcheckheader(b, &h, h.command, 7, &pdata, &bytecount, errmsgp)) {
		smbbufferfree(&b);
		return 0;
	}
	if (h.errclass) {
		*errclassp = h.errclass;
		*errorp = h.error;
		smbbufferfree(&b);
		return 0;
	}
	*fidp = smbnhgets(pdata); pdata += 2;
	*attrp = smbnhgets(pdata); pdata += 2;
	*mtimep = smbnhgetl(pdata); pdata += 4;
	*sizep = smbnhgets(pdata); pdata += 4;
	*accessallowedp = smbnhgets(pdata);
	return 1;
}
Пример #4
0
int
decoderesponse(SmbTransaction *t, Args *a, SmbBuffer *b, char **errmsgp)
{
	if (t->out.tpcount > smbbufferwritemaxoffset(t->out.parameters)) {
		smbstringprint(errmsgp, "decoderesponse: too many parameters for buffer");
		return 0;
	}
	if (t->out.tdcount > smbbufferwritemaxoffset(t->out.data)) {
		smbstringprint(errmsgp, "decoderesponse: too much data for buffer");
		return 0;
	}
	if (a->pdisplacement + a->pcount > t->out.tpcount) {
		smbstringprint(errmsgp, "decoderesponse: more parameters than tpcount");
		return 0;
	}
	if (a->pdisplacement != smbbufferwriteoffset(t->out.parameters)) {
		smbstringprint(errmsgp, "decoderesponse: parameter displacement inconsistent");
		return 0;
	}
	if (a->ddisplacement + a->dcount > t->out.tdcount) {
		smbstringprint(errmsgp, "decoderesponse: more data than tdcount");
		return 0;
	}
	if (a->ddisplacement != smbbufferwriteoffset(t->out.data)) {
		smbstringprint(errmsgp, "decoderesponse: data displacement inconsistent");
		return 0;
	}
	assert(a->scount == 0);
	if (a->pcount) {
		if (!smbbufferreadskipto(b, a->poffset)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid parameter offset");
			return 0;
		}
		if (!smbbuffercopy(t->out.parameters, b, a->pcount)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for parameters");
			return 0;
		}
	}
	if (a->dcount) {
		if (!smbbufferreadskipto(b, a->doffset)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: invalid data offset");
			return 0;
		}
		if (!smbbuffercopy(t->out.data, b, a->dcount)) {
			smbstringprint(errmsgp, "smbtransactiondecoderesponse: not enough data for data");
			return 0;
		}
	}
	return 1;
}
Пример #5
0
int
smbbufferputheader(SmbBuffer *b, SmbHeader *h, SmbPeerInfo *p)
{
	SmbRawHeader *rh;
	if (offsetof(SmbRawHeader, parameterwords[0]) > smbbufferwritespace(b))
		return 0;
	if (smbbufferwriteoffset(b) == 0) {
		rh = (SmbRawHeader *)smbbufferwritepointer(b);
		rh->protocol[0] = 0xff;
		memcpy(rh->protocol + 1, "SMB", 3);
		rh->flags = SMB_FLAGS_SERVER_TO_REDIR | SmbHeaderFlagCaseless;
		rh->command = h->command;
		smbhnputs(rh->flags2, BASE_FLAGS | (smbsendunicode(p) ? SMB_FLAGS2_UNICODE : 0));
		memset(rh->extra, 0, sizeof(rh->extra));
		if (!smbbufferputbytes(b, nil, offsetof(SmbRawHeader, parameterwords[0])))
			return 0;
		rh->wordcount = h->wordcount;
	}
	else {
		rh = (SmbRawHeader *)smbbufferreadpointer(b);
		smbbufferputb(b, h->wordcount);
	}
	rh->status[0] = h->errclass;
	rh->status[1] = 0;
	smbhnputs(rh->status + 2, h->error);
	smbhnputs(rh->tid, h->tid);
	smbhnputs(rh->pid, h->pid);
	smbhnputs(rh->uid, h->uid);
	smbhnputs(rh->mid, h->mid);
	return 1;
}
Пример #6
0
int
smbbufferputandxheader(SmbBuffer *b, SmbHeader *h, SmbPeerInfo *p, uchar andxcommand, ulong *andxoffsetfixupp)
{
	if (!smbbufferputheader(b, h, p)
		|| !smbbufferputb(b, andxcommand)
		|| !smbbufferputb(b, 0))
		return 0;
	*andxoffsetfixupp = smbbufferwriteoffset(b);
	return smbbufferputbytes(b, nil, 2);
}
Пример #7
0
static void
populate(SmbSession *s, SmbDirCache *dc, Reprog *r, ushort informationlevel, ushort flags, ushort scount,
	ushort *ep, ulong *nameoffsetp)
{
	ushort e;
	ulong nameoffset;
	e = 0;
	nameoffset = 0;
	while (dc->i < dc->n && e < scount) {
		ulong backup;
		int rv;
		
		if (!smbmatch(dc->buf[dc->i].name, r)) {
			dc->i++;
			continue;
		}
		rv = 0;
		backup = smbbufferwriteoffset(s->transaction.out.data);
		switch (informationlevel) {
		case SMB_INFO_STANDARD:
			if (flags & SMB_FIND_RETURN_RESUME_KEYS) {
				if (!smbbufferputl(s->transaction.out.data, dc->i)) {
					rv = 0;
					break;
				}
			}
			rv = standardflatten(s, s->transaction.out.data, dc->buf + dc->i, &nameoffset);
			break;
		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
			rv = findbothflatten(s->transaction.out.data, &s->peerinfo, dc->buf + dc->i, dc->i, &nameoffset);
			break;
		}
		if (rv == 0) {
			smbbufferwritebackup(s->transaction.out.data, backup);
			break;
		}
		dc->i++;
		e++;
	}
	*ep = e;
	*nameoffsetp = nameoffset;
}
Пример #8
0
SmbProcessResult
smbcomecho(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
	ushort echocount, e;
	if (!smbcheckwordcount("comecho", h, 1))
		return SmbProcessResultFormat;
	echocount = smbnhgets(pdata);
	for (e = 0; e < echocount; e++) {
		ulong bytecountfixupoffset;
		SmbProcessResult pr;
		if (!smbbufferputheader(s->response, h, &s->peerinfo)
			|| !smbbufferputs(s->response, e))
			return SmbProcessResultMisc;
		bytecountfixupoffset = smbbufferwriteoffset(s->response);
		if (!smbbufferputbytes(s->response, smbbufferreadpointer(b), smbbufferreadspace(b))
			|| !smbbufferfixuprelatives(s->response, bytecountfixupoffset))
			return SmbProcessResultMisc;
		pr = smbresponsesend(s);
		if (pr != SmbProcessResultOk)
			return SmbProcessResultDie;
	}
	return SmbProcessResultOk;
}
Пример #9
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;
}
Пример #10
0
ushort
smbresponseoffset(SmbSession *s)
{
	return smbbufferwriteoffset(s->response);
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
0
int
smbtransactionexecute(SmbTransaction *t, SmbHeader *h, SmbPeerInfo *p, SmbBuffer *iob, SmbTransactionMethod *method, void *magic, SmbHeader *rhp,
		      char **errmsgp)
{
	uint8_t sentwordcount;
	uint16_t sentbytecount;
	SmbHeader rh;
	smbbufferreset(iob);
	if (!(*method->encodeprimary)(t, h, p, iob, &sentwordcount, &sentbytecount, errmsgp))
		return 0;
//	smblogprint(-1, "sent...\n");
//	smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
	if (!(*method->sendrequest)(magic, iob, errmsgp))
		return 0;
	if (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount) {
		uint8_t wordcount;
		uint16_t bytecount;
		/* secondary needed */
		if (method->encodesecondary == nil || method->receiveintermediate == nil) {
			smbstringprint(errmsgp, "buffer too small and secondaries not allowed");
			return 0;
		}
		if (!(*method->receiveintermediate)(magic, &wordcount, &bytecount, errmsgp))
			return 0;
		if (sentwordcount != wordcount || sentbytecount != bytecount) {
			smbstringprint(errmsgp, "server intermediate reply counts differ");
			return 0;
		}
		do {
			if (!(*method->encodesecondary)(t, h, iob, errmsgp))
				return 0;
			if (!(*method->sendrequest)(magic, iob, errmsgp))
				return 0;
		} while (t->in.pcount < t->in.tpcount || t->in.dcount < t->in.tdcount);
	}
	if (method->receiveresponse == nil || method->decoderesponse == nil)
		return 1;
	do {
		uint8_t *pdata;
		uint16_t bytecount;

		if (!(*method->receiveresponse)(magic, iob, errmsgp))
			return 0;
		if (!smbbuffergetheader(iob, &rh, &pdata, &bytecount)) {
			smbstringprint(errmsgp, "smbtransactionexecute: invalid response header");
			return 0;
		}
		if (!smbcheckheaderdirection(&rh, 1, errmsgp))
			return 0;
		if (rh.errclass != SUCCESS) {
			smbstringprint(errmsgp, "smbtransactionexecute: remote error %d/%d", rh.errclass, rh.error);
			return 0;
		}
		if (!smbbuffertrimreadlen(iob, bytecount)) {
			smbstringprint(errmsgp, "smbtransactionexecute: invalid bytecount");
			return 0;
		}
//		smblogprint(-1, "received...\n");
//		smblogdata(-1, smblogprint, smbbufferreadpointer(iob), smbbufferreadspace(iob));
		if (!(*method->decoderesponse)(t, &rh, pdata, iob, errmsgp))
			return 0;
	} while (smbbufferwriteoffset(t->out.parameters) < t->out.tpcount || smbbufferwriteoffset(t->out.data) < t->out.tdcount);
	if (rhp)
		*rhp = rh;
	return 1;
}
Пример #14
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;
}
Пример #15
0
static int
_transactionencodeprimary(SmbTransaction *t, uint8_t cmd, SmbHeader *h,
			  SmbPeerInfo *p, SmbBuffer *ob,
	uint8_t *wordcountp, uint16_t *bytecountp, char **errmsgp)
{
	SmbHeader mh;
	uint32_t countsfixupoffset, bytecountfixupoffset;
	int x;
	mh = *h;
	*wordcountp = mh.wordcount = 14 + t->in.scount;
	mh.flags &= ~SMB_FLAGS_SERVER_TO_REDIR;
	mh.command = cmd;
	if (!smbbufferputheader(ob, &mh, p)) {
	toosmall:
		smbstringprint(errmsgp, "output buffer too small");
		return 0;
	}
	if (t->in.tpcount > 65535 || t->in.tdcount > 65535 || t->in.maxpcount > 65535 || t->in.maxdcount > 65535) {
		smbstringprint(errmsgp, "counts too big");
		return 0;
	}
	if (!smbbufferputs(ob, t->in.tpcount)
		|| !smbbufferputs(ob, t->in.tdcount)
		|| !smbbufferputs(ob, t->in.maxpcount)
		|| !smbbufferputs(ob, t->in.maxdcount)
		|| !smbbufferputb(ob, t->in.maxscount)
		|| !smbbufferputb(ob, 0)
		|| !smbbufferputs(ob, t->in.flags)
		|| !smbbufferputl(ob, 0)
		|| !smbbufferputs(ob, 0))
		goto toosmall;
	countsfixupoffset = smbbufferwriteoffset(ob);
	if (!smbbufferputs(ob, 0)
		|| !smbbufferputs(ob, 0)
		|| !smbbufferputs(ob, 0)
		|| !smbbufferputs(ob, 0))
		goto toosmall;
	if (!smbbufferputb(ob, t->in.scount)
		|| !smbbufferputb(ob, 0))
		goto toosmall;
	for (x = 0; x < t->in.scount; x++)
		if (!smbbufferputs(ob, t->in.setup[x]))
			goto toosmall;
	bytecountfixupoffset = smbbufferwriteoffset(ob);
	if (!smbbufferputs(ob, 0))
		goto toosmall;
	smbbufferwritelimit(ob, smbbufferwriteoffset(ob) + 65535);
	if (!smbbufferputstring(ob, p, SMB_STRING_UPCASE, t->in.name))
		goto toosmall;
	if (t->in.pcount < t->in.tpcount) {
		uint32_t align = smbbufferwriteoffset(ob) & 1;
		uint32_t pthistime;
		pthistime = smbbufferwritespace(ob) - align;
		if (pthistime > t->in.tpcount - t->in.pcount)
			pthistime = t->in.tpcount - t->in.pcount;
		if (pthistime > 65535)
			pthistime = 65535;
		if (smbbufferwriteoffset(ob) > 65535)
			pthistime = 0;
		if (pthistime) {
			assert(smbbufferalignl2(ob, 0));
			assert(smbbufferoffsetputs(ob, countsfixupoffset, pthistime));
			assert(smbbufferoffsetputs(ob, countsfixupoffset + 2, smbbufferwriteoffset(ob)));
			assert(smbbufferputbytes(ob, t->in.parameters + t->in.pcount, pthistime));
		}
		t->in.pcount += pthistime;
	}
	if (t->in.dcount < t->in.tdcount) {
		uint32_t align = smbbufferwriteoffset(ob) & 1;
		uint32_t dthistime;
		dthistime = smbbufferwritespace(ob) - align;
		if (dthistime > t->in.tdcount - t->in.dcount)
			dthistime = t->in.tdcount - t->in.dcount;
		if (dthistime > 65535)
			dthistime = 65535;
		if (smbbufferwriteoffset(ob) > 65535)
			dthistime = 0;
		if (dthistime) {
			assert(smbbufferalignl2(ob, 0));
			assert(smbbufferoffsetputs(ob, countsfixupoffset + 4, dthistime));
			assert(smbbufferoffsetputs(ob, countsfixupoffset + 6, smbbufferwriteoffset(ob)));
			assert(smbbufferputbytes(ob, t->in.data + t->in.dcount, dthistime));
		}
		t->in.dcount += dthistime;
	}
	*bytecountp = smbbufferwriteoffset(ob) - bytecountfixupoffset - 2;
	assert(smbbufferoffsetputs(ob, bytecountfixupoffset, *bytecountp));
	return 1;
}
Пример #16
0
int
_smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uint8_t *pdata,
			     SmbBuffer *b, int hasname, char **errmsgp)
{
	uint16_t poffset, doffset;

	if (h->wordcount < 14) {
		smbstringprint(errmsgp, "word count less than 14");
		return -1;
	}
	t->in.scount = pdata[13 * 2];
	if (h->wordcount != 14 + t->in.scount) {
		smbstringprint(errmsgp, "smbcomtransaction: word count invalid\n");
		return -1;
	}
	t->in.tpcount = smbnhgets(pdata); pdata += 2;
	t->in.tdcount = smbnhgets(pdata); pdata += 2;
	t->in.maxpcount = smbnhgets(pdata); pdata += 2;
	t->in.maxdcount = smbnhgets(pdata); pdata += 2;
	t->in.maxscount = *pdata++;
	pdata++;
	t->in.flags = smbnhgets(pdata); pdata += 2;
	pdata += 4; /* timeout */
	pdata += 2;
	t->in.pcount = smbnhgets(pdata); pdata += 2;
	poffset = smbnhgets(pdata); pdata += 2;
	t->in.dcount = smbnhgets(pdata); pdata += 2;
	doffset = smbnhgets(pdata); pdata += 2;
	pdata++; /* scount */
	pdata++; /* reserved */
	smbfree(&t->in.setup);
	if (t->in.scount) {
		int x;
		t->in.setup = smbemalloc(t->in.scount * sizeof(uint16_t));
		for (x = 0; x < t->in.scount; x++) {
			t->in.setup[x] = smbnhgets(pdata);
			pdata += 2;
		}
	}
	smbfree(&t->in.name);
	if (hasname && !smbbuffergetstring(b, h, SMB_STRING_PATH, &t->in.name)) {
		smbstringprint(errmsgp, "not enough bdata for name");
		return -1;
	}
	if (poffset + t->in.pcount > smbbufferwriteoffset(b)) {
		smbstringprint(errmsgp, "not enough bdata for parameters");
		return -1;
	}
	if (t->in.pcount > t->in.tpcount) {
		smbstringprint(errmsgp, "too many parameters");
		return -1;
	}
	smbfree(&t->in.parameters);
	t->in.parameters = smbemalloc(t->in.tpcount);
	memcpy(t->in.parameters, smbbufferpointer(b, poffset), t->in.pcount);
	if (doffset + t->in.dcount > smbbufferwriteoffset(b)) {
		smbstringprint(errmsgp, "not enough bdata for data");
		return -1;
	}
	if (t->in.dcount > t->in.tdcount) {
		smbstringprint(errmsgp, "too much data");
		return -1;
	}
	smbfree(&t->in.data);
	t->in.data = smbemalloc(t->in.tdcount);
	memcpy(t->in.data, smbbufferpointer(b, doffset), t->in.dcount);
	if (t->in.dcount < t->in.tdcount || t->in.pcount < t->in.tpcount)
		return 0;
	return 1;
}