X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fauth.c;h=a5fc1bd6bc32dfaaea6af37ada412400df08c572;hp=9a6bfb1a8a4a1b38c7778eeb6ed7869aac908361;hb=de4afebf8fa879fec442d7b6c456b571b004b2b4;hpb=37a8acc7ee2527693d0c8ba82b2eaea249abde34 diff --git a/pppd/auth.c b/pppd/auth.c index 9a6bfb1..a5fc1bd 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.68 2001/03/08 05:11:10 paulus Exp $" +#define RCSID "$Id: auth.c,v 1.73 2002/01/22 16:02:58 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. @@ -407,6 +422,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 +440,7 @@ link_down(unit) num_np_open = 0; num_np_up = 0; if (phase != PHASE_DEAD) - new_phase(PHASE_TERMINATE); + new_phase(PHASE_ESTABLISH); } /* @@ -509,6 +525,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 +744,7 @@ np_down(unit, proto) { if (--num_np_up == 0) { UNTIMEOUT(check_idle, NULL); + UNTIMEOUT(connect_time_expired, NULL); new_phase(PHASE_NETWORK); } } @@ -933,6 +951,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 +1141,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 +1271,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 +1302,6 @@ null_login(unit) if (addrs != 0) free_wordlist(addrs); - fclose(f); return ret; } @@ -1376,6 +1406,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 +1459,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; @@ -1605,8 +1648,15 @@ set_allowed_addrs(unit, addrs, opts) * which is a single host, then use that if we find one. */ if (suggested_ip != 0 - && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) + && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { wo->hisaddr = suggested_ip; + /* + * Do we insist on this address? No, if there are other + * addresses authorized than the suggested one. + */ + if (n > 1) + wo->accept_remote = 1; + } } /* @@ -1624,11 +1674,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);