X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fauth.c;h=727c69d4af8d92bf55924d95eef3edf1c3070b17;hb=fda3a821c1f0eda47ef53632f6a42084924b7167;hp=3d232be9dde64064d6f6efc201c9a09be0aec69f;hpb=d05576dd19391b5f606538f8bf8b4e98370fcd8f;p=ppp.git diff --git a/pppd/auth.c b/pppd/auth.c index 3d232be..727c69d 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.72 2002/01/11 18:07:45 etbe Exp $" +#define RCSID "$Id: auth.c,v 1.77 2002/05/21 17:26:49 dfs 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; @@ -138,6 +143,8 @@ int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; int (*null_auth_hook) __P((struct wordlist **paddrs, struct wordlist **popts)) = NULL; +int (*allowed_address_hook) __P((u_int32_t addr)) = NULL; + /* A notifier for when the peer has authenticated itself, and we are proceeding to the network phase. */ struct notifier *auth_up_notifier = NULL; @@ -167,6 +174,13 @@ bool uselogin = 0; /* Use /etc/passwd for checking PAP */ bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +#ifdef CHAPMS +bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#else +bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ +bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ +#endif bool usehostname = 0; /* Use hostname for our_name */ bool auth_required = 0; /* Always require authentication from peer */ bool allow_any_ip = 0; /* Allow peer to use any IP address */ @@ -175,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. */ @@ -216,30 +224,68 @@ 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, + "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV | OPT_A2COPY, &allow_any_ip }, { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, "Require PAP authentication from peer", - OPT_PRIOSUB | 1, &auth_required }, + OPT_PRIOSUB | OPT_A2COPY | 1, &auth_required }, { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, "Require PAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | 1, &auth_required }, { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, "Require CHAP authentication from peer", - OPT_PRIOSUB | 1, &auth_required }, + 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, "Require CHAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + OPT_ALIAS | OPT_PRIOSUB | OPT_A2COPY | OPT_A3OR | MDTYPE_MD5, + &auth_required, 0, 0, NULL, 0, 0, &lcp_wantoptions[0].chap_mdtype }, +#ifdef CHAPMS + { "require-mschap", o_bool, &lcp_wantoptions[0].neg_chap, + "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, + "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, + "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, + "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 }, +#endif { "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", OPT_ALIAS | 1 }, - { "refuse-chap", o_bool, &refuse_chap, - "Don't agree to auth to peer with CHAP", 1 }, + "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", OPT_ALIAS | 1 }, + "Don't allow CHAP authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, + &lcp_allowoptions[0].chap_mdtype }, +#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 }, + { "-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 }, + { "-mschap-v2", o_bool, &refuse_mschap_v2, + "Don't allow MS-CHAPv2 authentication with peer", + OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, + &lcp_allowoptions[0].chap_mdtype }, +#endif { "name", o_string, our_name, "Set local name for authentication", @@ -464,12 +510,12 @@ link_established(unit) && protp->lowerup != NULL) (*protp->lowerup)(unit); - if (auth_required && !(go->neg_chap || go->neg_upap)) { + if (auth_required && !(go->neg_upap || go->neg_chap)) { /* * We wanted the peer to authenticate itself, and it refused: * if we have some address(es) it can use without auth, fine, * otherwise treat it as though it authenticated with PAP using - * a username * of "" and a password of "". If that's not OK, + * a username of "" and a password of "". If that's not OK, * boot it out. */ if (noauth_addrs != NULL) { @@ -486,14 +532,14 @@ link_established(unit) used_login = 0; auth = 0; if (go->neg_chap) { - ChapAuthPeer(unit, our_name, go->chap_mdtype); + ChapAuthPeer(unit, our_name, CHAP_DIGEST(go->chap_mdtype)); auth |= CHAP_PEER; } else if (go->neg_upap) { upap_authpeer(unit); auth |= PAP_PEER; } if (ho->neg_chap) { - ChapAuthWithPeer(unit, user, ho->chap_mdtype); + ChapAuthWithPeer(unit, user, CHAP_DIGEST(ho->chap_mdtype)); auth |= CHAP_WITHPEER; } else if (ho->neg_upap) { if (passwd[0] == 0) { @@ -505,6 +551,7 @@ link_established(unit) auth |= PAP_WITHPEER; } auth_pending[unit] = auth; + auth_done[unit] = 0; if (!auth) network_phase(unit); @@ -550,42 +597,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"); + } } /* @@ -606,8 +677,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; { @@ -616,6 +687,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; @@ -634,6 +718,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. @@ -665,14 +752,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) @@ -684,6 +784,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. @@ -832,11 +935,11 @@ auth_check_options() if (auth_required) { allow_any_ip = 0; if (!wo->neg_chap && !wo->neg_upap) { - wo->neg_chap = 1; + wo->neg_chap = 1; wo->chap_mdtype = MDTYPE_ALL; wo->neg_upap = 1; } } else { - wo->neg_chap = 0; + wo->neg_chap = 0; wo->chap_mdtype = MDTYPE_NONE; wo->neg_upap = 0; } @@ -846,7 +949,7 @@ auth_check_options() */ lacks_ip = 0; can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); - if (!can_auth && wo->neg_chap) { + if (!can_auth && (wo->neg_chap)) { can_auth = have_chap_secret((explicit_remote? remote_name: NULL), our_name, 1, &lacks_ip); } @@ -887,7 +990,7 @@ auth_reset(unit) lcp_options *ao = &lcp_allowoptions[0]; ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); - ao->neg_chap = !refuse_chap + ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2) && (passwd[0] != 0 || have_chap_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); @@ -949,6 +1052,9 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) BZERO(passwd, sizeof(passwd)); if (addrs != 0) free_wordlist(addrs); + if (opts != 0) { + free_wordlist(opts); + } return ret? UPAP_AUTHACK: UPAP_AUTHNAK; } } @@ -1401,6 +1507,13 @@ have_chap_secret(client, server, need_ip, lacks_ipp) char *filename; struct wordlist *addrs; + if (chap_check_hook) { + ret = (*chap_check_hook)(); + if (ret >= 0) { + return ret; + } + } + filename = _PATH_CHAPFILE; f = fopen(filename, "r"); if (f == NULL) @@ -1447,6 +1560,12 @@ get_secret(unit, client, server, secret, secret_len, am_server) if (!am_server && passwd[0] != 0) { strlcpy(secbuf, passwd, sizeof(secbuf)); + } else if (!am_server && chap_passwd_hook) { + if ( (*chap_passwd_hook)(client, secbuf) < 0) { + error("Unable to obtain CHAP password for %s on %s from plugin", + client, server); + return 0; + } } else { filename = _PATH_CHAPFILE; addrs = NULL; @@ -1656,11 +1775,17 @@ auth_ip_addr(unit, addr) if (bad_ip_adrs(addr)) return 0; + if (allowed_address_hook) { + ok = allowed_address_hook(addr); + if (ok >= 0) return ok; + } + if (addresses[unit] != NULL) { ok = ip_addr_check(addr, addresses[unit]); if (ok >= 0) return ok; } + if (auth_required) return 0; /* no addresses authorized */ return allow_any_ip || privileged || !have_route_to(addr);