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; }
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; }