X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Foptions.c;h=49763764d0998092e1d8d9ec50a416b0674bc5dc;hp=2371ed3fba0a67fdf46030e89bc1eff67f82c25d;hb=de7942371374241e49ab63439c35b142882f150c;hpb=baef0b4051b99779132e712a304c0fe52ab9042e diff --git a/pppd/options.c b/pppd/options.c index 2371ed3..4976376 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -18,14 +18,13 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.50 1999/03/08 05:34:44 paulus Exp $"; +static char rcsid[] = "$Id: options.c,v 1.58 1999/05/12 06:19:48 paulus Exp $"; #endif #include #include #include #include -#include #include #include #include @@ -53,17 +52,10 @@ static char rcsid[] = "$Id: options.c,v 1.50 1999/03/08 05:34:44 paulus Exp $"; #include -#define FALSE 0 -#define TRUE 1 - #if defined(ultrix) || defined(NeXT) char *strdup __P((char *)); #endif -#ifndef GIDSET_TYPE -#define GIDSET_TYPE gid_t -#endif - /* * Option variables and default values. */ @@ -73,7 +65,7 @@ int dflag = 0; /* Tell libpcap we want debugging */ int debug = 0; /* Debug flag */ int kdebugflag = 0; /* Tell kernel to print debug messages */ int default_device = 1; /* Using /dev/tty or equivalent */ -char devnam[MAXPATHLEN] = "/dev/tty"; /* Device name */ +char devnam[MAXPATHLEN]; /* Device name */ int crtscts = 0; /* Use hardware flow control */ bool modem = 1; /* Use modem control lines */ int inspeed = 0; /* Input/Output speed requested */ @@ -84,24 +76,31 @@ bool updetach = 0; /* Detach once link is up */ char *connector = NULL; /* Script to establish physical link */ char *disconnector = NULL; /* Script to disestablish physical link */ char *welcomer = NULL; /* Script to run after phys link estab. */ +char *ptycommand = NULL; /* Command to run on other side of pty */ int maxconnect = 0; /* Maximum connect time */ char user[MAXNAMELEN]; /* Username for PAP */ char passwd[MAXSECRETLEN]; /* Password for PAP */ bool persist = 0; /* Reopen link after it goes down */ char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ -char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ -int explicit_remote = 0; /* User specified explicit remote name */ bool demand = 0; /* do dial-on-demand */ char *ipparam = NULL; /* Extra parameter for ip up/down scripts */ int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ int holdoff = 30; /* # seconds to pause before reconnecting */ +bool notty = 0; /* Stdin/out is not a tty */ +char *record_file = NULL; /* File to record chars sent/received */ +int using_pty = 0; +bool sync_serial = 0; /* Device is synchronous serial device */ +int log_to_fd = 1; /* send log messages to this fd too */ extern option_t auth_options[]; +extern struct stat devstat; +extern int prepass; /* Doing pre-pass to find device name */ struct option_info connector_info; struct option_info disconnector_info; struct option_info welcomer_info; struct option_info devnam_info; +struct option_info ptycommand_info; #ifdef PPP_FILTER struct bpf_program pass_filter;/* Filter program for packets to pass */ @@ -112,7 +111,7 @@ pcap_t pc; /* Fake struct pcap so we can compile expr */ /* * Prototypes */ -static int setdevname __P((char *, int)); +static int setdevname __P((char *)); static int setipaddr __P((char *)); static int setspeed __P((char *)); static int noopt __P((char **)); @@ -123,6 +122,7 @@ static int readfile __P((char **)); static int callfile __P((char **)); static int showversion __P((char **)); static int showhelp __P((char **)); +static void usage __P((void)); #ifdef PPP_FILTER static int setpassfilter __P((char **)); @@ -133,6 +133,7 @@ static int setactivefilter __P((char **)); static option_t *find_option __P((char *name)); static int process_option __P((option_t *, char **)); static int n_arguments __P((option_t *)); +static int number_option __P((char *, u_int32_t *, int)); /* * Valid arguments. @@ -159,11 +160,21 @@ option_t general_options[] = { { "-all", o_special_noarg, noopt, "Don't request/allow any LCP or IPCP options (useless)" }, { "connect", o_string, &connector, - "A program to set up a connection", OPT_A2INFO, &connector_info }, + "A program to set up a connection", + OPT_A2INFO | OPT_PRIVFIX, &connector_info }, { "disconnect", o_string, &disconnector, - "Program to disconnect serial device", OPT_A2INFO, &disconnector_info }, + "Program to disconnect serial device", + OPT_A2INFO | OPT_PRIVFIX, &disconnector_info }, { "welcome", o_string, &welcomer, - "Script to welcome client", OPT_A2INFO, &welcomer_info }, + "Script to welcome client", + OPT_A2INFO | OPT_PRIVFIX, &welcomer_info }, + { "pty", o_string, &ptycommand, + "Script to run on pseudo-tty master side", + OPT_A2INFO | OPT_PRIVFIX | OPT_PREPASS, &ptycommand_info }, + { "notty", o_bool, ¬ty, + "Input/output is not a tty", OPT_PREPASS | 1 }, + { "record", o_string, &record_file, + "Record characters sent/received to file" }, { "maxconnect", o_int, &maxconnect, "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF }, { "crtscts", o_int, &crtscts, @@ -189,9 +200,9 @@ option_t general_options[] = { { "local", o_bool, &modem, "Don't use modem control lines" }, { "file", o_special, readfile, - "Take options from a file" }, + "Take options from a file", OPT_PREPASS }, { "call", o_special, callfile, - "Take options from a privileged file" }, + "Take options from a privileged file", OPT_PREPASS }, { "persist", o_bool, &persist, "Keep on reopening connection after close", 1 }, { "nopersist", o_bool, &persist, @@ -204,6 +215,13 @@ option_t general_options[] = { "Show brief listing of options" }, { "-h", o_special_noarg, showhelp, "Show brief listing of options" }, + { "sync", o_bool, &sync_serial, + "Use synchronous HDLC serial encoding", 1 }, + { "logfd", o_int, &log_to_fd, + "Send log messages to this file descriptor" }, + { "nologfd", o_int, &log_to_fd, + "Don't send log messages to any file descriptor", + OPT_NOARG | OPT_VAL(-1) }, #ifdef PPP_FILTER { "pdebug", o_int, &dflag, @@ -241,6 +259,8 @@ See pppd(8) for more options.\n\ /* * parse_args - parse a string of arguments from the command line. + * If prepass is true, we are scanning for the device name and only + * processing a few options, so error messages are suppressed. */ int parse_args(argc, argv) @@ -278,7 +298,7 @@ parse_args(argc, argv) /* * Maybe a tty name, speed or IP address? */ - if ((ret = setdevname(arg, 0)) == 0 + if ((ret = setdevname(arg)) == 0 && (ret = setspeed(arg)) == 0 && (ret = setipaddr(arg)) == 0) { option_error("unrecognized option '%s'", arg); @@ -291,9 +311,10 @@ parse_args(argc, argv) return 1; } +#if 0 /* * scan_args - scan the command line arguments to get the tty name, - * if specified. + * if specified. Also checks whether the notty or pty option was given. */ void scan_args(argc, argv) @@ -308,6 +329,9 @@ scan_args(argc, argv) arg = *argv++; --argc; + if (strcmp(arg, "notty") == 0 || strcmp(arg, "pty") == 0) + using_pty = 1; + /* Skip options and their arguments */ opt = find_option(arg); if (opt != NULL) { @@ -321,6 +345,7 @@ scan_args(argc, argv) (void) setdevname(arg, 1); } } +#endif /* * options_from_file - Read a string of options from a file, @@ -334,7 +359,7 @@ options_from_file(filename, must_exist, check_prot, priv) int priv; { FILE *f; - int i, newline, ret; + int i, newline, ret, err; option_t *opt; int oldpriv; char *oldsource; @@ -345,21 +370,16 @@ options_from_file(filename, must_exist, check_prot, priv) if (check_prot) seteuid(getuid()); f = fopen(filename, "r"); + err = errno; if (check_prot) seteuid(0); if (f == NULL) { - if (!must_exist && errno == ENOENT) + if (!must_exist && err == ENOENT) return 1; + errno = err; option_error("Can't open options file %s: %m", filename); return 0; } -#if 0 /* check done by setting effective UID above */ - if (check_prot && !readable(fileno(f))) { - option_error("Can't open options file %s: access denied", filename); - fclose(f); - return 0; - } -#endif oldpriv = privileged_option; privileged_option = priv; @@ -393,7 +413,7 @@ options_from_file(filename, must_exist, check_prot, priv) /* * Maybe a tty name, speed or IP address? */ - if ((i = setdevname(cmd, 0)) == 0 + if ((i = setdevname(cmd)) == 0 && (i = setspeed(cmd)) == 0 && (i = setipaddr(cmd)) == 0) { option_error("In file %s: unrecognized option '%s'", @@ -422,17 +442,17 @@ options_from_user() char *user, *path, *file; int ret; struct passwd *pw; + size_t pl; pw = getpwuid(getuid()); if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) return 1; file = _PATH_USEROPT; - path = malloc(strlen(user) + strlen(file) + 2); + pl = strlen(user) + strlen(file) + 2; + path = malloc(pl); if (path == NULL) novm("init file name"); - strcpy(path, user); - strcat(path, "/"); - strcat(path, file); + slprintf(path, pl, "%s/%s", user, file); ret = options_from_file(path, 0, 1, privileged); free(path); return ret; @@ -447,20 +467,22 @@ options_for_tty() { char *dev, *path, *p; int ret; + size_t pl; dev = devnam; if (strncmp(dev, "/dev/", 5) == 0) dev += 5; - if (strcmp(dev, "tty") == 0) + if (dev[0] == 0 || strcmp(dev, "tty") == 0) return 1; /* don't look for /etc/ppp/options.tty */ - path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1); + pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1; + path = malloc(pl); if (path == NULL) novm("tty init file name"); - strcpy(path, _PATH_TTYOPT); + slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev); /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */ - for (p = path + strlen(path); *dev != 0; ++dev) - *p++ = (*dev == '/'? '.': *dev); - *p = 0; + for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p) + if (*p == '/') + *p = '.'; ret = options_from_file(path, 0, 0, 1); free(path); return ret; @@ -505,6 +527,9 @@ process_option(opt, argv) char *sv; int (*parser) __P((char **)); + if (prepass && (opt->flags & OPT_PREPASS) == 0) + return 1; + if ((opt->flags & OPT_PRIV) && !privileged_option) { option_error("using the %s option requires root privilege", opt->name); return 0; @@ -513,6 +538,13 @@ process_option(opt, argv) option_error("%s option is disabled", opt->name); return 0; } + if ((opt->flags & OPT_PRIVFIX) && !privileged_option) { + struct option_info *ip = (struct option_info *) opt->addr2; + if (ip && ip->priv) { + option_error("%s option cannot be overridden", opt->name); + return 0; + } + } switch (opt->type) { case o_bool: @@ -581,11 +613,7 @@ process_option(opt, argv) case o_string: if (opt->flags & OPT_STATIC) { - if (opt->upper_limit) { - strncpy((char *)(opt->addr), *argv, opt->upper_limit); - ((char *)(opt->addr))[opt->upper_limit-1] = 0; - } else - strcpy((char *)(opt->addr), *argv); + strlcpy((char *)(opt->addr), *argv, opt->upper_limit); } else { sv = strdup(*argv); if (sv == NULL) @@ -628,7 +656,7 @@ n_arguments(opt) /* * usage - print out a message telling how to use the program. */ -void +static void usage() { if (phase == PHASE_INITIALIZE) @@ -683,13 +711,18 @@ option_error __V((char *fmt, ...)) va_start(args); fmt = va_arg(args, char *); #endif - vfmtmsg(buf, sizeof(buf), fmt, args); + if (prepass) { + va_end(args); + return; + } + vslprintf(buf, sizeof(buf), fmt, args); va_end(args); if (phase == PHASE_INITIALIZE) fprintf(stderr, "%s: %s\n", progname, buf); syslog(LOG_ERR, "%s", buf); } +#if 0 /* * readable - check if a file is readable by the real user. */ @@ -698,9 +731,8 @@ readable(fd) int fd; { uid_t uid; - int ngroups, i; + int i; struct stat sbuf; - GIDSET_TYPE groups[NGROUPS_MAX]; uid = getuid(); if (uid == 0) @@ -711,12 +743,12 @@ readable(fd) return sbuf.st_mode & S_IRUSR; if (sbuf.st_gid == getgid()) return sbuf.st_mode & S_IRGRP; - ngroups = getgroups(NGROUPS_MAX, groups); for (i = 0; i < ngroups; ++i) if (sbuf.st_gid == groups[i]) return sbuf.st_mode & S_IRGRP; return sbuf.st_mode & S_IROTH; } +#endif /* * Read a word from a file. @@ -967,7 +999,7 @@ getword(f, word, newlinep, filename) /* * number_option - parse an unsigned numeric parameter for an option. */ -int +static int number_option(str, valp, base) char *str; u_int32_t *valp; @@ -1053,8 +1085,7 @@ callfile(argv) l = strlen(arg) + strlen(_PATH_PEERFILES) + 1; if ((fname = (char *) malloc(l)) == NULL) novm("call file name"); - strcpy(fname, _PATH_PEERFILES); - strcat(fname, arg); + slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg); ok = options_from_file(fname, 1, 1, 1); @@ -1165,9 +1196,8 @@ setspeed(arg) * setdevname - Set the device name. */ static int -setdevname(cp, quiet) +setdevname(cp) char *cp; - int quiet; { struct stat statbuf; char dev[MAXPATHLEN]; @@ -1176,25 +1206,33 @@ setdevname(cp, quiet) return 0; if (strncmp("/dev/", cp, 5) != 0) { - strcpy(dev, "/dev/"); - strncat(dev, cp, MAXPATHLEN - 5); - dev[MAXPATHLEN-1] = 0; + strlcpy(dev, "/dev/", sizeof(dev)); + strlcat(dev, cp, sizeof(dev)); cp = dev; } /* - * Check if there is a device by this name. + * Check if there is a character device by this name. */ if (stat(cp, &statbuf) < 0) { - if (errno == ENOENT || quiet) + if (errno == ENOENT) return 0; option_error("Couldn't stat %s: %m", cp); return -1; } + if (!S_ISCHR(statbuf.st_mode)) { + option_error("%s is not a character device", cp); + return -1; + } + + if (devnam_info.priv && !privileged_option) { + option_error("device name cannot be overridden"); + return -1; + } - (void) strncpy(devnam, cp, MAXPATHLEN); - devnam[MAXPATHLEN-1] = 0; - default_device = FALSE; + strlcpy(devnam, cp, sizeof(devnam)); + devstat = statbuf; + default_device = 0; devnam_info.priv = privileged_option; devnam_info.source = option_source; @@ -1219,6 +1257,8 @@ setipaddr(arg) */ if ((colon = strchr(arg, ':')) == NULL) return 0; + if (prepass) + return 1; /* * If colon first character, then no local addr. @@ -1252,10 +1292,8 @@ setipaddr(arg) return -1; } else { remote = *(u_int32_t *)hp->h_addr; - if (remote_name[0] == 0) { - strncpy(remote_name, colon, MAXNAMELEN); - remote_name[MAXNAMELEN-1] = 0; - } + if (remote_name[0] == 0) + strlcpy(remote_name, colon, sizeof(remote_name)); } } if (bad_ip_adrs(remote)) {