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: 5e5a47797235a024dd10ee59906ae75b5791e841 $
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: 5e5a47797235a024dd10ee59906ae75b5791e841 $")
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
54 /*
55 * We need a response, of type EAP-MD5, with at least
56 * one byte of type data (EAP-MD5) following the 4-byte
57 * EAP-Packet header.
58 */
59 if (!eap_round ||
60 !eap_round->response ||
61 (eap_round->response->code != FR_MD5_RESPONSE) ||
62 eap_round->response->type.num != FR_EAP_METHOD_MD5 ||
63 !eap_round->response->type.data ||
64 (eap_round->response->length <= MD5_HEADER_LEN) ||
65 (eap_round->response->type.data[0] == 0)) {
66 REDEBUG("corrupted data");
67 return NULL;
68 }
69
70 /*
71 * Sanity check the EAP-MD5 packet sent to us
72 * by the client.
73 */
74 data = (md5_packet_t *)eap_round->response->type.data;
75 if (data->value_size > (eap_round->response->length - 6)) {
76 REDEBUG("corrupted data");
77 return NULL;
78 }
79
80 MEM(packet = talloc_zero(eap_round, MD5_PACKET));
81
82 /*
83 * Code & id for MD5 & EAP are same
84 *
85 * but md5_length = length of the EAP-MD5 data, which
86 * doesn't include the EAP header, or the octet saying
87 * EAP-MD5.
88 */
89 packet->code = eap_round->response->code;
90 packet->id = eap_round->response->id;
91 packet->length = eap_round->response->length - (MD5_HEADER_LEN + 1);
92
93 /*
94 * Already checked the size above.
95 */
96 packet->value_size = data->value_size;
97
98 /*
99 * Allocate room for the data, and copy over the data.
100 */
101 MEM(packet->value = talloc_array(packet, uint8_t, packet->value_size));
102 memcpy(packet->value, data->value_name, packet->value_size);
103
104 /*
105 * Name is optional and is present after Value. We
106 * ignore it.
107 */
108
109 return packet;
110}
111
112
113/*
114 * verify = MD5(id+password+challenge_sent)
115 */
116int eap_md5_verify(request_t *request, MD5_PACKET *packet, fr_pair_t *password,
117 uint8_t *challenge)
118{
119 char *ptr;
120 char string[1 + FR_MAX_STRING_LEN + MD5_CHALLENGE_LEN];
121 uint8_t digest[16];
122 unsigned short len;
123
124 /*
125 * Sanity check it.
126 */
127 if (packet->value_size != 16) {
128 REDEBUG("Expected 16 bytes of response to challenge, got %d", packet->value_size);
129 return 0;
130 }
131
132 if ((1 + password->vp_length + MD5_CHALLENGE_LEN) > sizeof(string)) {
133 REDEBUG("Password is too long (expected <= %u", FR_MAX_STRING_LEN);
134 return 0;
135 }
136
137 len = 0;
138 ptr = string;
139
140 /*
141 * This is really rad_chap_pwencode()...
142 */
143 *ptr++ = packet->id;
144 len++;
145 memcpy(ptr, password->vp_strvalue, password->vp_length);
146 ptr += password->vp_length;
147 len += password->vp_length;
148
149 /*
150 * The challenge size is hard-coded.
151 */
152 memcpy(ptr, challenge, MD5_CHALLENGE_LEN);
153 len += MD5_CHALLENGE_LEN;
154
155 fr_md5_calc(digest, (uint8_t *)string, len);
156
157 /*
158 * The length of the response is always 16 for MD5.
159 */
160 if (fr_digest_cmp(digest, packet->value, 16) != 0) {
161 return 0;
162 }
163
164 return 1;
165}
166
167/*
168 * Compose the portions of the reply packet specific to the
169 * EAP-MD5 protocol, in the EAP reply typedata
170 */
172{
173 uint8_t *ptr;
174
175 /*
176 * We really only send Challenge (EAP-Identity),
177 * and EAP-Success, and EAP-Failure.
178 */
179 if (reply->code < 3) {
180 eap_round->request->type.num = FR_EAP_METHOD_MD5;
181
182 fr_assert(reply->length > 0);
183
184 eap_round->request->type.data = talloc_array(eap_round->request,
185 uint8_t,
186 reply->length);
187 if (!eap_round->request->type.data) {
188 talloc_free(reply);
189 return 0;
190 }
191 ptr = eap_round->request->type.data;
192 *ptr++ = (uint8_t)(reply->value_size & 0xFF);
193 memcpy(ptr, reply->value, reply->value_size);
194
195 /* Just the Challenge length */
196 eap_round->request->type.length = reply->value_size + 1;
197
198 /*
199 * We don't send a name.
200 */
201 } else {
202 eap_round->request->type.length = 0;
203 /* TODO: In future we might add message here wrt rfc1994 */
204 }
205 eap_round->request->code = reply->code;
206 talloc_free(reply);
207
208 return 1;
209}
#define RCSID(id)
Definition build.h:487
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
#define MEM(x)
Definition debug.h:36
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:116
int eap_md5_compose(eap_round_t *eap_round, MD5_PACKET *reply)
Definition eap_md5.c:171
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
unsigned char value_size
Definition eap_md5.h:40
talloc_free(hp)
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:505
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static fr_slen_t data
Definition value.h:1340
#define FR_MAX_STRING_LEN
Definition value.h:30