void smbsharedfileput(SmbFile *f, SmbSharedFile *sf, int share) { SmbSharedFileEntry *sfe, **sfep; qlock(&sharedfiletable); for (sfep = &sharedfiletable.list; (sfe = *sfep) != nil; sfep = &sfe->next) { if (sfe == sf) { sfe->ref--; if (sfe->ref == 0) { *sfep = sfe->next; if (sfe->deleteonclose && f) smbremovefile(f->t, nil, f->name); smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileput: removed\n"); locklistfree(&sfe->locklist); free(sfe); } else { sfe->share = sharesubtract(sfe->share, share); smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileput: ref %d share %d\n", sfe->ref, sfe->share); } break; } } qunlock(&sharedfiletable); }
int smbsharedfileunlock(SmbSharedFile *sf, SmbSession *s, uint16_t pid, int64_t base, int64_t limit) { SmbLockListEntry smblock; SmbLockListEntry *l, **lp; smblock.s = s; smblock.pid = pid; smblock.base = base; smblock.limit = limit; if (sf->locklist == nil) goto failed; for (lp = &sf->locklist->head; (l = *lp) != nil; lp = &l->next) { if (l->s != s || l->pid != pid) continue; switch (lockorder(&smblock, l)) { case 0: *lp = l->next; free(l); smblogprintif(smbglobals.log.locks, "smbsharedfilelock: unlock [%lld, %lld) succeeded\n", base, limit); return 1; case -1: goto failed; } } failed: smblogprintif(smbglobals.log.locks, "smbsharedfilelock: unlock [%lld, %lld) failed\n", base, limit); return 0; }
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; }
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; }
SmbSharedFile * smbsharedfileget(Dir *d, int p9mode, int *sharep) { SmbSharedFileEntry *sfe; qlock(&sharedfiletable); for (sfe = sharedfiletable.list; sfe; sfe = sfe->next) { if (sfe->type == d->type && sfe->dev == d->dev && sfe->path == d->qid.path) { if (p9denied(p9mode, sfe->share)) { qunlock(&sharedfiletable); return nil; } *sharep = sharesubtract(*sharep, sfe->share); sfe->share = shareadd(sfe->share, *sharep); sfe->ref++; goto done; } } sfe = smbemallocz(sizeof(SmbSharedFileEntry), 1); sfe->type = d->type; sfe->dev = d->dev; sfe->path = d->qid.path; // sfe->name = smbestrdup(name); sfe->ref = 1; sfe->share = *sharep; sfe->next = sharedfiletable.list; sharedfiletable.list = sfe; done: smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileget: ref %d share %d\n", sfe->ref, sfe->share); qunlock(&sharedfiletable); return sfe; }
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; }
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; }
void smbfileclose(SmbSession *s, SmbFile *f) { smblogprintif(smbglobals.log.fids, "smbfileclose: 0x%.4x/0x%.4x %s%s\n", f->t->id, f->id, f->t->serv->path, f->name); smbidmapremove(s->fidmap, f); smbfilefree(&f); }
void smbsearchclose(SmbSession *s, SmbSearch *search) { if (search) { smblogprintif(smbglobals.log.sids, "smbsearchclose: tid 0x%.4ux sid 0x%.4ux\n", search->t->id, search->id); smbidmapremove(s->sidmap, search); smbsearchfree(&search); } }
int nbssaccept(void *v, NbSession *s, NBSSWRITEFN **writep) { SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1); smbs->nbss = s; s->magic = smbs; smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND; *writep = nbwrite; smblogprintif(smbglobals.log.sessions, "netbios session started\n"); return 1; }
int cifsaccept(SmbCifsSession *s, SMBCIFSWRITEFN **writep) { SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1); smbs->cifss = s; s->magic = smbs; smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND; *writep = cifswrite; smblogprintif(smbglobals.log.sessions, "cifs session started\n"); return 1; }
SmbSearch * smbsearchnew(SmbSession *s, SmbDirCache *dc, Reprog *r, SmbTree *t) { SmbSearch *search; if (s->sidmap == nil) s->sidmap = smbidmapnew(); search = smbemalloc(sizeof(SmbSearch)); smbidmapadd(s->sidmap, search); search->dc = dc; search->rep = r; search->t = t; smblogprintif(smbglobals.log.sids, "smbsearchnew: 0x%.4ux\n", search->id); return search; }
int smbsharedfilelock(SmbSharedFile *sf, SmbSession *s, uint16_t pid, int64_t base, int64_t limit) { SmbLockListEntry smblock; SmbLockListEntry *l, *nl, **lp; smblock.s = s; smblock.pid = pid; smblock.base = base; smblock.limit = limit; if (sf->locklist) { for (l = sf->locklist->head; l; l = l->next) if (lockconflict(l, &smblock)) { smblogprintif(smbglobals.log.locks, "smbsharedfilelock: lock [%lld, %lld) failed because conflicts with [%lld, %lld)\n", base, limit, l->base, l->limit); return 0; } } if (sf->locklist == nil) sf->locklist = smbemallocz(sizeof(SmbLockList), 1); for (lp = &sf->locklist->head; (l = *lp) != nil; lp = &l->next) if (lockorder(&smblock, l) <= 0) break; smblogprintif(smbglobals.log.locks, "smbsharedfilelock: lock [%lld, %lld) succeeded\n", base, limit); nl = smbemalloc(sizeof(*nl)); *nl = smblock; nl->next = *lp; *lp = nl; //{ // smblogprintif(smbglobals.log.locks,"smbsharedfilelock: list\n"); // for (l = sf->locklist->head; l; l = l->next) // smblogprintif(smbglobals.log.locks, "smbsharedfilelock: [%lld, %lld)\n", l->base, l->limit); //} 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; }
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; }
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; }