diff options
author | wollman <wollman@FreeBSD.org> | 1996-12-11 20:59:33 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1996-12-11 20:59:33 +0000 |
commit | 83f39a352fd47b026ef54bebe526949cf5b76367 (patch) | |
tree | 0f44d37675a614d1efef4ab2c3ea8aa9f9136e2d /sbin/routed/parms.c | |
parent | df774327d2e70a847613acdd71454d2411ec3a7b (diff) | |
download | FreeBSD-src-83f39a352fd47b026ef54bebe526949cf5b76367.zip FreeBSD-src-83f39a352fd47b026ef54bebe526949cf5b76367.tar.gz |
New version of Vern's routed. This includes more byte-order fixes,
some MD5 fixes, better tracing, configurable redirect processing,
and a fix to split-horizon/poisoned-reverse treatment.
Submitted by: Vernon J. Schryver <vjs@mica.denver.sgi.com>
Diffstat (limited to 'sbin/routed/parms.c')
-rw-r--r-- | sbin/routed/parms.c | 233 |
1 files changed, 137 insertions, 96 deletions
diff --git a/sbin/routed/parms.c b/sbin/routed/parms.c index ab5c75e..87ca4a8 100644 --- a/sbin/routed/parms.c +++ b/sbin/routed/parms.c @@ -36,10 +36,11 @@ static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; #elif defined(__NetBSD__) static char rcsid[] = "$NetBSD$"; #endif -#ident "$Revision: 1.10 $" +#ident "$Revision: 1.12 $" #include "defs.h" #include "pathnames.h" +#include <sys/stat.h> struct parm *parms; @@ -54,6 +55,7 @@ get_parms(struct interface *ifp) { static warned_auth_in, warned_auth_out; struct parm *parmp; + int i, num_passwds = 0; /* get all relevant parameters */ @@ -68,9 +70,14 @@ get_parms(struct interface *ifp) * so get its settings */ ifp->int_state |= parmp->parm_int_state; - if (parmp->parm_auth.type != RIP_AUTH_NONE) - bcopy(&parmp->parm_auth, &ifp->int_auth, - sizeof(ifp->int_auth)); + for (i = 0; i < MAX_AUTH_KEYS; i++) { + if (parmp->parm_auth[0].type == RIP_AUTH_NONE + || num_passwds >= MAX_AUTH_KEYS) + break; + bcopy(&parmp->parm_auth[i], + &ifp->int_auth[num_passwds++], + sizeof(ifp->int_auth[0])); + } if (parmp->parm_rdisc_pref != 0) ifp->int_rdisc_pref = parmp->parm_rdisc_pref; if (parmp->parm_rdisc_int != 0) @@ -114,7 +121,7 @@ get_parms(struct interface *ifp) ifp->int_state |= IS_NO_RIP; if (!IS_RIP_IN_OFF(ifp->int_state) - && ifp->int_auth.type != RIP_AUTH_NONE + && ifp->int_auth[0].type != RIP_AUTH_NONE && !(ifp->int_state & IS_NO_RIPV1_IN) && !warned_auth_in) { msglog("Warning: RIPv1 input via %s" @@ -123,14 +130,14 @@ get_parms(struct interface *ifp) warned_auth_in = 1; } if (!IS_RIP_OUT_OFF(ifp->int_state) - && ifp->int_auth.type != RIP_AUTH_NONE - && !(ifp->int_state & IS_NO_RIPV1_OUT) - && !warned_auth_out) { - msglog("Warning: RIPv1 output via %s" - " will be sent without authentication", - ifp->int_name); - warned_auth_out = 1; - ifp->int_auth.type = RIP_AUTH_NONE; + && ifp->int_auth[0].type != RIP_AUTH_NONE + && !(ifp->int_state & IS_NO_RIPV1_OUT)) { + if (!warned_auth_out) { + msglog("Warning: RIPv1 output via %s" + " will be sent without authentication", + ifp->int_name); + warned_auth_out = 1; + } } } @@ -160,6 +167,7 @@ gwkludge(void) struct interface *ifp; naddr dst, netmask, gate; int metric, n; + struct stat sb; u_int state; char *type; @@ -168,6 +176,12 @@ gwkludge(void) if (fp == 0) return; + if (0 > fstat(fileno(fp), &sb)) { + msglog("could not stat() "_PATH_GATEWAYS); + (void)fclose(fp); + return; + } + for (;;) { if (0 == fgets(lbuf, sizeof(lbuf)-1, fp)) break; @@ -185,10 +199,12 @@ gwkludge(void) */ if (strncasecmp("net", lptr, 3) && strncasecmp("host", lptr, 4)) { - p = parse_parms(lptr); + p = parse_parms(lptr, + (sb.st_uid == 0 + && !(sb.st_mode&(S_IRWXG|S_IRWXO)))); if (p != 0) { if (strcasecmp(p,lptr)) - msglog("bad %s in "_PATH_GATEWAYS + msglog("%s in "_PATH_GATEWAYS " entry \"%s\"", p, lptr); else msglog("bad \"%s\" in "_PATH_GATEWAYS, @@ -225,6 +241,7 @@ gwkludge(void) " entry \"%s\"", dname, lptr); continue; } + HTONL(dst); /* make network # into IP address */ } else { msglog("bad \"%s\" in "_PATH_GATEWAYS " entry \"%s\"", lptr); @@ -333,12 +350,14 @@ gwkludge(void) trace_if("Add", ifp); } + + (void)fclose(fp); } /* strtok(), but honoring backslash */ -static int /* -1=bad */ +static int /* 0=ok, -1=bad */ parse_quote(char **linep, char *delims, char *delimp, @@ -352,9 +371,7 @@ parse_quote(char **linep, if (*pc == '\0') return -1; - for (;;) { - if (lim == 0) - return -1; + while (lim != 0) { c = *pc++; if (c == '\0') break; @@ -388,11 +405,13 @@ parse_quote(char **linep, --lim; } exit: + if (lim == 0) + return -1; + + *buf = '\0'; if (delimp != 0) *delimp = c; *linep = pc-1; - if (lim != 0) - *buf = '\0'; return 0; } @@ -413,7 +432,7 @@ parse_ts(time_t *tp, buf,bufsize) || buf[bufsize-1] != '\0' || buf[bufsize-2] != '\0') { - sprintf(buf,"timestamp %.25s", val0); + sprintf(buf,"bad timestamp %.25s", val0); return buf; } strcat(buf,"\n"); @@ -421,14 +440,14 @@ parse_ts(time_t *tp, if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min)) { - sprintf(buf,"timestamp %.25s", val0); + sprintf(buf,"bad timestamp %.25s", val0); return buf; } if (tm.tm_year <= 37) tm.tm_year += 100; if ((*tp = mktime(&tm)) == -1) { - sprintf(buf,"timestamp %.25s", val0); + sprintf(buf,"bad timestamp %.25s", val0); return buf; } @@ -436,92 +455,93 @@ parse_ts(time_t *tp, } -/* Get one or more password, key ID's, and expiration dates in - * the format - * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min|passwd|... +/* Get a password, key ID, and expiration date in the format + * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min */ static char * /* 0 or error message */ -get_passwds(char *tgt, - char *val, - struct parm *parmp, - u_char type) +get_passwd(char *tgt, + char *val, + struct parm *parmp, + u_char type, + int safe) /* 1=from secure file */ { static char buf[80]; char *val0, *p, delim; - struct auth_key *akp, *akp2; + struct auth k, *ap, *ap2; int i; u_long l; - if (parmp->parm_auth.type != RIP_AUTH_NONE) - return "duplicate authentication"; - parmp->parm_auth.type = type; + if (!safe) + return "unsafe password"; - bzero(buf, sizeof(buf)); + for (ap = parmp->parm_auth, i = 0; + ap->type != RIP_AUTH_NONE; i++, ap++) { + if (i >= MAX_AUTH_KEYS) + return "too many passwords"; + } - akp = parmp->parm_auth.keys; - for (i = 0; i < MAX_AUTH_KEYS; i++, val++, akp++) { - if ((delim = *val) == '\0') - break; - val0 = val; - if (0 > parse_quote(&val, "| ,\n\r", &delim, - (char *)akp->key, sizeof(akp->key))) - return tgt; + bzero(&k, sizeof(k)); + k.type = type; + k.end = -1-DAY; - akp->end = -1; + val0 = val; + if (0 > parse_quote(&val, "| ,\n\r", &delim, + (char *)k.key, sizeof(k.key))) + return tgt; - if (delim != '|') { - if (type == RIP_AUTH_MD5) - return "missing Keyid"; - break; - } + if (delim != '|') { + if (type == RIP_AUTH_MD5) + return "missing Keyid"; + } else { val0 = ++val; + buf[sizeof(buf)-1] = '\0'; if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf)) || buf[sizeof(buf)-1] != '\0' || (l = strtoul(buf,&p,0)) > 255 || *p != '\0') { - sprintf(buf,"KeyID \"%.20s\"", val0); + sprintf(buf,"bad KeyID \"%.20s\"", val0); return buf; } - for (akp2 = parmp->parm_auth.keys; akp2 < akp; akp2++) { - if (akp2->keyid == l) { - *val = '\0'; + for (ap2 = parmp->parm_auth; ap2 < ap; ap2++) { + if (ap2->keyid == l) { sprintf(buf,"duplicate KeyID \"%.20s\"", val0); return buf; } } - akp->keyid = (int)l; - - if (delim != '|') - break; - - val0 = ++val; - if (0 != (p = parse_ts(&akp->start,&val,val0,&delim, - buf,sizeof(buf)))) - return p; - if (delim != '|') - return "missing second timestamp"; - val0 = ++val; - if (0 != (p = parse_ts(&akp->end,&val,val0,&delim, - buf,sizeof(buf)))) - return p; - if ((u_long)akp->start > (u_long)akp->end) { - sprintf(buf,"out of order timestamp %.30s",val0); - return buf; + k.keyid = (int)l; + + if (delim == '|') { + val0 = ++val; + if (0 != (p = parse_ts(&k.start,&val,val0,&delim, + buf,sizeof(buf)))) + return p; + if (delim != '|') + return "missing second timestamp"; + val0 = ++val; + if (0 != (p = parse_ts(&k.end,&val,val0,&delim, + buf,sizeof(buf)))) + return p; + if ((u_long)k.start > (u_long)k.end) { + sprintf(buf,"out of order timestamp %.30s", + val0); + return buf; + } } - - if (delim != '|') - break; } + if (delim != '\0') + return tgt; - return (delim != '\0') ? tgt : 0; + bcopy(&k, ap, sizeof(*ap)); + return 0; } /* Parse a set of parameters for an interface. */ char * /* 0 or error message */ -parse_parms(char *line) +parse_parms(char *line, + int safe) /* 1=from secure file */ { #define PARS(str) (!strcasecmp(tgt, str)) #define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str))) @@ -554,6 +574,7 @@ parse_parms(char *line) free(intnetp); return line; } + HTONL(intnetp->intnet_addr); intnetp->intnet_next = intnets; intnets = intnetp; return 0; @@ -591,7 +612,7 @@ parse_parms(char *line) * The parm_net stuff is needed to allow several * -F settings. */ - if (!getnet(val, &addr, &mask) + if (!getnet(val0, &addr, &mask) || parm.parm_name[0] != '\0') return tgt; parm.parm_net = addr; @@ -599,14 +620,21 @@ parse_parms(char *line) parm.parm_name[0] = '\n'; } else if (PARSEQ("passwd")) { - tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_PW); - if (tgt) + /* since cleartext passwords are so weak allow + * them anywhere + */ + tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1); + if (tgt) { + *val0 = '\0'; return tgt; + } } else if (PARSEQ("md5_passwd")) { - tgt = get_passwds(tgt, val0, &parm, RIP_AUTH_MD5); - if (tgt) + tgt = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe); + if (tgt) { + *val0 = '\0'; return tgt; + } } else if (PARS("no_ag")) { parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG); @@ -693,6 +721,9 @@ parse_parms(char *line) tgates = tg; parm.parm_int_state |= IS_DISTRUST; + } else if (PARS("redirect_ok")) { + parm.parm_int_state |= IS_REDIRECT_OK; + } else { return tgt; /* error */ } @@ -708,16 +739,24 @@ parse_parms(char *line) char * /* 0 or error message */ check_parms(struct parm *new) { - struct parm *parmp; + struct parm *parmp, **parmpp; + int i, num_passwds; /* set implicit values */ if (new->parm_int_state & IS_NO_ADV_IN) new->parm_int_state |= IS_NO_SOL_OUT; + for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) { + if (new->parm_auth[i].type != RIP_AUTH_NONE) + num_passwds++; + } + /* compare with existing sets of parameters */ - for (parmp = parms; parmp != 0; parmp = parmp->parm_next) { + for (parmpp = &parms; + (parmp = *parmpp) != 0; + parmpp = &parmp->parm_next) { if (strcmp(new->parm_name, parmp->parm_name)) continue; if (!on_net(htonl(parmp->parm_net), @@ -726,12 +765,12 @@ check_parms(struct parm *new) parmp->parm_net, parmp->parm_mask)) continue; - if (parmp->parm_auth.type != RIP_AUTH_NONE - && new->parm_auth.type != RIP_AUTH_NONE - && bcmp(&parmp->parm_auth, &new->parm_auth, - sizeof(parmp->parm_auth))) { - return "conflicting, duplicate authentication"; + for (i = 0; i < MAX_AUTH_KEYS; i++) { + if (parmp->parm_auth[i].type != RIP_AUTH_NONE) + num_passwds++; } + if (num_passwds > MAX_AUTH_KEYS) + return "too many conflicting passwords"; if ((0 != (new->parm_int_state & GROUP_IS_SOL) && 0 != (parmp->parm_int_state & GROUP_IS_SOL) @@ -760,10 +799,12 @@ check_parms(struct parm *new) } } + /* link new entry on the so that when the entries are scanned, + * they affect the result in the order the operator specified. + */ parmp = (struct parm*)malloc(sizeof(*parmp)); bcopy(new, parmp, sizeof(*parmp)); - parmp->parm_next = parms; - parms = parmp; + *parmpp = parmp; return 0; } @@ -774,13 +815,13 @@ check_parms(struct parm *new) */ int /* 0=bad */ getnet(char *name, - naddr *netp, /* host byte order */ - naddr *maskp) + naddr *netp, /* a network so host byte order */ + naddr *maskp) /* masks are always in host order */ { int i; struct netent *np; - naddr mask; - struct in_addr in; + naddr mask; /* in host byte order */ + struct in_addr in; /* a network and so host byte order */ char hname[MAXHOSTNAMELEN+1]; char *mname, *p; @@ -812,7 +853,7 @@ getnet(char *name, /* we cannot use the interfaces here because we have not * looked at them yet. */ - mask = std_mask(in.s_addr); + mask = std_mask(htonl(in.s_addr)); if ((~mask & in.s_addr) != 0) mask = HOST_MASK; } else { |