From: Paul Mackerras Date: Wed, 28 Aug 1996 06:41:35 +0000 (+0000) Subject: priv option stuff; fix the way name, user options work. X-Git-Tag: RELEASE_2_3_6~357 X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=571f3c157bcf2faa07caa584ddbb3f373cdb41db priv option stuff; fix the way name, user options work. --- diff --git a/pppd/options.c b/pppd/options.c index 43f8e3d..2db98fc 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.32 1996/07/01 01:18:23 paulus Exp $"; +static char rcsid[] = "$Id: options.c,v 1.33 1996/08/28 06:41:35 paulus Exp $"; #endif #include @@ -102,6 +102,12 @@ int holdoff = 30; /* # seconds to pause before reconnecting */ int refuse_pap = 0; /* Set to say we won't do PAP */ int refuse_chap = 0; /* Set to say we won't do CHAP */ +struct option_info auth_req_info; +struct option_info connector_info; +struct option_info disconnector_info; +struct option_info welcomer_info; +struct option_info devnam_info; + /* * Prototypes */ @@ -150,12 +156,15 @@ static int setname __P((char **)); static int setuser __P((char **)); static int setremote __P((char **)); static int setauth __P((void)); +static int setnoauth __P((void)); static int readfile __P((char **)); +static int callfile __P((char **)); static int setdefaultroute __P((void)); static int setnodefaultroute __P((void)); static int setproxyarp __P((void)); static int setnoproxyarp __P((void)); static int setpersist __P((void)); +static int setnopersist __P((void)); static int setdologin __P((void)); static int setusehostname __P((void)); static int setnoipdflt __P((void)); @@ -213,7 +222,6 @@ static int setdnsaddr __P((char **)); static int number_option __P((char *, u_int32_t *, int)); static int int_option __P((char *, int *)); static int readable __P((int fd)); -static void option_error __P((char *fmt, ...)); /* * Valid arguments. @@ -279,11 +287,13 @@ static struct cmd { {"local", 0, setlocal}, /* Don't use modem control lines */ {"lock", 0, setlock}, /* Lock serial device (with lock file) */ {"name", 1, setname}, /* Set local name for authentication */ - {"user", 1, setuser}, /* Set username for PAP auth with peer */ + {"user", 1, setuser}, /* Set name for auth with peer */ {"usehostname", 0, setusehostname}, /* Must use hostname for auth. */ {"remotename", 1, setremote}, /* Set remote name for authentication */ {"auth", 0, setauth}, /* Require authentication from peer */ + {"noauth", 0, setnoauth}, /* Don't require peer to authenticate */ {"file", 1, readfile}, /* Take options from a file */ + {"call", 1, callfile}, /* Take options from a privileged file */ {"defaultroute", 0, setdefaultroute}, /* Add default route */ {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ @@ -291,6 +301,7 @@ static struct cmd { {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ {"persist", 0, setpersist}, /* Keep on reopening connection after close */ + {"nopersist", 0, setnopersist}, /* Turn off persist option */ {"demand", 0, setdemand}, /* Dial on demand */ {"login", 0, setdologin}, /* Use system password database for UPAP */ {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */ @@ -381,11 +392,11 @@ See pppd(8) for more options.\n\ "; static char *current_option; /* the name of the option being parsed */ - +static int privileged_option; /* set iff the current option came from root */ +static char *option_source; /* string saying where the option came from */ /* - * parse_args - parse a string of arguments, from the command - * line or from a file. + * parse_args - parse a string of arguments from the command line. */ int parse_args(argc, argv) @@ -396,6 +407,8 @@ parse_args(argc, argv) struct cmd *cmdp; int ret; + privileged_option = privileged; + option_source = "command line"; while (argc > 0) { arg = *argv++; --argc; @@ -484,14 +497,16 @@ usage() * and interpret them. */ int -options_from_file(filename, must_exist, check_prot) +options_from_file(filename, must_exist, check_prot, priv) char *filename; int must_exist; int check_prot; + int priv; { FILE *f; int i, newline, ret; struct cmd *cmdp; + int oldpriv; char *argv[MAXARGS]; char args[MAXARGS][MAXWORDLEN]; char cmd[MAXWORDLEN]; @@ -508,6 +523,9 @@ options_from_file(filename, must_exist, check_prot) return 0; } + oldpriv = privileged_option; + privileged_option = priv; + ret = 0; while (getword(f, cmd, &newline, filename)) { /* * First see if it's a command. @@ -522,34 +540,35 @@ options_from_file(filename, must_exist, check_prot) option_error( "In file %s: too few parameters for option '%s'", filename, cmd); - fclose(f); - return 0; + goto err; } argv[i] = args[i]; } current_option = cmd; - if (!(*cmdp->cmd_func)(argv)) { - fclose(f); - return 0; - } + if (!(*cmdp->cmd_func)(argv)) + goto err; } else { /* * Maybe a tty name, speed or IP address? */ - if ((ret = setdevname(cmd, 0)) == 0 - && (ret = setspeed(cmd)) == 0 - && (ret = setipaddr(cmd)) == 0) { + if ((i = setdevname(cmd, 0)) == 0 + && (i = setspeed(cmd)) == 0 + && (i = setipaddr(cmd)) == 0) { option_error("In file %s: unrecognized option '%s'", filename, cmd); - fclose(f); - return 0; + goto err; } - if (ret < 0) /* error */ - return 0; + if (i < 0) /* error */ + goto err; } } - return 1; + ret = 1; + +err: + fclose(f); + privileged_option = oldpriv; + return ret; } /* @@ -573,7 +592,7 @@ options_from_user() strcpy(path, user); strcat(path, "/"); strcat(path, file); - ret = options_from_file(path, 0, 1); + ret = options_from_file(path, 0, 1, privileged); free(path); return ret; } @@ -601,7 +620,7 @@ options_for_tty() for (p = path + strlen(path); *dev != 0; ++dev) *p++ = (*dev == '/'? '.': *dev); *p = 0; - ret = options_from_file(path, 0, 0); + ret = options_from_file(path, 0, 0, 1); free(path); return ret; } @@ -957,9 +976,54 @@ static int readfile(argv) char **argv; { - return options_from_file(*argv, 1, 1); + return options_from_file(*argv, 1, 1, privileged_option); +} + +/* + * callfile - take commands from /etc/ppp/peers/. + * Name may not contain /../, start with / or ../, or end in /.. + */ +static int +callfile(argv) + char **argv; +{ + char *fname, *arg, *p; + int l, ok; + + arg = *argv; + ok = 1; + if (arg[0] == '/' || arg[0] == 0) + ok = 0; + else { + for (p = arg; *p != 0; ) { + if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) { + ok = 0; + break; + } + while (*p != '/' && *p != 0) + ++p; + if (*p == '/') + ++p; + } + } + if (!ok) { + option_error("call option value may not contain .. or start with /"); + return 0; + } + + l = strlen(arg) + strlen(_PATH_PEERFILES) + 1; + if ((fname = (char *) malloc(l)) == NULL) + novm("call file name"); + strcpy(fname, _PATH_PEERFILES); + strcat(fname, arg); + + ok = options_from_file(fname, 1, 1, 1); + + free(fname); + return ok; } + /* * setdebug - Set debug (command line argument). */ @@ -1150,7 +1214,7 @@ static int reqpap() { lcp_wantoptions[0].neg_upap = 1; - auth_required = 1; + setauth(); return 1; } @@ -1216,7 +1280,7 @@ static int reqchap() { lcp_wantoptions[0].neg_chap = 1; - auth_required = 1; + setauth(); return (1); } @@ -1276,7 +1340,9 @@ setconnector(argv) connector = strdup(*argv); if (connector == NULL) novm("connect script"); - + connector_info.priv = privileged_option; + connector_info.source = option_source; + return (1); } @@ -1290,6 +1356,8 @@ setdisconnector(argv) disconnector = strdup(*argv); if (disconnector == NULL) novm("disconnect script"); + disconnector_info.priv = privileged_option; + disconnector_info.source = option_source; return (1); } @@ -1304,7 +1372,9 @@ setwelcomer(argv) welcomer = strdup(*argv); if (welcomer == NULL) novm("welcome script"); - + welcomer_info.priv = privileged_option; + welcomer_info.source = option_source; + return (1); } @@ -1318,10 +1388,14 @@ setmaxconnect(argv) int value; if (!int_option(*argv, &value)) - return 0; + return 0; if (value < 0) { - option_error("maxconnect time must be positive"); - return 0; + option_error("maxconnect time must be positive"); + return 0; + } + if (maxconnect > 0 && (value == 0 || value > maxconnect)) { + option_error("maxconnect time cannot be increased"); + return 0; } maxconnect = value; return 1; @@ -1334,6 +1408,10 @@ static int setdomain(argv) char **argv; { + if (!privileged_option) { + option_error("using the domain option requires root privilege"); + return 0; + } gethostname(hostname, MAXNAMELEN); if (**argv != 0) { if (**argv != '.') @@ -1442,10 +1520,12 @@ setdevname(cp, quiet) option_error("Couldn't stat %s: %m", cp); return -1; } - + (void) strncpy(devnam, cp, MAXPATHLEN); devnam[MAXPATHLEN-1] = 0; default_device = FALSE; + devnam_info.priv = privileged_option; + devnam_info.source = option_source; return 1; } @@ -1480,10 +1560,6 @@ setipaddr(arg) return -1; } else { local = *(u_int32_t *)hp->h_addr; - if (our_name[0] == 0) { - strncpy(our_name, arg, MAXNAMELEN); - our_name[MAXNAMELEN-1] = 0; - } } } if (bad_ip_adrs(local)) { @@ -1609,6 +1685,7 @@ static int setdemand() { demand = 1; + persist = 1; return 1; } @@ -1644,6 +1721,10 @@ static int setname(argv) char **argv; { + if (!privileged_option) { + option_error("using the name option requires root privilege"); + return 0; + } if (our_name[0] == 0) { strncpy(our_name, argv[0], MAXNAMELEN); our_name[MAXNAMELEN-1] = 0; @@ -1673,13 +1754,29 @@ static int setauth() { auth_required = 1; + if (privileged_option > auth_req_info.priv) { + auth_req_info.priv = privileged_option; + auth_req_info.source = option_source; + } + return 1; +} + +static int +setnoauth() +{ + if (auth_required && privileged_option < auth_req_info.priv) { + option_error("cannot override auth option set by %s", + auth_req_info.source); + return 0; + } + auth_required = 0; return 1; } static int setdefaultroute() { - if (!ipcp_allowoptions[0].default_route) { + if (!ipcp_allowoptions[0].default_route && !privileged_option) { option_error("defaultroute option is disabled"); return 0; } @@ -1698,7 +1795,7 @@ setnodefaultroute() static int setproxyarp() { - if (!ipcp_allowoptions[0].proxy_arp) { + if (!ipcp_allowoptions[0].proxy_arp && !privileged_option) { option_error("proxyarp option is disabled"); return 0; } @@ -1721,6 +1818,13 @@ setpersist() return 1; } +static int +setnopersist() +{ + persist = 0; + return 1; +} + static int setdologin() {