All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_eap_gtc.c
Go to the documentation of this file.
1 /*
2  * rlm_eap_gtc.c Handles that are called from eap
3  *
4  * Version: $Id: 27e073c1dff888683584f20a6c409b7af03e55e0 $
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,2006 The FreeRADIUS server project
21  */
22 
23 RCSID("$Id: 27e073c1dff888683584f20a6c409b7af03e55e0 $")
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #include "eap.h"
29 
30 #include <freeradius-devel/rad_assert.h>
31 
32 /*
33  * EAP-GTC is just ASCII data carried inside of the EAP session.
34  * The length of the data is indicated by the encapsulating EAP
35  * protocol.
36  */
37 typedef struct rlm_eap_gtc_t {
38  char const *challenge;
39  char const *auth_type_name;
40  int auth_type;
42 
44  { FR_CONF_OFFSET("challenge", PW_TYPE_STRING, rlm_eap_gtc_t, challenge), .dflt = "Password: " },
45 
46  { FR_CONF_OFFSET("auth_type", PW_TYPE_STRING, rlm_eap_gtc_t, auth_type_name), .dflt = "PAP" },
48 };
49 
50 
51 static int CC_HINT(nonnull) mod_process(void *instance, eap_session_t *eap_session);
52 
53 /*
54  * Attach the module.
55  */
56 static int mod_instantiate(CONF_SECTION *cs, void **instance)
57 {
59  fr_dict_enum_t *dval;
60 
61  *instance = inst = talloc_zero(cs, rlm_eap_gtc_t);
62  if (!inst) return -1;
63 
64  /*
65  * Parse the configuration attributes.
66  */
67  if (cf_section_parse(cs, inst, module_config) < 0) {
68  return -1;
69  }
70 
71  if (inst->auth_type_name && *inst->auth_type_name) {
72  dval = fr_dict_enum_by_name(NULL, fr_dict_attr_by_num(NULL, 0, PW_AUTH_TYPE), inst->auth_type_name);
73  if (!dval) {
74  ERROR("rlm_eap_gtc: Unknown Auth-Type %s",
75  inst->auth_type_name);
76  return -1;
77  }
78 
79  inst->auth_type = dval->value;
80  } else {
81  inst->auth_type = PW_AUTH_TYPE_LOCAL;
82  }
83  return 0;
84 }
85 
86 /*
87  * Initiate the EAP-GTC session by sending a challenge to the peer.
88  */
89 static int mod_session_init(void *instance, eap_session_t *eap_session)
90 {
91  char challenge_str[1024];
92  int length;
93  eap_round_t *eap_round = eap_session->this_round;
94  rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) instance;
95 
96  if (radius_xlat(challenge_str, sizeof(challenge_str), eap_session->request, inst->challenge, NULL, NULL) < 0) {
97  return 0;
98  }
99 
100  length = strlen(challenge_str);
101 
102  /*
103  * We're sending a request...
104  */
105  eap_round->request->code = PW_EAP_REQUEST;
106 
107  eap_round->request->type.data = talloc_array(eap_round->request,
108  uint8_t, length);
109  if (!eap_round->request->type.data) {
110  return 0;
111  }
112 
113  memcpy(eap_round->request->type.data, challenge_str, length);
114  eap_round->request->type.length = length;
115 
116  /*
117  * We don't need to authorize the user at this point.
118  *
119  * We also don't need to keep the challenge, as it's
120  * stored in 'eap_session->this_round', which will be given back
121  * to us...
122  */
123  eap_session->process = mod_process;
124 
125  return 1;
126 }
127 
128 
129 /*
130  * Authenticate a previously sent challenge.
131  */
132 static int mod_process(void *instance, eap_session_t *eap_session)
133 {
134  VALUE_PAIR *vp;
135  eap_round_t *eap_round = eap_session->this_round;
136  rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) instance;
137  REQUEST *request = eap_session->request;
138 
139  /*
140  * Get the Cleartext-Password for this user.
141  */
142 
143  /*
144  * Sanity check the response. We need at least one byte
145  * of data.
146  */
147  if (eap_round->response->length <= 4) {
148  ERROR("rlm_eap_gtc: corrupted data");
149  eap_round->request->code = PW_EAP_FAILURE;
150  return 0;
151  }
152 
153 #if 0
154  if ((rad_debug_lvl > 2) && fr_log_fp) {
155  int i;
156 
157  for (i = 0; i < eap_round->response->length - 4; i++) {
158  if ((i & 0x0f) == 0) fprintf(fr_log_fp, "%d: ", i);
159 
160  fprintf(fr_log_fp, "%02x ", eap_round->response->type.data[i]);
161 
162  if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
163  }
164  }
165 #endif
166 
167  /*
168  * Handle passwords here.
169  */
170  if (inst->auth_type == PW_AUTH_TYPE_LOCAL) {
171  /*
172  * For now, do cleartext password authentication.
173  */
174  vp = fr_pair_find_by_num(request->config, 0, PW_CLEARTEXT_PASSWORD, TAG_ANY);
175  if (!vp) {
176  REDEBUG2("Cleartext-Password is required for authentication");
177  eap_round->request->code = PW_EAP_FAILURE;
178  return 0;
179  }
180 
181  if (eap_round->response->type.length != vp->vp_length) {
182  REDEBUG2("Passwords are of different length. %u %u", (unsigned) eap_round->response->type.length, (unsigned) vp->vp_length);
183  eap_round->request->code = PW_EAP_FAILURE;
184  return 0;
185  }
186 
187  if (memcmp(eap_round->response->type.data,
188  vp->vp_strvalue, vp->vp_length) != 0) {
189  REDEBUG2("Passwords are different");
190  eap_round->request->code = PW_EAP_FAILURE;
191  return 0;
192  }
193 
194  /*
195  * EAP packets can be ~64k long maximum, and
196  * we don't like that.
197  */
198  } else if (eap_round->response->type.length <= 128) {
199  int rcode;
200 
201  /*
202  * If there was a User-Password in the request,
203  * why the heck are they using EAP-GTC?
204  */
205  fr_pair_delete_by_num(&request->packet->vps, 0, PW_USER_PASSWORD, TAG_ANY);
206 
207  vp = pair_make_request("User-Password", NULL, T_OP_EQ);
208  if (!vp) return 0;
209 
210  fr_pair_value_bstrncpy(vp, eap_round->response->type.data, eap_round->response->type.length);
211 
212  /*
213  * Add the password to the request, and allow
214  * another module to do the work of authenticating it.
215  */
216  request->password = vp;
217 
218  /*
219  * This is a wild & crazy hack.
220  */
221  rcode = process_authenticate(inst->auth_type, request);
222  if (rcode != RLM_MODULE_OK) {
223  eap_round->request->code = PW_EAP_FAILURE;
224  return 0;
225  }
226 
227  } else {
228  ERROR("rlm_eap_gtc: Response is too large to understand");
229  eap_round->request->code = PW_EAP_FAILURE;
230  return 0;
231 
232  }
233 
234  eap_round->request->code = PW_EAP_SUCCESS;
235 
236  return 1;
237 }
238 
239 /*
240  * The module name should be the only globally exported symbol.
241  * That is, everything else should be 'static'.
242  */
244 rlm_eap_module_t rlm_eap_gtc = {
245  .name = "eap_gtc",
246  .instantiate = mod_instantiate, /* Create new submodule instance */
247  .session_init = mod_session_init, /* Initialise a new EAP session */
248  .process = mod_process /* Process next round of EAP method */
249 };
size_t length
Definition: eap_types.h:135
FILE * fr_log_fp
Definition: radius.c:81
VALUE_PAIR * config
VALUE_PAIR (s) used to set per request parameters for modules and the server core at runtime...
Definition: radiusd.h:227
The module is OK, continue.
Definition: radiusd.h:91
rlm_eap_module_t rlm_eap_gtc
Definition: rlm_eap_gtc.c:244
eap_process_t process
Callback that should be used to process the next round.
Definition: eap.h:82
#define REDEBUG2(fmt,...)
Definition: log.h:255
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
#define pair_make_request(_a, _b, _c)
Definition: radiusd.h:545
uint8_t length
Definition: proto_bfd.c:203
VALUE_PAIR * password
Cached password VALUE_PAIR from request RADIUS_PACKET.
Definition: radiusd.h:223
eap_packet_t * request
Packet we will send to the peer.
Definition: eap.h:45
#define inst
Definition: token.h:46
static int mod_instantiate(CONF_SECTION *conf, void *instance)
Definition: rlm_always.c:55
static int mod_process(void *instance, eap_session_t *eap_session)
Definition: rlm_eap_gtc.c:132
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
eap_type_data_t type
Definition: eap_types.h:136
fr_dict_enum_t * fr_dict_enum_by_name(fr_dict_t *dict, fr_dict_attr_t const *da, char const *val)
Definition: dict.c:3703
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
static int CC_HINT(nonnull)
Definition: rlm_eap_gtc.c:51
rlm_rcode_t process_authenticate(int type, REQUEST *request)
Definition: modules.c:2106
Tracks the progress of a single session of any EAP method.
Definition: eap.h:60
int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables)
Parse a configuration section into user-supplied variables.
Definition: conffile.c:2234
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
size_t length
Definition: eap_types.h:123
Contains a pair of request and response packets.
Definition: eap.h:43
ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
char const * name
The name of the sub-module (without rlm_ prefix).
Definition: eap.h:96
void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int attr, int8_t tag)
Delete matching pairs.
Definition: pair.c:797
char const * auth_type_name
Definition: rlm_eap_gtc.c:39
#define TAG_ANY
Definition: pair.h:191
Interface to call EAP sub mdoules.
Definition: eap.h:95
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
static CONF_PARSER module_config[]
Definition: rlm_eap_gtc.c:43
int value
Enum value.
Definition: dict.h:96
char const * challenge
Definition: rlm_eap_gtc.c:38
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
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
Definition: pair.c:2043
eap_packet_t * response
Packet we received from the peer.
Definition: eap.h:44
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
Definition: dict.c:3519
String of printable characters.
Definition: radius.h:33
#define RCSID(id)
Definition: build.h:135
#define ERROR(fmt,...)
Definition: log.h:145
eap_code_t code
Definition: eap_types.h:133
Value of an enumerated attribute.
Definition: dict.h:94
uint8_t * data
Definition: eap_types.h:124
struct rlm_eap_gtc_t rlm_eap_gtc_t