2 * hostapd / EAP-MD5 server
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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.
18 #include <netinet/in.h>
27 #define CHALLENGE_LEN 16
30 u8 challenge
[CHALLENGE_LEN
];
31 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
35 static void * eap_md5_init(struct eap_sm
*sm
)
37 struct eap_md5_data
*data
;
39 data
= malloc(sizeof(*data
));
42 memset(data
, 0, sizeof(*data
));
43 data
->state
= CONTINUE
;
49 static void eap_md5_reset(struct eap_sm
*sm
, void *priv
)
51 struct eap_md5_data
*data
= priv
;
56 static u8
* eap_md5_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
59 struct eap_md5_data
*data
= priv
;
63 if (hostapd_get_rand(data
->challenge
, CHALLENGE_LEN
)) {
64 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to get random data");
65 data
->state
= FAILURE
;
69 *reqDataLen
= sizeof(*req
) + 2 + CHALLENGE_LEN
;
70 req
= malloc(*reqDataLen
);
72 wpa_printf(MSG_ERROR
, "EAP-MD5: Failed to allocate memory for "
74 data
->state
= FAILURE
;
78 req
->code
= EAP_CODE_REQUEST
;
80 req
->length
= htons(*reqDataLen
);
81 pos
= (u8
*) (req
+ 1);
82 *pos
++ = EAP_TYPE_MD5
;
83 *pos
++ = CHALLENGE_LEN
;
84 memcpy(pos
, data
->challenge
, CHALLENGE_LEN
);
85 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Challenge", pos
, CHALLENGE_LEN
);
87 data
->state
= CONTINUE
;
93 static Boolean
eap_md5_check(struct eap_sm
*sm
, void *priv
,
94 u8
*respData
, size_t respDataLen
)
100 resp
= (struct eap_hdr
*) respData
;
101 pos
= (u8
*) (resp
+ 1);
102 if (respDataLen
< sizeof(*resp
) + 2 || *pos
!= EAP_TYPE_MD5
||
103 (len
= ntohs(resp
->length
)) > respDataLen
) {
104 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid frame");
108 if (*pos
!= MD5_MAC_LEN
||
109 sizeof(*resp
) + 2 + MD5_MAC_LEN
> len
) {
110 wpa_printf(MSG_INFO
, "EAP-MD5: Invalid response "
111 "(response_len=%d respDataLen=%lu",
112 *pos
, (unsigned long) respDataLen
);
120 static void eap_md5_process(struct eap_sm
*sm
, void *priv
,
121 u8
*respData
, size_t respDataLen
)
123 struct eap_md5_data
*data
= priv
;
124 struct eap_hdr
*resp
;
128 u8 hash
[MD5_MAC_LEN
];
130 if (sm
->user
== NULL
|| sm
->user
->password
== NULL
) {
131 wpa_printf(MSG_INFO
, "EAP-MD5: Password not configured");
132 data
->state
= FAILURE
;
136 resp
= (struct eap_hdr
*) respData
;
137 pos
= (u8
*) (resp
+ 1);
138 pos
+= 2; /* Skip type and len */
139 wpa_hexdump(MSG_MSGDUMP
, "EAP-MD5: Response", pos
, MD5_MAC_LEN
);
141 addr
[0] = &resp
->identifier
;
143 addr
[1] = sm
->user
->password
;
144 len
[1] = sm
->user
->password_len
;
145 addr
[2] = data
->challenge
;
146 len
[2] = CHALLENGE_LEN
;
147 md5_vector(3, addr
, len
, hash
);
149 if (memcmp(hash
, pos
, MD5_MAC_LEN
) == 0) {
150 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Success");
151 data
->state
= SUCCESS
;
153 wpa_printf(MSG_DEBUG
, "EAP-MD5: Done - Failure");
154 data
->state
= FAILURE
;
159 static Boolean
eap_md5_isDone(struct eap_sm
*sm
, void *priv
)
161 struct eap_md5_data
*data
= priv
;
162 return data
->state
!= CONTINUE
;
166 static Boolean
eap_md5_isSuccess(struct eap_sm
*sm
, void *priv
)
168 struct eap_md5_data
*data
= priv
;
169 return data
->state
== SUCCESS
;
173 const struct eap_method eap_method_md5
=
175 .method
= EAP_TYPE_MD5
,
177 .init
= eap_md5_init
,
178 .reset
= eap_md5_reset
,
179 .buildReq
= eap_md5_buildReq
,
180 .check
= eap_md5_check
,
181 .process
= eap_md5_process
,
182 .isDone
= eap_md5_isDone
,
183 .isSuccess
= eap_md5_isSuccess
,