X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fchap-new.c;h=565713f2cfa7bf2ed060c1211260673a46a29e60;hb=bdd34ab1f2f87acb23c6d92feee7354ac53005ff;hp=e5fe16106d85ad80508d5ad070fe4c983dce8856;hpb=67e53ed830e2e6f881a52518c32f2fa628778018;p=ppp.git diff --git a/pppd/chap-new.c b/pppd/chap-new.c index e5fe161..565713f 100644 --- a/pppd/chap-new.c +++ b/pppd/chap-new.c @@ -28,15 +28,20 @@ * 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 $" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include #include "pppd.h" +#include "session.h" #include "chap-new.h" #include "chap-md5.h" -#ifdef CHAPMS +#ifdef PPP_WITH_CHAPMS #include "chap_ms.h" #define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) #else @@ -54,20 +59,26 @@ 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; +int chapms_strip_domain = 0; /* * 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 }, + { "chapms-strip-domain", o_bool, &chapms_strip_domain, + "Strip the domain prefix before the Username", 1 }, { NULL } }; @@ -113,7 +124,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 +140,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; @@ -143,7 +155,7 @@ chap_init(int unit) memset(&server, 0, sizeof(server)); chap_md5_init(); -#ifdef CHAPMS +#ifdef PPP_WITH_CHAPMS chapms_init(); #endif } @@ -158,6 +170,18 @@ chap_register_digest(struct chap_digest_type *dp) chap_digests = dp; } +/* + * Lookup a digest type by code + */ +struct chap_digest_type * +chap_find_digest(int digest_code) { + struct chap_digest_type *dp = NULL; + for (dp = chap_digests; dp != NULL; dp = dp->next) + if (dp->code == digest_code) + break; + return dp; +} + /* * chap_lowerup - we can start doing stuff now. */ @@ -170,7 +194,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 +203,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; } @@ -200,9 +226,8 @@ chap_auth_peer(int unit, char *our_name, int digest_code) error("CHAP: peer authentication already started!"); return; } - for (dp = chap_digests; dp != NULL; dp = dp->next) - if (dp->code == digest_code) - break; + + dp = chap_find_digest(digest_code); if (dp == NULL) fatal("CHAP digest 0x%x requested but not available", digest_code); @@ -213,7 +238,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 +264,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 +293,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 +364,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) { @@ -335,6 +373,14 @@ chap_handle_response(struct chap_server_state *ss, int id, /* Null terminate and clean remote name. */ slprintf(rname, sizeof(rname), "%.*v", len, name); name = rname; + + /* strip the MS domain name */ + if (chapms_strip_domain && strrchr(rname, '\\')) { + char tmp[MAXNAMELEN+1]; + + strcpy(tmp, strrchr(rname, '\\') + 1); + strcpy(rname, tmp); + } } if (chap_verify_hook) @@ -366,6 +412,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 +437,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 +540,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 +566,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 +610,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 +618,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 +632,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;