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

📄 eap.c

📁 自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多
💻 C
📖 第 1 页 / 共 4 页
字号:
	return (path);}static intopen_pn_file(modebits)mode_t modebits;{	char *path;	int fd, err;	if ((path = name_of_pn_file()) == NULL)		return (-1);	fd = open(path, modebits, S_IRUSR | S_IWUSR);	err = errno;	free(path);	errno = err;	return (fd);}static voidremove_pn_file(){	char *path;	if ((path = name_of_pn_file()) != NULL) {		(void) unlink(path);		(void) free(path);	}}static voidwrite_pseudonym(esp, inp, len, id)eap_state *esp;u_char *inp;int len, id;{	u_char val;	u_char *datp, *digp;	SHA1_CTX ctxt;	u_char dig[SHA_DIGESTSIZE];	int dsize, fd, olen = len;	/*	 * Do the decoding by working backwards.  This eliminates the need	 * to save the decoded output in a separate buffer.	 */	val = id;	while (len > 0) {		if ((dsize = len % SHA_DIGESTSIZE) == 0)			dsize = SHA_DIGESTSIZE;		len -= dsize;		datp = inp + len;		SHA1Init(&ctxt);		SHA1Update(&ctxt, &val, 1);		SHA1Update(&ctxt, esp->es_client.ea_skey, SESSION_KEY_LEN);		if (len > 0) {			SHA1Update(&ctxt, datp, SHA_DIGESTSIZE);		} else {			SHA1Update(&ctxt, esp->es_client.ea_name,			    esp->es_client.ea_namelen);		}		SHA1Final(dig, &ctxt);		for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++)			*datp++ ^= *digp;	}	/* Now check that the result is sane */	if (olen <= 0 || *inp + 1 > olen) {		dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp);		return;	}	/* Save it away */	fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC);	if (fd < 0) {		dbglog("EAP: error saving pseudonym: %m");		return;	}	len = write(fd, inp + 1, *inp);	if (close(fd) != -1 && len == *inp) {		dbglog("EAP: saved pseudonym");		esp->es_usedpseudo = 0;	} else {		dbglog("EAP: failed to save pseudonym");		remove_pn_file();	}}#endif /* USE_SRP *//* * eap_request - Receive EAP Request message (client mode). */static voideap_request(esp, inp, id, len)eap_state *esp;u_char *inp;int id;int len;{	u_char typenum;	u_char vallen;	int secret_len;	char secret[MAXWORDLEN];	char rhostname[256];	MD5_CTX mdContext;	u_char hash[MD5_SIGNATURE_SIZE];#ifdef USE_SRP	struct t_client *tc;	struct t_num sval, gval, Nval, *Ap, Bval;	u_char vals[2];	SHA1_CTX ctxt;	u_char dig[SHA_DIGESTSIZE];	int fd;#endif /* USE_SRP */	/*	 * Note: we update es_client.ea_id *only if* a Response	 * message is being generated.  Otherwise, we leave it the	 * same for duplicate detection purposes.	 */	esp->es_client.ea_requests++;	if (esp->es_client.ea_maxrequests != 0 &&	    esp->es_client.ea_requests > esp->es_client.ea_maxrequests) {		info("EAP: received too many Request messages");		if (esp->es_client.ea_timeout > 0) {			UNTIMEOUT(eap_client_timeout, (void *)esp);		}		auth_withpeer_fail(esp->es_unit, PPP_EAP);		return;	}	if (len <= 0) {		error("EAP: empty Request message discarded");		return;	}	GETCHAR(typenum, inp);	len--;	switch (typenum) {	case EAPT_IDENTITY:		if (len > 0)			info("EAP: Identity prompt \"%.*q\"", len, inp);#ifdef USE_SRP		if (esp->es_usepseudo &&		    (esp->es_usedpseudo == 0 ||			(esp->es_usedpseudo == 1 &&			    id == esp->es_client.ea_id))) {			esp->es_usedpseudo = 1;			/* Try to get a pseudonym */			if ((fd = open_pn_file(O_RDONLY)) >= 0) {				strcpy(rhostname, SRP_PSEUDO_ID);				len = read(fd, rhostname + SRP_PSEUDO_LEN,				    sizeof (rhostname) - SRP_PSEUDO_LEN);				/* XXX NAI unsupported */				if (len > 0) {					eap_send_response(esp, id, typenum,					    rhostname, len + SRP_PSEUDO_LEN);				}				(void) close(fd);				if (len > 0)					break;			}		}		/* Stop using pseudonym now. */		if (esp->es_usepseudo && esp->es_usedpseudo != 2) {			remove_pn_file();			esp->es_usedpseudo = 2;		}#endif /* USE_SRP */		eap_send_response(esp, id, typenum, esp->es_client.ea_name,		    esp->es_client.ea_namelen);		break;	case EAPT_NOTIFICATION:		if (len > 0)			info("EAP: Notification \"%.*q\"", len, inp);		eap_send_response(esp, id, typenum, NULL, 0);		break;	case EAPT_NAK:		/*		 * Avoid the temptation to send Response Nak in reply		 * to Request Nak here.  It can only lead to trouble.		 */		warn("EAP: unexpected Nak in Request; ignored");		/* Return because we're waiting for something real. */		return;	case EAPT_MD5CHAP:		if (len < 1) {			error("EAP: received MD5-Challenge with no data");			/* Bogus request; wait for something real. */			return;		}		GETCHAR(vallen, inp);		len--;		if (vallen < 8 || vallen > len) {			error("EAP: MD5-Challenge with bad length %d (8..%d)",			    vallen, len);			/* Try something better. */			eap_send_nak(esp, id, EAPT_SRP);			break;		}		/* Not so likely to happen. */		if (vallen >= len + sizeof (rhostname)) {			dbglog("EAP: trimming really long peer name down");			BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);			rhostname[sizeof (rhostname) - 1] = '\0';		} else {			BCOPY(inp + vallen, rhostname, len - vallen);			rhostname[len - vallen] = '\0';		}		/* In case the remote doesn't give us his name. */		if (explicit_remote ||		    (remote_name[0] != '\0' && vallen == len))			strlcpy(rhostname, remote_name, sizeof (rhostname));		/*		 * Get the secret for authenticating ourselves with		 * the specified host.		 */		if (!get_secret(esp->es_unit, esp->es_client.ea_name,		    rhostname, secret, &secret_len, 0)) {			dbglog("EAP: no MD5 secret for auth to %q", rhostname);			eap_send_nak(esp, id, EAPT_SRP);			break;		}		MD5_Init(&mdContext);		typenum = id;		MD5_Update(&mdContext, &typenum, 1);		MD5_Update(&mdContext, secret, secret_len);		BZERO(secret, sizeof (secret));		MD5_Update(&mdContext, inp, vallen);		MD5_Final(hash, &mdContext);		eap_chap_response(esp, id, hash, esp->es_client.ea_name,		    esp->es_client.ea_namelen);		break;#ifdef USE_SRP	case EAPT_SRP:		if (len < 1) {			error("EAP: received empty SRP Request");			/* Bogus request; wait for something real. */			return;		}		/* Get subtype */		GETCHAR(vallen, inp);		len--;		switch (vallen) {		case EAPSRP_CHALLENGE:			tc = NULL;			if (esp->es_client.ea_session != NULL) {				tc = (struct t_client *)esp->es_client.				    ea_session;				/*				 * If this is a new challenge, then start				 * over with a new client session context.				 * Otherwise, just resend last response.				 */				if (id != esp->es_client.ea_id) {					t_clientclose(tc);					esp->es_client.ea_session = NULL;					tc = NULL;				}			}			/* No session key just yet */			esp->es_client.ea_skey = NULL;			if (tc == NULL) {				GETCHAR(vallen, inp);				len--;				if (vallen >= len) {					error("EAP: badly-formed SRP Challenge"					    " (name)");					/* Ignore badly-formed messages */					return;				}				BCOPY(inp, rhostname, vallen);				rhostname[vallen] = '\0';				INCPTR(vallen, inp);				len -= vallen;				/*				 * In case the remote doesn't give us his name,				 * use configured name.				 */				if (explicit_remote ||				    (remote_name[0] != '\0' && vallen == 0)) {					strlcpy(rhostname, remote_name,					    sizeof (rhostname));				}				if (esp->es_client.ea_peer != NULL)					free(esp->es_client.ea_peer);				esp->es_client.ea_peer = strdup(rhostname);				esp->es_client.ea_peerlen = strlen(rhostname);				GETCHAR(vallen, inp);				len--;				if (vallen >= len) {					error("EAP: badly-formed SRP Challenge"					    " (s)");					/* Ignore badly-formed messages */					return;				}				sval.data = inp;				sval.len = vallen;				INCPTR(vallen, inp);				len -= vallen;				GETCHAR(vallen, inp);				len--;				if (vallen > len) {					error("EAP: badly-formed SRP Challenge"					    " (g)");					/* Ignore badly-formed messages */					return;				}				/* If no generator present, then use value 2 */				if (vallen == 0) {					gval.data = (u_char *)"\002";					gval.len = 1;				} else {					gval.data = inp;					gval.len = vallen;				}				INCPTR(vallen, inp);				len -= vallen;				/*				 * If no modulus present, then use well-known				 * value.				 */				if (len == 0) {					Nval.data = (u_char *)wkmodulus;					Nval.len = sizeof (wkmodulus);				} else {					Nval.data = inp;					Nval.len = len;				}				tc = t_clientopen(esp->es_client.ea_name,				    &Nval, &gval, &sval);				if (tc == NULL) {					eap_send_nak(esp, id, EAPT_MD5CHAP);					break;				}				esp->es_client.ea_session = (void *)tc;				/* Add Challenge ID & type to verifier */				vals[0] = id;				vals[1] = EAPT_SRP;				t_clientaddexdata(tc, vals, 2);			}			Ap = t_clientgenexp(tc);			eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data,			    Ap->len);			break;		case EAPSRP_SKEY:			tc = (struct t_client *)esp->es_client.ea_session;			if (tc == NULL) {				warn("EAP: peer sent Subtype 2 without 1");				eap_send_nak(esp, id, EAPT_MD5CHAP);				break;			}			if (esp->es_client.ea_skey != NULL) {				/*				 * ID number should not change here.  Warn				 * if it does (but otherwise ignore).				 */				if (id != esp->es_client.ea_id) {					warn("EAP: ID changed from %d to %d "					    "in SRP Subtype 2 rexmit",					    esp->es_client.ea_id, id);				}			} else {				if (get_srp_secret(esp->es_unit,				    esp->es_client.ea_name,				    esp->es_client.ea_peer, secret, 0) == 0) {					/*					 * Can't work with this peer because					 * the secret is missing.  Just give					 * up.					 */					eap_send_nak(esp, id, EAPT_MD5CHAP);					break;				}				Bval.data = inp;				Bval.len = len;				t_clientpasswd(tc, secret);				BZERO(secret, sizeof (secret));				esp->es_client.ea_skey =				    t_clientgetkey(tc, &Bval);				if (esp->es_client.ea_skey == NULL) {					/* Server is rogue; stop now */					error("EAP: SRP server is rogue");					goto client_failure;				}			}			eap_srpval_response(esp, id, SRPVAL_EBIT,			    t_clientresponse(tc));			break;		case EAPSRP_SVALIDATOR:			tc = (struct t_client *)esp->es_client.ea_session;			if (tc == NULL || esp->es_client.ea_skey == NULL) {				warn("EAP: peer sent Subtype 3 without 1/2");				eap_send_nak(esp, id, EAPT_MD5CHAP);				break;			}			/*			 * If we're already open, then this ought to be a			 * duplicate.  Otherwise, check that the server is			 * who we think it is.			 */			if (esp->es_client.ea_state == eapOpen) {				if (id != esp->es_client.ea_id) {					warn("EAP: ID changed from %d to %d "					    "in SRP Subtype 3 rexmit",					    esp->es_client.ea_id, id);				}			} else {				len -= sizeof (u_int32_t) + SHA_DIGESTSIZE;				if (len < 0 || t_clientverify(tc, inp +					sizeof (u_int32_t)) != 0) {					error("EAP: SRP server verification "					    "failed");					goto client_failure;				}				GETLONG(esp->es_client.ea_keyflags, inp);				/* Save pseudonym if user wants it. */				if (len > 0 && esp->es_usepseudo) {					INCPTR(SHA_DIGESTSIZE, inp);					write_pseudonym(esp, inp, len, id);				}			}			/*			 * We've verified our peer.  We're now mostly done,			 * except for waiting on the regular EAP Success			 * message.			 */			eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0);			break;		case EAPSRP_LWRECHALLENGE:			if (len < 4) {				warn("EAP: malformed Lightweight rechallenge");				return;			}			SHA1Init(&ctxt);			vals[0] = id;			SHA1Update(&ctxt, vals, 1);			SHA1Update(&ctxt, esp->es_client.ea_skey,			    SESSION_KEY_LEN);			SHA1Update(&ctxt, inp, len);			SHA1Update(&ctxt, esp->es_client.ea_name,			    esp->es_client.ea_namelen);			SHA1Final(dig, &ctxt);			eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig,			    SHA_DIGESTSIZE);			break;		default:			error("EAP: unknown SRP Subtype %d", vallen);			eap_send_nak(esp, id, EAPT_MD5CHAP);			break;		}		break;#endif /* USE_SRP */	default:		info("EAP: unknown authentication type %d; Naking", typenum);		eap_send_nak(esp, id, EAPT_SRP);		break;	}	if (esp->es_client.ea_timeout > 0) {		UNTIMEOUT(eap_client_timeout, (void *)esp);		TIMEOUT(eap_client_timeout, (void *)esp,		    esp->es_client.ea_timeout);	}	return;#ifdef USE_SRPclient_failure:	esp->es_client.ea_state = eapBadAuth;	if (esp->es_client.ea_timeout > 0) {		UNTIMEOUT(eap_client_timeout, (void *)esp);	}	esp->es_client.ea_session = NULL;	t_clientclose(tc);	auth_withpeer_fail(esp->es_unit, PPP_EAP);#endif /* USE_SRP */}/* * eap_response - Receive EAP Response message (server mode). */static voideap_response(esp, inp, id, len)eap_state *esp;u_char *inp;int id;int len;{	u_char typenum;	u_char vallen;	int secret_len;	char secret[MAXSECRETLEN];	char rhostname[256];	MD5_CTX mdContext;	u_char hash[MD5_SIGNATURE_SIZE];#ifdef USE_SRP	struct t_server *ts;	struct t_num A;	SHA1_CTX ctxt;	u_char dig[SHA_DIGESTSIZE];#endif /* USE_SRP */	if (esp->es_server.ea_id != id) {		dbglog("EAP: discarding Response %d; expected ID %d", id,		    esp->es_server.ea_id);		return;	}	esp->es_server.ea_responses++;	if (len <= 0) {		error("EAP: empty Response message discarded");		return;	}	GETCHAR(typenum, inp);	len--;	switch (typenum) {	case EAPT_IDENTITY:		if (esp->es_server.ea_state != eapIdentify) {			dbglog("EAP discarding unwanted Identify \"%.q\"", len,			    inp);			break;		}		info("EAP: unauthenticated peer name \"%.*q\"", len, inp);		if (esp->es_server.ea_peer != NULL &&		    esp->es_server.ea_peer != remote_name)			free(esp->es_server.ea_peer);		esp->es_server.ea_peer = malloc(len + 1);		if (esp->es_server.ea_peer == NULL) {			esp->es_server.ea_peerlen = 0;			eap_figure_next_state(esp, 1);			break;		}		BCOPY(inp, esp->es_server.ea_peer, len);		esp->es_server.ea_peer[len] = '\0';		esp->es_server.ea_peerlen = len;		eap_figure_next_state(esp, 0);		break;	case EAPT_NOTIFICATION:		dbglog("EAP unexpected Notification; response discarded");		break;	case EAPT_NAK:		if (len < 1) {			info("EAP: Nak Response with no suggested protocol");			eap_figure_next_state(esp, 1);			break;		}		GETCHAR(vallen, inp);		len--;		if (!explicit_remote && esp->es_server.ea_state == eapIdentify){			/* Peer cannot Nak Identify Request */			eap_figure_next_state(esp, 1);			break;		}		switch (vallen) {		case EAPT_SRP:			/* Run through SRP validator selection again. */			esp->es_server.ea_state = eapIdentify;			eap_figure_next_state(esp, 0);			break;		case EAPT_MD5CHAP:			esp->es_server.ea_state = eapMD5Chall;			break;		default:			dbglog("EAP: peer requesting unknown Type %d", vallen);			switch (esp->es_server.ea_state) {			case eapSRP1:			case eapSRP2:			case eapSRP3:				esp->es_server.ea_state = eapMD5Chall;				break;			case eapMD5Chall:			case eapSRP4:				esp->es_server.ea_state = eapIdentify;				eap_figure_next_state(esp, 0);				break;			default:				break;

⌨️ 快捷键说明

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