X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fauth.c;h=61b50e5b95d68e9bf249f683ab2b9c6faf504e0a;hp=94871bfae51b31617436ddaccfdae408f69fbd64;hb=bcfa20820fc9ff3b25bcf62308e3e737c1897dc6;hpb=fe3b3b7599b968bc7b4e5a423bae0e17005f4bf1 diff --git a/pppd/auth.c b/pppd/auth.c index 94871bf..61b50e5 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.69 2001/03/12 22:50:01 paulus Exp $" +#define RCSID "$Id: auth.c,v 1.75 2002/03/05 15:14:04 dfs Exp $" #include #include @@ -64,6 +64,7 @@ #define PW_PPP PW_LOGIN #endif #endif +#include #include "pppd.h" #include "fsm.h" @@ -132,6 +133,20 @@ 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; + +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; + +/* 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. @@ -154,6 +169,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 */ @@ -203,30 +225,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", @@ -407,6 +467,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); @@ -424,7 +485,7 @@ link_down(unit) num_np_open = 0; num_np_up = 0; if (phase != PHASE_DEAD) - new_phase(PHASE_TERMINATE); + new_phase(PHASE_ESTABLISH); } /* @@ -450,12 +511,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) { @@ -472,14 +533,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) { @@ -509,6 +570,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; @@ -727,6 +789,7 @@ np_down(unit, proto) { if (--num_np_up == 0) { UNTIMEOUT(check_idle, NULL); + UNTIMEOUT(connect_time_expired, NULL); new_phase(PHASE_NETWORK); } } @@ -816,11 +879,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; } @@ -830,7 +893,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); } @@ -871,7 +934,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)); @@ -933,6 +996,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; } } @@ -1120,7 +1186,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); @@ -1250,19 +1316,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); @@ -1271,7 +1347,6 @@ null_login(unit) if (addrs != 0) free_wordlist(addrs); - fclose(f); return ret; } @@ -1376,6 +1451,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) @@ -1422,6 +1504,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; @@ -1631,11 +1719,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);