예제 #1
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;
}
예제 #2
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;
}