]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/auth.c
__linux__ (already defined by compiler) not _linux_ (manually defined)
[ppp.git] / pppd / auth.c
index 61b50e5b95d68e9bf249f683ab2b9c6faf504e0a..cf042686a33557e14fb1f81ce29b83c7a28c787b 100644 (file)
@@ -32,7 +32,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: auth.c,v 1.75 2002/03/05 15:14:04 dfs Exp $"
+#define RCSID  "$Id: auth.c,v 1.88 2002/10/27 12:56:26 fcusack Exp $"
 
 #include <stdio.h>
 #include <stddef.h>
 
 #include <stdio.h>
 #include <stddef.h>
@@ -46,7 +46,7 @@
 #include <sys/socket.h>
 #include <utmp.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <utmp.h>
 #include <fcntl.h>
-#if defined(_PATH_LASTLOG) && defined(_linux_)
+#if defined(_PATH_LASTLOG) && defined(__linux__)
 #include <lastlog.h>
 #endif
 
 #include <lastlog.h>
 #endif
 
@@ -69,6 +69,8 @@
 #include "pppd.h"
 #include "fsm.h"
 #include "lcp.h"
 #include "pppd.h"
 #include "fsm.h"
 #include "lcp.h"
+#include "ccp.h"
+#include "ecp.h"
 #include "ipcp.h"
 #include "upap.h"
 #include "chap.h"
 #include "ipcp.h"
 #include "upap.h"
 #include "chap.h"
@@ -91,6 +93,9 @@ char peer_authname[MAXNAMELEN];
 /* Records which authentication operations haven't completed yet. */
 static int auth_pending[NUM_PPP];
 
 /* Records which authentication operations haven't completed yet. */
 static int auth_pending[NUM_PPP];
 
+/* Records which authentication operations have been completed. */
+int auth_done[NUM_PPP];
+
 /* Set if we have successfully called plogin() */
 static int logged_in;
 
 /* Set if we have successfully called plogin() */
 static int logged_in;
 
@@ -101,6 +106,12 @@ static struct permitted_ip *addresses[NUM_PPP];
    without authenticating itself. */
 static struct wordlist *noauth_addrs;
 
    without authenticating itself. */
 static struct wordlist *noauth_addrs;
 
+/* Remote telephone number, if available */
+char remote_number[MAXNAMELEN];
+
+/* Wordlist giving remote telephone numbers which may connect. */
+static struct wordlist *permitted_numbers;
+
 /* Extra options to apply, from the secrets file entry for the peer. */
 static struct wordlist *extra_options;
 
 /* Extra options to apply, from the secrets file entry for the peer. */
 static struct wordlist *extra_options;
 
@@ -184,12 +195,6 @@ char remote_name[MAXNAMELEN];      /* Peer's name for authentication */
 
 static char *uafname;          /* name of most recent +ua file */
 
 
 static char *uafname;          /* name of most recent +ua file */
 
-/* Bits in auth_pending[] */
-#define PAP_WITHPEER   1
-#define PAP_PEER       2
-#define CHAP_WITHPEER  4
-#define CHAP_PEER      8
-
 extern char *crypt __P((const char *, const char *));
 
 /* Prototypes for procedures local to this file. */
 extern char *crypt __P((const char *, const char *));
 
 /* Prototypes for procedures local to this file. */
@@ -215,9 +220,14 @@ static int  some_ip_ok __P((struct wordlist *));
 static int  setupapfile __P((char **));
 static int  privgroup __P((char **));
 static int  set_noauth_addr __P((char **));
 static int  setupapfile __P((char **));
 static int  privgroup __P((char **));
 static int  set_noauth_addr __P((char **));
+static int  set_permitted_number __P((char **));
 static void check_access __P((FILE *, char *));
 static int  wordlist_count __P((struct wordlist *));
 
 static void check_access __P((FILE *, char *));
 static int  wordlist_count __P((struct wordlist *));
 
+#ifdef MAXOCTETS
+static void check_maxoctets __P((void *));
+#endif
+
 /*
  * Authentication-related options.
  */
 /*
  * Authentication-related options.
  */
@@ -225,39 +235,39 @@ option_t auth_options[] = {
     { "auth", o_bool, &auth_required,
       "Require authentication from peer", OPT_PRIO | 1 },
     { "noauth", o_bool, &auth_required,
     { "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 | OPT_A2COPY,
+      "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",
       &allow_any_ip },
     { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
       "Require PAP authentication from peer",
-      OPT_PRIOSUB | OPT_A2COPY | 1, &auth_required },
+      OPT_PRIOSUB | 1, &auth_required },
     { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
       "Require PAP authentication from peer",
     { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
       "Require PAP authentication from peer",
-      OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | 1, &auth_required },
-    { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
+      OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required },
+    { "require-chap", o_bool, &auth_required,
       "Require CHAP authentication from peer",
       "Require CHAP authentication from peer",
-      OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MD5,
-      &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
-    { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
+      OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5,
+      &lcp_wantoptions[0].chap_mdtype },
+    { "+chap", o_bool, &auth_required,
       "Require CHAP authentication from peer",
       "Require CHAP authentication from peer",
-      OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MD5,
-      &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
+      OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5,
+      &lcp_wantoptions[0].chap_mdtype },
 #ifdef CHAPMS
 #ifdef CHAPMS
-    { "require-mschap", o_bool, &lcp_wantoptions[0].neg_chap,
+    { "require-mschap", o_bool, &auth_required,
       "Require MS-CHAP authentication from peer",
       "Require MS-CHAP authentication from peer",
-      OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT,
-      &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
-    { "+mschap", o_bool, &lcp_wantoptions[0].neg_chap,
+      OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT,
+      &lcp_wantoptions[0].chap_mdtype },
+    { "+mschap", o_bool, &auth_required,
       "Require MS-CHAP authentication from peer",
       "Require MS-CHAP authentication from peer",
-      OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT,
-      &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
-    { "require-mschap-v2", o_bool, &lcp_wantoptions[0].neg_chap,
+      OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT,
+      &lcp_wantoptions[0].chap_mdtype },
+    { "require-mschap-v2", o_bool, &auth_required,
       "Require MS-CHAPv2 authentication from peer",
       "Require MS-CHAPv2 authentication from peer",
-      OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT_V2,
-      &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
-    { "+mschap-v2", o_bool, &lcp_wantoptions[0].neg_chap,
+      OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2,
+      &lcp_wantoptions[0].chap_mdtype },
+    { "+mschap-v2", o_bool, &auth_required,
       "Require MS-CHAPv2 authentication from peer",
       "Require MS-CHAPv2 authentication from peer",
-      OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MICROSOFT_V2,
-      &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype },
+      OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2,
+      &lcp_wantoptions[0].chap_mdtype },
 #endif
 
     { "refuse-pap", o_bool, &refuse_pap,
 #endif
 
     { "refuse-pap", o_bool, &refuse_pap,
@@ -265,7 +275,8 @@ option_t auth_options[] = {
     { "-pap", o_bool, &refuse_pap,
       "Don't allow PAP authentication with peer", OPT_ALIAS | 1 },
     { "refuse-chap", o_bool, &refuse_chap,
     { "-pap", o_bool, &refuse_pap,
       "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", OPT_A2CLRB | MDTYPE_MD5,
+      "Don't agree to auth to peer with CHAP",
+      OPT_A2CLRB | MDTYPE_MD5,
       &lcp_allowoptions[0].chap_mdtype },
     { "-chap", o_bool, &refuse_chap,
       "Don't allow CHAP authentication with peer",
       &lcp_allowoptions[0].chap_mdtype },
     { "-chap", o_bool, &refuse_chap,
       "Don't allow CHAP authentication with peer",
@@ -274,14 +285,16 @@ option_t auth_options[] = {
 #ifdef CHAPMS
     { "refuse-mschap", o_bool, &refuse_mschap,
       "Don't agree to auth to peer with MS-CHAP",
 #ifdef CHAPMS
     { "refuse-mschap", o_bool, &refuse_mschap,
       "Don't agree to auth to peer with MS-CHAP",
-      OPT_A2CLRB | MDTYPE_MICROSOFT, &lcp_allowoptions[0].chap_mdtype },
+      OPT_A2CLRB | MDTYPE_MICROSOFT,
+      &lcp_allowoptions[0].chap_mdtype },
     { "-mschap", o_bool, &refuse_mschap,
       "Don't allow MS-CHAP authentication with peer",
       OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT,
       &lcp_allowoptions[0].chap_mdtype },
     { "refuse-mschap-v2", o_bool, &refuse_mschap_v2,
       "Don't agree to auth to peer with MS-CHAPv2",
     { "-mschap", o_bool, &refuse_mschap,
       "Don't allow MS-CHAP authentication with peer",
       OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT,
       &lcp_allowoptions[0].chap_mdtype },
     { "refuse-mschap-v2", o_bool, &refuse_mschap_v2,
       "Don't agree to auth to peer with MS-CHAPv2",
-      OPT_A2CLRB | MDTYPE_MICROSOFT_V2, &lcp_allowoptions[0].chap_mdtype },
+      OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
+      &lcp_allowoptions[0].chap_mdtype },
     { "-mschap-v2", o_bool, &refuse_mschap_v2,
       "Don't allow MS-CHAPv2 authentication with peer",
       OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
     { "-mschap-v2", o_bool, &refuse_mschap_v2,
       "Don't allow MS-CHAPv2 authentication with peer",
       OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
@@ -323,6 +336,14 @@ option_t auth_options[] = {
       "Set IP address(es) which can be used without authentication",
       OPT_PRIV | OPT_A2LIST },
 
       "Set IP address(es) which can be used without authentication",
       OPT_PRIV | OPT_A2LIST },
 
+    { "remotenumber", o_string, remote_number,
+      "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC,
+      NULL, MAXNAMELEN },
+
+    { "allow-number", o_special, (void *)set_permitted_number,
+      "Set telephone number(s) which are allowed to connect",
+      OPT_PRIV | OPT_A2LIST },
+
     { NULL }
 };
 
     { NULL }
 };
 
@@ -427,6 +448,28 @@ set_noauth_addr(argv)
 }
 
 
 }
 
 
+/*
+ * set_permitted_number - set remote telephone number(s) that may connect.
+ */
+static int
+set_permitted_number(argv)
+    char **argv;
+{
+    char *number = *argv;
+    int l = strlen(number) + 1;
+    struct wordlist *wp;
+
+    wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l);
+    if (wp == NULL)
+       novm("allow-number argument");
+    wp->word = (char *) (wp + 1);
+    wp->next = permitted_numbers;
+    BCOPY(number, wp->word, l);
+    permitted_numbers = wp;
+    return 1;
+}
+
+
 /*
  * An Open on LCP has requested a change from Dead to Establish phase.
  * Do what's necessary to bring the physical layer up.
 /*
  * An Open on LCP has requested a change from Dead to Establish phase.
  * Do what's necessary to bring the physical layer up.
@@ -552,6 +595,7 @@ link_established(unit)
        auth |= PAP_WITHPEER;
     }
     auth_pending[unit] = auth;
        auth |= PAP_WITHPEER;
     }
     auth_pending[unit] = auth;
+    auth_done[unit] = 0;
 
     if (!auth)
        network_phase(unit);
 
     if (!auth)
        network_phase(unit);
@@ -566,6 +610,10 @@ network_phase(unit)
 {
     lcp_options *go = &lcp_gotoptions[unit];
 
 {
     lcp_options *go = &lcp_gotoptions[unit];
 
+    /* Log calling number. */
+    if (*remote_number)
+       notice("peer from calling number %q authorized", remote_number);
+
     /*
      * If the peer had to authenticate, run the auth-up script now.
      */
     /*
      * If the peer had to authenticate, run the auth-up script now.
      */
@@ -597,14 +645,16 @@ network_phase(unit)
        free_wordlist(extra_options);
        extra_options = 0;
     }
        free_wordlist(extra_options);
        extra_options = 0;
     }
-    start_networks();
+    start_networks(unit);
 }
 
 void
 }
 
 void
-start_networks()
+start_networks(unit)
+    int unit;
 {
     int i;
     struct protent *protp;
 {
     int i;
     struct protent *protp;
+    int ecp_required, mppe_required;
 
     new_phase(PHASE_NETWORK);
 
 
     new_phase(PHASE_NETWORK);
 
@@ -622,12 +672,37 @@ start_networks()
     if (!demand)
        set_filters(&pass_filter, &active_filter);
 #endif
     if (!demand)
        set_filters(&pass_filter, &active_filter);
 #endif
+    /* Start CCP and ECP */
+    for (i = 0; (protp = protocols[i]) != NULL; ++i)
+       if ((protp->protocol == PPP_ECP || protp->protocol == PPP_CCP)
+           && protp->enabled_flag && protp->open != NULL)
+           (*protp->open)(0);
+
+    /*
+     * Bring up other network protocols iff encryption is not required.
+     */
+    ecp_required = ecp_gotoptions[unit].required;
+    mppe_required = ccp_gotoptions[unit].mppe;
+    if (!ecp_required && !mppe_required)
+       continue_networks(unit);
+}
+
+void
+continue_networks(unit)
+    int unit;
+{
+    int i;
+    struct protent *protp;
+
+    /*
+     * Start the "real" network protocols.
+     */
     for (i = 0; (protp = protocols[i]) != NULL; ++i)
     for (i = 0; (protp = protocols[i]) != NULL; ++i)
-        if (protp->protocol < 0xC000 && protp->enabled_flag
-           && protp->open != NULL) {
+       if (protp->protocol < 0xC000
+           && protp->protocol != PPP_CCP && protp->protocol != PPP_ECP
+           && protp->enabled_flag && protp->open != NULL) {
            (*protp->open)(0);
            (*protp->open)(0);
-           if (protp->protocol != PPP_CCP)
-               ++num_np_open;
+           ++num_np_open;
        }
 
     if (num_np_open == 0)
        }
 
     if (num_np_open == 0)
@@ -653,8 +728,8 @@ auth_peer_fail(unit, protocol)
  * The peer has been successfully authenticated using `protocol'.
  */
 void
  * The peer has been successfully authenticated using `protocol'.
  */
 void
-auth_peer_success(unit, protocol, name, namelen)
-    int unit, protocol;
+auth_peer_success(unit, protocol, prot_flavor, name, namelen)
+    int unit, protocol, prot_flavor;
     char *name;
     int namelen;
 {
     char *name;
     int namelen;
 {
@@ -663,6 +738,19 @@ auth_peer_success(unit, protocol, name, namelen)
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_PEER;
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_PEER;
+       switch (prot_flavor) {
+       case CHAP_DIGEST_MD5:
+           bit |= CHAP_MD5_PEER;
+           break;
+#ifdef CHAPMS
+       case CHAP_MICROSOFT:
+           bit |= CHAP_MS_PEER;
+           break;
+       case CHAP_MICROSOFT_V2:
+           bit |= CHAP_MS2_PEER;
+           break;
+#endif
+       }
        break;
     case PPP_PAP:
        bit = PAP_PEER;
        break;
     case PPP_PAP:
        bit = PAP_PEER;
@@ -681,6 +769,9 @@ auth_peer_success(unit, protocol, name, namelen)
     peer_authname[namelen] = 0;
     script_setenv("PEERNAME", peer_authname, 0);
 
     peer_authname[namelen] = 0;
     script_setenv("PEERNAME", peer_authname, 0);
 
+    /* Save the authentication method for later. */
+    auth_done[unit] |= bit;
+
     /*
      * If there is no more authentication still to be done,
      * proceed to the network (or callback) phase.
     /*
      * If there is no more authentication still to be done,
      * proceed to the network (or callback) phase.
@@ -712,14 +803,27 @@ auth_withpeer_fail(unit, protocol)
  * We have successfully authenticated ourselves with the peer using `protocol'.
  */
 void
  * We have successfully authenticated ourselves with the peer using `protocol'.
  */
 void
-auth_withpeer_success(unit, protocol)
-    int unit, protocol;
+auth_withpeer_success(unit, protocol, prot_flavor)
+    int unit, protocol, prot_flavor;
 {
     int bit;
 
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_WITHPEER;
 {
     int bit;
 
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_WITHPEER;
+       switch (prot_flavor) {
+       case CHAP_DIGEST_MD5:
+           bit |= CHAP_MD5_WITHPEER;
+           break;
+#ifdef CHAPMS
+       case CHAP_MICROSOFT:
+           bit |= CHAP_MS_WITHPEER;
+           break;
+       case CHAP_MICROSOFT_V2:
+           bit |= CHAP_MS2_WITHPEER;
+           break;
+#endif
+       }
        break;
     case PPP_PAP:
        if (passwd_from_file)
        break;
     case PPP_PAP:
        if (passwd_from_file)
@@ -731,6 +835,9 @@ auth_withpeer_success(unit, protocol)
        bit = 0;
     }
 
        bit = 0;
     }
 
+    /* Save the authentication method for later. */
+    auth_done[unit] |= bit;
+
     /*
      * If there is no more authentication still being done,
      * proceed to the network (or callback) phase.
     /*
      * If there is no more authentication still being done,
      * proceed to the network (or callback) phase.
@@ -771,6 +878,11 @@ np_up(unit, proto)
        if (maxconnect > 0)
            TIMEOUT(connect_time_expired, 0, maxconnect);
 
        if (maxconnect > 0)
            TIMEOUT(connect_time_expired, 0, maxconnect);
 
+#ifdef MAXOCTETS
+       if (maxoctets > 0)
+           TIMEOUT(check_maxoctets, NULL, maxoctets_timeout);
+#endif
+
        /*
         * Detach now, if the updetach option was given.
         */
        /*
         * Detach now, if the updetach option was given.
         */
@@ -790,6 +902,9 @@ np_down(unit, proto)
     if (--num_np_up == 0) {
        UNTIMEOUT(check_idle, NULL);
        UNTIMEOUT(connect_time_expired, NULL);
     if (--num_np_up == 0) {
        UNTIMEOUT(check_idle, NULL);
        UNTIMEOUT(connect_time_expired, NULL);
+#ifdef MAXOCTETS
+       UNTIMEOUT(check_maxoctets, NULL);
+#endif 
        new_phase(PHASE_NETWORK);
     }
 }
        new_phase(PHASE_NETWORK);
     }
 }
@@ -807,6 +922,44 @@ np_finished(unit, proto)
     }
 }
 
     }
 }
 
+#ifdef MAXOCTETS
+static void
+check_maxoctets(arg)
+    void *arg;
+{
+    int diff;
+    unsigned int used;
+
+    update_link_stats(ifunit);
+    link_stats_valid=0;
+    
+    switch(maxoctets_dir) {
+       case PPP_OCTETS_DIRECTION_IN:
+           used = link_stats.bytes_in;
+           break;
+       case PPP_OCTETS_DIRECTION_OUT:
+           used = link_stats.bytes_out;
+           break;
+       case PPP_OCTETS_DIRECTION_MAXOVERAL:
+       case PPP_OCTETS_DIRECTION_MAXSESSION:
+           used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out;
+           break;
+       default:
+           used = link_stats.bytes_in+link_stats.bytes_out;
+           break;
+    }
+    diff = maxoctets - used;
+    if(diff < 0) {
+       notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used);
+       lcp_close(0, "Traffic limit");
+       need_holdoff = 0;
+       status = EXIT_TRAFFIC_LIMIT;
+    } else {
+        TIMEOUT(check_maxoctets, NULL, maxoctets_timeout);
+    }
+}
+#endif
+
 /*
  * check_idle - check whether the link has been idle for long
  * enough that we can shut it down.
 /*
  * check_idle - check whether the link has been idle for long
  * enough that we can shut it down.
@@ -875,6 +1028,10 @@ auth_check_options()
        default_auth = 1;
     }
 
        default_auth = 1;
     }
 
+    /* If we selected any CHAP flavors, we should probably negotiate it. :-) */
+    if (wo->chap_mdtype)
+       wo->neg_chap = 1;
+
     /* If authentication is required, ask peer for CHAP or PAP. */
     if (auth_required) {
        allow_any_ip = 0;
     /* If authentication is required, ask peer for CHAP or PAP. */
     if (auth_required) {
        allow_any_ip = 0;
@@ -1027,19 +1184,14 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg)
            ret = UPAP_AUTHACK;
            if (uselogin || login_secret) {
                /* login option or secret is @login */
            ret = UPAP_AUTHACK;
            if (uselogin || login_secret) {
                /* login option or secret is @login */
-               ret = plogin(user, passwd, msg);
-               if (ret == UPAP_AUTHNAK)
-                   warn("PAP login failure for %s", user);
-               else
+               if ((ret = plogin(user, passwd, msg)) == UPAP_AUTHACK)
                    used_login = 1;
            }
            if (secret[0] != 0 && !login_secret) {
                /* password given in pap-secrets - must match */
                if ((cryptpap || strcmp(passwd, secret) != 0)
                    used_login = 1;
            }
            if (secret[0] != 0 && !login_secret) {
                /* password given in pap-secrets - must match */
                if ((cryptpap || strcmp(passwd, secret) != 0)
-                   && strcmp(crypt(passwd, secret), secret) != 0) {
+                   && strcmp(crypt(passwd, secret), secret) != 0)
                    ret = UPAP_AUTHNAK;
                    ret = UPAP_AUTHNAK;
-                   warn("PAP authentication failure for %s", user);
-               }
            }
        }
        fclose(f);
            }
        }
        fclose(f);
@@ -1249,7 +1401,7 @@ plogin(user, passwd, msg)
     tty = devnam;
     if (strncmp(tty, "/dev/", 5) == 0)
        tty += 5;
     tty = devnam;
     if (strncmp(tty, "/dev/", 5) == 0)
        tty += 5;
-    logwtmp(tty, user, remote_name);           /* Add wtmp login entry */
+    logwtmp(tty, user, ifname);                /* Add wtmp login entry */
 
 #if defined(_PATH_LASTLOG) && !defined(USE_PAM)
     if (pw != (struct passwd *)NULL) {
 
 #if defined(_PATH_LASTLOG) && !defined(USE_PAM)
     if (pw != (struct passwd *)NULL) {
@@ -1776,6 +1928,34 @@ some_ip_ok(addrs)
     return 0;
 }
 
     return 0;
 }
 
+/*
+ * auth_number - check whether the remote number is allowed to connect.
+ * Returns 1 if authorized, 0 otherwise.
+ */
+int
+auth_number()
+{
+    struct wordlist *wp = permitted_numbers;
+    int l;
+
+    /* Allow all if no authorization list. */
+    if (!wp)
+       return 1;
+
+    /* Allow if we have a match in the authorization list. */
+    while (wp) {
+       /* trailing '*' wildcard */
+       l = strlen(wp->word);
+       if ((wp->word)[l - 1] == '*')
+           l--;
+       if (!strncasecmp(wp->word, remote_number, l))
+           return 1;
+       wp = wp->next;
+    }
+
+    return 0;
+}
+
 /*
  * check_access - complain if a secret file has too-liberal permissions.
  */
 /*
  * check_access - complain if a secret file has too-liberal permissions.
  */