chap-new.c
来自「自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多」· C语言 代码 · 共 640 行 · 第 1/2 页
C
640 行
/* * chap-new.c - New CHAP implementation. * * Copyright (c) 2003 Paul Mackerras. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * 3. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Paul Mackerras * <paulus@samba.org>". * * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#define RCSID "$Id: chap-new.c,v 1.8 2005/07/13 10:41:58 paulus Exp $"#include <stdlib.h>#include <string.h>#include "pppd.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)#endifint 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, char *message, int message_space) = NULL;/* * Option variables. */int chap_timeout_time = 3;int chap_max_transmits = 10;int chap_rechallenge_time = 0;/* * Command-line options. */static option_t chap_option_list[] = { { "chap-restart", o_int, &chap_timeout_time, "Set timeout for CHAP", 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 }, { NULL }};/* * Internal state. */static struct chap_client_state { int flags; char *name; struct chap_digest_type *digest; unsigned char priv[64]; /* private area for digest's use */} client;/* * These limits apply to challenge and response packets we send. * The +4 is the +1 that we actually need rounded up. */#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN)#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN)static struct chap_server_state { int flags; int id; char *name; struct chap_digest_type *digest; 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 */#define LOWERUP 1#define AUTH_STARTED 2#define AUTH_DONE 4#define AUTH_FAILED 8#define TIMEOUT_PENDING 0x10#define CHALLENGE_VALID 0x20/* * Prototypes. */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_generate_challenge(struct chap_server_state *ss);static void chap_handle_response(struct chap_server_state *ss, int code, unsigned char *pkt, int len);static int chap_verify_response(char *name, char *ourname, int id, struct chap_digest_type *digest, unsigned char *challenge, unsigned char *response, 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, unsigned char *pkt, int len);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);/* List of digest types that we know about */static struct chap_digest_type *chap_digests;/* * chap_init - reset to initial state. */static voidchap_init(int unit){ memset(&client, 0, sizeof(client)); memset(&server, 0, sizeof(server)); chap_md5_init();#ifdef CHAPMS chapms_init();#endif}/* * Add a new digest type to the list. */voidchap_register_digest(struct chap_digest_type *dp){ dp->next = chap_digests; chap_digests = dp;}/* * chap_lowerup - we can start doing stuff now. */static voidchap_lowerup(int unit){ struct chap_client_state *cs = &client; struct chap_server_state *ss = &server; cs->flags |= LOWERUP; ss->flags |= LOWERUP; if (ss->flags & AUTH_STARTED) chap_timeout(ss);}static voidchap_lowerdown(int unit){ struct chap_client_state *cs = &client; struct chap_server_state *ss = &server; cs->flags = 0; if (ss->flags & TIMEOUT_PENDING) UNTIMEOUT(chap_timeout, ss); ss->flags = 0;}/* * chap_auth_peer - Start authenticating the peer. * If the lower layer is already up, we start sending challenges, * otherwise we wait for the lower layer to come up. */voidchap_auth_peer(int unit, char *our_name, int digest_code){ struct chap_server_state *ss = &server; struct chap_digest_type *dp; if (ss->flags & AUTH_STARTED) { error("CHAP: peer authentication already started!"); return; } for (dp = chap_digests; dp != NULL; dp = dp->next) if (dp->code == digest_code) break; if (dp == NULL) fatal("CHAP digest 0x%x requested but not available", digest_code); ss->digest = dp; ss->name = our_name; /* Start with a random ID value */ ss->id = (unsigned char)(drand48() * 256); ss->flags |= AUTH_STARTED; if (ss->flags & LOWERUP) chap_timeout(ss);}/* * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. * There isn't much to do until we receive a challenge. */voidchap_auth_with_peer(int unit, char *our_name, int digest_code){ struct chap_client_state *cs = &client; struct chap_digest_type *dp; if (cs->flags & AUTH_STARTED) { error("CHAP: authentication with peer already started!"); return; } for (dp = chap_digests; dp != NULL; dp = dp->next) if (dp->code == digest_code) break; if (dp == NULL) fatal("CHAP digest 0x%x requested but not available", digest_code); cs->digest = dp; cs->name = our_name; cs->flags |= AUTH_STARTED;}/* * chap_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 voidchap_timeout(void *arg){ struct chap_server_state *ss = arg; ss->flags &= ~TIMEOUT_PENDING; if ((ss->flags & CHALLENGE_VALID) == 0) { ss->challenge_xmits = 0; chap_generate_challenge(ss); ss->flags |= CHALLENGE_VALID; } else if (ss->challenge_xmits >= chap_max_transmits) { ss->flags &= ~CHALLENGE_VALID; ss->flags |= AUTH_DONE | AUTH_FAILED; auth_peer_fail(0, PPP_CHAP); return; } output(0, ss->challenge, ss->challenge_pktlen); ++ss->challenge_xmits; ss->flags |= TIMEOUT_PENDING; TIMEOUT(chap_timeout, arg, chap_timeout_time);}/* * chap_generate_challenge - generate a challenge string and format * the challenge packet in ss->challenge_pkt. */static voidchap_generate_challenge(struct chap_server_state *ss){ int clen = 1, nlen, len; unsigned char *p; p = ss->challenge; MAKEHEADER(p, PPP_CHAP); p += CHAP_HDRLEN; ss->digest->generate_challenge(p); clen = *p; nlen = strlen(ss->name); memcpy(p + 1 + clen, ss->name, nlen); len = CHAP_HDRLEN + 1 + clen + nlen; ss->challenge_pktlen = PPP_HDRLEN + len; p = ss->challenge + PPP_HDRLEN; p[0] = CHAP_CHALLENGE; p[1] = ++ss->id; p[2] = len >> 8; p[3] = len;}/* * chap_handle_response - check the response to our challenge. */static voidchap_handle_response(struct chap_server_state *ss, int id, unsigned char *pkt, int len){ int response_len, ok, mlen; unsigned char *response, *p; char *name = NULL; /* initialized to shut gcc up */ int (*verifier)(char *, char *, int, struct chap_digest_type *, unsigned char *, unsigned char *, char *, int); char rname[MAXNAMELEN+1]; if ((ss->flags & LOWERUP) == 0) return; if (id != ss->challenge[PPP_HDRLEN+1] || len < 2) return; if (ss->flags & CHALLENGE_VALID) { response = pkt;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?