/* * return true of the speaker may speak for the user * * a speaker may always speak for himself/herself */ int speaksfor(char *speaker, char *user) { Ndbtuple *tp, *ntp; Ndbs s; int ok; char notuser[Maxpath]; if(strcmp(speaker, user) == 0) return 1; if(db == 0) return 0; tp = ndbsearch(db, &s, "hostid", speaker); if(tp == 0) return 0; ok = 0; snprint(notuser, sizeof notuser, "!%s", user); for(ntp = tp; ntp; ntp = ntp->entry) if(strcmp(ntp->attr, "uid") == 0){ if(strcmp(ntp->val, notuser) == 0){ ok = 0; break; } if(*ntp->val == '*' || strcmp(ntp->val, user) == 0) ok = 1; } ndbfree(tp); return ok; }
/* * look through a containing subset */ static Ndbtuple* subnet(Ndb *db, uint8_t *net, Ndbtuple *f, int prefix) { Ndbs s; Ndbtuple *t, *nt, *xt; char netstr[128]; uint8_t mask[IPaddrlen]; int masklen; t = nil; sprint(netstr, "%I", net); nt = ndbsearch(db, &s, "ip", netstr); while(nt != nil){ xt = ndbfindattr(nt, nt, "ipnet"); if(xt){ xt = ndbfindattr(nt, nt, "ipmask"); if(xt) parseipmask(mask, xt->val); else ipmove(mask, defmask(net)); masklen = prefixlen(mask); if(masklen <= prefix){ t = ndbconcatenate(t, filter(db, nt, f)); nt = nil; } } ndbfree(nt); nt = ndbsnext(&s, "ip", netstr); } ndbsetmalloctag(t, getcallerpc(&db)); return t; }
/* * generic query lookup. The query is of one of the following * forms: * * attr1=val1 attr2=val2 attr3=val3 ... * * returns the matching tuple * * ipinfo attr=val attr1 attr2 attr3 ... * * is like ipinfo and returns the attr{1-n} * associated with the ip address. */ static char *genquery(struct mfile *mf, char *query) { int i, n; char *p; char *attr[Maxattr]; char *val[Maxattr]; struct ndbtuple *t; struct ndbs s; n = getfields(query, attr, COUNT_OF(attr), 1, " "); if (n == 0) return "bad query"; if (strcmp(attr[0], "ipinfo") == 0) return ipinfoquery(mf, attr, n); /* parse pairs */ for (i = 0; i < n; i++) { p = strchr(attr[i], '='); if (p == 0) return "bad query"; *p++ = 0; val[i] = p; } /* give dns a chance */ if ((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]) { t = dnsiplookup(val[0], &s); if (t) { if (qmatch(t, attr, val, n)) { qreply(mf, t); ndbfree(t); return 0; } ndbfree(t); } } /* first pair is always the key. It can't be a '*' */ t = ndbsearch(db, &s, attr[0], val[0]); /* search is the and of all the pairs */ while (t) { if (qmatch(t, attr, val, n)) { qreply(mf, t); ndbfree(t); return 0; } ndbfree(t); t = ndbsnext(&s, attr[0], val[0]); } return "no match"; }
void search(Ndb *db, char *attr, char *val, char *rattr) { char *p; Ndbs s; Ndbtuple *t, *nt; /* first entry with a matching rattr */ if(rattr && !all){ p = ndbgetvalue(db, &s, attr, val, rattr, &t); if (multiple) prmatch(t, rattr); else if(p) Bprint(&bout, "%s\n", p); ndbfree(t); free(p); return; } /* all entries with matching rattrs */ if(rattr) { for(t = ndbsearch(db, &s, attr, val); t != nil; t = ndbsnext(&s, attr, val)){ prmatch(t, rattr); ndbfree(t); } return; } /* all entries */ for(t = ndbsearch(db, &s, attr, val); t; t = ndbsnext(&s, attr, val)){ for(nt = t; nt; nt = nt->entry) Bprint(&bout, "%s=%s ", nt->attr, nt->val); Bprint(&bout, "\n"); ndbfree(t); } }
/* * the database entry in 'file' indicates the list of files * that makeup the database. Open each one and search in * the same order. */ struct ndb* ndbopen(char *file) { struct ndb *db, *first, *last; struct ndbs s; struct ndbtuple *t, *nt; if(file == 0) file = deffile; db = doopen(file); if(db == 0) { return 0; } first = last = db; t = ndbsearch(db, &s, "database", ""); fseek(db->b, 0, 0); if(t == 0) { return db; } for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "file") != 0) continue; if(strcmp(nt->val, file) == 0){ /* default file can be reordered in the list */ if(first->next == 0) continue; if(strcmp(first->file, file) == 0){ db = first; first = first->next; last->next = db; db->next = 0; last = db; } continue; } db = doopen(nt->val); if(db == 0) continue; last->next = db; last = db; } ndbfree(t); return first; }
/* * search for a tuple that has the given 'attr=val' and also 'rattr=x'. * copy 'x' into 'buf' and return the whole tuple. * * return 0 if not found. */ char* ndbgetvalue(struct ndb *db, struct ndbs *s, char *attr, char *val, char *rattr, struct ndbtuple **pp) { struct ndbtuple *t, *nt; char *rv; struct ndbs temps; if(s == NULL) s = &temps; if(pp) *pp = NULL; t = ndbsearch(db, s, attr, val); while(t){ /* first look on same line (closer binding) */ nt = s->t; for(;;){ if(strcmp(rattr, nt->attr) == 0){ rv = strdup(nt->val); if(pp != NULL) *pp = t; else ndbfree(t); return rv; } nt = nt->line; if(nt == s->t) break; } /* search whole tuple */ for(nt = t; nt; nt = nt->entry){ if(strcmp(rattr, nt->attr) == 0){ rv = strdup(nt->val); if(pp != NULL) *pp = t; else ndbfree(t); return rv; } } ndbfree(t); t = ndbsnext(s, attr, val); } return NULL; }
static void recursesubnet(Ndb *db, uchar *addr, uchar *mask, char *attr, char *name, char *name1) { Ndbs s; Ndbtuple *t, *nt; uchar submask[IPaddrlen], net[IPaddrlen]; char ip[Ndbvlen]; int found; maskip(addr, mask, net); sprint(ip, "%I", net); t = ndbsearch(db, &s, "ip", ip); if(t == 0) return; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ipmask") == 0){ parseip(submask, nt->val); if(memcmp(submask, mask, IPaddrlen) != 0) recursesubnet(db, addr, submask, attr, name, name1); break; } } if(name[0] == 0){ found = 0; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, attr) == 0){ if(found){ strcpy(name, nt->val); name1[0] = 0; found = 1; } else { strcpy(name1, nt->val); break; } } } } ndbfree(t); }
/* * return the ip addresses for a type of server for system ip */ int lookupserver(char *attr, uchar ipaddrs[2][IPaddrlen], Ipinfo *iip) { Ndbtuple *t, *nt; Ndbs s; char ip[32]; char name[Ndbvlen]; char name1[Ndbvlen]; int i; name[0] = name1[0] = 0; snprint(ip, sizeof(ip), "%I", iip->ipaddr); t = ndbsearch(db, &s, "ip", ip); while(t){ for(nt = t; nt; nt = nt->entry){ if(strcmp(attr, nt->attr) == 0){ if(*name == 0) strcpy(name, nt->val); else { strcpy(name1, nt->val); break; } } } if(name[0]) break; t = ndbsnext(&s, "ip", ip); } if(name[0] == 0) recursesubnet(db, iip->ipaddr, classmask[CLASS(iip->ipaddr)], attr, name, name1); i = 0; if(name[0] && getipaddr(db, name, *ipaddrs, iip) == 1){ ipaddrs++; i++; } if(name1[0] && getipaddr(db, name1, *ipaddrs, iip) == 1) i++; return i; }
int dbctlr(char* name, Vga* vga) { Ndb *db; Ndbs s; Ndbtuple *tuple; Ndbtuple *pcituple; db = dbopen(name); /* * Search vgadb for a matching BIOS string or PCI id. * If we have both, the BIOS string wins. */ pcituple = nil; for(tuple = ndbsearch(db, &s, "ctlr", ""); tuple; tuple = ndbsnext(&s, "ctlr", "")){ if(!pcituple && dbpci(vga, tuple)) pcituple = tuple; if(dbbios(vga, tuple)){ save(vga, tuple); if(pcituple && pcituple != tuple) ndbfree(pcituple); ndbfree(tuple); ndbclose(db); return 1; } if(tuple != pcituple) ndbfree(tuple); } if(pcituple){ save(vga, pcituple); ndbfree(pcituple); } ndbclose(db); if(pcituple) return 1; return 0; }
/* * lookup a subnet and fill in anything we can */ static void recursesubnet(Ndb *db, uint8_t *mask, Ipinfo *iip, char *fs, char *gw, char *au) { Ndbs s; Ndbtuple *t; uint8_t submask[IPaddrlen]; char ip[Ndbvlen]; memmove(iip->ipmask, mask, 4); maskip(iip->ipaddr, iip->ipmask, iip->ipnet); sprint(ip, "%I", iip->ipnet); t = ndbsearch(db, &s, "ip", ip); print("%s->", ip); if(t){ /* look for a further subnet */ if(lookval(t, s.t, "ipmask", ip)){ parseip(submask, ip); /* recurse only if it has changed */ if(!equivip(submask, mask)) recursesubnet(db, submask, iip, fs, gw, au); } /* fill in what we don't have */ if(gw[0] == 0) lookval(t, s.t, "ipgw", gw); if(fs[0] == 0) lookval(t, s.t, "fs", fs); if(au[0] == 0) lookval(t, s.t, "auth", au); ndbfree(t); } }
/* * find out everything we can about a system from what has been * specified. */ int ipinfo(Ndb *db, char *etherin, char *ipin, char *name, Ipinfo *iip) { Ndbtuple *t; Ndbs s; char ether[Ndbvlen]; char ip[Ndbvlen]; char fsname[Ndbvlen]; char gwname[Ndbvlen]; char auname[Ndbvlen]; memset(iip, 0, sizeof(Ipinfo)); fsname[0] = 0; gwname[0] = 0; auname[0] = 0; /* * look for a matching entry */ t = 0; if(etherin) t = ndbgetval(db, &s, "ether", etherin, "ip", ip); if(t == 0 && ipin) t = ndbsearch(db, &s, "ip", ipin); if(t == 0 && name) t = ndbgetval(db, &s, ipattr(name), name, "ip", ip); if(t){ /* * copy in addresses and name */ if(lookval(t, s.t, "ip", ip)) parseip(iip->ipaddr, ip); if(lookval(t, s.t, "ether", ether)) parseether(iip->etheraddr, ether); lookval(t, s.t, "dom", iip->domain); /* * Look for bootfile, fs, and gateway. * If necessary, search through all entries for * this ip address. */ while(t){ if(iip->bootf[0] == 0) lookval(t, s.t, "bootf", iip->bootf); if(fsname[0] == 0) lookval(t, s.t, "fs", fsname); if(gwname[0] == 0) lookval(t, s.t, "ipgw", gwname); if(auname[0] == 0) lookval(t, s.t, "auth", auname); ndbfree(t); if(iip->bootf[0] && fsname[0] && gwname[0] && auname[0]) break; t = ndbsnext(&s, "ether", ether); } } else if(ipin) { /* * copy in addresses (all we know) */ parseip(iip->ipaddr, ipin); if(etherin) parseether(iip->etheraddr, etherin); } else return -1; /* * Look up the client's network and find a subnet mask for it. * Fill in from the subnet (or net) entry anything we can't figure * out from the client record. */ recursesubnet(db, classmask[CLASS(iip->ipaddr)], iip, fsname, gwname, auname); /* lookup fs's and gw's ip addresses */ if(fsname[0]) lookupip(db, fsname, iip->fsip, iip); if(gwname[0]) lookupip(db, gwname, iip->gwip, iip); if(auname[0]) lookupip(db, auname, iip->auip, iip); return 0; }
/* returns 0 on success, error message on failure */ char* secureidcheck(char *user, char *response) { Packet *req = nil, *resp = nil; ulong u[4]; uchar x[16]; char *radiussecret; char ruser[ 64]; char dest[3*IPaddrlen+20]; Secret shared, pass; char *rv = "authentication failed"; Ndbs s; Ndbtuple *t, *nt, *tt; uchar *ip; static Ndb *netdb; if(netdb == nil) netdb = ndbopen(0); /* bad responses make them disable the fob, avoid silly checks */ if(strlen(response) < 4 || strpbrk(response,"abcdefABCDEF") != nil) goto out; /* get radius secret */ radiussecret = ndbgetvalue(db, &s, "radius", "lra-radius", "secret", &t); if(radiussecret == nil){ syslog(0, AUTHLOG, "secureidcheck: nil radius secret: %r"); goto out; } /* translate user name if we have to */ strcpy(ruser, user); for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "uid") == 0 && strcmp(nt->val, user) == 0) for(tt = nt->line; tt != nt; tt = tt->line) if(strcmp(tt->attr, "rid") == 0){ strcpy(ruser, tt->val); break; } } ndbfree(t); u[0] = fastrand(); u[1] = fastrand(); u[2] = fastrand(); u[3] = fastrand(); req = newRequest((uchar*)u); if(req == nil) goto out; shared.s = (uchar*)radiussecret; shared.len = strlen(radiussecret); ip = getipv4addr(); if(ip == nil){ syslog(0, AUTHLOG, "no interfaces: %r\n"); goto out; } if(setAttribute(req, R_NASIPAddress, ip + IPv4off, 4) < 0) goto out; if(setAttribute(req, R_UserName, (uchar*)ruser, strlen(ruser)) < 0) goto out; pass.s = (uchar*)response; pass.len = strlen(response); hide(&shared, req->authenticator, &pass, x); if(setAttribute(req, R_UserPassword, x, 16) < 0) goto out; t = ndbsearch(netdb, &s, "sys", "lra-radius"); if(t == nil){ syslog(0, AUTHLOG, "secureidcheck: nil radius sys search: %r\n"); goto out; } for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; snprint(dest,sizeof dest,"udp!%s!oradius", nt->val); resp = rpc(dest, &shared, req); if(resp == nil){ syslog(0, AUTHLOG, "%s nil response", dest); continue; } if(resp->ID != req->ID){ syslog(0, AUTHLOG, "%s mismatched ID req=%d resp=%d", dest, req->ID, resp->ID); freePacket(resp); resp = nil; continue; } switch(resp->code){ case R_AccessAccept: syslog(0, AUTHLOG, "%s accepted ruser=%s", dest, ruser); rv = nil; break; case R_AccessReject: syslog(0, AUTHLOG, "%s rejected ruser=%s %s", dest, ruser, replymsg(resp)); rv = "secureid failed"; break; case R_AccessChallenge: syslog(0, AUTHLOG, "%s challenge ruser=%s %s", dest, ruser, replymsg(resp)); rv = "secureid out of sync"; break; default: syslog(0, AUTHLOG, "%s code=%d ruser=%s %s", dest, resp->code, ruser, replymsg(resp)); break; } break; /* we have a proper reply, no need to ask again */ } ndbfree(t); free(radiussecret); out: freePacket(req); freePacket(resp); return rv; }
Mode* dbmode(char* name, char* type, char* size) { Ndb *db; Ndbs s; Ndbtuple *t, *tuple; Mode *mode; char attr[Namelen+1]; ulong videobw; db = dbopen(name); mode = alloc(sizeof(Mode)); strcpy(attr, type); videobw = 0; /* * Look for the attr=size entry. */ if(dbmonitor(db, mode, attr, size)){ strcpy(mode->type, type); strcpy(mode->size, size); ndbclose(db); return mode; } if(mode->videobw && videobw == 0) /* we at least found that; save it away */ videobw = mode->videobw; /* * Not found. Look for an attr="" entry and then * for an alias=attr within. */ buggery: for(tuple = ndbsearch(db, &s, attr, ""); tuple; tuple = ndbsnext(&s, attr, "")){ for(t = tuple->entry; t; t = t->entry){ if(strcmp(t->attr, "alias")) continue; strcpy(attr, t->val); if(dbmonitor(db, mode, attr, size)){ strcpy(mode->type, type); strcpy(mode->size, size); ndbfree(tuple); ndbclose(db); if(videobw) mode->videobw = videobw; return mode; } /* * Found an alias but no match for size, * restart looking for attr="" with the * new attr. */ ndbfree(tuple); goto buggery; } ndbfree(tuple); } free(mode); ndbclose(db); return 0; }
static int dbmonitor(Ndb* db, Mode* mode, char* type, char* size) { Ndbs s; Ndbtuple *t, *tuple; char *p, attr[Namelen+1], val[Namelen+1], buf[2*Namelen+1]; int clock, x, i; /* * Clock rate hack. * If the size is 'XxYxZ@NMHz' then override the database entry's * 'clock=' with 'N*1000000'. */ clock = 0; strcpy(buf, size); if(p = strchr(buf, '@')){ *p++ = 0; if((clock = strtol(p, &p, 0)) && strcmp(p, "MHz") == 0) clock *= 1000000; } memset(mode, 0, sizeof(Mode)); if((p = strchr(buf, 'x')) && (p = strchr(p+1, 'x'))){ *p++ = 0; mode->z = atoi(p); } strcpy(attr, type); strcpy(val, buf); if(p = ndbgetvalue(db, &s, attr, "", "videobw", nil)){ mode->videobw = atol(p)*1000000UL; free(p); } if(mode->x == 0 && ((mode->x = strtol(val, &p, 0)) == 0 || *p++ != 'x')) return 0; if(mode->y == 0 && (mode->y = strtol(p, &p, 0)) == 0) return 0; i = 0; buggery: if((tuple = ndbsearch(db, &s, attr, val)) == 0) return 0; for(t = tuple->entry; t; t = t->entry){ if(strcmp(t->attr, "clock") == 0 && mode->frequency == 0) mode->frequency = strtod(t->val, 0)*1000000; else if(strcmp(t->attr, "defaultclock") == 0 && mode->deffrequency == 0) mode->deffrequency = strtod(t->val, 0)*1000000; else if(strcmp(t->attr, "ht") == 0 && mode->ht == 0) mode->ht = strtol(t->val, 0, 0); else if(strcmp(t->attr, "shb") == 0 && mode->shb == 0) mode->shb = strtol(t->val, 0, 0); else if(strcmp(t->attr, "ehb") == 0 && mode->ehb == 0) mode->ehb = strtol(t->val, 0, 0); else if(strcmp(t->attr, "shs") == 0 && mode->shs == 0) mode->shs = strtol(t->val, 0, 0); else if(strcmp(t->attr, "ehs") == 0 && mode->ehs == 0) mode->ehs = strtol(t->val, 0, 0); else if(strcmp(t->attr, "vt") == 0 && mode->vt == 0) mode->vt = strtol(t->val, 0, 0); else if(strcmp(t->attr, "vrs") == 0 && mode->vrs == 0) mode->vrs = strtol(t->val, 0, 0); else if(strcmp(t->attr, "vre") == 0 && mode->vre == 0) mode->vre = strtol(t->val, 0, 0); else if(strcmp(t->attr, "hsync") == 0) mode->hsync = *t->val; else if(strcmp(t->attr, "vsync") == 0) mode->vsync = *t->val; else if(strcmp(t->attr, "interlace") == 0) mode->interlace = *t->val; else if(strcmp(t->attr, "include") == 0 /*&& strcmp(t->val, val) != 0*/){ strcpy(attr, t->attr); strcpy(val, t->val); ndbfree(tuple); if(i++ > 5) error("dbmonitor: implausible include depth at %s=%s\n", attr, val); goto buggery; } else if(strcmp(t->attr, "include") == 0){ print("warning: bailed out of infinite loop in attr %s=%s\n", attr, val); } else addattr(&mode->attr, t); } ndbfree(tuple); if((x = strtol(size, &p, 0)) == 0 || x != mode->x || *p++ != 'x') return 0; if((x = strtol(p, &p, 0)) == 0 || x != mode->y || *p++ != 'x') return 0; if((x = strtol(p, &p, 0)) == 0 || x != mode->z) return 0; if(clock) mode->frequency = clock; return 1; }
/* * lookup info about a client in the database. Find an address on the * same net as riip. */ int lookup(Bootp *bp, Info *iip, Info *riip) { Ndbtuple *t, *nt; Ndbs s; char *hwattr; char *hwval, hwbuf[33]; uchar ciaddr[IPaddrlen]; if(opendb() == nil){ warning(1, "can't open db"); return -1; } memset(iip, 0, sizeof(*iip)); /* client knows its address? */ v4tov6(ciaddr, bp->ciaddr); if(validip(ciaddr)){ if(lookupip(ciaddr, iip, 0) < 0) { if (debug) warning(0, "don't know %I", ciaddr); return -1; /* don't know anything about it */ } if(!samenet(riip->ipaddr, iip)){ warning(0, "%I not on %I", ciaddr, riip->ipnet); return -1; } /* * see if this is a masquerade, i.e., if the ether * address doesn't match what we expected it to be. */ if(memcmp(iip->etheraddr, zeroes, 6) != 0) if(memcmp(bp->chaddr, iip->etheraddr, 6) != 0) warning(0, "ciaddr %I rcvd from %E instead of %E", ciaddr, bp->chaddr, iip->etheraddr); return 0; } if(bp->hlen > Maxhwlen) return -1; switch(bp->htype){ case 1: hwattr = "ether"; hwval = hwbuf; snprint(hwbuf, sizeof(hwbuf), "%E", bp->chaddr); break; default: syslog(0, blog, "not ethernet %E, htype %d, hlen %d", bp->chaddr, bp->htype, bp->hlen); return -1; } /* * use hardware address to find an ip address on * same net as riip */ t = ndbsearch(db, &s, hwattr, hwval); while(t){ for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; parseip(ciaddr, nt->val); if(lookupip(ciaddr, iip, 0) < 0) continue; if(samenet(riip->ipaddr, iip)){ ndbfree(t); return 0; } } ndbfree(t); t = ndbsnext(&s, hwattr, hwval); } return -1; }