2 * hostapd / EAP-MD5 server
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "eap_common/chap.h"
22 #define CHALLENGE_LEN 16
25 u8 challenge
[CHALLENGE_LEN
];
26 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
30 static void * eap_md5_init(struct eap_sm
*sm
)
32 struct eap_md5_data
*data
;
34 data
= os_zalloc(sizeof(*data
));
37 data
->state
= CONTINUE
;
43 static void eap_md5_reset(struct eap_sm
*sm
, void *priv
)
45 struct eap_md5_data
*data
= priv
;
50 static struct wpabuf
* eap_md5_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
52 struct eap_md5_data
*data
= priv
;
55 if (os_get_random(data
->challenge
, CHALLENGE_LEN
)) {
56 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to get random data");
57 data
->state
= FAILURE
;
61 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, 1 + CHALLENGE_LEN
,
62 EAP_CODE_REQUEST
, id
);
64 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to allocate memory for "
66 data
->state
= FAILURE
;
70 wpabuf_put_u8(req
, CHALLENGE_LEN
);
71 wpabuf_put_data(req
, data
->challenge
, CHALLENGE_LEN
);
72 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Challenge", data
->challenge
,
75 data
->state
= CONTINUE
;
81 static Boolean
eap_md5_check(struct eap_sm
*sm
, void *priv
,
82 struct wpabuf
*respData
)
87 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, respData
, &len
);
88 if (pos
== NULL
|| len
< 1) {
89 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid frame");
92 if (*pos
!= CHAP_MD5_LEN
|| 1 + CHAP_MD5_LEN
> len
) {
93 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid response "
94 "(response_len=%d payload_len=%lu",
95 *pos
, (unsigned long) len
);
103 static void eap_md5_process(struct eap_sm
*sm
, void *priv
,
104 struct wpabuf
*respData
)
106 struct eap_md5_data
*data
= priv
;
109 u8 hash
[CHAP_MD5_LEN
], id
;
111 if (sm
->user
== NULL
|| sm
->user
->password
== NULL
||
112 sm
->user
->password_hash
) {
113 wpa_printf(MSG_INFO
, "EAP-MD5: Plaintext password not "
115 data
->state
= FAILURE
;
119 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, respData
, &plen
);
120 if (pos
== NULL
|| *pos
!= CHAP_MD5_LEN
|| plen
< 1 + CHAP_MD5_LEN
)
121 return; /* Should not happen - frame already validated */
123 pos
++; /* Skip response len */
124 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Response", pos
, CHAP_MD5_LEN
);
126 id
= eap_get_id(respData
);
127 chap_md5(id
, sm
->user
->password
, sm
->user
->password_len
,
128 data
->challenge
, CHALLENGE_LEN
, hash
);
130 if (os_memcmp(hash
, pos
, CHAP_MD5_LEN
) == 0) {
131 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Success");
132 data
->state
= SUCCESS
;
134 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Failure");
135 data
->state
= FAILURE
;
140 static Boolean
eap_md5_isDone(struct eap_sm
*sm
, void *priv
)
142 struct eap_md5_data
*data
= priv
;
143 return data
->state
!= CONTINUE
;
147 static Boolean
eap_md5_isSuccess(struct eap_sm
*sm
, void *priv
)
149 struct eap_md5_data
*data
= priv
;
150 return data
->state
== SUCCESS
;
154 int eap_server_md5_register(void)
156 struct eap_method
*eap
;
159 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
160 EAP_VENDOR_IETF
, EAP_TYPE_MD5
, "MD5");
164 eap
->init
= eap_md5_init
;
165 eap
->reset
= eap_md5_reset
;
166 eap
->buildReq
= eap_md5_buildReq
;
167 eap
->check
= eap_md5_check
;
168 eap
->process
= eap_md5_process
;
169 eap
->isDone
= eap_md5_isDone
;
170 eap
->isSuccess
= eap_md5_isSuccess
;
172 ret
= eap_server_method_register(eap
);
174 eap_server_method_free(eap
);