SmbBuffer * smbbuffernew(ulong maxlen) { SmbBuffer *b; b = smbemalloc(sizeof(SmbBuffer)); b->buf = smbemalloc(maxlen); b->realmaxlen = b->maxlen = maxlen; b->rn = 0; b->wn = 0; b->flags = STRUCT | BUFFER; return b; }
char * smbstringdup(SmbHeader *h, uchar *base, uchar **bdatap, uchar *edata) { char *p; if (h && h->flags2 & SMB_FLAGS2_UNICODE) { uchar *bdata = *bdatap; uchar *savebdata; Rune r; int l; char *q; l = 0; if ((bdata - base) & 1) bdata++; savebdata = bdata; do { if (bdata + 2 > edata) return nil; r = smbnhgets(bdata); bdata += 2; l += runelen(r); } while (r != 0); p = smbemalloc(l); bdata = savebdata; q = p; do { r = smbnhgets(bdata); bdata += 2; q += runetochar(q, &r); } while (r != 0); *bdatap = bdata; return p; } return smbstrdup(bdatap, edata); }
char * smbestrdup(char *p) { char *q; q = smbemalloc(strlen(p) + 1); return strcpy(q, p); }
static Session * createsession(int fd) { Session *s; s = smbemalloc(sizeof(Session)); s->fd = fd; s->state = Connected; qlock(&sessions); if (!(*tcp.accept)(s, &s->write)) { qunlock(&sessions); free(s); return nil; } s->thread = procrfork(tcpreader, s, 32768, RFNAMEG); if (s->thread < 0) { qunlock(&sessions); (*s->write)(s, nil, -1); free(s); return nil; } s->next = sessions.head; sessions.head = s; qunlock(&sessions); return s; }
SmbBuffer * smbbufferinit(void *base, void *bdata, ulong blen) { SmbBuffer *b; b = smbemalloc(sizeof(*b)); b->buf = base; b->flags = STRUCT; b->rn = (uchar *)bdata - (uchar *)base; b->wn = b->rn + blen; b->realmaxlen = b->maxlen = b->wn; return b; }
int smbbuffergetucs2(SmbBuffer *b, ulong flags, char **sp) { uchar *bdata = b->buf + b->rn; uchar *edata = b->buf + b->wn; Rune r; int l; char *p, *q; uchar *savebdata; int first; l = 0; if ((flags & SMB_STRING_UNALIGNED) == 0 && (bdata - b->buf) & 1) bdata++; savebdata = bdata; first = 1; do { if (bdata + 2 > edata) { l++; break; } r = smbnhgets(bdata); bdata += 2; if (first && (flags & SMB_STRING_PATH) && r != '\\') l++; first = 0; if (flags & SMB_STRING_CONVERT_MASK) r = smbruneconvert(r, flags); l += runelen(r); } while (r != 0); p = smbemalloc(l); bdata = savebdata; q = p; first = 1; do { if (bdata + 2 > edata) { *q = 0; break; } r = smbnhgets(bdata); bdata += 2; if (first && (flags & SMB_STRING_PATH) && r != '\\') *q++ = '/'; first = 0; if (flags & SMB_STRING_CONVERT_MASK) r = smbruneconvert(r, flags); q += runetochar(q, &r); } while (r != 0); b->rn = bdata - b->buf; *sp = p; 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; }
void smbbuffersetbuf(SmbBuffer *s, void *p, ulong maxlen) { s->realmaxlen = s->maxlen = maxlen; if (s->buf) { if (s->flags & BUFFER) free(s->buf); s->buf = nil; } s->flags &= ~BUFFER; if (p) s->buf = p; else { s->buf = smbemalloc(maxlen); s->flags |= BUFFER; } smbbufferreset(s); }
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; }
SmbProcessResult smbtruncatefile(SmbSession *s, SmbFile *f, vlong offset) { Dir *d; ulong o; uchar *db = nil; vlong length; int rv; SmbProcessResult pr; d = dirfstat(f->fd); assert(d); length = d->length; free(d); if (length == offset) return SmbProcessResultReply; rv = dirfwstatlength(f->fd, offset); if (rv == 0) { pr = SmbProcessResultReply; goto done; } //smblogprint(-1, "dirfwstatlength failed: %r\n"); if (length > offset) { int nfd; char *fullpath; if (offset > INMEMORYTRUNCTHRESH) { smblogprint(-1, "smbcomwrite: truncation beyond %lud not supported\n", offset); pr = SmbProcessResultUnimp; goto done; } db = smbemalloc(offset); if (pread(f->fd, db, offset, 0) != offset) { pr = SmbProcessResultMisc; goto done; } fullpath = nil; smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name); nfd = open(fullpath, f->p9mode | OTRUNC); free(fullpath); if (nfd < 0) { smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } close(nfd); if (pwrite(f->fd, db, offset, 0) != offset) { pr = SmbProcessResultMisc; goto done; } pr = SmbProcessResultReply; } else { db = smbemalloc(16384); memset(db, 0, 16384); o = length; while (o < offset) { long tt = 16384; if (tt > offset - o) tt = offset - o; if (pwrite(f->fd, db, tt, o) != tt) { smbseterror(s, ERRDOS, ERRnoaccess); pr = SmbProcessResultError; goto done; } o += tt; } pr = SmbProcessResultReply; } done: free(db); 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; }
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; }