X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fauth.c;h=a1e9fd26a8ff8e2293a065b329d46482338b44a3;hp=61b50e5b95d68e9bf249f683ab2b9c6faf504e0a;hb=b2f8595268e72c1668eb8f2e4d942b6290266db5;hpb=bcfa20820fc9ff3b25bcf62308e3e737c1897dc6 diff --git a/pppd/auth.c b/pppd/auth.c index 61b50e5..a1e9fd2 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -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 #include @@ -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.