All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_eap_leap.c
Go to the documentation of this file.
1 /*
2  * rlm_eap_leap.c Handles that are called from eap
3  *
4  * Version: $Id: ff429475ab83f4ccb07e5651343e5d98999434c1 $
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 2003 Alan DeKok <aland@freeradius.org>
21  * Copyright 2006 The FreeRADIUS server project
22  */
23 
24 RCSID("$Id: ff429475ab83f4ccb07e5651343e5d98999434c1 $")
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include "eap_leap.h"
30 
31 static int CC_HINT(nonnull) mod_process(void *instance, eap_session_t *eap_session);
32 
33 /*
34  * send an initial eap-leap request
35  * ie access challenge to the user/peer.
36 
37  * Frame eap reply packet.
38  * len = header + type + leap_methoddata
39  * leap_methoddata = value_size + value
40  */
41 static int CC_HINT(nonnull) mod_session_init(UNUSED void *instance, eap_session_t *eap_session)
42 {
43  REQUEST *request = eap_session->request;
44  leap_session_t *session;
45  leap_packet_t *reply;
46 
47  RDEBUG2("Stage 2");
48 
49  /*
50  * LEAP requires a User-Name attribute
51  */
52  if (!eap_session->request->username) {
53  REDEBUG("User-Name is required for EAP-LEAP authentication");
54  return 0;
55  }
56 
57  reply = eap_leap_initiate(request, eap_session->this_round, eap_session->request->username);
58  if (!reply) {
59  return 0;
60  }
61 
62  eap_leap_compose(request, eap_session->this_round, reply);
63 
64  eap_session->opaque = session = talloc(eap_session, leap_session_t);
65  if (!eap_session->opaque) {
66  talloc_free(reply);
67  return 0;
68  }
69 
70  /*
71  * Remember which stage we're in, and which challenge
72  * we sent to the AP. The later stages will take care
73  * of filling in the peer response.
74  */
75  session->stage = 4; /* the next stage we're in */
76  memcpy(session->peer_challenge, reply->challenge, reply->count);
77 
78  RDEBUG2("Successfully initiated");
79 
80  talloc_free(reply);
81 
82  eap_session->process = mod_process;
83 
84  return 1;
85 }
86 
87 static int mod_process(UNUSED void *instance, eap_session_t *eap_session)
88 {
89  int rcode;
90  REQUEST *request = eap_session->request;
91  leap_session_t *session;
92  leap_packet_t *packet;
93  leap_packet_t *reply;
94  VALUE_PAIR *password;
95 
96  if (!eap_session->opaque) {
97  REDEBUG("Cannot authenticate without LEAP history");
98  return 0;
99  }
100  session = talloc_get_type_abort(eap_session->opaque, leap_session_t);
101  reply = NULL;
102 
103  /*
104  * Extract the LEAP packet.
105  */
106  if (!(packet = eap_leap_extract(request, eap_session->this_round))) {
107  return 0;
108  }
109 
110  /*
111  * The password is never sent over the wire.
112  * Always get the configured password, for each user.
113  */
114  password = fr_pair_find_by_num(eap_session->request->config, 0, PW_CLEARTEXT_PASSWORD, TAG_ANY);
115  if (!password) {
116  password = fr_pair_find_by_num(eap_session->request->config, 0, PW_NT_PASSWORD, TAG_ANY);
117  }
118 
119  if (!password) {
120  REDEBUG("No Cleartext-Password or NT-Password configured for this user");
121  talloc_free(packet);
122  return 0;
123  }
124 
125  /*
126  * We've already sent the AP challenge. This packet
127  * should contain the NtChallengeResponse
128  */
129  switch (session->stage) {
130  case 4: /* Verify NtChallengeResponse */
131  RDEBUG2("Stage 4");
132  rcode = eap_leap_stage4(request, packet, password, session);
133  session->stage = 6;
134 
135  /*
136  * We send EAP-Success or EAP-Fail, and not
137  * any LEAP packet. So we return here.
138  */
139  if (!rcode) {
140  eap_session->this_round->request->code = PW_EAP_FAILURE;
141  talloc_free(packet);
142  return 0;
143  }
144 
145  eap_session->this_round->request->code = PW_EAP_SUCCESS;
146 
147  /*
148  * Do this only for Success.
149  */
150  eap_session->this_round->request->id = eap_session->this_round->response->id + 1;
151  eap_session->this_round->set_request_id = true;
152 
153  /*
154  * LEAP requires a challenge in stage 4, not
155  * an Access-Accept, which is normally returned
156  * by eap_compose() in eap.c, when the EAP reply code
157  * is EAP_SUCCESS.
158  */
159  eap_session->request->reply->code = PW_CODE_ACCESS_CHALLENGE;
160  talloc_free(packet);
161  return 1;
162 
163  case 6: /* Issue session key */
164  RDEBUG2("Stage 6");
165  reply = eap_leap_stage6(request, packet, eap_session->request->username, password, session);
166  break;
167 
168  /*
169  * Stages 1, 3, and 5 are requests from the AP.
170  * Stage 2 is handled by initiate()
171  */
172  default:
173  RDEBUG("Internal sanity check failed on stage");
174  break;
175  }
176 
177  talloc_free(packet);
178 
179  /*
180  * Process the packet. We don't care about any previous
181  * EAP packets, as
182  */
183  if (!reply) {
184  return 0;
185  }
186 
187  eap_leap_compose(request, eap_session->this_round, reply);
188  talloc_free(reply);
189  return 1;
190 }
191 
192 /*
193  * The module name should be the only globally exported symbol.
194  * That is, everything else should be 'static'.
195  */
197 rlm_eap_module_t rlm_eap_leap = {
198  .name = "eap_leap",
199  .session_init = mod_session_init, /* Initialise a new EAP session */
200  .process = mod_process /* Process next round of EAP method */
201 };
VALUE_PAIR * config
VALUE_PAIR (s) used to set per request parameters for modules and the server core at runtime...
Definition: radiusd.h:227
RFC2865 - Access-Challenge.
Definition: radius.h:102
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
Definition: radiusd.h:222
#define UNUSED
Definition: libradius.h:134
eap_packet_t * request
Packet we will send to the peer.
Definition: eap.h:45
void * opaque
Opaque data used by EAP methods.
Definition: eap.h:80
leap_packet_t * eap_leap_initiate(REQUEST *request, eap_round_t *eap_round, VALUE_PAIR *user_name)
Definition: eap_leap.c:346
REQUEST * request
Request that contains the response we're processing.
Definition: eap.h:71
static int mod_session_init(void *instance, eap_session_t *eap_session)
Definition: rlm_eap_gtc.c:89
unsigned char * challenge
Definition: eap_leap.h:46
uint8_t id
Definition: eap_types.h:134
Tracks the progress of a single session of any EAP method.
Definition: eap.h:60
unsigned int code
Packet code (type).
Definition: libradius.h:155
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition: eap.h:77
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
char const * name
The name of the sub-module (without rlm_ prefix).
Definition: eap.h:96
int eap_leap_stage4(REQUEST *request, leap_packet_t *packet, VALUE_PAIR *password, leap_session_t *session)
Definition: eap_leap.c:207
#define RDEBUG2(fmt,...)
Definition: log.h:244
#define TAG_ANY
Definition: pair.h:191
Interface to call EAP sub mdoules.
Definition: eap.h:95
int eap_leap_compose(REQUEST *request, eap_round_t *eap_round, leap_packet_t *reply)
Definition: eap_leap.c:396
#define REDEBUG(fmt,...)
Definition: log.h:254
uint8_t peer_challenge[8]
Definition: eap_leap.h:57
static int CC_HINT(nonnull)
Definition: rlm_eap_leap.c:31
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
leap_packet_t * eap_leap_stage6(REQUEST *request, leap_packet_t *packet, VALUE_PAIR *user_name, VALUE_PAIR *password, leap_session_t *session)
Definition: eap_leap.c:240
eap_packet_t * response
Packet we received from the peer.
Definition: eap.h:44
int count
Definition: eap_leap.h:45
#define RCSID(id)
Definition: build.h:135
static int mod_process(UNUSED void *instance, eap_session_t *eap_session)
Definition: rlm_eap_leap.c:87
rlm_eap_module_t rlm_eap_leap
Definition: rlm_eap_leap.c:197
bool set_request_id
Definition: eap.h:46
leap_packet_t * eap_leap_extract(REQUEST *request, eap_round_t *eap_round)
Definition: eap_leap.c:59
#define RDEBUG(fmt,...)
Definition: log.h:243
eap_code_t code
Definition: eap_types.h:133