static SmbProcessResult netwkstagetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata) { uint16_t level; uint16_t usefulbytes; SmbProcessResult pr; int moredata; /* WrLh * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail */ if (!smbbuffergets(inparam, &level)) { fmtfail: pr = SmbProcessResultFormat; goto done; } smblogprintif(smbglobals.log.rap2, "netwkstagetinfo(%lud, %lud)\n", level, smbbufferwritespace(outdata)); if (level != 10) goto fmtfail; usefulbytes = 22 + smbstrlen(smbglobals.serverinfo.name) + smbstrlen(getuser()) + 3 * smbstrlen(smbglobals.primarydomain); moredata = usefulbytes > smbbufferwritespace(outdata); assert(smbbufferputl(outdata, 0)); assert(smbbufferputl(outdata, 0)); assert(smbbufferputl(outdata, 0)); assert(smbbufferputb(outdata, smbglobals.serverinfo.vmaj)); assert(smbbufferputb(outdata, smbglobals.serverinfo.vmin)); assert(smbbufferputl(outdata, 0)); assert(smbbufferputl(outdata, 0)); assert(smbbufferfixupabsolutel(outdata, 0)); assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.serverinfo.name)); assert(smbbufferfixupabsolutel(outdata, 4)); assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, getuser())); assert(smbbufferfixupabsolutel(outdata, 8)); assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain)); assert(smbbufferfixupabsolutel(outdata, 14)); assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain)); assert(smbbufferfixupabsolutel(outdata, 18)); assert(smbbufferputstring(outdata, nil, SMB_STRING_ASCII, smbglobals.primarydomain)); if (!smbbufferputs(outparam, moredata ? SMB_RAP_ERROR_MORE_DATA : SMB_RAP_NERR_SUCCESS) || !smbbufferputs(outparam, 0) || !smbbufferputs(outparam, usefulbytes)) { pr = SmbProcessResultFormat; goto done; } pr = SmbProcessResultReply; done: return pr; }
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; }
static SmbProcessResult netservergetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata) { uint16_t level; SmbProcessResult pr; /* WrLh * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail */ if (!smbbuffergets(inparam, &level)) { fmtfail: pr = SmbProcessResultFormat; goto done; } smblogprintif(smbglobals.log.rap2, "netservergetinfo(%lud, %lud)\n", level, smbbufferwritespace(outdata)); if (level > 1) goto fmtfail; pr = onethingfill(outparam, outdata, &shareinfo, level, &smbglobals.serverinfo); done: return pr; }
static SmbProcessResult netserverenum2(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata) { uint16_t level, rbl; char *domain; uint32_t servertype; SmbProcessResult pr; SmbServerInfo *si[3]; SmbServerInfo domainsi; int entries; /* WrLehDz * ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail, * ulong fServerType, char *pszDomain */ if (!smbbuffergets(inparam, &level) || !smbbuffergets(inparam, &rbl) || !smbbuffergetl(inparam, &servertype) || !smbbuffergetstr(inparam, 0, &domain)) { fmtfail: pr = SmbProcessResultFormat; goto done; } smblogprintif(smbglobals.log.rap2, "netserverenum2(%lud, %lud, 0x%.8lux, %s)\n", level, smbbufferwritespace(outdata), servertype, domain); if (level > 1) goto fmtfail; if (servertype == 0xffffffff) servertype &= ~(SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY); if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0 && (servertype & SV_TYPE_DOMAIN_ENUM) == 0) servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); entries = 0; if ((servertype & SV_TYPE_SERVER) != 0 && (domain[0] == 0 || cistrcmp(domain, smbglobals.primarydomain) == 0)) { si[entries++] = &smbglobals.serverinfo; } if ((servertype & SV_TYPE_DOMAIN_ENUM) != 0) { /* there's only one that I know about */ memset(&domainsi, 0, sizeof(domainsi)); domainsi.name = smbglobals.primarydomain; domainsi.stype = SV_TYPE_DOMAIN_ENUM; si[entries++] = &domainsi; } si[entries] = 0; pr = thingfill(outparam, outdata, &serverinfo, level, si); done: free(domain); return pr; }
int smbclienttrans2(SmbClient *c, uchar scount, ushort *setup, SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata, SmbHeader *rh, char **errmsgp) { SmbTransaction transaction; SmbHeader h; memset(&transaction, 0, sizeof(transaction)); transaction.in.scount = scount; transaction.in.setup = setup; transaction.in.parameters = smbbufferreadpointer(inparam); transaction.in.tpcount = smbbufferreadspace(inparam); transaction.in.maxpcount = smbbufferwritespace(outparam); transaction.in.maxdcount = smbbufferwritespace(outdata); transaction.out.parameters = outparam; transaction.out.data = outdata; h = c->protoh; h.tid = c->sharetid; h.mid = 0; return smbtransactionexecute(&transaction, &h, &c->peerinfo, c->b, &method, c, rh, errmsgp); }
int smbclientrap(SmbClient *c, SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata, char **errmsgp) { SmbTransaction transaction; SmbHeader h; memset(&transaction, 0, sizeof(transaction)); transaction.in.name = smbglobals.pipelanman; transaction.in.parameters = smbbufferreadpointer(inparam); transaction.in.tpcount = smbbufferreadspace(inparam); transaction.in.maxpcount = smbbufferwritespace(outparam); transaction.in.maxdcount = smbbufferwritespace(outdata); transaction.out.parameters = outparam; transaction.out.data = outdata; h = c->protoh; h.tid = c->ipctid; h.mid = 0; return smbtransactionexecute(&transaction, &h, &c->peerinfo, c->b, &smbtransactionmethodrap, c, nil, errmsgp); }
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; }
static SmbProcessResult netshareenum(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata) { uint16_t level; /* WrLeh */ /* ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ENTCOUNT pcEntriesRead, ushort *pcTotalAvail */ if (!smbbuffergets(inparam, &level)) return SmbProcessResultFormat; smblogprintif(smbglobals.log.rap2, "netshareenum(%lud, %lud)\n", level, smbbufferwritespace(outdata)); if (level != 1) return SmbProcessResultFormat; return thingfill(outparam, outdata, &shareinfo, level, nil); }
static SmbProcessResult netsharegetinfo(SmbBuffer *inparam, SmbBuffer *outparam, SmbBuffer *outdata) { char *netname; uint16_t level; SmbProcessResult pr; SmbService *serv; /* * zWrLh * char *pszNetName, ushort sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, ushort *pcbTotalAvail */ if (!smbbuffergetstrinline(inparam, &netname) || !smbbuffergets(inparam, &level)) { fmtfail: pr = SmbProcessResultFormat; goto done; } smblogprintif(smbglobals.log.rap2, "netsharegetinfo(%s, %lud, %lud)\n", netname, level, smbbufferwritespace(outdata)); if (level > 2) goto fmtfail; for (serv = smbservices; serv; serv = serv->next) if (cistrcmp(serv->name, netname) == 0) break; if (serv == nil) { smblogprint(-1, "netsharegetinfo: service %s unimplemented\n", netname); pr = SmbProcessResultUnimp; goto done; } pr = onethingfill(outparam, outdata, &shareinfo, level, serv); done: return pr; }
ushort smbresponsespace(SmbSession *sess) { return smbbufferwritespace(sess->response); }
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; }
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; }
int smbnetserverenum2(SmbClient *c, uint32_t stype, char *domain, int *entriesp, SmbRapServerInfo1 **sip, char **errmsgp) { int rv; uint16_t ec, entries, total, converter; SmbRapServerInfo1 *si = nil; SmbBuffer *ipb = smbbuffernew(512); SmbBuffer *odb = smbbuffernew(65535); SmbBuffer *opb = smbbuffernew(8); smbbufferputs(ipb, 104); smbbufferputstring(ipb, nil, SMB_STRING_ASCII, "WrLehDz"); smbbufferputstring(ipb, nil, SMB_STRING_ASCII, "B16BBDz"); smbbufferputs(ipb, 1); smbbufferputs(ipb, smbbufferwritespace(odb)); smbbufferputl(ipb, stype); smbbufferputstring(ipb, nil, SMB_STRING_ASCII, domain); rv = !smbclientrap(c, ipb, opb, odb, errmsgp); smbbufferfree(&ipb); if (rv == 0) { char *remark, *eremark; int remarkspace; int i; if (!smbbuffergets(opb, &ec) || !smbbuffergets(opb, &converter) || !smbbuffergets(opb, &entries) || !smbbuffergets(opb, &total)) { smbstringprint(errmsgp, "smbnetserverenum2: not enough return parameters"); rv = -1; goto done; } if (ec != 0) { rv = ec; goto done; } if (smbbufferreadspace(odb) < entries * 26) { smbstringprint(errmsgp, "smbnetserverenum2: not enough return data"); rv = -1; goto done; } remarkspace = smbbufferreadspace(odb) - entries * 26; si = smbemalloc(entries * sizeof(SmbRapServerInfo1) + remarkspace); remark = (char *)&si[entries]; eremark = remark + remarkspace; for (i = 0; i < entries; i++) { uint32_t offset; int remarklen; assert(smbbuffergetbytes(odb, si[i].name, 16)); assert(smbbuffergetb(odb, &si[i].vmaj)); assert(smbbuffergetb(odb, &si[i].vmin)); assert(smbbuffergetl(odb, &si[i].type)); assert(smbbuffergetl(odb, &offset)); offset -= converter; if (!smbbufferoffsetcopystr(odb, offset, remark, eremark - remark, &remarklen)) { smbstringprint(errmsgp, "smbnetserverenum2: invalid string offset"); rv = -1; goto done; } si[i].remark = remark; remark += remarklen; } *sip = si; si = nil; *entriesp = entries; } else rv = -1; done: free(si); smbbufferfree(&opb); smbbufferfree(&odb); return rv; }