2 * hostapd / EAP-MD5 server
3 * Copyright (c) 2004-2006, 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.
24 #define CHALLENGE_LEN 16
27 u8 challenge
[CHALLENGE_LEN
];
28 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
32 static void * eap_md5_init(struct eap_sm
*sm
)
34 struct eap_md5_data
*data
;
36 data
= wpa_zalloc(sizeof(*data
));
39 data
->state
= CONTINUE
;
45 static void eap_md5_reset(struct eap_sm
*sm
, void *priv
)
47 struct eap_md5_data
*data
= priv
;
52 static u8
* eap_md5_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
55 struct eap_md5_data
*data
= priv
;
59 if (hostapd_get_rand(data
->challenge
, CHALLENGE_LEN
)) {
60 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to get random data");
61 data
->state
= FAILURE
;
65 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_MD5
, reqDataLen
,
66 1 + CHALLENGE_LEN
, EAP_CODE_REQUEST
, id
, &pos
);
68 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to allocate memory for "
70 data
->state
= FAILURE
;
74 *pos
++ = CHALLENGE_LEN
;
75 memcpy(pos
, data
->challenge
, CHALLENGE_LEN
);
76 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Challenge", pos
, CHALLENGE_LEN
);
78 data
->state
= CONTINUE
;
84 static Boolean
eap_md5_check(struct eap_sm
*sm
, void *priv
,
85 u8
*respData
, size_t respDataLen
)
90 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_MD5
,
91 respData
, respDataLen
, &len
);
92 if (pos
== NULL
|| len
< 1) {
93 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid frame");
96 if (*pos
!= MD5_MAC_LEN
|| 1 + MD5_MAC_LEN
> len
) {
97 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid response "
98 "(response_len=%d payload_len=%lu",
99 *pos
, (unsigned long) len
);
107 static void eap_md5_process(struct eap_sm
*sm
, void *priv
,
108 u8
*respData
, size_t respDataLen
)
110 struct eap_md5_data
*data
= priv
;
111 struct eap_hdr
*resp
;
115 u8 hash
[MD5_MAC_LEN
];
117 if (sm
->user
== NULL
|| sm
->user
->password
== NULL
||
118 sm
->user
->password_hash
) {
119 wpa_printf(MSG_INFO
, "EAP-MD5: Plaintext password not "
121 data
->state
= FAILURE
;
125 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_MD5
,
126 respData
, respDataLen
, &plen
);
127 if (pos
== NULL
|| *pos
!= MD5_MAC_LEN
|| plen
< 1 + MD5_MAC_LEN
)
128 return; /* Should not happen - frame already validated */
130 pos
++; /* Skip response len */
131 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Response", pos
, MD5_MAC_LEN
);
133 resp
= (struct eap_hdr
*) respData
;
134 addr
[0] = &resp
->identifier
;
136 addr
[1] = sm
->user
->password
;
137 len
[1] = sm
->user
->password_len
;
138 addr
[2] = data
->challenge
;
139 len
[2] = CHALLENGE_LEN
;
140 md5_vector(3, addr
, len
, hash
);
142 if (memcmp(hash
, pos
, MD5_MAC_LEN
) == 0) {
143 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Success");
144 data
->state
= SUCCESS
;
146 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Failure");
147 data
->state
= FAILURE
;
152 static Boolean
eap_md5_isDone(struct eap_sm
*sm
, void *priv
)
154 struct eap_md5_data
*data
= priv
;
155 return data
->state
!= CONTINUE
;
159 static Boolean
eap_md5_isSuccess(struct eap_sm
*sm
, void *priv
)
161 struct eap_md5_data
*data
= priv
;
162 return data
->state
== SUCCESS
;
166 int eap_server_md5_register(void)
168 struct eap_method
*eap
;
171 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
172 EAP_VENDOR_IETF
, EAP_TYPE_MD5
, "MD5");
176 eap
->init
= eap_md5_init
;
177 eap
->reset
= eap_md5_reset
;
178 eap
->buildReq
= eap_md5_buildReq
;
179 eap
->check
= eap_md5_check
;
180 eap
->process
= eap_md5_process
;
181 eap
->isDone
= eap_md5_isDone
;
182 eap
->isSuccess
= eap_md5_isSuccess
;
184 ret
= eap_server_method_register(eap
);
186 eap_server_method_free(eap
);