139beb93cSSam Leffler /*
239beb93cSSam Leffler * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994)
3f05cddf9SRui Paulo * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler *
5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo * See README for more details.
739beb93cSSam Leffler */
839beb93cSSam Leffler
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler
1139beb93cSSam Leffler #include "common.h"
1239beb93cSSam Leffler #include "eap_i.h"
1339beb93cSSam Leffler #include "eap_common/chap.h"
1439beb93cSSam Leffler
1539beb93cSSam Leffler
eap_md5_init(struct eap_sm * sm)1639beb93cSSam Leffler static void * eap_md5_init(struct eap_sm *sm)
1739beb93cSSam Leffler {
1839beb93cSSam Leffler /* No need for private data. However, must return non-NULL to indicate
1939beb93cSSam Leffler * success. */
2039beb93cSSam Leffler return (void *) 1;
2139beb93cSSam Leffler }
2239beb93cSSam Leffler
2339beb93cSSam Leffler
eap_md5_deinit(struct eap_sm * sm,void * priv)2439beb93cSSam Leffler static void eap_md5_deinit(struct eap_sm *sm, void *priv)
2539beb93cSSam Leffler {
2639beb93cSSam Leffler }
2739beb93cSSam Leffler
2839beb93cSSam Leffler
eap_md5_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)2939beb93cSSam Leffler static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
3039beb93cSSam Leffler struct eap_method_ret *ret,
3139beb93cSSam Leffler const struct wpabuf *reqData)
3239beb93cSSam Leffler {
3339beb93cSSam Leffler struct wpabuf *resp;
3439beb93cSSam Leffler const u8 *pos, *challenge, *password;
3539beb93cSSam Leffler u8 *rpos, id;
3639beb93cSSam Leffler size_t len, challenge_len, password_len;
3739beb93cSSam Leffler
3839beb93cSSam Leffler password = eap_get_config_password(sm, &password_len);
3939beb93cSSam Leffler if (password == NULL) {
4039beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
4139beb93cSSam Leffler eap_sm_request_password(sm);
42*c1d255d3SCy Schubert ret->ignore = true;
4339beb93cSSam Leffler return NULL;
4439beb93cSSam Leffler }
4539beb93cSSam Leffler
4639beb93cSSam Leffler pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len);
4739beb93cSSam Leffler if (pos == NULL || len == 0) {
4839beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
4939beb93cSSam Leffler pos, (unsigned long) len);
50*c1d255d3SCy Schubert ret->ignore = true;
5139beb93cSSam Leffler return NULL;
5239beb93cSSam Leffler }
5339beb93cSSam Leffler
5439beb93cSSam Leffler /*
5539beb93cSSam Leffler * CHAP Challenge:
5639beb93cSSam Leffler * Value-Size (1 octet) | Value(Challenge) | Name(optional)
5739beb93cSSam Leffler */
5839beb93cSSam Leffler challenge_len = *pos++;
5939beb93cSSam Leffler if (challenge_len == 0 || challenge_len > len - 1) {
6039beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
6139beb93cSSam Leffler "(challenge_len=%lu len=%lu)",
6239beb93cSSam Leffler (unsigned long) challenge_len, (unsigned long) len);
63*c1d255d3SCy Schubert ret->ignore = true;
6439beb93cSSam Leffler return NULL;
6539beb93cSSam Leffler }
66*c1d255d3SCy Schubert ret->ignore = false;
6739beb93cSSam Leffler challenge = pos;
6839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
6939beb93cSSam Leffler challenge, challenge_len);
7039beb93cSSam Leffler
7139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
7239beb93cSSam Leffler ret->methodState = METHOD_DONE;
73e28a4053SRui Paulo ret->decision = DECISION_COND_SUCC;
74*c1d255d3SCy Schubert ret->allowNotifications = true;
7539beb93cSSam Leffler
7639beb93cSSam Leffler resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN,
7739beb93cSSam Leffler EAP_CODE_RESPONSE, eap_get_id(reqData));
7839beb93cSSam Leffler if (resp == NULL)
7939beb93cSSam Leffler return NULL;
8039beb93cSSam Leffler
8139beb93cSSam Leffler /*
8239beb93cSSam Leffler * CHAP Response:
8339beb93cSSam Leffler * Value-Size (1 octet) | Value(Response) | Name(optional)
8439beb93cSSam Leffler */
8539beb93cSSam Leffler wpabuf_put_u8(resp, CHAP_MD5_LEN);
8639beb93cSSam Leffler
8739beb93cSSam Leffler id = eap_get_id(resp);
8839beb93cSSam Leffler rpos = wpabuf_put(resp, CHAP_MD5_LEN);
89f05cddf9SRui Paulo if (chap_md5(id, password, password_len, challenge, challenge_len,
90f05cddf9SRui Paulo rpos)) {
91f05cddf9SRui Paulo wpa_printf(MSG_INFO, "EAP-MD5: CHAP MD5 operation failed");
92*c1d255d3SCy Schubert ret->ignore = true;
93f05cddf9SRui Paulo wpabuf_free(resp);
94f05cddf9SRui Paulo return NULL;
95f05cddf9SRui Paulo }
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
eap_peer_md5_register(void)10239beb93cSSam Leffler int eap_peer_md5_register(void)
10339beb93cSSam Leffler {
10439beb93cSSam Leffler struct eap_method *eap;
10539beb93cSSam Leffler
10639beb93cSSam Leffler eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
10739beb93cSSam Leffler EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
10839beb93cSSam Leffler if (eap == NULL)
10939beb93cSSam Leffler return -1;
11039beb93cSSam Leffler
11139beb93cSSam Leffler eap->init = eap_md5_init;
11239beb93cSSam Leffler eap->deinit = eap_md5_deinit;
11339beb93cSSam Leffler eap->process = eap_md5_process;
11439beb93cSSam Leffler
115780fb4a2SCy Schubert return eap_peer_method_register(eap);
11639beb93cSSam Leffler }
117