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); }
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 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); }
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 int serverinfoput(SmbBuffer *b, uint16_t level, void *data) { SmbServerInfo *si = data; if (!smbbufferputstrn(b, si->name, 16, 1)) return 0; if (level > 0) { if (!smbbufferputb(b, si->vmaj) || !smbbufferputb(b, si->vmin) || !smbbufferputl(b, si->stype) || !smbbufferputl(b, 0)) return 0; } if (level > 1) return 0; return 1; }
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 int shareinfoput(SmbBuffer *b, uint16_t level, void *data) { SmbService *serv = data; if (!smbbufferputstrn(b, serv->name, 13, 0)) return 0; if (level > 0) { if (!smbbufferputb(b, 0) || !smbbufferputs(b, serv->stype) || !smbbufferputl(b, 0)) return 0; } if (level > 1) { if (!smbbufferputs(b, 7) || !smbbufferputs(b, -1) || !smbbufferputs(b, serv->ref) || !smbbufferputl(b, 0) || !smbbufferfill(b, 0, 10)) return 0; } if (level > 2) return 0; return 1; }
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; }
int smbresponseputb(SmbSession *s, uchar b) { return smbbufferputb(s->response, b); }
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; }