/* * translate an ip service name into a port number. If it's a numeric port * number, look for restricted access. * * the service '*' needs no translation. */ static char *ipserv(struct network *np, char *name, char *buf, int blen) { char *p; int alpha = 0; int restr = 0; char port[10]; struct ndbtuple *t, *nt; struct ndbs s; /* '*' means any service */ if (strcmp(name, "*") == 0) { strlcpy(buf, name, blen); return buf; } /* see if it's numeric or symbolic */ port[0] = 0; for (p = name; *p; p++) { if (!isdigit(*p)) { if (isalpha(*p) || *p == '-' || *p == '$') alpha = 1; else return 0; } } t = NULL; p = NULL; if (alpha) { p = ndbgetvalue(db, &s, np->net, name, "port", &t); if (p == NULL) return 0; } else { /* look up only for tcp ports < 1024 to get the restricted * attribute */ if (atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) p = ndbgetvalue(db, &s, "port", name, "port", &t); if (p == NULL) p = strdup(name); } if (t) { for (nt = t; nt; nt = nt->entry) if (strcmp(nt->attr, "restricted") == 0) restr = 1; ndbfree(t); } snprintf(buf, blen, "%s%s", p, restr ? "!r" : ""); free(p); return buf; }
/* * lookup a telephone number */ static struct ndbtuple *telcolookup(struct network *np, char *host, char *serv, int nolookup) { struct ndbtuple *t; struct ndbs s; werrstr("can't translate address"); free(ndbgetvalue(db, &s, "sys", host, "telco", &t)); if (t == 0) return ndbnew("telco", host); return reorder(t, s.t); }
static void expand_meta(DS *ds) { static Ndb *db; Ndbs s; char *sys, *smtpserver; /* can't ask cs, so query database directly. */ sys = sysname(); if(db == nil) db = ndbopen(0); smtpserver = ndbgetvalue(db, &s, "sys", sys, "smtp", nil); snprint(ds->host, 128, "%s", smtpserver); }
/* return list of ip addresses for a name */ Ndbtuple* ndbgetipaddr(Ndb *db, char *val) { char *attr, *p; Ndbtuple *it, *first, *last, *next; Ndbs s; /* already an IP address? */ attr = ipattr(val); if(strcmp(attr, "ip") == 0){ it = ndbnew("ip", val); ndbsetmalloctag(it, getcallerpc(&db)); return it; } /* look it up */ p = ndbgetvalue(db, &s, attr, val, "ip", &it); if(p == nil) return nil; free(p); /* remove the non-ip entries */ first = last = nil; for(; it; it = next){ next = it->entry; if(strcmp(it->attr, "ip") == 0){ if(first == nil) first = it; else last->entry = it; it->entry = nil; it->line = first; last = it; } else { it->entry = nil; ndbfree(it); } } ndbsetmalloctag(first, getcallerpc(&db)); return first; }
struct ndbtuple* ndbgetval(struct ndb *db, struct ndbs *s, char *attr, char *val, char *rattr, char *buf) { struct ndbtuple *t; char *p; p = ndbgetvalue(db, s, attr, val, rattr, &t); if(p == NULL){ if(buf != NULL) *buf = 0; } else { if(buf != NULL){ strncpy(buf, p, Ndbvlen-1); buf[Ndbvlen-1] = 0; } free(p); } ndbsetmalloctag(t, getcallerpc(&db)); return t; }
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); } }
/* * fill in all the requested attributes for a system. * if the system's entry doesn't have all required, * walk through successively more inclusive networks * for inherited attributes. */ Ndbtuple* ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n) { Ndbtuple *t, *nt, *f; Ndbs s; char *ipstr; uint8_t net[IPaddrlen], ip[IPaddrlen]; int prefix, smallestprefix, force; int64_t r; /* just in case */ fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); /* get needed attributes */ f = mkfilter(n, alist); /* * first look for a matching entry with an ip address */ t = nil; ipstr = ndbgetvalue(db, &s, attr, val, "ip", &nt); if(ipstr == nil){ /* none found, make one up */ if(strcmp(attr, "ip") != 0) { ndbfree(f); return nil; } t = ndbnew("ip", val); t->line = t; t->entry = nil; r = parseip(net, val); if(r == -1) ndbfree(t); } else { /* found one */ while(nt != nil){ nt = ndbreorder(nt, s.t); t = ndbconcatenate(t, nt); nt = ndbsnext(&s, attr, val); } r = parseip(net, ipstr); free(ipstr); } if(r < 0){ ndbfree(f); return nil; } ipmove(ip, net); t = filter(db, t, f); /* * now go through subnets to fill in any missing attributes */ if(isv4(net)){ prefix = 127; smallestprefix = 100; force = 0; } else { /* in v6, the last 8 bytes have no structure (we hope) */ prefix = 64; smallestprefix = 2; memset(net+8, 0, 8); force = 1; } /* * to find a containing network, keep turning off * the lower bit and look for a network with * that address and a shorter mask. tedius but * complete, we may need to find a trick to speed this up. */ for(; prefix >= smallestprefix; prefix--){ if(filtercomplete(f)) break; if(!force && (net[prefix/8] & (1<<(7-(prefix%8)))) == 0) continue; force = 0; net[prefix/8] &= ~(1<<(7-(prefix%8))); t = ndbconcatenate(t, subnet(db, net, f, prefix)); } /* * if there's an unfulfilled ipmask, make one up */ nt = ndbfindattr(f, f, "ipmask"); if(nt && !(nt->ptr & Fignore)){ char x[64]; snprint(x, sizeof(x), "%M", defmask(ip)); t = ndbconcatenate(t, ndbnew("ipmask", x)); } ndbfree(f); ndbsetmalloctag(t, getcallerpc(&db)); return t; }
/* 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; }
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; }
/* * get the system name */ static void ipid(void) { uint8_t addr[6]; struct ndbtuple *t, *tt; char *p, *attr; struct ndbs s; int f; char buf[Maxpath]; /* use environment, ether addr, or ipaddr to get system name */ if (mysysname == 0) { /* * environment has priority. * * on the sgi power the default system name * is the ip address. ignore that. * */ p = getenv("sysname"); if (p && *p) { attr = ipattr(p); if (strcmp(attr, "ip") != 0) mysysname = strdup(p); } /* * the /net/ndb contains what the network * figured out from DHCP. use that name if * there is one. */ if (mysysname == 0 && netdb != NULL) { ndbreopen(netdb); for (tt = t = ndbparse(netdb); t != NULL; t = t->entry) { if (strcmp(t->attr, "sys") == 0) { mysysname = strdup(t->val); break; } } ndbfree(tt); } /* next network database, ip address, and ether address to find * a name */ if (mysysname == 0) { t = NULL; if (isvalidip(ipa)) free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t)); if (t == NULL) { for (f = 0; f < 3; f++) { snprintf(buf, sizeof(buf), "%s/ether%d", mntpt, f); if (myetheraddr(addr, buf) < 0) continue; snprintf(eaddr, sizeof(eaddr), "%E", addr); free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t)); if (t != NULL) break; } } for (tt = t; tt != NULL; tt = tt->entry) { if (strcmp(tt->attr, "sys") == 0) { mysysname = strdup(tt->val); break; } } ndbfree(t); } /* nothing else worked, use the ip address */ if (mysysname == 0 && isvalidip(ipa)) mysysname = strdup(ipaddr); /* set /dev/sysname if we now know it */ if (mysysname) { f = open("/dev/sysname", O_RDWR); if (f >= 0) { write(f, mysysname, strlen(mysysname)); close(f); } } } }
/* * lookup (and translate) an ip destination */ static struct ndbtuple *iplookup(struct network *np, char *host, char *serv, int nolookup) { char *attr, *dnsname; struct ndbtuple *t, *nt; struct ndbs s; char ts[Maxservice]; char dollar[Maxhost]; uint8_t ip[IPaddrlen]; uint8_t net[IPaddrlen]; uint8_t tnet[IPaddrlen]; struct ipifc *ifc; struct iplifc *lifc; /* * start with the service since it's the most likely to fail * and costs the least */ werrstr("can't translate address"); if (serv == 0 || ipserv(np, serv, ts, sizeof(ts)) == 0) { werrstr("can't translate service"); return 0; } /* for dial strings with no host */ if (strcmp(host, "*") == 0) return ndbnew("ip", "*"); /* * hack till we go v6 :: = 0.0.0.0 */ if (strcmp("::", host) == 0) return ndbnew("ip", "*"); /* * '$' means the rest of the name is an attribute that we * need to search for */ if (*host == '$') { if (ipattrlookup(db, ipaddr, host + 1, dollar, sizeof(dollar))) host = dollar; } /* * turn '[ip address]' into just 'ip address' */ if (*host == '[' && host[strlen(host) - 1] == ']') { host++; host[strlen(host) - 1] = 0; } /* * just accept addresses */ attr = ipattr(host); if (strcmp(attr, "ip") == 0) return ndbnew("ip", host); /* * give the domain name server the first opportunity to * resolve domain names. if that fails try the database. */ t = 0; werrstr("can't translate address"); if (strcmp(attr, "dom") == 0) t = dnsiplookup(host, &s); if (t == 0) free(ndbgetvalue(db, &s, attr, host, "ip", &t)); if (t == 0) { dnsname = ndbgetvalue(db, &s, attr, host, "dom", NULL); if (dnsname) { t = dnsiplookup(dnsname, &s); free(dnsname); } } if (t == 0) t = dnsiplookup(host, &s); if (t == 0) return 0; /* * reorder the tuple to have the matched line first and * save that in the request structure. */ t = reorder(t, s.t); /* * reorder according to our interfaces */ spinlock_lock(&ipifclock); for (ifc = ipifcs; ifc != NULL; ifc = ifc->next) { for (lifc = ifc->lifc; lifc != NULL; lifc = lifc->next) { maskip(lifc->ip, lifc->mask, net); for (nt = t; nt; nt = nt->entry) { if (strcmp(nt->attr, "ip") != 0) continue; parseip(ip, nt->val); maskip(ip, lifc->mask, tnet); if (memcmp(net, tnet, IPaddrlen) == 0) { t = reorder(t, nt); spinlock_unlock(&ipifclock); return t; } } } } spinlock_unlock(&ipifclock); return t; }