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; }
SmbProcessResult smbrap2(SmbSession *s) { char *pstring; char *dstring; uint16_t pno; RapTableEntry *e; SmbProcessResult pr; SmbBuffer *inparam; inparam = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(inparam, &pno) || !smbbuffergetstrinline(inparam, &pstring) || !smbbuffergetstrinline(inparam, &dstring)) { smblogprintif(smbglobals.log.rap2, "smbrap2: not enough parameters\n"); pr = SmbProcessResultFormat; goto done; } if (pno > nelem(raptable) || raptable[pno].name == nil) { smblogprint(-1, "smbrap2: unsupported procedure %ud\n", pno); pr = SmbProcessResultUnimp; goto done; } e = raptable + pno; pr = (*e->procedure)(inparam, s->transaction.out.parameters, s->transaction.out.data); done: smbbufferfree(&inparam); return pr; }
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 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 smbbuffergetheader(SmbBuffer *b, SmbHeader *h, uint8_t **parametersp, uint16_t *bytecountp) { SmbOpTableEntry *ote; SmbRawHeader *rh; rh = (SmbRawHeader *)smbbufferreadpointer(b); if (!smbbuffergetbytes(b, nil, (int32_t)offsetof(SmbRawHeader, parameterwords[0]))) { smblogprint(-1, "smbgetheader: short packet\n"); return 0; } if (rh->protocol[0] != 0xff || memcmp(rh->protocol + 1, "SMB", 3) != 0) { smblogprint(-1, "smbgetheader: invalid protocol\n"); return 0; } h->command = rh->command; ote = smboptable + h->command; if (ote->name == nil) { smblogprint(-1, "smbgetheader: illegal opcode 0x%.2ux\n", h->command); return 0; } h->errclass = rh->status[0]; h->error = smbnhgets(rh->status + 2); h->flags = rh->flags; h->flags2 = smbnhgets(rh->flags2); if (h->flags & ~(SmbHeaderFlagCaseless | SMB_FLAGS_SERVER_TO_REDIR | SmbHeaderFlagReserved | SmbHeaderFlagServerIgnore)) smblogprint(-1, "smbgetheader: warning: unexpected flags 0x%.2ux\n", h->flags); h->wordcount = rh->wordcount; if (parametersp) *parametersp = smbbufferreadpointer(b); if (!smbbuffergetbytes(b, nil, h->wordcount * 2)) { smblogprint(-1, "smbgetheader: not enough data for parameter words\n"); return 0; } h->tid = smbnhgets(rh->tid); h->pid = smbnhgets(rh->pid); h->uid = smbnhgets(rh->uid); h->mid = smbnhgets(rh->mid); if (!smbbuffergets(b, bytecountp)) *bytecountp = 0; if (!smbbufferpushreadlimit(b, smbbufferreadoffset(b) + *bytecountp)) return 0; smblogprint(h->command, "%s %s: tid 0x%.4ux pid 0x%.4ux uid 0x%.4ux mid 0x%.4ux\n", ote->name, (h->flags & SMB_FLAGS_SERVER_TO_REDIR) ? "response" : "request", h->tid, h->pid, h->uid, h->mid); 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); }
SmbProcessResult smbchaincommand(SmbSession *s, SmbHeader *h, uint32_t andxoffsetfixup, uint8_t cmd, uint16_t offset, SmbBuffer *b) { SmbOpTableEntry *ote; uint8_t *pdata; uint16_t bytecount; h->command = cmd; ote = smboptable + cmd; if (ote->process == nil) { smblogprint(-1, "smbchaincommand: %s (0x%.2ux) not implemented\n", ote->name, cmd); return SmbProcessResultUnimp; } if (!smbresponsealignl2(s, 2) || !smbresponseoffsetputs(s, andxoffsetfixup, smbresponseoffset(s)) || !smbbufferpopreadlimit(b)) return SmbProcessResultMisc; if (!smbbufferreadskipto(b, offset)) { smblogprint(-1, "smbchaincommand: illegal offset\n"); return SmbProcessResultFormat; } if (!smbbuffergetb(b, &h->wordcount)) { smblogprint(-1, "smbchaincommand: not enough space for wordcount\n"); return SmbProcessResultFormat; } pdata = smbbufferreadpointer(b); if (!smbbuffergetbytes(b, nil, h->wordcount * 2)) { smblogprint(-1, "smbchaincommand: not enough space for parameters\n"); return SmbProcessResultFormat; } if (!smbbuffergets(b, &bytecount)) { smblogprint(-1, "smbchaincommand: not enough space for bytecount\n"); return SmbProcessResultFormat; } if (!smbbufferpushreadlimit(b, smbbufferreadoffset(b) + bytecount)) { smblogprint(-1, "smbchaincommand: not enough space for bytes\n"); return SmbProcessResultFormat; } smblogprint(cmd, "chaining to %s\n", ote->name); return (*ote->process)(s, h, pdata, b); }
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; }
static int getlock(SmbBuffer *b, int large, ushort *pidp, uvlong *offsetp, uvlong *lengthp) { ulong ohigh, olow; ulong lhigh, llow; if (!smbbuffergets(b, pidp)) return 0; if (large && !smbbuffergetbytes(b, nil, 2)) return 0; if (large) { if (!smbbuffergetl(b, &ohigh) || !smbbuffergetl(b, &olow) || !smbbuffergetl(b, &lhigh) || !smbbuffergetl(b, &llow)) return 0; *offsetp = ((uvlong)ohigh << 32) | olow; *lengthp = ((uvlong)lhigh << 32) | llow; return 1; } if (!smbbuffergetl(b, &olow) || !smbbuffergetl(b, &llow)) return 0; *offsetp = olow; *lengthp = llow; return 1; }
int smbclienttrans2findfirst2(SmbClient *c, ushort searchcount, char *filename, ushort *sidp, ushort *searchcountp, ushort *endofsearchp,SmbFindFileBothDirectoryInfo *ip, char **errmsgp) { int rv; ushort setup; SmbBuffer *inparam; SmbBuffer *outparam; SmbBuffer *outdata; SmbHeader rh; setup = SMB_TRANS2_FIND_FIRST2; inparam = smbbuffernew(512); smbbufferputs(inparam, 0x16); smbbufferputs(inparam, searchcount); smbbufferputs(inparam, 7); smbbufferputs(inparam, SMB_FIND_FILE_BOTH_DIRECTORY_INFO); smbbufferputl(inparam, 0); smbbufferputstring(inparam, &c->peerinfo, 0, filename); outparam = smbbuffernew(10); outdata = smbbuffernew(65535); rv = smbclienttrans2(c, 1, &setup, inparam, outparam, outdata, &rh, errmsgp); smbbufferfree(&inparam); if (rv) { ushort eaerroroffset, lastnameoffset; ulong nextentry; int i; if (!smbbuffergets(outparam, sidp) || !smbbuffergets(outparam, searchcountp) || !smbbuffergets(outparam, endofsearchp) || !smbbuffergets(outparam, &eaerroroffset) || !smbbuffergets(outparam, &lastnameoffset)) { smbstringprint(errmsgp, "smbclienttrans2findfirst2: not enough parameters returned"); rv = 0; goto done; } nextentry = 0; smblogprint(-1, "returned data:\n"); smblogdata(-1, smblogprint, smbbufferreadpointer(outdata), smbbufferreadspace(outdata), 256); for (i = 0; i < *searchcountp; i++) { SmbFindFileBothDirectoryInfo *info = ip + i; ulong neo, filenamelength, easize; uchar shortnamelength; if (i && !smbbufferreadskipto(outdata, nextentry)) { underflow: smbstringprint(errmsgp, "smbclientrans2findfirst2: not enough data returned"); rv = 0; goto done; } if (!smbbuffergetl(outdata, &neo)) goto underflow; nextentry = smbbufferreadoffset(outdata) + neo - 4; print("neo 0x%.8lux\n", neo); if (!smbbuffergetl(outdata, &info->fileindex) || !smbbuffergetv(outdata, &info->creationtime) || !smbbuffergetv(outdata, &info->lastaccesstime) || !smbbuffergetv(outdata, &info->lastwritetime) || !smbbuffergetv(outdata, &info->changetime) || !smbbuffergetv(outdata, &info->endoffile) || !smbbuffergetv(outdata, &info->allocationsize)) goto underflow; print("got here\n"); if (!smbbuffergetl(outdata, &info->extfileattributes) || !smbbuffergetl(outdata, &filenamelength) || !smbbuffergetl(outdata, &easize) || !smbbuffergetb(outdata, &shortnamelength) || !smbbuffergetbytes(outdata, nil, 1) || !smbbuffergetbytes(outdata, nil, 24) || !smbbuffergetstring(outdata, &rh, SMB_STRING_REVPATH, &info->filename)) goto underflow; print("got here as well\n"); } } done: smbbufferfree(&outparam); smbbufferfree(&outdata); return rv; }
SmbProcessResult smbtrans2setfileinformation(SmbSession *s, SmbHeader *h) { SmbTree *t; ushort infolevel; SmbBuffer *b; SmbProcessResult pr; ushort fid; SmbFile *f; vlong newsize; uvlong atime, mtime; ulong attr; ulong mode; t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) { misc: pr = SmbProcessResultMisc; goto done; } f = smbidmapfind(s->fidmap, fid); if (f == nil) { smbseterror(s, ERRDOS, ERRbadfid); pr = SmbProcessResultError; goto done; } switch (infolevel) { case SMB_SET_FILE_ALLOCATION_INFO: case SMB_SET_FILE_END_OF_FILE_INFO: if (s->transaction.in.tdcount < 8) goto misc; newsize = smbnhgetv(s->transaction.in.data); pr = smbtruncatefile(s, f, newsize); if (pr == SmbProcessResultReply && !smbbufferputs(s->transaction.out.parameters, 0)) goto misc; break; case SMB_SET_FILE_BASIC_INFO: if (s->transaction.in.tdcount < 4 * 8 + 4) goto misc; atime = smbnhgetv(s->transaction.in.data + 8); mtime = smbnhgetv(s->transaction.in.data + 24); attr = smbnhgetv(s->transaction.in.data + 32); if (attr) { Dir *od = dirfstat(f->fd); if (od == nil) goto noaccess; mode = smbdosattr2plan9wstatmode(od->mode, attr); free(od); } else mode = 0xffffffff; if (atime || mtime || mode != 0xffffffff) { Dir d; memset(&d, 0xff, sizeof(d)); d.name = d.uid = d.gid = d.muid = nil; if (atime) d.atime = smbtime2plan9time(atime); if (mtime) d.mtime = smbtime2plan9time(mtime); d.mode = mode; if (dirfwstat(f->fd, &d) < 0) { noaccess: smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } } if (!smbbufferputs(s->transaction.out.parameters, 0)) goto misc; pr = SmbProcessResultReply; break; case SMB_SET_FILE_DISPOSITION_INFO: if (s->transaction.in.tdcount < 1) goto misc; f->sf->deleteonclose = *s->transaction.in.data; if (!smbbufferputs(s->transaction.out.parameters, 0)) goto misc; pr = SmbProcessResultReply; break; default: smblogprint(-1, "smbtrans2setfileinformation: infolevel 0x%.4ux not implemented\n", infolevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; break; } done: smbbufferfree(&b); return pr; }
SmbProcessResult smbtrans2setpathinformation(SmbSession *s, SmbHeader *h) { char *fullpath, *path; SmbTree *t; ushort infolevel; SmbBuffer *b; SmbProcessResult pr; ushort atime, adate, mtime, mdate; ulong attr; ulong mode; ulong size; // uvlong length; t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); path = nil; if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4) || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) { misc: pr = SmbProcessResultMisc; goto done; } fullpath = nil; smbstringprint(&fullpath, "%s%s", t->serv->path, path); translogprint(s->transaction.in.setup[0], "path %s\n", path); translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel); translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath); switch (infolevel) { case SMB_INFO_STANDARD: if (s->transaction.in.tdcount < 6 * 4 + 2 * 2) goto misc; adate = smbnhgets(s->transaction.in.data + 6); atime = smbnhgets(s->transaction.in.data + 4); mdate = smbnhgets(s->transaction.in.data + 10); mtime = smbnhgets(s->transaction.in.data + 8); size = smbnhgetl(s->transaction.in.data + 12); attr = smbnhgets(s->transaction.in.data + 20); if (attr) { Dir *od = dirstat(fullpath); if (od == nil) goto noaccess; mode = smbdosattr2plan9wstatmode(od->mode, attr); free(od); } else mode = 0xffffffff; translogprint(s->transaction.in.setup[0], "mode 0%od\n", mode); // if (size) // length = size; // else // length = ~0LL; translogprint(s->transaction.in.setup[0], "size %lld\n", size); translogprint(s->transaction.in.setup[0], "adate %d atime %d", adate, atime); translogprint(s->transaction.in.setup[0], "mdate %d mtime %d\n", mdate, mtime); if (size || adate || atime || mdate || mtime || mode != 0xffffffff) { Dir d; memset(&d, 0xff, sizeof(d)); d.name = d.uid = d.gid = d.muid = nil; if (adate || atime) d.atime = smbdatetime2plan9time(adate, atime, s->tzoff); if (mdate || mtime) d.mtime = smbdatetime2plan9time(mdate, mtime, s->tzoff); d.mode = mode; d.length = size; if (dirwstat(fullpath, &d) < 0) { noaccess: smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } } if (!smbbufferputs(s->transaction.out.parameters, 0)) goto misc; pr = SmbProcessResultReply; break; default: smblogprint(-1, "smbtrans2setpathinformation: infolevel 0x%.4ux not implemented\n", infolevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; break; } done: smbbufferfree(&b); return pr; }
SmbProcessResult smbcomwrite(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) { SmbTree *t; SmbFile *f; ushort fid; ushort count; ulong offset; long nb; ushort yacount; uchar fmt; if (h->wordcount != 5) return SmbProcessResultFormat; fid = smbnhgets(pdata); pdata += 2; count = smbnhgets(pdata); pdata += 2; offset = smbnhgetl(pdata); smblogprint(SMB_COM_WRITE, "smbcomwrite: fid 0x%.4ux count 0x%.4ux offset 0x%.8lux\n", fid, count, offset); if (!smbbuffergetb(b, &fmt) || fmt != 1 || !smbbuffergets(b, &yacount) || yacount != count || smbbufferreadspace(b) < count) return SmbProcessResultFormat; 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; } if (count == 0) { SmbProcessResult pr = smbtruncatefile(s, f, offset); if (pr != SmbProcessResultReply) return pr; nb = 0; } else { seek(f->fd, offset, 0); nb = write(f->fd, smbbufferreadpointer(b), count); if (nb < 0) { smbseterror(s, ERRDOS, ERRnoaccess); return SmbProcessResultError; } } h->wordcount = 1; if (!smbbufferputheader(s->response, h, &s->peerinfo) || !smbbufferputs(s->response, nb) || !smbbufferputs(s->response, 0)) return SmbProcessResultMisc; return SmbProcessResultReply; }
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; }
SmbProcessResult smbtrans2findnext2(SmbSession *s, SmbHeader *h) { SmbBuffer *b; int debug; ushort sid, scount, infolevel; ulong resumekey; ushort flags; char *filename = nil; SmbProcessResult pr; ushort e; ulong nameoffset; ushort eos; SmbTree *t; SmbSearch *search; debug = smboptable[h->command].debug || smbtrans2optable[SMB_TRANS2_FIND_NEXT2].debug || smbglobals.log.find; b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(b, &sid) || !smbbuffergets(b, &scount) || !smbbuffergets(b, &infolevel) || !smbbuffergetl(b, &resumekey) || !smbbuffergets(b, &flags) || !smbbuffergetstring(b, h, 0, &filename)) { pr = SmbProcessResultFormat; goto done; } smblogprintif(debug, "smbtrans2findnext2: sid %d scount %d infolevel 0x%.4ux resumekey %lud flags 0x%.4ux filename %s\n", sid, scount, infolevel, resumekey, flags, filename); if (infolevel != SMB_INFO_STANDARD && infolevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { smblogprint(-1, "smbtrans2findnext2: infolevel 0x%.4ux not implemented\n", infolevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; goto done; } t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } search = smbidmapfind(s->sidmap, sid); if (search == nil) { smbseterror(s, ERRDOS, ERRnofiles); pr = SmbProcessResultError; goto done; } if (search->t != t) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } if ((flags & (1 << 3)) == 0) { long i; if (filename == nil) { smbseterror(s, ERRDOS, ERRnofiles); pr = SmbProcessResultError; goto done; } for (i = 0; i < search->dc->n; i++) if (strcmp(search->dc->buf[i].name, filename) == 0) { search->dc->i = i + 1; break; } } populate(s, search->dc, search->rep, infolevel, flags, scount, &e, &nameoffset); eos = search->dc->i >= search->dc->n; if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos)) smbsearchclose(s, search); smbbufferputs(s->transaction.out.parameters, e); smbbufferputs(s->transaction.out.parameters, eos); smbbufferputs(s->transaction.out.parameters, 0); smbbufferputs(s->transaction.out.parameters, nameoffset); pr = SmbProcessResultReply; done: smbbufferfree(&b); free(filename); return pr; }
SmbProcessResult smbtrans2findfirst2(SmbSession *s, SmbHeader *h) { SmbBuffer *b; char *pattern = nil; char *dir = nil; char *name = nil; ushort searchattributes, searchcount, flags, informationlevel; ulong searchstoragetype; SmbDirCache *dc = nil; ushort e; ulong nameoffset; ushort eos; SmbSearch *search; SmbProcessResult pr; Reprog *r = nil; SmbTree *t; int debug; debug = smboptable[h->command].debug || smbtrans2optable[SMB_TRANS2_FIND_FIRST2].debug || smbglobals.log.find; poolcheck(mainmem); b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount); if (!smbbuffergets(b, &searchattributes) || !smbbuffergets(b, &searchcount) || !smbbuffergets(b, &flags) || !smbbuffergets(b, &informationlevel) || !smbbuffergetl(b, &searchstoragetype) || !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) { pr = SmbProcessResultFormat; goto done; } smbloglock(); smblogprintif(debug, "searchattributes: 0x%.4ux\n", searchattributes); smblogprintif(debug, "searchcount: 0x%.4ux\n", searchcount); smblogprintif(debug, "flags: 0x%.4ux\n", flags); smblogprintif(debug, "informationlevel: 0x%.4ux\n", informationlevel); smblogprintif(debug, "searchstoragetype: 0x%.8lux\n", searchstoragetype); smblogprintif(debug, "pattern: %s\n", pattern); smblogunlock(); smbpathsplit(pattern, &dir, &name); if (informationlevel != SMB_INFO_STANDARD && informationlevel != SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { smblogprint(-1, "smbtrans2findfirst2: infolevel 0x%.4ux not implemented\n", informationlevel); smbseterror(s, ERRDOS, ERRunknownlevel); pr = SmbProcessResultError; goto done; } t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } dc = smbmkdircache(t, dir); if (dc == nil) { smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } poolcheck(mainmem); r = smbmkrep(name); populate(s, dc, r, informationlevel, flags, searchcount, &e, &nameoffset); poolcheck(mainmem); eos = dc->i >= dc->n; if ((flags & SMB_FIND_CLOSE) != 0 || ((flags & SMB_FIND_CLOSE_EOS) != 0 && eos)) smbdircachefree(&dc); poolcheck(mainmem); if (dc) { /* create a search handle */ search = smbsearchnew(s, dc, r, t); r = nil; dc = nil; } else search = nil; smbbufferputs(s->transaction.out.parameters, search ? search->id : 0); smbbufferputs(s->transaction.out.parameters, e); smbbufferputs(s->transaction.out.parameters, eos); smbbufferputs(s->transaction.out.parameters, 0); smbbufferputs(s->transaction.out.parameters, nameoffset); pr = SmbProcessResultReply; done: smbbufferfree(&b); free(pattern); free(dir); free(name); smbdircachefree(&dc); free(r); return pr; }