udp: Merge udp_send and udp_output
[dragonfly.git] / contrib / hostapd / src / eap_peer / eap_md5.c
1 /*
2  * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994)
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19 #include "eap_common/chap.h"
20
21
22 static void * eap_md5_init(struct eap_sm *sm)
23 {
24         /* No need for private data. However, must return non-NULL to indicate
25          * success. */
26         return (void *) 1;
27 }
28
29
30 static void eap_md5_deinit(struct eap_sm *sm, void *priv)
31 {
32 }
33
34
35 static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
36                                        struct eap_method_ret *ret,
37                                        const struct wpabuf *reqData)
38 {
39         struct wpabuf *resp;
40         const u8 *pos, *challenge, *password;
41         u8 *rpos, id;
42         size_t len, challenge_len, password_len;
43
44         password = eap_get_config_password(sm, &password_len);
45         if (password == NULL) {
46                 wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
47                 eap_sm_request_password(sm);
48                 ret->ignore = TRUE;
49                 return NULL;
50         }
51
52         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len);
53         if (pos == NULL || len == 0) {
54                 wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
55                            pos, (unsigned long) len);
56                 ret->ignore = TRUE;
57                 return NULL;
58         }
59
60         /*
61          * CHAP Challenge:
62          * Value-Size (1 octet) | Value(Challenge) | Name(optional)
63          */
64         challenge_len = *pos++;
65         if (challenge_len == 0 || challenge_len > len - 1) {
66                 wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
67                            "(challenge_len=%lu len=%lu)",
68                            (unsigned long) challenge_len, (unsigned long) len);
69                 ret->ignore = TRUE;
70                 return NULL;
71         }
72         ret->ignore = FALSE;
73         challenge = pos;
74         wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
75                     challenge, challenge_len);
76
77         wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
78         ret->methodState = METHOD_DONE;
79         ret->decision = DECISION_UNCOND_SUCC;
80         ret->allowNotifications = TRUE;
81
82         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN,
83                              EAP_CODE_RESPONSE, eap_get_id(reqData));
84         if (resp == NULL)
85                 return NULL;
86
87         /*
88          * CHAP Response:
89          * Value-Size (1 octet) | Value(Response) | Name(optional)
90          */
91         wpabuf_put_u8(resp, CHAP_MD5_LEN);
92
93         id = eap_get_id(resp);
94         rpos = wpabuf_put(resp, CHAP_MD5_LEN);
95         chap_md5(id, password, password_len, challenge, challenge_len, rpos);
96         wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN);
97
98         return resp;
99 }
100
101
102 int eap_peer_md5_register(void)
103 {
104         struct eap_method *eap;
105         int ret;
106
107         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
108                                     EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
109         if (eap == NULL)
110                 return -1;
111
112         eap->init = eap_md5_init;
113         eap->deinit = eap_md5_deinit;
114         eap->process = eap_md5_process;
115
116         ret = eap_peer_method_register(eap);
117         if (ret)
118                 eap_peer_method_free(eap);
119         return ret;
120 }