2 * hostapd / EAP-MD5 server
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "crypto/random.h"
14 #include "eap_common/chap.h"
17 #define CHALLENGE_LEN 16
20 u8 challenge
[CHALLENGE_LEN
];
21 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
25 static void * eap_md5_init(struct eap_sm
*sm
)
27 struct eap_md5_data
*data
;
29 data
= os_zalloc(sizeof(*data
));
32 data
->state
= CONTINUE
;
38 static void eap_md5_reset(struct eap_sm
*sm
, void *priv
)
40 struct eap_md5_data
*data
= priv
;
45 static struct wpabuf
* eap_md5_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
47 struct eap_md5_data
*data
= priv
;
50 if (random_get_bytes(data
->challenge
, CHALLENGE_LEN
)) {
51 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to get random data");
52 data
->state
= FAILURE
;
56 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, 1 + CHALLENGE_LEN
,
57 EAP_CODE_REQUEST
, id
);
59 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to allocate memory for "
61 data
->state
= FAILURE
;
65 wpabuf_put_u8(req
, CHALLENGE_LEN
);
66 wpabuf_put_data(req
, data
->challenge
, CHALLENGE_LEN
);
67 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Challenge", data
->challenge
,
70 data
->state
= CONTINUE
;
76 static Boolean
eap_md5_check(struct eap_sm
*sm
, void *priv
,
77 struct wpabuf
*respData
)
82 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, respData
, &len
);
83 if (pos
== NULL
|| len
< 1) {
84 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid frame");
87 if (*pos
!= CHAP_MD5_LEN
|| 1 + CHAP_MD5_LEN
> len
) {
88 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid response "
89 "(response_len=%d payload_len=%lu",
90 *pos
, (unsigned long) len
);
98 static void eap_md5_process(struct eap_sm
*sm
, void *priv
,
99 struct wpabuf
*respData
)
101 struct eap_md5_data
*data
= priv
;
104 u8 hash
[CHAP_MD5_LEN
], id
;
106 if (sm
->user
== NULL
|| sm
->user
->password
== NULL
||
107 sm
->user
->password_hash
) {
108 wpa_printf(MSG_INFO
, "EAP-MD5: Plaintext password not "
110 data
->state
= FAILURE
;
114 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, respData
, &plen
);
115 if (pos
== NULL
|| *pos
!= CHAP_MD5_LEN
|| plen
< 1 + CHAP_MD5_LEN
)
116 return; /* Should not happen - frame already validated */
118 pos
++; /* Skip response len */
119 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Response", pos
, CHAP_MD5_LEN
);
121 id
= eap_get_id(respData
);
122 if (chap_md5(id
, sm
->user
->password
, sm
->user
->password_len
,
123 data
->challenge
, CHALLENGE_LEN
, hash
)) {
124 wpa_printf(MSG_INFO
, "EAP-MD5: CHAP MD5 operation failed");
125 data
->state
= FAILURE
;
129 if (os_memcmp_const(hash
, pos
, CHAP_MD5_LEN
) == 0) {
130 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Success");
131 data
->state
= SUCCESS
;
133 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Failure");
134 data
->state
= FAILURE
;
139 static Boolean
eap_md5_isDone(struct eap_sm
*sm
, void *priv
)
141 struct eap_md5_data
*data
= priv
;
142 return data
->state
!= CONTINUE
;
146 static Boolean
eap_md5_isSuccess(struct eap_sm
*sm
, void *priv
)
148 struct eap_md5_data
*data
= priv
;
149 return data
->state
== SUCCESS
;
153 int eap_server_md5_register(void)
155 struct eap_method
*eap
;
157 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
158 EAP_VENDOR_IETF
, EAP_TYPE_MD5
, "MD5");
162 eap
->init
= eap_md5_init
;
163 eap
->reset
= eap_md5_reset
;
164 eap
->buildReq
= eap_md5_buildReq
;
165 eap
->check
= eap_md5_check
;
166 eap
->process
= eap_md5_process
;
167 eap
->isDone
= eap_md5_isDone
;
168 eap
->isSuccess
= eap_md5_isSuccess
;
170 return eap_server_method_register(eap
);