]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/auth.c
Experemental per session traffic limiting.
[ppp.git] / pppd / auth.c
index 61b50e5b95d68e9bf249f683ab2b9c6faf504e0a..a1e9fd26a8ff8e2293a065b329d46482338b44a3 100644 (file)
@@ -32,7 +32,7 @@
  * 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.78 2002/07/13 06:24:36 kad Exp $"
 
 #include <stdio.h>
 #include <stddef.h>
@@ -69,6 +69,8 @@
 #include "pppd.h"
 #include "fsm.h"
 #include "lcp.h"
+#include "ccp.h"
+#include "ecp.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 have been completed. */
+int auth_done[NUM_PPP];
+
 /* Set if we have successfully called plogin() */
 static int logged_in;
 
@@ -184,12 +189,6 @@ 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
-#define CHAP_WITHPEER  4
-#define CHAP_PEER      8
-
 extern char *crypt __P((const char *, const char *));
 
 /* Prototypes for procedures local to this file. */
@@ -218,6 +217,10 @@ static int  set_noauth_addr __P((char **));
 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.
  */
@@ -552,6 +555,7 @@ link_established(unit)
        auth |= PAP_WITHPEER;
     }
     auth_pending[unit] = auth;
+    auth_done[unit] = 0;
 
     if (!auth)
        network_phase(unit);
@@ -597,42 +601,66 @@ network_phase(unit)
        free_wordlist(extra_options);
        extra_options = 0;
     }
-    start_networks();
+    start_networks(unit);
 }
 
 void
-start_networks()
+start_networks(unit)
+    int unit;
 {
+    static int started = 0;
     int i;
     struct protent *protp;
+    int ecp_required, mppe_required;
 
-    new_phase(PHASE_NETWORK);
+    if (!started) {
+       started = 1;
+       new_phase(PHASE_NETWORK);
 
 #ifdef HAVE_MULTILINK
-    if (multilink) {
-       if (mp_join_bundle()) {
-           if (updetach && !nodetach)
-               detach();
-           return;
+       if (multilink) {
+           if (mp_join_bundle()) {
+               if (updetach && !nodetach)
+                   detach();
+               return;
+           }
        }
-    }
 #endif /* HAVE_MULTILINK */
 
 #ifdef PPP_FILTER
-    if (!demand)
-       set_filters(&pass_filter, &active_filter);
+       if (!demand)
+           set_filters(&pass_filter, &active_filter);
 #endif
-    for (i = 0; (protp = protocols[i]) != NULL; ++i)
-        if (protp->protocol < 0xC000 && protp->enabled_flag
-           && protp->open != NULL) {
-           (*protp->open)(0);
-           if (protp->protocol != PPP_CCP)
+       /* 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 after encryption has completed.
+     * OPENED here merely means that negotiation has completed.  It is
+     * up to the protocol to correctly terminate or disable LCP/NCP 
+     * based on the result of the negotiation.
+     */
+    ecp_required = ecp_gotoptions[unit].required;
+    mppe_required = ccp_gotoptions[unit].mppe;
+    if ((!ecp_required && !mppe_required)
+       || (ecp_required && ecp_fsm[unit].state == OPENED)
+       || (mppe_required && ccp_fsm[unit].state == OPENED)) {
+       for (i = 0; (protp = protocols[i]) != NULL; ++i)
+           if (protp->protocol < 0xC000
+               && protp->protocol != PPP_CCP && protp->protocol != PPP_ECP
+               && protp->enabled_flag && protp->open != NULL) {
+               (*protp->open)(0);
                ++num_np_open;
-       }
+           }
 
-    if (num_np_open == 0)
-       /* nothing to do */
-       lcp_close(0, "No network protocols running");
+       if (num_np_open == 0)
+           /* nothing to do */
+           lcp_close(0, "No network protocols running");
+    }
 }
 
 /*
@@ -653,8 +681,8 @@ auth_peer_fail(unit, protocol)
  * 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;
 {
@@ -663,6 +691,19 @@ auth_peer_success(unit, protocol, name, namelen)
     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;
@@ -681,6 +722,9 @@ auth_peer_success(unit, protocol, name, namelen)
     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.
@@ -712,14 +756,27 @@ auth_withpeer_fail(unit, protocol)
  * 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;
+       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)
@@ -731,6 +788,9 @@ auth_withpeer_success(unit, protocol)
        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.
@@ -771,6 +831,11 @@ np_up(unit, proto)
        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.
         */
@@ -790,6 +855,9 @@ np_down(unit, proto)
     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);
     }
 }
@@ -807,6 +875,43 @@ 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_MAX:
+           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.