The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
eap_md5.c
Go to the documentation of this file.
1/*
2 * eap_md5.c EAP MD5 functionality.
3 *
4 * Version: $Id: 243a8ed880e5053f43c252c378f17ec303a95287 $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * @copyright 2000,2001,2006 The FreeRADIUS server project
21 * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
22 */
23
24/*
25 *
26 * MD5 Packet Format in EAP Type-Data
27 * --- ------ ------ -- --- ---------
28 * 0 1 2 3
29 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
30 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 * | Value-Size | Value ...
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | Name ...
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 *
36 */
37RCSID("$Id: 243a8ed880e5053f43c252c378f17ec303a95287 $")
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <freeradius-devel/eap/base.h>
42
43#include "eap_md5.h"
44#include <freeradius-devel/util/md5.h>
45
46/*
47 * We expect only RESPONSE for which SUCCESS or FAILURE is sent back
48 */
50{
52 MD5_PACKET *packet;
53 unsigned short name_len;
54
55 /*
56 * We need a response, of type EAP-MD5, with at least
57 * one byte of type data (EAP-MD5) following the 4-byte
58 * EAP-Packet header.
59 */
60 if (!eap_round ||
61 !eap_round->response ||
62 (eap_round->response->code != FR_MD5_RESPONSE) ||
63 eap_round->response->type.num != FR_EAP_METHOD_MD5 ||
64 !eap_round->response->type.data ||
65 (eap_round->response->length <= MD5_HEADER_LEN) ||
66 (eap_round->response->type.data[0] == 0)) {
67 REDEBUG("corrupted data");
68 return NULL;
69 }
70
71 packet = talloc_zero(eap_round, MD5_PACKET);
72 if (!packet) return NULL;
73
74 /*
75 * Code & id for MD5 & EAP are same
76 *
77 * but md5_length = length of the EAP-MD5 data, which
78 * doesn't include the EAP header, or the octet saying
79 * EAP-MD5.
80 */
81 packet->code = eap_round->response->code;
82 packet->id = eap_round->response->id;
83 packet->length = eap_round->response->length - (MD5_HEADER_LEN + 1);
84
85 /*
86 * Sanity check the EAP-MD5 packet sent to us
87 * by the client.
88 */
89 data = (md5_packet_t *)eap_round->response->type.data;
90
91 /*
92 * Already checked the size above.
93 */
94 packet->value_size = data->value_size;
95
96 /*
97 * Allocate room for the data, and copy over the data.
98 */
99 packet->value = talloc_array(packet, uint8_t, packet->value_size);
100 if (!packet->value) {
101 talloc_free(packet);
102 return NULL;
103 }
104 memcpy(packet->value, data->value_name, packet->value_size);
105
106 /*
107 * Name is optional and is present after Value, but we
108 * need to check for it, as eap_md5_compose()
109 */
110 name_len = packet->length - (packet->value_size + 1);
111 if (name_len) {
112 packet->name = talloc_array(packet, char, name_len + 1);
113 if (!packet->name) {
114 talloc_free(packet);
115 return NULL;
116 }
117 memcpy(packet->name, data->value_name + packet->value_size,
118 name_len);
119 packet->name[name_len] = 0;
120 }
121
122 return packet;
123}
124
125
126/*
127 * verify = MD5(id+password+challenge_sent)
128 */
129int eap_md5_verify(request_t *request, MD5_PACKET *packet, fr_pair_t* password,
130 uint8_t *challenge)
131{
132 char *ptr;
133 char string[1 + FR_MAX_STRING_LEN*2];
134 uint8_t digest[16];
135 unsigned short len;
136
137 /*
138 * Sanity check it.
139 */
140 if (packet->value_size != 16) {
141 REDEBUG("Expected 16 bytes of response to challenge, got %d", packet->value_size);
142 return 0;
143 }
144
145 len = 0;
146 ptr = string;
147
148 /*
149 * This is really rad_chap_pwencode()...
150 */
151 *ptr++ = packet->id;
152 len++;
153 memcpy(ptr, password->vp_strvalue, password->vp_length);
154 ptr += password->vp_length;
155 len += password->vp_length;
156
157 /*
158 * The challenge size is hard-coded.
159 */
160 memcpy(ptr, challenge, MD5_CHALLENGE_LEN);
161 len += MD5_CHALLENGE_LEN;
162
163 fr_md5_calc(digest, (uint8_t *)string, len);
164
165 /*
166 * The length of the response is always 16 for MD5.
167 */
168 if (fr_digest_cmp(digest, packet->value, 16) != 0) {
169 return 0;
170 }
171
172 return 1;
173}
174
175/*
176 * Compose the portions of the reply packet specific to the
177 * EAP-MD5 protocol, in the EAP reply typedata
178 */
180{
181 uint8_t *ptr;
182 unsigned short name_len;
183
184 /*
185 * We really only send Challenge (EAP-Identity),
186 * and EAP-Success, and EAP-Failure.
187 */
188 if (reply->code < 3) {
189 eap_round->request->type.num = FR_EAP_METHOD_MD5;
190
191 fr_assert(reply->length > 0);
192
193 eap_round->request->type.data = talloc_array(eap_round->request,
194 uint8_t,
195 reply->length);
196 if (!eap_round->request->type.data) {
197 talloc_free(reply);
198 return 0;
199 }
200 ptr = eap_round->request->type.data;
201 *ptr++ = (uint8_t)(reply->value_size & 0xFF);
202 memcpy(ptr, reply->value, reply->value_size);
203
204 /* Just the Challenge length */
205 eap_round->request->type.length = reply->value_size + 1;
206
207 /*
208 * Return the name, if necessary.
209 *
210 * Don't see why this is *ever* necessary...
211 */
212 name_len = reply->length - (reply->value_size + 1);
213 if (name_len && reply->name) {
214 ptr += reply->value_size;
215 memcpy(ptr, reply->name, name_len);
216 /* Challenge length + Name length */
217 eap_round->request->type.length += name_len;
218 }
219 } else {
220 eap_round->request->type.length = 0;
221 /* TODO: In future we might add message here wrt rfc1994 */
222 }
223 eap_round->request->code = reply->code;
224 talloc_free(reply);
225
226 return 1;
227}
#define RCSID(id)
Definition build.h:483
eap_type_data_t type
Definition compose.h:39
size_t length
Definition compose.h:38
eap_packet_t * response
Packet we received from the peer.
Definition compose.h:49
eap_code_t code
Definition compose.h:36
uint8_t id
Definition compose.h:37
eap_packet_t * request
Packet we will send to the peer.
Definition compose.h:50
Contains a pair of request and response packets.
Definition compose.h:48
eap_type_t num
Definition types.h:110
size_t length
Definition types.h:111
uint8_t * data
Definition types.h:112
@ FR_EAP_METHOD_MD5
Definition types.h:49
int eap_md5_verify(request_t *request, MD5_PACKET *packet, fr_pair_t *password, uint8_t *challenge)
Definition eap_md5.c:129
int eap_md5_compose(eap_round_t *eap_round, MD5_PACKET *reply)
Definition eap_md5.c:179
MD5_PACKET * eap_md5_extract(request_t *request, eap_round_t *eap_round)
Definition eap_md5.c:49
#define MD5_HEADER_LEN
Definition eap_md5.h:12
#define FR_MD5_RESPONSE
Definition eap_md5.h:7
unsigned char id
Definition eap_md5.h:38
#define MD5_CHALLENGE_LEN
Definition eap_md5.h:13
unsigned short length
Definition eap_md5.h:39
unsigned char code
Definition eap_md5.h:37
unsigned char * value
Definition eap_md5.h:41
char * name
Definition eap_md5.h:42
unsigned char value_size
Definition eap_md5.h:40
talloc_free(reap)
void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Perform a single digest operation on a single input buffer.
unsigned char uint8_t
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
Definition misc.c:472
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static fr_slen_t data
Definition value.h:1265
#define FR_MAX_STRING_LEN
Definition value.h:30