* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#define RCSID "$Id: auth.c,v 1.66 2000/07/24 14:58:14 paulus Exp $"
+#define RCSID "$Id: auth.c,v 1.70 2001/04/27 23:13:06 paulus Exp $"
#include <stdio.h>
#include <stddef.h>
/* Hook for a plugin to get the PAP password for authenticating us */
int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL;
+/* Hook for a plugin to say whether it is OK if the peer
+ refuses to authenticate. */
+int (*null_auth_hook) __P((struct wordlist **paddrs,
+ struct wordlist **popts)) = NULL;
+
+/* A notifier for when the peer has authenticated itself,
+ and we are proceeding to the network phase. */
+struct notifier *auth_up_notifier = NULL;
+
+/* A notifier for when the link goes down. */
+struct notifier *link_down_notifier = NULL;
+
/*
* This is used to ensure that we don't start an auth-up/down
* script while one is already running.
bool explicit_remote = 0; /* User specified explicit remote name */
char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+static char *uafname; /* name of most recent +ua file */
+
/* Bits in auth_pending[] */
#define PAP_WITHPEER 1
#define PAP_PEER 2
* Authentication-related options.
*/
option_t auth_options[] = {
+ { "auth", o_bool, &auth_required,
+ "Require authentication from peer", OPT_PRIO | 1 },
+ { "noauth", o_bool, &auth_required,
+ "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV,
+ &allow_any_ip },
{ "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
- "Require PAP authentication from peer", 1, &auth_required },
+ "Require PAP authentication from peer",
+ OPT_PRIOSUB | 1, &auth_required },
{ "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
- "Require PAP authentication from peer", 1, &auth_required },
+ "Require PAP authentication from peer",
+ OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required },
+ { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ "Require CHAP authentication from peer",
+ OPT_PRIOSUB | 1, &auth_required },
+ { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ "Require CHAP authentication from peer",
+ OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required },
+
{ "refuse-pap", o_bool, &refuse_pap,
"Don't agree to auth to peer with PAP", 1 },
{ "-pap", o_bool, &refuse_pap,
- "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,
- "Require CHAP authentication from peer", 1, &auth_required },
+ "Don't allow PAP authentication with peer", OPT_ALIAS | 1 },
+
{ "refuse-chap", o_bool, &refuse_chap,
"Don't agree to auth to peer with CHAP", 1 },
{ "-chap", o_bool, &refuse_chap,
- "Don't allow CHAP authentication with peer", 1 },
+ "Don't allow CHAP authentication with peer", OPT_ALIAS | 1 },
+
{ "name", o_string, our_name,
"Set local name for authentication",
- OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN },
+ OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN },
+
+ { "+ua", o_special, (void *)setupapfile,
+ "Get PAP user and password from file",
+ OPT_PRIO | OPT_A2STRVAL, &uafname },
+
{ "user", o_string, user,
- "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN },
+ "Set name for auth with peer", OPT_PRIO | OPT_STATIC, NULL, MAXNAMELEN },
+
+ { "password", o_string, passwd,
+ "Password for authenticating us to the peer",
+ OPT_PRIO | OPT_STATIC | OPT_HIDE, NULL, MAXSECRETLEN },
+
{ "usehostname", o_bool, &usehostname,
"Must use hostname for authentication", 1 },
+
{ "remotename", o_string, remote_name,
- "Set remote name for authentication", OPT_STATIC,
+ "Set remote name for authentication", OPT_PRIO | OPT_STATIC,
&explicit_remote, MAXNAMELEN },
- { "auth", o_bool, &auth_required,
- "Require authentication from peer", 1 },
- { "noauth", o_bool, &auth_required,
- "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip },
- { "login", o_bool, &uselogin,
+
+ { "login", o_bool, &uselogin,
"Use system password database for PAP", 1 },
+
{ "papcrypt", o_bool, &cryptpap,
"PAP passwords are encrypted", 1 },
- { "+ua", o_special, (void *)setupapfile,
- "Get PAP user and password from file" },
- { "password", o_string, passwd,
- "Password for authenticating us to the peer", OPT_STATIC,
- NULL, MAXSECRETLEN },
+
{ "privgroup", o_special, (void *)privgroup,
- "Allow group members to use privileged options", OPT_PRIV },
+ "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST },
+
{ "allow-ip", o_special, (void *)set_noauth_addr,
"Set IP address(es) which can be used without authentication",
- OPT_PRIV },
+ OPT_PRIV | OPT_A2LIST },
+
{ NULL }
};
setupapfile(argv)
char **argv;
{
- FILE * ufile;
+ FILE *ufile;
int l;
+ char u[MAXNAMELEN], p[MAXSECRETLEN];
+ char *fname;
lcp_allowoptions[0].neg_upap = 1;
/* open user info file */
+ fname = strdup(*argv);
+ if (fname == NULL)
+ novm("+ua file name");
seteuid(getuid());
- ufile = fopen(*argv, "r");
+ ufile = fopen(fname, "r");
seteuid(0);
if (ufile == NULL) {
- option_error("unable to open user login data file %s", *argv);
+ option_error("unable to open user login data file %s", fname);
return 0;
}
- check_access(ufile, *argv);
+ check_access(ufile, fname);
+ uafname = fname;
/* get username */
- if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
- || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
- option_error("unable to read user login data file %s", *argv);
+ if (fgets(u, MAXNAMELEN - 1, ufile) == NULL
+ || fgets(p, MAXSECRETLEN - 1, ufile) == NULL){
+ option_error("unable to read user login data file %s", fname);
return 0;
}
fclose(ufile);
/* get rid of newlines */
- l = strlen(user);
- if (l > 0 && user[l-1] == '\n')
- user[l-1] = 0;
- l = strlen(passwd);
- if (l > 0 && passwd[l-1] == '\n')
- passwd[l-1] = 0;
+ l = strlen(u);
+ if (l > 0 && u[l-1] == '\n')
+ u[l-1] = 0;
+ l = strlen(p);
+ if (l > 0 && p[l-1] == '\n')
+ p[l-1] = 0;
+
+ if (override_value("user", option_priority, fname))
+ strlcpy(user, u, sizeof(user));
+ if (override_value("passwd", option_priority, fname))
+ strlcpy(passwd, p, sizeof(passwd));
return (1);
}
int i;
struct protent *protp;
+ notify(link_down_notifier, 0);
auth_state = s_down;
if (auth_script_state == s_up && auth_script_pid == 0) {
update_link_stats(unit);
num_np_open = 0;
num_np_up = 0;
if (phase != PHASE_DEAD)
- new_phase(PHASE_TERMINATE);
+ new_phase(PHASE_ESTABLISH);
}
/*
* If the peer had to authenticate, run the auth-up script now.
*/
if (go->neg_chap || go->neg_upap) {
+ notify(auth_up_notifier, 0);
auth_state = s_up;
if (auth_script_state == s_down && auth_script_pid == 0) {
auth_script_state = s_up;
}
#endif /* HAVE_MULTILINK */
-#if 0
+#ifdef PPP_FILTER
if (!demand)
set_filters(&pass_filter, &active_filter);
#endif
/* If authentication is required, ask peer for CHAP or PAP. */
if (auth_required) {
+ allow_any_ip = 0;
if (!wo->neg_chap && !wo->neg_upap) {
wo->neg_chap = 1;
wo->neg_upap = 1;
struct wordlist *addrs, *opts;
char secret[MAXWORDLEN];
+ /*
+ * Check if a plugin wants to handle this.
+ */
+ ret = -1;
+ if (null_auth_hook)
+ ret = (*null_auth_hook)(&addrs, &opts);
+
/*
* Open the file of pap secrets and scan for a suitable secret.
*/
- filename = _PATH_UPAPFILE;
- addrs = NULL;
- f = fopen(filename, "r");
- if (f == NULL)
- return 0;
- check_access(f, filename);
+ if (ret <= 0) {
+ filename = _PATH_UPAPFILE;
+ addrs = NULL;
+ f = fopen(filename, "r");
+ if (f == NULL)
+ return 0;
+ check_access(f, filename);
- i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename);
- ret = i >= 0 && secret[0] == 0;
- BZERO(secret, sizeof(secret));
+ i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename);
+ ret = i >= 0 && secret[0] == 0;
+ BZERO(secret, sizeof(secret));
+ fclose(f);
+ }
if (ret)
set_allowed_addrs(unit, addrs, opts);
if (addrs != 0)
free_wordlist(addrs);
- fclose(f);
return ret;
}
* which is a single host, then use that if we find one.
*/
if (suggested_ip != 0
- && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr)))
+ && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) {
wo->hisaddr = suggested_ip;
+ /*
+ * Do we insist on this address? No, if there are other
+ * addresses authorized than the suggested one.
+ */
+ if (n > 1)
+ wo->accept_remote = 1;
+ }
}
/*
for (;;) {
if (!getword(f, word, &newline, filename) || newline)
break;
- ap = (struct wordlist *) malloc(sizeof(struct wordlist));
+ ap = (struct wordlist *)
+ malloc(sizeof(struct wordlist) + strlen(word) + 1);
if (ap == NULL)
novm("authorized addresses");
- ap->word = strdup(word);
- if (ap->word == NULL)
- novm("authorized addresses");
+ ap->word = (char *) (ap + 1);
+ strcpy(ap->word, word);
*app = ap;
app = &ap->next;
}