*/
#ifndef lint
-static char rcsid[] = "$Id: auth.c,v 1.40 1999/01/19 23:59:14 paulus Exp $";
+static char rcsid[] = "$Id: auth.c,v 1.46 1999/03/16 03:15:12 paulus Exp $";
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
-#include <syslog.h>
#include <pwd.h>
+#include <grp.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Used for storing a sequence of words. Usually malloced. */
struct wordlist {
struct wordlist *next;
- char word[1];
+ char *word;
};
/* Bits in scan_authfile return value */
static void free_wordlist __P((struct wordlist *));
static void auth_script __P((char *));
static void set_allowed_addrs __P((int, struct wordlist *));
-
-#ifdef OLD_OPTIONS
-static int setupapfile __P((char **));
-#endif
+static int setupapfile __P((char **));
+static int privgroup __P((char **));
/*
* Authentication-related options.
{ "refuse-pap", o_bool, &refuse_pap,
"Don't agree to auth to peer with PAP", 1 },
{ "-pap", o_bool, &refuse_pap,
- "Don't allow UPAP authentication with peer", 1 },
+ "Don't allow PAP authentication with peer", 1 },
{ "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
"Require CHAP authentication from peer", 1, &auth_required },
{ "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
"Use system password database for PAP", 1 },
{ "papcrypt", o_bool, &cryptpap,
"PAP passwords are encrypted", 1 },
-#if OLD_OPTIONS
{ "+ua", o_special, setupapfile,
"Get PAP user and password from file" },
-#endif
+ { "privgroup", o_special, privgroup,
+ "Allow group members to use privileged options", OPT_PRIV },
{ NULL }
};
-#if OLD_OPTIONS
/*
* setupapfile - specifies UPAP info for authenticating with peer.
*/
lcp_allowoptions[0].neg_upap = 1;
/* open user info file */
- if ((ufile = fopen(*argv, "r")) == NULL) {
+ seteuid(getuid());
+ ufile = fopen(*argv, "r");
+ seteuid(0);
+ if (ufile == NULL) {
option_error("unable to open user login data file %s", *argv);
return 0;
}
+#if 0 /* check done by setting effective UID above */
if (!readable(fileno(ufile))) {
option_error("%s: access denied", *argv);
return 0;
}
+#endif
check_access(ufile, *argv);
/* get username */
return (1);
}
-#endif
+
+
+/*
+ * privgroup - allow members of the group to have privileged access.
+ */
+static int
+privgroup(argv)
+ char **argv;
+{
+ struct group *g;
+ int i;
+
+ g = getgrnam(*argv);
+ if (g == 0) {
+ option_error("group %s is unknown", *argv);
+ return 0;
+ }
+ for (i = 0; i < ngroups; ++i) {
+ if (groups[i] == g->gr_gid) {
+ privileged = 1;
+ break;
+ }
+ }
+ return 1;
+}
/*
if (logged_in)
plogout();
phase = PHASE_DEAD;
- syslog(LOG_NOTICE, "Connection terminated.");
+ notice("Connection terminated.");
}
/*
* of "" and a password of "". If that's not OK, boot it out.
*/
if (!wo->neg_upap || !null_login(unit)) {
- syslog(LOG_WARNING, "peer refused to authenticate");
+ warn("peer refused to authenticate: terminating link");
lcp_close(unit, "peer refused to authenticate");
return;
}
if (passwd[0] == 0) {
passwd_from_file = 1;
if (!get_pap_passwd(passwd))
- syslog(LOG_ERR, "No secret found for PAP login");
+ error("No secret found for PAP login");
}
upap_authwithpeer(unit, user, passwd);
auth |= PAP_WITHPEER;
bit = PAP_PEER;
break;
default:
- syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
- protocol);
+ warn("auth_peer_success: unknown protocol %x", protocol);
return;
}
bit = PAP_WITHPEER;
break;
default:
- syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
- protocol);
+ warn("auth_withpeer_success: unknown protocol %x", protocol);
bit = 0;
}
itime = MIN(idle.xmit_idle, idle.recv_idle);
if (itime >= idle_time_limit) {
/* link is idle: shut it down. */
- syslog(LOG_INFO, "Terminating connection due to lack of activity.");
+ info("Terminating connection due to lack of activity.");
lcp_close(0, "Link inactive");
} else {
TIMEOUT(check_idle, NULL, idle_time_limit - itime);
connect_time_expired(arg)
void *arg;
{
- syslog(LOG_INFO, "Connect time expired");
+ info("Connect time expired");
lcp_close(0, "Connect time expired"); /* Close connection */
}
/* Default our_name to hostname, and user to our_name */
if (our_name[0] == 0 || usehostname)
- strcpy(our_name, hostname);
+ strlcpy(our_name, sizeof(our_name), hostname);
if (user[0] == 0)
- strcpy(user, our_name);
+ strlcpy(user, sizeof(user), our_name);
/* If authentication is required, ask peer for CHAP or PAP. */
if (auth_required) {
wo->neg_upap = 0;
}
+ /*
+ * If we have a default route, require the peer to authenticate
+ * unless the noauth option was given.
+ */
+ if (!auth_required && !allow_any_ip && have_route_to(0))
+ auth_required = 1;
+
/*
* Check whether we have appropriate secrets to use
* to authenticate the peer.
remote_name, our_name);
exit(1);
}
-
- /*
- * Check whether the user tried to override certain values
- * set by root.
- */
- if (allow_any_ip) {
- if ((connector != NULL && connector_info.priv == 0)
- || (disconnector != NULL && disconnector_info.priv == 0)
- || (welcomer != NULL && welcomer_info.priv == 0)) {
- option_error("connect, disconnect and welcome options");
- option_error("are privileged when noauth option is used");
- exit(1);
- }
- }
}
/*
ret = UPAP_AUTHACK;
f = fopen(filename, "r");
if (f == NULL) {
- syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
+ error("Can't open PAP password file %s: %m", filename);
ret = UPAP_AUTHNAK;
} else {
secret, &addrs, filename) < 0
|| (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)
&& strcmp(crypt(passwd, secret), secret) != 0)) {
- syslog(LOG_WARNING, "PAP authentication failure for %s", user);
+ warn("PAP authentication failure for %s", user);
ret = UPAP_AUTHNAK;
}
fclose(f);
if (uselogin && ret == UPAP_AUTHACK) {
ret = plogin(user, passwd, msg, msglen);
if (ret == UPAP_AUTHNAK) {
- syslog(LOG_WARNING, "PAP login failure for %s", user);
+ warn("PAP login failure for %s", user);
}
}
* On 10'th, drop the connection.
*/
if (attempts++ >= 10) {
- syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s",
- attempts, devnam, user);
+ warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user);
quit();
}
if (attempts > 3)
|| ((spwd->sp_max >= 0 && spwd->sp_max < 10000)
&& spwd->sp_lstchg >= 0
&& now >= spwd->sp_lstchg + spwd->sp_max)) {
- syslog(LOG_WARNING, "Password for %s has expired", user);
+ warn("Password for %s has expired", user);
return (UPAP_AUTHNAK);
}
pw->pw_passwd = spwd->sp_pwdp;
(void)lseek(fd, (off_t)(pw->pw_uid * sizeof(ll)), SEEK_SET);
memset((void *)&ll, 0, sizeof(ll));
(void)time(&ll.ll_time);
- (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+ (void)strlcpy(ll.ll_line, sizeof(ll.ll_line), tty);
(void)write(fd, (char *)&ll, sizeof(ll));
(void)close(fd);
}
#endif /* #ifdef USE_PAM */
- syslog(LOG_INFO, "user %s logged in", user);
+ info("user %s logged in", user);
logged_in = TRUE;
return (UPAP_AUTHACK);
* get_pap_passwd - get a password for authenticating ourselves with
* our peer using PAP. Returns 1 on success, 0 if no suitable password
* could be found.
+ * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null).
*/
static int
get_pap_passwd(passwd)
fclose(f);
if (ret < 0)
return 0;
- if (passwd != NULL) {
- strncpy(passwd, secret, MAXSECRETLEN);
- passwd[MAXSECRETLEN-1] = 0;
- }
+ if (passwd != NULL)
+ strlcpy(passwd, MAXSECRETLEN, secret);
BZERO(secret, sizeof(secret));
return 1;
}
f = fopen(filename, "r");
if (f == NULL) {
- syslog(LOG_ERR, "Can't open chap secret file %s: %m", filename);
+ error("Can't open chap secret file %s: %m", filename);
return 0;
}
check_access(f, filename);
len = strlen(secbuf);
if (len > MAXSECRETLEN) {
- syslog(LOG_ERR, "Secret for %s on %s is too long", client, server);
+ error("Secret for %s on %s is too long", client, server);
len = MAXSECRETLEN;
}
BCOPY(secbuf, secret, len);
int unit;
u_int32_t addr;
{
+
+ if (addresses[unit] == NULL) {
+ if (auth_required)
+ return 0; /* no addresses authorized */
+ return allow_any_ip || !have_route_to(addr);
+ }
return ip_addr_check(addr, addresses[unit]);
}
if (bad_ip_adrs(addr))
return 0;
- if (addrs == NULL) {
- if (auth_required)
- return 0; /* no addresses authorized */
- return allow_any_ip || !have_route_to(addr);
- }
+ if (addrs == NULL)
+ return 0; /* no addresses authorized */
for (; addrs != NULL; addrs = addrs->next) {
/* "-" means no addresses authorized, "*" means any address allowed */
bit_count = (int) strtol (ptr_mask+1, (char **) 0, 10);
if (bit_count <= 0 || bit_count > 32) {
- syslog (LOG_WARNING,
- "invalid address length %s in auth. address list",
- ptr_mask);
+ warn("invalid address length %v in auth. address list",
+ ptr_mask);
continue;
}
*ptr_mask = '\0';
*ptr_mask = '/';
if (a == (u_int32_t)-1L)
- syslog (LOG_WARNING,
- "unknown host %s in auth. address list",
- addrs->word);
+ warn("unknown host %s in auth. address list", addrs->word);
else
/* Here a and addr are in network byte order,
and mask is in host order. */
struct stat sbuf;
if (fstat(fileno(f), &sbuf) < 0) {
- syslog(LOG_WARNING, "cannot stat secret file %s: %m", filename);
+ warn("cannot stat secret file %s: %m", filename);
} else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
- syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", filename);
+ warn("Warning - secret file %s has world and/or group access",
+ filename);
}
}
* NONWILD_CLIENT set if the secret didn't have "*" for the client, and
* NONWILD_SERVER set if the secret didn't have "*" for the server.
* Any following words on the line (i.e. address authorization
- * info) are placed in a wordlist and returned in *addrs.
+ * info) are placed in a wordlist and returned in *addrs.
+ * We assume secret is NULL or points to MAXWORDLEN bytes of space.
*/
static int
scan_authfile(f, client, server, ipaddr, secret, addrs, filename)
* Special syntax: @filename means read secret from file.
*/
if (word[0] == '@') {
- strcpy(atfile, word+1);
+ strlcpy(atfile, sizeof(atfile), word+1);
if ((sf = fopen(atfile, "r")) == NULL) {
- syslog(LOG_WARNING, "can't open indirect secret file %s",
- atfile);
+ warn("can't open indirect secret file %s", atfile);
continue;
}
check_access(sf, atfile);
if (!getword(sf, word, &xxx, atfile)) {
- syslog(LOG_WARNING, "no secret in indirect secret file %s",
- atfile);
+ warn("no secret in indirect secret file %s", atfile);
fclose(sf);
continue;
}
fclose(sf);
}
if (secret != NULL)
- strcpy(lsecret, word);
+ strlcpy(lsecret, sizeof(lsecret), word);
/*
* Now read address authorization info and make a wordlist.
for (;;) {
if (!getword(f, word, &newline, filename) || newline)
break;
- ap = (struct wordlist *) malloc(sizeof(struct wordlist)
- + strlen(word));
+ ap = (struct wordlist *) malloc(sizeof(struct wordlist));
if (ap == NULL)
novm("authorized addresses");
ap->next = NULL;
- strcpy(ap->word, word);
+ ap->word = strdup(word);
+ if (ap->word == NULL)
+ novm("authorized address");
if (alist == NULL)
alist = ap;
else
/*
* Check if the given IP address is allowed by the wordlist.
+ * XXX accepts this entry even if it has no allowed IP addresses
+ * if they didn't specify a remote IP address. XXX
*/
if (ipaddr != 0 && !ip_addr_check(ipaddr, alist)) {
free_wordlist(alist);
free_wordlist(addr_list);
addr_list = alist;
if (secret != NULL)
- strcpy(secret, lsecret);
+ strlcpy(secret, MAXWORDLEN, lsecret);
if (!newline)
break;
if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL)
user_name = pw->pw_name;
else {
- sprintf(struid, "%d", getuid());
+ slprintf(struid, sizeof(struid), "%d", getuid());
user_name = struid;
}
- sprintf(strspeed, "%d", baud_rate);
+ slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
argv[0] = script;
argv[1] = ifname;