⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap.c

📁 自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) * * Copyright (c) 2001 by Sun Microsystems, Inc. * All rights reserved. * * Non-exclusive rights to redistribute, modify, translate, and use * this software in source and binary forms, in whole or in part, is * hereby granted, provided that the above copyright notice is * duplicated in any source form, and that neither the name of the * copyright holder nor the author is used to endorse or promote * products derived from this software. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Original version by James Carlson * * This implementation of EAP supports MD5-Challenge and SRP-SHA1 * authentication styles.  Note that support of MD5-Challenge is a * requirement of RFC 2284, and that it's essentially just a * reimplementation of regular RFC 1994 CHAP using EAP messages. * * As an authenticator ("server"), there are multiple phases for each * style.  In the first phase of each style, the unauthenticated peer * name is queried using the EAP Identity request type.  If the * "remotename" option is used, then this phase is skipped, because * the peer's name is presumed to be known. * * For MD5-Challenge, there are two phases, and the second phase * consists of sending the challenge itself and handling the * associated response. * * For SRP-SHA1, there are four phases.  The second sends 's', 'N', * and 'g'.  The reply contains 'A'.  The third sends 'B', and the * reply contains 'M1'.  The forth sends the 'M2' value. * * As an authenticatee ("client"), there's just a single phase -- * responding to the queries generated by the peer.  EAP is an * authenticator-driven protocol. * * Based on draft-ietf-pppext-eap-srp-03.txt. */#define RCSID	"$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"/* * TODO: */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pwd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <assert.h>#include <errno.h>#include "pppd.h"#include "pathnames.h"#include "md5.h"#include "eap.h"#ifdef USE_SRP#include <t_pwd.h>#include <t_server.h>#include <t_client.h>#include "pppcrypt.h"#endif /* USE_SRP */#ifndef SHA_DIGESTSIZE#define	SHA_DIGESTSIZE 20#endifstatic const char rcsid[] = RCSID;eap_state eap_states[NUM_PPP];		/* EAP state; one for each unit */#ifdef USE_SRPstatic char *pn_secret = NULL;		/* Pseudonym generating secret */#endif/* * Command-line options. */static option_t eap_option_list[] = {    { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout,      "Set retransmit timeout for EAP Requests (server)" },    { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests,      "Set max number of EAP Requests sent (server)" },    { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout,      "Set time limit for peer EAP authentication" },    { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests,      "Set max number of EAP Requests allows (client)" },    { "eap-interval", o_int, &eap_states[0].es_rechallenge,      "Set interval for EAP rechallenge" },#ifdef USE_SRP    { "srp-interval", o_int, &eap_states[0].es_lwrechallenge,      "Set interval for SRP lightweight rechallenge" },    { "srp-pn-secret", o_string, &pn_secret,      "Long term pseudonym generation secret" },    { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo,      "Use pseudonym if offered one by server", 1 },#endif    { NULL }};/* * Protocol entry points. */static void eap_init __P((int unit));static void eap_input __P((int unit, u_char *inp, int inlen));static void eap_protrej __P((int unit));static void eap_lowerup __P((int unit));static void eap_lowerdown __P((int unit));static int  eap_printpkt __P((u_char *inp, int inlen,    void (*)(void *arg, char *fmt, ...), void *arg));struct protent eap_protent = {	PPP_EAP,		/* protocol number */	eap_init,		/* initialization procedure */	eap_input,		/* process a received packet */	eap_protrej,		/* process a received protocol-reject */	eap_lowerup,		/* lower layer has gone up */	eap_lowerdown,		/* lower layer has gone down */	NULL,			/* open the protocol */	NULL,			/* close the protocol */	eap_printpkt,		/* print a packet in readable form */	NULL,			/* process a received data packet */	1,			/* protocol enabled */	"EAP",			/* text name of protocol */	NULL,			/* text name of corresponding data protocol */	eap_option_list,	/* list of command-line options */	NULL,			/* check requested options; assign defaults */	NULL,			/* configure interface for demand-dial */	NULL			/* say whether to bring up link for this pkt */};/* * A well-known 2048 bit modulus. */static const u_char wkmodulus[] = {	0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B,	0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F,	0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07,	0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50,	0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED,	0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D,	0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D,	0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50,	0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0,	0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3,	0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8,	0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8,	0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA,	0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74,	0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7,	0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B,	0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16,	0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81,	0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A,	0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48,	0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D,	0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA,	0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78,	0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6,	0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29,	0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8,	0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82,	0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6,	0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4,	0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75,	0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2,	0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73};/* Local forward declarations. */static void eap_server_timeout __P((void *arg));/* * Convert EAP state code to printable string for debug. */static const char *eap_state_name(esc)enum eap_state_code esc;{	static const char *state_names[] = { EAP_STATES };	return (state_names[(int)esc]);}/* * eap_init - Initialize state for an EAP user.  This is currently * called once by main() during start-up. */static voideap_init(unit)int unit;{	eap_state *esp = &eap_states[unit];	BZERO(esp, sizeof (*esp));	esp->es_unit = unit;	esp->es_server.ea_timeout = EAP_DEFTIMEOUT;	esp->es_server.ea_maxrequests = EAP_DEFTRANSMITS;	esp->es_server.ea_id = (u_char)(drand48() * 0x100);	esp->es_client.ea_timeout = EAP_DEFREQTIME;	esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;}/* * eap_client_timeout - Give up waiting for the peer to send any * Request messages. */static voideap_client_timeout(arg)void *arg;{	eap_state *esp = (eap_state *) arg;	if (!eap_client_active(esp))		return;	error("EAP: timeout waiting for Request from peer");	auth_withpeer_fail(esp->es_unit, PPP_EAP);	esp->es_client.ea_state = eapBadAuth;}/* * eap_authwithpeer - Authenticate to our peer (behave as client). * * Start client state and wait for requests.  This is called only * after eap_lowerup. */voideap_authwithpeer(unit, localname)int unit;char *localname;{	eap_state *esp = &eap_states[unit];	/* Save the peer name we're given */	esp->es_client.ea_name = localname;	esp->es_client.ea_namelen = strlen(localname);	esp->es_client.ea_state = eapListen;	/*	 * Start a timer so that if the other end just goes	 * silent, we don't sit here waiting forever.	 */	if (esp->es_client.ea_timeout > 0)		TIMEOUT(eap_client_timeout, (void *)esp,		    esp->es_client.ea_timeout);}/* * Format a standard EAP Failure message and send it to the peer. * (Server operation) */static voideap_send_failure(esp)eap_state *esp;{	u_char *outp;	outp = outpacket_buf;    	MAKEHEADER(outp, PPP_EAP);	PUTCHAR(EAP_FAILURE, outp);	esp->es_server.ea_id++;	PUTCHAR(esp->es_server.ea_id, outp);	PUTSHORT(EAP_HEADERLEN, outp);	output(esp->es_unit, outpacket_buf, EAP_HEADERLEN + PPP_HDRLEN);	esp->es_server.ea_state = eapBadAuth;	auth_peer_fail(esp->es_unit, PPP_EAP);}/* * Format a standard EAP Success message and send it to the peer. * (Server operation) */static voideap_send_success(esp)eap_state *esp;{	u_char *outp;	outp = outpacket_buf;    	MAKEHEADER(outp, PPP_EAP);	PUTCHAR(EAP_SUCCESS, outp);	esp->es_server.ea_id++;	PUTCHAR(esp->es_server.ea_id, outp);	PUTSHORT(EAP_HEADERLEN, outp);	output(esp->es_unit, outpacket_buf, PPP_HDRLEN + EAP_HEADERLEN);	auth_peer_success(esp->es_unit, PPP_EAP, 0,	    esp->es_server.ea_peer, esp->es_server.ea_peerlen);}#ifdef USE_SRP/* * Set DES key according to pseudonym-generating secret and current * date. */static boolpncrypt_setkey(int timeoffs){	struct tm *tp;	char tbuf[9];	SHA1_CTX ctxt;	u_char dig[SHA_DIGESTSIZE];	time_t reftime;	if (pn_secret == NULL)		return (0);	reftime = time(NULL) + timeoffs;	tp = localtime(&reftime);	SHA1Init(&ctxt);	SHA1Update(&ctxt, pn_secret, strlen(pn_secret));	strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp);	SHA1Update(&ctxt, tbuf, strlen(tbuf));	SHA1Final(dig, &ctxt);	return (DesSetkey(dig));}static char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";struct b64state {	u_int32_t bs_bits;	int bs_offs;};static intb64enc(bs, inp, inlen, outp)struct b64state *bs;u_char *inp;int inlen;u_char *outp;{	int outlen = 0;	while (inlen > 0) {		bs->bs_bits = (bs->bs_bits << 8) | *inp++;		inlen--;		bs->bs_offs += 8;		if (bs->bs_offs >= 24) {			*outp++ = base64[(bs->bs_bits >> 18) & 0x3F];			*outp++ = base64[(bs->bs_bits >> 12) & 0x3F];			*outp++ = base64[(bs->bs_bits >> 6) & 0x3F];			*outp++ = base64[bs->bs_bits & 0x3F];			outlen += 4;			bs->bs_offs = 0;			bs->bs_bits = 0;		}	}	return (outlen);}static intb64flush(bs, outp)struct b64state *bs;u_char *outp;{	int outlen = 0;	if (bs->bs_offs == 8) {		*outp++ = base64[(bs->bs_bits >> 2) & 0x3F];		*outp++ = base64[(bs->bs_bits << 4) & 0x3F];		outlen = 2;	} else if (bs->bs_offs == 16) {		*outp++ = base64[(bs->bs_bits >> 10) & 0x3F];		*outp++ = base64[(bs->bs_bits >> 4) & 0x3F];		*outp++ = base64[(bs->bs_bits << 2) & 0x3F];		outlen = 3;	}	bs->bs_offs = 0;	bs->bs_bits = 0;	return (outlen);}static intb64dec(bs, inp, inlen, outp)struct b64state *bs;u_char *inp;int inlen;u_char *outp;{	int outlen = 0;	char *cp;	while (inlen > 0) {		if ((cp = strchr(base64, *inp++)) == NULL)			break;		bs->bs_bits = (bs->bs_bits << 6) | (cp - base64);		inlen--;		bs->bs_offs += 6;		if (bs->bs_offs >= 8) {			*outp++ = bs->bs_bits >> (bs->bs_offs - 8);			outlen++;			bs->bs_offs -= 8;		}	}	return (outlen);}#endif /* USE_SRP *//* * Assume that current waiting server state is complete and figure * next state to use based on available authentication data.  'status' * indicates if there was an error in handling the last query.  It is * 0 for success and non-zero for failure. */static voideap_figure_next_state(esp, status)eap_state *esp;int status;{#ifdef USE_SRP	unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp;	struct t_pw tpw;	struct t_confent *tce, mytce;	char *cp, *cp2;	struct t_server *ts;	int id, i, plen, toffs;	u_char vals[2];	struct b64state bs;#endif /* USE_SRP */	esp->es_server.ea_timeout = esp->es_savedtime;	switch (esp->es_server.ea_state) {	case eapBadAuth:		return;	case eapIdentify:#ifdef USE_SRP		/* Discard any previous session. */		ts = (struct t_server *)esp->es_server.ea_session;		if (ts != NULL) {			t_serverclose(ts);			esp->es_server.ea_session = NULL;			esp->es_server.ea_skey = NULL;		}#endif /* USE_SRP */		if (status != 0) {			esp->es_server.ea_state = eapBadAuth;			break;		}#ifdef USE_SRP		/* If we've got a pseudonym, try to decode to real name. */		if (esp->es_server.ea_peerlen > SRP_PSEUDO_LEN &&		    strncmp(esp->es_server.ea_peer, SRP_PSEUDO_ID,			SRP_PSEUDO_LEN) == 0 &&		    (esp->es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 <		    sizeof (secbuf)) {			BZERO(&bs, sizeof (bs));			plen = b64dec(&bs,			    esp->es_server.ea_peer + SRP_PSEUDO_LEN,			    esp->es_server.ea_peerlen - SRP_PSEUDO_LEN,			    secbuf);			toffs = 0;			for (i = 0; i < 5; i++) {				pncrypt_setkey(toffs);				toffs -= 86400;				if (!DesDecrypt(secbuf, clear)) {					dbglog("no DES here; cannot decode "					    "pseudonym");					return;				}				id = *(unsigned char *)clear;				if (id + 1 <= plen && id + 9 > plen)					break;			}			if (plen % 8 == 0 && i < 5) {				/*				 * Note that this is always shorter than the				 * original stored string, so there's no need				 * to realloc.				 */				if ((i = plen = *(unsigned char *)clear) > 7)					i = 7;				esp->es_server.ea_peerlen = plen;				dp = (unsigned char *)esp->es_server.ea_peer;				BCOPY(clear + 1, dp, i);				plen -= i;				dp += i;				sp = secbuf + 8;				while (plen > 0) {					(void) DesDecrypt(sp, dp);					sp += 8;					dp += 8;					plen -= 8;				}				esp->es_server.ea_peer[					esp->es_server.ea_peerlen] = '\0';				dbglog("decoded pseudonym to \"%.*q\"",				    esp->es_server.ea_peerlen,				    esp->es_server.ea_peer);			} else {				dbglog("failed to decode real name");				/* Stay in eapIdentfy state; requery */				break;			}		}		/* Look up user in secrets database. */		if (get_srp_secret(esp->es_unit, esp->es_server.ea_peer,		    esp->es_server.ea_name, (char *)secbuf, 1) != 0) {			/* Set up default in case SRP entry is bad */			esp->es_server.ea_state = eapMD5Chall;			/* Get t_confent based on index in srp-secrets */			id = strtol((char *)secbuf, &cp, 10);			if (*cp++ != ':' || id < 0)				break;			if (id == 0) {				mytce.index = 0;				mytce.modulus.data = (u_char *)wkmodulus;				mytce.modulus.len = sizeof (wkmodulus);				mytce.generator.data = (u_char *)"\002";				mytce.generator.len = 1;				tce = &mytce;			} else if ((tce = gettcid(id)) != NULL) {				/*				 * Client will have to verify this modulus/				 * generator combination, and that will take				 * a while.  Lengthen the timeout here.				 */				if (esp->es_server.ea_timeout > 0 &&				    esp->es_server.ea_timeout < 30)					esp->es_server.ea_timeout = 30;			} else {				break;			}			if ((cp2 = strchr(cp, ':')) == NULL)				break;			*cp2++ = '\0';			tpw.pebuf.name = esp->es_server.ea_peer;			tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf,			    cp);			tpw.pebuf.password.data = tpw.pwbuf;			tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf,			    cp2);			tpw.pebuf.salt.data = tpw.saltbuf;			if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL)				break;			esp->es_server.ea_session = (void *)ts;			esp->es_server.ea_state = eapSRP1;			vals[0] = esp->es_server.ea_id + 1;			vals[1] = EAPT_SRP;			t_serveraddexdata(ts, vals, 2);			/* Generate B; must call before t_servergetkey() */			t_servergenexp(ts);			break;		}#endif /* USE_SRP */		esp->es_server.ea_state = eapMD5Chall;		break;	case eapSRP1:#ifdef USE_SRP		ts = (struct t_server *)esp->es_server.ea_session;		if (ts != NULL && status != 0) {			t_serverclose(ts);			esp->es_server.ea_session = NULL;			esp->es_server.ea_skey = NULL;		}#endif /* USE_SRP */		if (status == 1) {			esp->es_server.ea_state = eapMD5Chall;		} else if (status != 0 || esp->es_server.ea_session == NULL) {			esp->es_server.ea_state = eapBadAuth;		} else {			esp->es_server.ea_state = eapSRP2;		}		break;	case eapSRP2:#ifdef USE_SRP		ts = (struct t_server *)esp->es_server.ea_session;		if (ts != NULL && status != 0) {			t_serverclose(ts);			esp->es_server.ea_session = NULL;			esp->es_server.ea_skey = NULL;		}#endif /* USE_SRP */		if (status != 0 || esp->es_server.ea_session == NULL) {			esp->es_server.ea_state = eapBadAuth;		} else {			esp->es_server.ea_state = eapSRP3;		}		break;	case eapSRP3:	case eapSRP4:#ifdef USE_SRP		ts = (struct t_server *)esp->es_server.ea_session;		if (ts != NULL && status != 0) {			t_serverclose(ts);			esp->es_server.ea_session = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -