xref: /freebsd/contrib/wpa/src/eap_peer/eap_md5.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994)
339beb93cSSam Leffler  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
539beb93cSSam Leffler  * This program is free software; you can redistribute it and/or modify
639beb93cSSam Leffler  * it under the terms of the GNU General Public License version 2 as
739beb93cSSam Leffler  * published by the Free Software Foundation.
839beb93cSSam Leffler  *
939beb93cSSam Leffler  * Alternatively, this software may be distributed under the terms of BSD
1039beb93cSSam Leffler  * license.
1139beb93cSSam Leffler  *
1239beb93cSSam Leffler  * See README and COPYING for more details.
1339beb93cSSam Leffler  */
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #include "includes.h"
1639beb93cSSam Leffler 
1739beb93cSSam Leffler #include "common.h"
1839beb93cSSam Leffler #include "eap_i.h"
1939beb93cSSam Leffler #include "eap_common/chap.h"
2039beb93cSSam Leffler 
2139beb93cSSam Leffler 
2239beb93cSSam Leffler static void * eap_md5_init(struct eap_sm *sm)
2339beb93cSSam Leffler {
2439beb93cSSam Leffler 	/* No need for private data. However, must return non-NULL to indicate
2539beb93cSSam Leffler 	 * success. */
2639beb93cSSam Leffler 	return (void *) 1;
2739beb93cSSam Leffler }
2839beb93cSSam Leffler 
2939beb93cSSam Leffler 
3039beb93cSSam Leffler static void eap_md5_deinit(struct eap_sm *sm, void *priv)
3139beb93cSSam Leffler {
3239beb93cSSam Leffler }
3339beb93cSSam Leffler 
3439beb93cSSam Leffler 
3539beb93cSSam Leffler static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
3639beb93cSSam Leffler 				       struct eap_method_ret *ret,
3739beb93cSSam Leffler 				       const struct wpabuf *reqData)
3839beb93cSSam Leffler {
3939beb93cSSam Leffler 	struct wpabuf *resp;
4039beb93cSSam Leffler 	const u8 *pos, *challenge, *password;
4139beb93cSSam Leffler 	u8 *rpos, id;
4239beb93cSSam Leffler 	size_t len, challenge_len, password_len;
4339beb93cSSam Leffler 
4439beb93cSSam Leffler 	password = eap_get_config_password(sm, &password_len);
4539beb93cSSam Leffler 	if (password == NULL) {
4639beb93cSSam Leffler 		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
4739beb93cSSam Leffler 		eap_sm_request_password(sm);
4839beb93cSSam Leffler 		ret->ignore = TRUE;
4939beb93cSSam Leffler 		return NULL;
5039beb93cSSam Leffler 	}
5139beb93cSSam Leffler 
5239beb93cSSam Leffler 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len);
5339beb93cSSam Leffler 	if (pos == NULL || len == 0) {
5439beb93cSSam Leffler 		wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
5539beb93cSSam Leffler 			   pos, (unsigned long) len);
5639beb93cSSam Leffler 		ret->ignore = TRUE;
5739beb93cSSam Leffler 		return NULL;
5839beb93cSSam Leffler 	}
5939beb93cSSam Leffler 
6039beb93cSSam Leffler 	/*
6139beb93cSSam Leffler 	 * CHAP Challenge:
6239beb93cSSam Leffler 	 * Value-Size (1 octet) | Value(Challenge) | Name(optional)
6339beb93cSSam Leffler 	 */
6439beb93cSSam Leffler 	challenge_len = *pos++;
6539beb93cSSam Leffler 	if (challenge_len == 0 || challenge_len > len - 1) {
6639beb93cSSam Leffler 		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
6739beb93cSSam Leffler 			   "(challenge_len=%lu len=%lu)",
6839beb93cSSam Leffler 			   (unsigned long) challenge_len, (unsigned long) len);
6939beb93cSSam Leffler 		ret->ignore = TRUE;
7039beb93cSSam Leffler 		return NULL;
7139beb93cSSam Leffler 	}
7239beb93cSSam Leffler 	ret->ignore = FALSE;
7339beb93cSSam Leffler 	challenge = pos;
7439beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
7539beb93cSSam Leffler 		    challenge, challenge_len);
7639beb93cSSam Leffler 
7739beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
7839beb93cSSam Leffler 	ret->methodState = METHOD_DONE;
7939beb93cSSam Leffler 	ret->decision = DECISION_UNCOND_SUCC;
8039beb93cSSam Leffler 	ret->allowNotifications = TRUE;
8139beb93cSSam Leffler 
8239beb93cSSam Leffler 	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN,
8339beb93cSSam Leffler 			     EAP_CODE_RESPONSE, eap_get_id(reqData));
8439beb93cSSam Leffler 	if (resp == NULL)
8539beb93cSSam Leffler 		return NULL;
8639beb93cSSam Leffler 
8739beb93cSSam Leffler 	/*
8839beb93cSSam Leffler 	 * CHAP Response:
8939beb93cSSam Leffler 	 * Value-Size (1 octet) | Value(Response) | Name(optional)
9039beb93cSSam Leffler 	 */
9139beb93cSSam Leffler 	wpabuf_put_u8(resp, CHAP_MD5_LEN);
9239beb93cSSam Leffler 
9339beb93cSSam Leffler 	id = eap_get_id(resp);
9439beb93cSSam Leffler 	rpos = wpabuf_put(resp, CHAP_MD5_LEN);
9539beb93cSSam Leffler 	chap_md5(id, password, password_len, challenge, challenge_len, rpos);
9639beb93cSSam Leffler 	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN);
9739beb93cSSam Leffler 
9839beb93cSSam Leffler 	return resp;
9939beb93cSSam Leffler }
10039beb93cSSam Leffler 
10139beb93cSSam Leffler 
10239beb93cSSam Leffler int eap_peer_md5_register(void)
10339beb93cSSam Leffler {
10439beb93cSSam Leffler 	struct eap_method *eap;
10539beb93cSSam Leffler 	int ret;
10639beb93cSSam Leffler 
10739beb93cSSam Leffler 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
10839beb93cSSam Leffler 				    EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
10939beb93cSSam Leffler 	if (eap == NULL)
11039beb93cSSam Leffler 		return -1;
11139beb93cSSam Leffler 
11239beb93cSSam Leffler 	eap->init = eap_md5_init;
11339beb93cSSam Leffler 	eap->deinit = eap_md5_deinit;
11439beb93cSSam Leffler 	eap->process = eap_md5_process;
11539beb93cSSam Leffler 
11639beb93cSSam Leffler 	ret = eap_peer_method_register(eap);
11739beb93cSSam Leffler 	if (ret)
11839beb93cSSam Leffler 		eap_peer_method_free(eap);
11939beb93cSSam Leffler 	return ret;
12039beb93cSSam Leffler }
121