X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fchap-new.c;h=2714bff6478589412aeed098f77262e89a91349c;hp=ef002d1e1dd3c807b01d501d5c80a2a6a182d264;hb=afc4b130bbd6f5f5cd9baafdc7e836d8f6238deb;hpb=71d3de90eae52087b405e962ca650b71cec79c67 diff --git a/pppd/chap-new.c b/pppd/chap-new.c index ef002d1..2714bff 100644 --- a/pppd/chap-new.c +++ b/pppd/chap-new.c @@ -10,16 +10,11 @@ * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to + * 2. The name(s) of the authors of this software must not be used to * endorse or promote products derived from this software without * prior written permission. * - * 4. Redistributions of any form whatsoever must retain the following + * 3. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Paul Mackerras * ". @@ -33,23 +28,29 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id" +#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" #ifdef CHAPMS #include "chap_ms.h" +#define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) +#else +#define MDTYPE_ALL (MDTYPE_MD5) #endif +int chap_mdtype_all = MDTYPE_ALL; + /* Hook for a plugin to validate CHAP challenge */ int (*chap_verify_hook)(char *name, char *ourname, int id, struct chap_digest_type *digest, unsigned char *challenge, unsigned char *response, - unsigned char *message, int message_space) = NULL; + char *message, int message_space) = NULL; /* * Option variables. @@ -96,6 +97,7 @@ static struct chap_server_state { int challenge_xmits; int challenge_pktlen; unsigned char challenge[CHAL_MAX_PKTLEN]; + char message[256]; } server; /* Values for flags in chap_client_state and chap_server_state */ @@ -119,7 +121,7 @@ static void chap_handle_response(struct chap_server_state *ss, int code, static int chap_verify_response(char *name, char *ourname, int id, struct chap_digest_type *digest, unsigned char *challenge, unsigned char *response, - unsigned char *message, int message_space); + char *message, int message_space); static void chap_respond(struct chap_client_state *cs, int id, unsigned char *pkt, int len); static void chap_handle_status(struct chap_client_state *cs, int code, int id, @@ -216,7 +218,7 @@ chap_auth_peer(int unit, char *our_name, int digest_code) } /* - * chap_auth_peer - Prepare to authenticate ourselves to the peer. + * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. * There isn't much to do until we receive a challenge. */ void @@ -306,27 +308,23 @@ chap_handle_response(struct chap_server_state *ss, int id, { int response_len, ok, mlen; unsigned char *response, *p; - unsigned char *name = NULL; /* initialized to shut gcc up */ + char *name = NULL; /* initialized to shut gcc up */ int (*verifier)(char *, char *, int, struct chap_digest_type *, - unsigned char *, unsigned char *, unsigned char *, int); + unsigned char *, unsigned char *, char *, int); char rname[MAXNAMELEN+1]; - unsigned char message[256]; if ((ss->flags & LOWERUP) == 0) return; if (id != ss->challenge[PPP_HDRLEN+1] || len < 2) return; - if ((ss->flags & AUTH_DONE) == 0) { - if ((ss->flags & CHALLENGE_VALID) == 0) - return; + if (ss->flags & CHALLENGE_VALID) { response = pkt; GETCHAR(response_len, pkt); len -= response_len + 1; /* length of name */ - name = pkt + response_len; + name = (char *)pkt + response_len; if (len < 0) return; - ss->flags &= ~CHALLENGE_VALID; if (ss->flags & TIMEOUT_PENDING) { ss->flags &= ~TIMEOUT_PENDING; UNTIMEOUT(chap_timeout, ss); @@ -346,39 +344,59 @@ chap_handle_response(struct chap_server_state *ss, int id, verifier = chap_verify_response; ok = (*verifier)(name, ss->name, id, ss->digest, ss->challenge + PPP_HDRLEN + CHAP_HDRLEN, - response, message, sizeof(message)); + response, ss->message, sizeof(ss->message)); if (!ok || !auth_number()) { ss->flags |= AUTH_FAILED; warn("Peer %q failed CHAP authentication", name); } - } + } else if ((ss->flags & AUTH_DONE) == 0) + return; /* send the response */ p = outpacket_buf; MAKEHEADER(p, PPP_CHAP); - mlen = strlen(message); + mlen = strlen(ss->message); len = CHAP_HDRLEN + mlen; p[0] = (ss->flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; p[1] = id; p[2] = len >> 8; p[3] = len; if (mlen > 0) - memcpy(p + CHAP_HDRLEN, message, mlen); + memcpy(p + CHAP_HDRLEN, ss->message, mlen); output(0, outpacket_buf, PPP_HDRLEN + len); - if ((ss->flags & AUTH_DONE) == 0) { - ss->flags |= AUTH_DONE; + 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 { - auth_peer_success(0, PPP_CHAP, ss->digest->code, - name, strlen(name)); + if ((ss->flags & AUTH_DONE) == 0) + auth_peer_success(0, PPP_CHAP, + ss->digest->code, + name, strlen(name)); if (chap_rechallenge_time) { ss->flags |= TIMEOUT_PENDING; TIMEOUT(chap_timeout, ss, chap_rechallenge_time); } } + ss->flags |= AUTH_DONE; } } @@ -391,14 +409,14 @@ static int chap_verify_response(char *name, char *ourname, int id, struct chap_digest_type *digest, unsigned char *challenge, unsigned char *response, - unsigned char *message, int message_space) + char *message, int message_space) { int ok; - char secret[MAXSECRETLEN]; + unsigned char secret[MAXSECRETLEN]; int secret_len; /* Get the secret that the peer is supposed to know */ - if (!get_secret(0, name, ourname, secret, &secret_len, 1)) { + if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) { error("No CHAP secret found for authenticating %q", name); return 0; } @@ -480,7 +498,7 @@ chap_handle_status(struct chap_client_state *cs, int code, int id, 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"; @@ -500,6 +518,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); } } @@ -551,6 +570,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); } }