X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fchap-new.c;h=0b1bb86e77c0d35a03b6e58629ace81748ec36e5;hb=2ae35d6c067d198c5e0bb4ac2d480271f3de3540;hp=e5fe16106d85ad80508d5ad070fe4c983dce8856;hpb=67e53ed830e2e6f881a52518c32f2fa628778018;p=ppp.git diff --git a/pppd/chap-new.c b/pppd/chap-new.c index e5fe161..0b1bb86 100644 --- a/pppd/chap-new.c +++ b/pppd/chap-new.c @@ -28,11 +28,12 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id: chap-new.c,v 1.7 2005/07/10 07:31:26 paulus Exp $" +#define RCSID "$Id: chap-new.c,v 1.9 2007/06/19 02:08:35 carlsonj Exp $" #include #include #include "pppd.h" +#include "session.h" #include "chap-new.h" #include "chap-md5.h" @@ -54,20 +55,23 @@ int (*chap_verify_hook)(char *name, char *ourname, int id, /* * Option variables. */ -int chap_timeout_time = 3; +int chap_server_timeout_time = 3; int chap_max_transmits = 10; int chap_rechallenge_time = 0; +int chap_client_timeout_time = 60; /* * Command-line options. */ static option_t chap_option_list[] = { - { "chap-restart", o_int, &chap_timeout_time, - "Set timeout for CHAP", OPT_PRIO }, + { "chap-restart", o_int, &chap_server_timeout_time, + "Set timeout for CHAP (as server)", OPT_PRIO }, { "chap-max-challenge", o_int, &chap_max_transmits, "Set max #xmits for challenge", OPT_PRIO }, { "chap-interval", o_int, &chap_rechallenge_time, "Set interval for rechallenge", OPT_PRIO }, + { "chap-timeout", o_int, &chap_client_timeout_time, + "Set timeout for CHAP (as client)", OPT_PRIO }, { NULL } }; @@ -113,7 +117,8 @@ static struct chap_server_state { static void chap_init(int unit); static void chap_lowerup(int unit); static void chap_lowerdown(int unit); -static void chap_timeout(void *arg); +static void chap_server_timeout(void *arg); +static void chap_client_timeout(void *arg); static void chap_generate_challenge(struct chap_server_state *ss); static void chap_handle_response(struct chap_server_state *ss, int code, unsigned char *pkt, int len); @@ -128,7 +133,7 @@ static void chap_handle_status(struct chap_client_state *cs, int code, int id, static void chap_protrej(int unit); static void chap_input(int unit, unsigned char *pkt, int pktlen); static int chap_print_pkt(unsigned char *p, int plen, - void (*printer) __P((void *, char *, ...)), void *arg); + void (*printer)(void *, char *, ...), void *arg); /* List of digest types that we know about */ static struct chap_digest_type *chap_digests; @@ -170,7 +175,7 @@ chap_lowerup(int unit) cs->flags |= LOWERUP; ss->flags |= LOWERUP; if (ss->flags & AUTH_STARTED) - chap_timeout(ss); + chap_server_timeout(ss); } static void @@ -179,9 +184,11 @@ chap_lowerdown(int unit) struct chap_client_state *cs = &client; struct chap_server_state *ss = &server; + if (cs->flags & TIMEOUT_PENDING) + UNTIMEOUT(chap_client_timeout, cs); cs->flags = 0; if (ss->flags & TIMEOUT_PENDING) - UNTIMEOUT(chap_timeout, ss); + UNTIMEOUT(chap_server_timeout, ss); ss->flags = 0; } @@ -213,7 +220,7 @@ chap_auth_peer(int unit, char *our_name, int digest_code) ss->id = (unsigned char)(drand48() * 256); ss->flags |= AUTH_STARTED; if (ss->flags & LOWERUP) - chap_timeout(ss); + chap_server_timeout(ss); } /* @@ -239,16 +246,17 @@ chap_auth_with_peer(int unit, char *our_name, int digest_code) cs->digest = dp; cs->name = our_name; - cs->flags |= AUTH_STARTED; + cs->flags |= AUTH_STARTED | TIMEOUT_PENDING; + TIMEOUT(chap_client_timeout, cs, chap_client_timeout_time); } /* - * chap_timeout - It's time to send another challenge to the peer. + * chap_server_timeout - It's time to send another challenge to the peer. * This could be either a retransmission of a previous challenge, * or a new challenge to start re-authentication. */ static void -chap_timeout(void *arg) +chap_server_timeout(void *arg) { struct chap_server_state *ss = arg; @@ -267,7 +275,19 @@ chap_timeout(void *arg) output(0, ss->challenge, ss->challenge_pktlen); ++ss->challenge_xmits; ss->flags |= TIMEOUT_PENDING; - TIMEOUT(chap_timeout, arg, chap_timeout_time); + TIMEOUT(chap_server_timeout, arg, chap_server_timeout_time); +} + +/* chap_client_timeout - Authentication with peer timed out. */ +static void +chap_client_timeout(void *arg) +{ + struct chap_client_state *cs = arg; + + cs->flags &= ~TIMEOUT_PENDING; + cs->flags |= AUTH_DONE | AUTH_FAILED; + error("CHAP authentication timed out"); + auth_withpeer_fail(0, PPP_CHAP); } /* @@ -326,7 +346,7 @@ chap_handle_response(struct chap_server_state *ss, int id, if (ss->flags & TIMEOUT_PENDING) { ss->flags &= ~TIMEOUT_PENDING; - UNTIMEOUT(chap_timeout, ss); + UNTIMEOUT(chap_server_timeout, ss); } if (explicit_remote) { @@ -366,6 +386,22 @@ chap_handle_response(struct chap_server_state *ss, int id, if (ss->flags & CHALLENGE_VALID) { ss->flags &= ~CHALLENGE_VALID; + if (!(ss->flags & AUTH_DONE) && !(ss->flags & AUTH_FAILED)) { + /* + * Auth is OK, so now we need to check session restrictions + * to ensure everything is OK, but only if we used a + * plugin, and only if we're configured to check. This + * allows us to do PAM checks on PPP servers that + * authenticate against ActiveDirectory, and use AD for + * account info (like when using Winbind integrated with + * PAM). + */ + if (session_mgmt && + session_check(name, NULL, devnam, NULL) == 0) { + ss->flags |= AUTH_FAILED; + warn("Peer %q failed CHAP Session verification", name); + } + } if (ss->flags & AUTH_FAILED) { auth_peer_fail(0, PPP_CHAP); } else { @@ -375,7 +411,7 @@ chap_handle_response(struct chap_server_state *ss, int id, name, strlen(name)); if (chap_rechallenge_time) { ss->flags |= TIMEOUT_PENDING; - TIMEOUT(chap_timeout, ss, + TIMEOUT(chap_server_timeout, ss, chap_rechallenge_time); } } @@ -478,10 +514,13 @@ chap_handle_status(struct chap_client_state *cs, int code, int id, return; cs->flags |= AUTH_DONE; + UNTIMEOUT(chap_client_timeout, cs); + cs->flags &= ~TIMEOUT_PENDING; + if (code == CHAP_SUCCESS) { /* used for MS-CHAP v2 mutual auth, yuck */ if (cs->digest->check_success != NULL) { - if (!(*cs->digest->check_success)(pkt, len, cs->priv)) + if (!(*cs->digest->check_success)(id, pkt, len)) code = CHAP_FAILURE; } else msg = "CHAP authentication succeeded"; @@ -501,6 +540,7 @@ chap_handle_status(struct chap_client_state *cs, int code, int id, auth_withpeer_success(0, PPP_CHAP, cs->digest->code); else { cs->flags |= AUTH_FAILED; + error("CHAP authentication failed"); auth_withpeer_fail(0, PPP_CHAP); } } @@ -544,7 +584,7 @@ chap_protrej(int unit) if (ss->flags & TIMEOUT_PENDING) { ss->flags &= ~TIMEOUT_PENDING; - UNTIMEOUT(chap_timeout, ss); + UNTIMEOUT(chap_server_timeout, ss); } if (ss->flags & AUTH_STARTED) { ss->flags = 0; @@ -552,6 +592,7 @@ chap_protrej(int unit) } if ((cs->flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { cs->flags &= ~AUTH_STARTED; + error("CHAP authentication failed due to protocol-reject"); auth_withpeer_fail(0, PPP_CHAP); } } @@ -565,7 +606,7 @@ static char *chap_code_names[] = { static int chap_print_pkt(unsigned char *p, int plen, - void (*printer) __P((void *, char *, ...)), void *arg) + void (*printer)(void *, char *, ...), void *arg) { int code, id, len; int clen, nlen;