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 + -
显示快捷键?