SmbProcessResult smbcomsetinformation(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b) { uint16_t attr; uint32_t utime; char *name; if (h->wordcount != 8) return SmbProcessResultFormat; attr = smbnhgets(pdata); pdata += 2; utime = smbnhgetl(pdata); if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &name)) return SmbProcessResultFormat; smblogprint(h->command, "smbcomsetinformation: attr 0x%.4ux utime %lud path %s\n", attr, utime, name); if (utime) { Dir d; memset(&d, 0xff, sizeof(d)); d.name = d.uid = d.gid = d.muid = nil; d.mtime = smbutime2plan9time(utime, s->tzoff); if (dirwstat(name, &d) < 0) { smbseterror(s, ERRDOS, ERRnoaccess); free(name); return SmbProcessResultError; } } free(name); return smbbufferputack(s->response, h, &s->peerinfo); }
SmbProcessResult smbcomcreatedirectory(SmbSession *s, SmbHeader *h, uint8_t *, SmbBuffer *b) { int fd; char *path; char *fullpath = nil; SmbTree *t; uint8_t fmt; if (h->wordcount != 0) return SmbProcessResultFormat; if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) return SmbProcessResultFormat; smblogprint(h->command, "smbcomcreatedirectory: %s\n", path); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); return SmbProcessResultError; } smbstringprint(&fullpath, "%s%s", t->serv->path, path); fd = create(fullpath, OREAD, DMDIR | 0775); if (fd < 0) { smblogprint(h->command, "smbcomcreatedirectory failed: %r\n"); smbseterror(s, ERRDOS, ERRnoaccess); free(path); return SmbProcessResultError; } close(fd); free(fullpath); free(path); return smbbufferputack(s->response, h, &s->peerinfo); }
SmbProcessResult smbcomdelete(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b) { SmbProcessResult pr; uint16_t sattr; uint8_t fmt; char *pattern = nil; char *dir = nil; char *name = nil; Reprog *r = nil; SmbTree *t; int x, count; SmbDirCache *dc = nil; if (h->wordcount != 1) return SmbProcessResultFormat; sattr = smbnhgets(pdata); if (!smbbuffergetb(b, &fmt) || fmt != 0x04 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &pattern)) return SmbProcessResultFormat; smblogprint(SMB_COM_DELETE, "searchattributes: 0x%.4x\npattern:%s\n", sattr, pattern); smbpathsplit(pattern, &dir, &name); t = smbidmapfind(s->tidmap, h->tid); if (t == nil) { smbseterror(s, ERRSRV, ERRinvtid); pr = SmbProcessResultError; goto done; } dc = smbmkdircache(t, dir); if (dc == nil) { pr = SmbProcessResultMisc; goto done; } r = smbmkrep(name); count = 0; for (x = 0; x < dc->n; x++) { if (!smbmatch(dc->buf[x].name, r)) continue; if (smbremovefile(t, dir, dc->buf[x].name) == 0) count++; } if (count == 0) { smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; } else pr = smbbufferputack(s->response,h, &s->peerinfo); done: free(pattern); free(dir); free(name); smbdircachefree(&dc); free(r); return pr; }
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 smbcomtreeconnectandx(SmbSession *s, SmbHeader *h, uint8_t *pdata, SmbBuffer *b) { uint8_t andxcommand; uint16_t andxoffset; char *path = nil; char *service = nil; uint16_t flags; uint16_t passwordlength; // ushort bytecount; uint8_t errclass; uint16_t error; SmbService *serv; SmbTree *tree; uint32_t andxfixupoffset, bytecountfixup; SmbProcessResult pr; if (!smbcheckwordcount("comtreeconnectandx", h, 4)) { fmtfail: pr = SmbProcessResultFormat; goto done; } switch (s->state) { case SmbSessionNeedNegotiate: smblogprint(-1, "smbcomtreeconnectandx: called when negotiate expected\n"); return SmbProcessResultUnimp; case SmbSessionNeedSetup: smbseterror(s, ERRDOS, ERRbadpw); return SmbProcessResultError; } andxcommand = *pdata++; switch (andxcommand) { case SMB_COM_OPEN: case SMB_COM_CREATE_NEW: case SMB_COM_DELETE_DIRECTORY: case SMB_COM_FIND_UNIQUE: case SMB_COM_CHECK_DIRECTORY: case SMB_COM_GET_PRINT_QUEUE: case SMB_COM_TRANSACTION: case SMB_COM_SET_INFORMATION: case SMB_COM_OPEN_ANDX: case SMB_COM_CREATE_DIRECTORY: case SMB_COM_FIND: case SMB_COM_RENAME: case SMB_COM_QUERY_INFORMATION: case SMB_COM_OPEN_PRINT_FILE: case SMB_COM_NO_ANDX_COMMAND: case SMB_COM_NT_RENAME: case SMB_COM_CREATE: case SMB_COM_DELETE: case SMB_COM_COPY: break; default: smblogprint(h->command, "smbcomtreeconnectandx: invalid andxcommand %s (0x%.2ux)\n", smboptable[andxcommand].name, andxcommand); goto fmtfail; } pdata++; andxoffset = smbnhgets(pdata); pdata += 2; flags = smbnhgets(pdata); pdata += 2; passwordlength = smbnhgets(pdata); //pdata += 2; // bytecount = smbnhgets(pdata); pdata += 2; smblogprint(h->command, "passwordlength: %ud\n", passwordlength); smblogprint(h->command, "flags: 0x%.4ux\n", flags); if (!smbbuffergetbytes(b, nil, passwordlength)) { smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for password\n"); goto fmtfail; } smblogprint(h->command, "offset %lud limit %lud\n", smbbufferreadoffset(b), smbbufferwriteoffset(b)); if (!smbbuffergetstring(b, h, SMB_STRING_PATH, &path) || !smbbuffergetstr(b, 0, &service)) { smblogprint(h->command, "smbcomtreeconnectandx: not enough bytes for strings\n"); goto fmtfail; } smblogprint(h->command, "path: %s\n", path); smblogprint(h->command, "service: %s\n", service); if (flags & 1) smbtreedisconnectbyid(s, h->tid); serv = smbservicefind(s, path, service, &errclass, &error); if (serv == nil) { pr = SmbProcessResultError; smbseterror(s, errclass, error); goto done; } tree = smbtreeconnect(s, serv); h->tid = tree->id; h->wordcount = 3; if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset) || !smbresponseputs(s, 1)) { misc: pr = SmbProcessResultMisc; goto done; } bytecountfixup = smbresponseoffset(s); if (!smbresponseputs(s, 0) || !smbresponseputstr(s, serv->type) || !smbresponseputstring(s, 1, s9p2000)) goto misc; if (!smbbufferfixuprelatives(s->response, bytecountfixup)) goto misc; if (andxcommand != SMB_COM_NO_ANDX_COMMAND) { pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b); } else pr = SmbProcessResultReply; done: free(path); free(service); 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 smbcomsessionsetupandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) { uchar andxcommand; ushort andxoffset; ulong andxfixupoffset; ushort vcnumber; ulong sessionkey; ushort caseinsensitivepasswordlength; ushort casesensitivepasswordlength; ushort bytecountfixup, offset; uchar *mschapreply; AuthInfo *ai; char *sp; SmbProcessResult pr; char *accountname = nil; char *primarydomain = nil; char *nativeos = nil; char *nativelanman = nil; if (!smbcheckwordcount("comsessionsetupandx", h, 13)) { fmtfail: pr = SmbProcessResultFormat; goto done; } andxcommand = *pdata++; switch (andxcommand) { case SMB_COM_TREE_CONNECT_ANDX: case SMB_COM_OPEN_ANDX: case SMB_COM_CREATE_NEW: case SMB_COM_DELETE: case SMB_COM_FIND: case SMB_COM_COPY: case SMB_COM_NT_RENAME: case SMB_COM_QUERY_INFORMATION: case SMB_COM_NO_ANDX_COMMAND: case SMB_COM_OPEN: case SMB_COM_CREATE: case SMB_COM_CREATE_DIRECTORY: case SMB_COM_DELETE_DIRECTORY: case SMB_COM_FIND_UNIQUE: case SMB_COM_RENAME: case SMB_COM_CHECK_DIRECTORY: case SMB_COM_SET_INFORMATION: case SMB_COM_OPEN_PRINT_FILE: break; default: smblogprint(h->command, "smbcomsessionsetupandx: invalid andxcommand %s (0x%.2ux)\n", smboptable[andxcommand].name, andxcommand); goto fmtfail; } pdata++; andxoffset = smbnhgets(pdata); pdata += 2; s->peerinfo.maxlen = smbnhgets(pdata); pdata += 2; smbresponseinit(s, s->peerinfo.maxlen); s->client.maxmpxcount = smbnhgets(pdata); pdata += 2; vcnumber = smbnhgets(pdata); pdata += 2; sessionkey = smbnhgetl(pdata); pdata += 4; caseinsensitivepasswordlength = smbnhgets(pdata); pdata += 2; casesensitivepasswordlength = smbnhgets(pdata); pdata += 2; pdata += 4; s->peerinfo.capabilities = smbnhgetl(pdata); /*pdata += 4;*/ smbloglock(); smblogprint(h->command, "andxcommand: %s offset %ud\n", smboptable[andxcommand].name, andxoffset); smblogprint(h->command, "client.maxbuffersize: %ud\n", s->peerinfo.maxlen); smblogprint(h->command, "client.maxmpxcount: %ud\n", s->client.maxmpxcount); smblogprint(h->command, "vcnumber: %ud\n", vcnumber); smblogprint(h->command, "sessionkey: 0x%.8lux\n", sessionkey); smblogprint(h->command, "caseinsensitivepasswordlength: %ud\n", caseinsensitivepasswordlength); smblogprint(h->command, "casesensitivepasswordlength: %ud\n", casesensitivepasswordlength); smblogprint(h->command, "clientcapabilities: 0x%.8lux\n", s->peerinfo.capabilities); smblogunlock(); mschapreply = smbbufferreadpointer(b); if (!smbbuffergetbytes(b, nil, caseinsensitivepasswordlength + casesensitivepasswordlength)) { smblogprint(h->command, "smbcomsessionsetupandx: not enough bdata for passwords\n"); goto fmtfail; } if (!smbbuffergetstring(b, h, 0, &accountname) || !smbbuffergetstring(b, h, 0, &primarydomain) || !smbbuffergetstring(b, h, 0, &nativeos) || !smbbuffergetstring(b, h, 0, &nativelanman)) { smblogprint(h->command, "smbcomsessionsetupandx: not enough bytes for strings\n"); goto fmtfail; } for (sp = accountname; *sp; sp++) *sp = tolower(*sp); smblogprint(h->command, "account: %s\n", accountname); smblogprint(h->command, "primarydomain: %s\n", primarydomain); smblogprint(h->command, "nativeos: %s\n", nativeos); smblogprint(h->command, "nativelanman: %s\n", nativelanman); if (s->client.accountname && accountname[0] && strcmp(s->client.accountname, accountname) != 0) { smblogprint(h->command, "smbcomsessionsetupandx: more than one user on VC (before %s, now %s)\n", s->client.accountname, accountname); smbseterror(s, ERRSRV, ERRtoomanyuids); errordone: pr = SmbProcessResultError; goto done; } if (s->client.accountname == nil) { /* first time */ if (accountname[0] == 0) { smbseterror(s, ERRSRV, ERRbaduid); goto errordone; } if ((casesensitivepasswordlength != 24 || caseinsensitivepasswordlength != 24)) { smblogprint(h->command, "smbcomsessionsetupandx: case sensitive/insensitive password length not 24\n"); smbseterror(s, ERRSRV, ERRbadpw); goto errordone; } memcpy(&s->client.mschapreply, mschapreply, sizeof(s->client.mschapreply)); if(s->cs == nil){ smbseterror(s, ERRSRV, ERRerror); goto errordone; } s->cs->user = accountname; s->cs->resp = &s->client.mschapreply; s->cs->nresp = sizeof(MSchapreply); ai = auth_response(s->cs); if (ai == nil) { smblogprint(h->command, "authentication failed\n"); smbseterror(s, ERRSRV, ERRbadpw); goto errordone; } smblogprint(h->command, "authentication succeeded\n"); if (auth_chuid(ai, nil) < 0) { smblogprint(h->command, "smbcomsessionsetupandx: chuid failed: %r\n"); auth_freeAI(ai); miscerror: pr = SmbProcessResultMisc; goto done; } auth_freeAI(ai); h->uid = 1; s->client.accountname = accountname; s->client.primarydomain = primarydomain; s->client.nativeos = nativeos; s->client.nativelanman = nativelanman; accountname = nil; primarydomain = nil; nativeos = nil; nativelanman = nil; } else { if (caseinsensitivepasswordlength == 24 && casesensitivepasswordlength == 24 && memcmp(&s->client.mschapreply, mschapreply, sizeof(MSchapreply)) != 0) { smblogprint(h->command, "second time authentication failed\n"); smbseterror(s, ERRSRV, ERRbadpw); goto errordone; } } /* CIFS says 4 with or without extended security, samba/ms says 3 without */ h->wordcount = 3; if (!smbresponseputandxheader(s, h, andxcommand, &andxfixupoffset)) goto miscerror; if (!smbresponseputs(s, 0)) goto miscerror; bytecountfixup = smbresponseoffset(s); if (!smbresponseputs(s, 0)) goto miscerror; if (!smbresponseputstring(s, 1, smbglobals.nativeos) || !smbresponseputstring(s, 1, smbglobals.serverinfo.nativelanman) || !smbresponseputstring(s, 1, smbglobals.primarydomain)) goto miscerror; offset = smbresponseoffset(s); smbresponseoffsetputs(s, bytecountfixup, offset - bytecountfixup - 2); s->state = SmbSessionEstablished; if (andxcommand != SMB_COM_NO_ANDX_COMMAND) pr = smbchaincommand(s, h, andxfixupoffset, andxcommand, andxoffset, b); else pr = SmbProcessResultReply; done: free(accountname); free(primarydomain); free(nativeos); free(nativelanman); return pr; }
int _smbtransactiondecodeprimary(SmbTransaction *t, SmbHeader *h, uint8_t *pdata, SmbBuffer *b, int hasname, char **errmsgp) { uint16_t poffset, doffset; if (h->wordcount < 14) { smbstringprint(errmsgp, "word count less than 14"); return -1; } t->in.scount = pdata[13 * 2]; if (h->wordcount != 14 + t->in.scount) { smbstringprint(errmsgp, "smbcomtransaction: word count invalid\n"); return -1; } t->in.tpcount = smbnhgets(pdata); pdata += 2; t->in.tdcount = smbnhgets(pdata); pdata += 2; t->in.maxpcount = smbnhgets(pdata); pdata += 2; t->in.maxdcount = smbnhgets(pdata); pdata += 2; t->in.maxscount = *pdata++; pdata++; t->in.flags = smbnhgets(pdata); pdata += 2; pdata += 4; /* timeout */ pdata += 2; t->in.pcount = smbnhgets(pdata); pdata += 2; poffset = smbnhgets(pdata); pdata += 2; t->in.dcount = smbnhgets(pdata); pdata += 2; doffset = smbnhgets(pdata); pdata += 2; pdata++; /* scount */ pdata++; /* reserved */ smbfree(&t->in.setup); if (t->in.scount) { int x; t->in.setup = smbemalloc(t->in.scount * sizeof(uint16_t)); for (x = 0; x < t->in.scount; x++) { t->in.setup[x] = smbnhgets(pdata); pdata += 2; } } smbfree(&t->in.name); if (hasname && !smbbuffergetstring(b, h, SMB_STRING_PATH, &t->in.name)) { smbstringprint(errmsgp, "not enough bdata for name"); return -1; } if (poffset + t->in.pcount > smbbufferwriteoffset(b)) { smbstringprint(errmsgp, "not enough bdata for parameters"); return -1; } if (t->in.pcount > t->in.tpcount) { smbstringprint(errmsgp, "too many parameters"); return -1; } smbfree(&t->in.parameters); t->in.parameters = smbemalloc(t->in.tpcount); memcpy(t->in.parameters, smbbufferpointer(b, poffset), t->in.pcount); if (doffset + t->in.dcount > smbbufferwriteoffset(b)) { smbstringprint(errmsgp, "not enough bdata for data"); return -1; } if (t->in.dcount > t->in.tdcount) { smbstringprint(errmsgp, "too much data"); return -1; } smbfree(&t->in.data); t->in.data = smbemalloc(t->in.tdcount); memcpy(t->in.data, smbbufferpointer(b, doffset), t->in.dcount); if (t->in.dcount < t->in.tdcount || t->in.pcount < t->in.tpcount) return 0; return 1; }
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; }