Made it 2.0.0, and removed the changes that are in 1.1.x, as
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_md5 / rlm_eap_md5.c
1 /*
2  * rlm_eap_md5.c    Handles that are called from eap
3  *
4  * Version:     $Id$
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2000,2001  The FreeRADIUS server project
21  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
22  */
23
24 #include <freeradius-devel/autoconf.h>
25
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include "eap_md5.h"
30
31 #include <freeradius-devel/rad_assert.h>
32
33 /*
34  *      Initiate the EAP-MD5 session by sending a challenge to the peer.
35  */
36 static int md5_initiate(void *type_data, EAP_HANDLER *handler)
37 {
38         int             i;
39         MD5_PACKET      *reply;
40
41         type_data = type_data;  /* -Wunused */
42
43         /*
44          *      Allocate an EAP-MD5 packet.
45          */
46         reply = eapmd5_alloc();
47         if (reply == NULL)  {
48                 radlog(L_ERR, "rlm_eap_md5: out of memory");
49                 return 0;
50         }
51
52         /*
53          *      Fill it with data.
54          */
55         reply->code = PW_MD5_CHALLENGE;
56         reply->length = 1 + MD5_CHALLENGE_LEN; /* one byte of value size */
57         reply->value_size = MD5_CHALLENGE_LEN;
58
59         /*
60          *      Allocate user data.
61          */
62         reply->value = malloc(reply->value_size);
63         if (reply->value == NULL) {
64                 radlog(L_ERR, "rlm_eap_md5: out of memory");
65                 eapmd5_free(&reply);
66                 return 0;
67         }
68
69         /*
70          *      Get a random challenge.
71          */
72         for (i = 0; i < reply->value_size; i++) {
73                 reply->value[i] = lrad_rand();
74         }
75         radlog(L_INFO, "rlm_eap_md5: Issuing Challenge");
76
77         /*
78          *      Keep track of the challenge.
79          */
80         handler->opaque = malloc(reply->value_size);
81         rad_assert(handler->opaque != NULL);
82         memcpy(handler->opaque, reply->value, reply->value_size);
83         handler->free_opaque = free;
84
85         /*
86          *      Compose the EAP-MD5 packet out of the data structure,
87          *      and free it.
88          */
89         eapmd5_compose(handler->eap_ds, reply);
90
91         /*
92          *      We don't need to authorize the user at this point.
93          *
94          *      We also don't need to keep the challenge, as it's
95          *      stored in 'handler->eap_ds', which will be given back
96          *      to us...
97          */
98         handler->stage = AUTHENTICATE;
99
100         return 1;
101 }
102
103
104 /*
105  *      Authenticate a previously sent challenge.
106  */
107 static int md5_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
108 {
109         MD5_PACKET      *packet;
110         MD5_PACKET      *reply;
111         VALUE_PAIR      *password;
112
113         /*
114          *      Get the User-Password for this user.
115          */
116         rad_assert(handler->request != NULL);
117         rad_assert(handler->stage == AUTHENTICATE);
118
119         password = pairfind(handler->request->config_items, PW_PASSWORD);
120         if (password == NULL) {
121                 radlog(L_INFO, "rlm_eap_md5: User-Password is required for EAP-MD5 authentication");
122                 return 0;
123         }
124
125         /*
126          *      Extract the EAP-MD5 packet.
127          */
128         if (!(packet = eapmd5_extract(handler->eap_ds)))
129                 return 0;
130
131         /*
132          *      Create a reply, and initialize it.
133          */
134         reply = eapmd5_alloc();
135         if (!reply) {
136                 return 0;
137         }
138         reply->id = handler->eap_ds->request->id;
139         reply->length = 0;
140
141         /*
142          *      Verify the received packet against the previous packet
143          *      (i.e. challenge) which we sent out.
144          */
145         if (eapmd5_verify(packet, password, handler->opaque)) {
146                 reply->code = PW_MD5_SUCCESS;
147         } else {
148                 reply->code = PW_MD5_FAILURE;
149         }
150
151         /*
152          *      Compose the EAP-MD5 packet out of the data structure,
153          *      and free it.
154          */
155         eapmd5_compose(handler->eap_ds, reply);
156
157         eapmd5_free(&packet);
158         return 1;
159 }
160
161 /*
162  *      The module name should be the only globally exported symbol.
163  *      That is, everything else should be 'static'.
164  */
165 EAP_TYPE rlm_eap_md5 = {
166         "eap_md5",
167         NULL,                           /* attach */
168         md5_initiate,                   /* Start the initial request */
169         NULL,                           /* authorization */
170         md5_authenticate,               /* authentication */
171         NULL                            /* detach */
172 };