]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/auth.c
Added <time.h> to stop warnings, and made it check errors from
[ppp.git] / pppd / auth.c
index 31b082e9089a15c1ba713ff09371233ef548940e..3d232be9dde64064d6f6efc201c9a09be0aec69f 100644 (file)
@@ -32,7 +32,7 @@
  * 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.72 2002/01/11 18:07:45 etbe Exp $"
 
 #include <stdio.h>
 #include <stddef.h>
@@ -64,6 +64,7 @@
 #define PW_PPP PW_LOGIN
 #endif
 #endif
+#include <time.h>
 
 #include "pppd.h"
 #include "fsm.h"
@@ -132,6 +133,18 @@ void (*pap_logout_hook) __P((void)) = NULL;
 /* 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.
@@ -160,6 +173,8 @@ bool allow_any_ip = 0;              /* Allow peer to use any IP address */
 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
@@ -198,50 +213,69 @@ static int  wordlist_count __P((struct wordlist *));
  * 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 }
 };
 
@@ -252,36 +286,47 @@ static int
 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);
 }
@@ -375,6 +420,7 @@ link_down(unit)
     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);
@@ -392,7 +438,7 @@ link_down(unit)
     num_np_open = 0;
     num_np_up = 0;
     if (phase != PHASE_DEAD)
-       new_phase(PHASE_TERMINATE);
+       new_phase(PHASE_ESTABLISH);
 }
 
 /*
@@ -477,6 +523,7 @@ network_phase(unit)
      * 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;
@@ -524,7 +571,7 @@ start_networks()
     }
 #endif /* HAVE_MULTILINK */
 
-#if 0
+#ifdef PPP_FILTER
     if (!demand)
        set_filters(&pass_filter, &active_filter);
 #endif
@@ -695,6 +742,7 @@ np_down(unit, proto)
 {
     if (--num_np_up == 0) {
        UNTIMEOUT(check_idle, NULL);
+       UNTIMEOUT(connect_time_expired, NULL);
        new_phase(PHASE_NETWORK);
     }
 }
@@ -782,6 +830,7 @@ auth_check_options()
 
     /* 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;
@@ -1087,7 +1136,7 @@ plogin(user, passwd, msg)
     if (pam_error == PAM_SUCCESS && !PAM_error) {    
         pam_error = pam_acct_mgmt (pamh, PAM_SILENT);
         if (pam_error == PAM_SUCCESS)
-           pam_open_session (pamh, PAM_SILENT);
+           pam_error = pam_open_session (pamh, PAM_SILENT);
     }
 
     *msg = (char *) pam_strerror (pamh, pam_error);
@@ -1217,19 +1266,29 @@ null_login(unit)
     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);
@@ -1238,7 +1297,6 @@ null_login(unit)
     if (addrs != 0)
        free_wordlist(addrs);
 
-    fclose(f);
     return ret;
 }
 
@@ -1572,8 +1630,15 @@ set_allowed_addrs(unit, addrs, opts)
      * 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;
+    }
 }
 
 /*
@@ -1776,12 +1841,12 @@ scan_authfile(f, client, server, secret, addrs, opts, filename)
        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;
        }