*/
#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.34 1996/09/14 05:16:56 paulus Exp $";
#endif
#include <ctype.h>
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
*/
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));
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.
{"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 */
{"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 */
";
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)
struct cmd *cmdp;
int ret;
+ privileged_option = privileged;
+ option_source = "command line";
while (argc > 0) {
arg = *argv++;
--argc;
* 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];
return 0;
}
+ oldpriv = privileged_option;
+ privileged_option = priv;
+ ret = 0;
while (getword(f, cmd, &newline, filename)) {
/*
* First see if it's a command.
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;
}
/*
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;
}
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;
}
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>.
+ * 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).
*/
reqpap()
{
lcp_wantoptions[0].neg_upap = 1;
- auth_required = 1;
+ setauth();
return 1;
}
reqchap()
{
lcp_wantoptions[0].neg_chap = 1;
- auth_required = 1;
+ setauth();
return (1);
}
connector = strdup(*argv);
if (connector == NULL)
novm("connect script");
-
+ connector_info.priv = privileged_option;
+ connector_info.source = option_source;
+
return (1);
}
disconnector = strdup(*argv);
if (disconnector == NULL)
novm("disconnect script");
+ disconnector_info.priv = privileged_option;
+ disconnector_info.source = option_source;
return (1);
}
welcomer = strdup(*argv);
if (welcomer == NULL)
novm("welcome script");
-
+ welcomer_info.priv = privileged_option;
+ welcomer_info.source = option_source;
+
return (1);
}
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;
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 != '.')
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;
}
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)) {
setdemand()
{
demand = 1;
+ persist = 1;
return 1;
}
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;
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;
}
return 1;
}
+static int
+setnopersist()
+{
+ persist = 0;
+ return 1;
+}
+
static int
setdologin()
{