The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_eap_pwd.c
Go to the documentation of this file.
1 /*
2  * Copyright holder grants permission for redistribution and use in source
3  * and binary forms, with or without modification, provided that the
4  * following conditions are met:
5  * 1. Redistribution of source code must retain the above copyright
6  * notice, this list of conditions, and the following disclaimer
7  * in all source files.
8  * 2. Redistribution in binary form must retain the above copyright
9  * notice, this list of conditions, and the following disclaimer
10  * in the documentation and/or other materials provided with the
11  * distribution.
12  *
13  * "DISCLAIMER OF LIABILITY
14  *
15  * THIS SOFTWARE IS PROVIDED BY DAN HARKINS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INDUSTRIAL LOUNGE BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE."
26  *
27  * This license and distribution terms cannot be changed. In other words,
28  * this code cannot simply be copied and put under a different distribution
29  * license (including the GNU public license).
30  *
31  * @copyright (c) Dan Harkins, 2012
32  */
33 RCSID("$Id: febcab0c3e1f75aa4bedf07ca091d8bc7017d8e8 $")
34 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
35 
36 #include <freeradius-devel/server/base.h>
37 #include <freeradius-devel/server/module_rlm.h>
38 #include <freeradius-devel/tls/base.h>
39 
40 #include "eap_pwd.h"
41 
42 typedef struct {
43  BN_CTX *bnctx;
44 
47  char const *server_id;
48  char const *virtual_server;
50 
51 #define MPPE_KEY_LEN 32
52 #define MSK_EMSK_LEN (2 * MPPE_KEY_LEN)
53 
55  { FR_CONF_OFFSET("group", rlm_eap_pwd_t, group), .dflt = "19" },
56  { FR_CONF_OFFSET("fragment_size", rlm_eap_pwd_t, fragment_size), .dflt = "1020" },
57  { FR_CONF_OFFSET_FLAGS("server_id", CONF_FLAG_REQUIRED, rlm_eap_pwd_t, server_id) },
59 };
60 
61 static fr_dict_t const *dict_freeradius;
62 static fr_dict_t const *dict_radius;
63 
66  { .out = &dict_freeradius, .proto = "freeradius" },
67  { .out = &dict_radius, .proto = "radius" },
68  { NULL }
69 };
70 
75 
78  { .out = &attr_cleartext_password, .name = "Password.Cleartext", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
79  { .out = &attr_framed_mtu, .name = "Framed-MTU", .type = FR_TYPE_UINT32, .dict = &dict_radius },
80  { .out = &attr_ms_mppe_send_key, .name = "Vendor-Specific.Microsoft.MPPE-Send-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
81  { .out = &attr_ms_mppe_recv_key, .name = "Vendor-Specific.Microsoft.MPPE-Recv-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
82  { NULL }
83 };
84 
85 static int send_pwd_request(request_t *request, pwd_session_t *session, eap_round_t *eap_round)
86 {
87  size_t len;
88  uint16_t totlen;
89  pwd_hdr *hdr;
90 
91  len = (session->out_len - session->out_pos) + sizeof(pwd_hdr);
92  fr_assert(len > 0);
93  eap_round->request->code = FR_EAP_CODE_REQUEST;
94  eap_round->request->type.num = FR_EAP_METHOD_PWD;
95  eap_round->request->type.length = (len > session->mtu) ? session->mtu : len;
96  eap_round->request->type.data = talloc_zero_array(eap_round->request, uint8_t, eap_round->request->type.length);
97  hdr = (pwd_hdr *)eap_round->request->type.data;
98 
99  switch (session->state) {
100  case PWD_STATE_ID_REQ:
102  break;
103 
104  case PWD_STATE_COMMIT:
106  break;
107 
108  case PWD_STATE_CONFIRM:
110  break;
111 
112  default:
113  REDEBUG("PWD state is invalid. Can't send request");
114  return -1;
115  }
116 
117  /*
118  * are we fragmenting?
119  */
120  if (((session->out_len - session->out_pos) + sizeof(pwd_hdr)) > session->mtu) {
122  if (session->out_pos == 0) {
123 
124  /*
125  * the first fragment, add the total length
126  */
128  totlen = ntohs(session->out_len);
129  memcpy(hdr->data, (char *)&totlen, sizeof(totlen));
130  memcpy(hdr->data + sizeof(uint16_t),
131  session->out,
132  session->mtu - sizeof(pwd_hdr) - sizeof(uint16_t));
133  session->out_pos += (session->mtu - sizeof(pwd_hdr) - sizeof(uint16_t));
134  } else {
135  /*
136  * an intermediate fragment
137  */
138  memcpy(hdr->data, session->out + session->out_pos, (session->mtu - sizeof(pwd_hdr)));
139  session->out_pos += (session->mtu - sizeof(pwd_hdr));
140  }
141  } else {
142  /*
143  * either it's not a fragment or it's the last fragment.
144  * The out buffer isn't needed anymore though so get rid of it.
145  */
146  memcpy(hdr->data, session->out + session->out_pos,
147  (session->out_len - session->out_pos));
148  talloc_free(session->out);
149  session->out = NULL;
150  session->out_pos = session->out_len = 0;
151  }
152  return 0;
153 }
154 
155 static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
156 {
157  rlm_eap_pwd_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_eap_pwd_t);
158  eap_session_t *eap_session = eap_session_get(request->parent);
159 
160  pwd_session_t *session;
161 
162  pwd_hdr *hdr;
163  pwd_id_packet_t *packet;
164  eap_packet_t *response;
165 
166  eap_round_t *eap_round;
167  size_t in_len;
168  rlm_rcode_t rcode = RLM_MODULE_OK;
169  uint16_t offset;
170  uint8_t exch, *in, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN];
171  uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
172 
173  if (((eap_round = eap_session->this_round) == NULL) || !inst) RETURN_MODULE_FAIL;
174 
175  session = talloc_get_type_abort(eap_session->opaque, pwd_session_t);
176  response = eap_session->this_round->response;
177  hdr = (pwd_hdr *)response->type.data;
178 
179  /*
180  * The header must be at least one byte.
181  */
182  if (!hdr || (response->type.length < sizeof(pwd_hdr))) {
183  REDEBUG("Packet with insufficient data");
185  }
186 
187  in = hdr->data;
188  in_len = response->type.length - sizeof(pwd_hdr);
189 
190  /*
191  * See if we're fragmenting, if so continue until we're done
192  */
193  if (session->out_pos) {
194  if (in_len) REDEBUG("PWD got something more than an ACK for a fragment");
195  if (send_pwd_request(request, session, eap_round) < 0) RETURN_MODULE_FAIL;
196 
198  }
199 
200  /*
201  * The first fragment will have a total length, make a
202  * buffer to hold all the fragments
203  */
204  if (EAP_PWD_GET_LENGTH_BIT(hdr)) {
205  if (session->in) {
206  REDEBUG("PWD already alloced buffer for fragments");
208  }
209 
210  if (in_len < 2) {
211  REDEBUG("Invalid packet: length bit set, but no length field");
213  }
214 
215  session->in_len = ntohs(in[0] * 256 | in[1]);
216  if (!session->in_len) {
217  DEBUG("EAP-PWD malformed packet (input length)");
219  }
220 
221  MEM(session->in = talloc_zero_array(session, uint8_t, session->in_len));
222 
223  session->in_pos = 0;
224  in += sizeof(uint16_t);
225  in_len -= sizeof(uint16_t);
226  }
227 
228  /*
229  * All fragments, including the 1st will have the M(ore) bit set,
230  * buffer those fragments!
231  */
232  if (EAP_PWD_GET_MORE_BIT(hdr)) {
233  if (!session->in) {
234  RDEBUG2("Unexpected fragment");
236  }
237 
238  if ((session->in_pos + in_len) > session->in_len) {
239  REDEBUG("Fragment overflows packet");
241  }
242 
243  memcpy(session->in + session->in_pos, in, in_len);
244  session->in_pos += in_len;
245 
246  /*
247  * send back an ACK for this fragment
248  */
249  exch = EAP_PWD_GET_EXCHANGE(hdr);
250  eap_round->request->code = FR_EAP_CODE_REQUEST;
251  eap_round->request->type.num = FR_EAP_METHOD_PWD;
252  eap_round->request->type.length = sizeof(pwd_hdr);
253 
254  MEM(eap_round->request->type.data = talloc_array(eap_round->request, uint8_t, sizeof(pwd_hdr)));
255 
256  hdr = (pwd_hdr *)eap_round->request->type.data;
257  EAP_PWD_SET_EXCHANGE(hdr, exch);
259  }
260 
261 
262  if (session->in) {
263  /*
264  * The last fragment...
265  */
266  if ((session->in_pos + in_len) > session->in_len) {
267  REDEBUG("PWD will overflow a fragment buffer");
269  }
270  memcpy(session->in + session->in_pos, in, in_len);
271  in = session->in;
272  in_len = session->in_len;
273  }
274 
275  switch (session->state) {
276  case PWD_STATE_ID_REQ:
277  {
278  fr_pair_t *known_good;
279  fr_dict_attr_t const *allowed_passwords[] = { attr_cleartext_password };
280  int ret;
281  bool ephemeral;
282  BIGNUM *x = NULL, *y = NULL;
283 
285  REDEBUG("PWD exchange is incorrect, Not ID");
287  }
288 
289  packet = (pwd_id_packet_t *) in;
290  if (in_len < sizeof(*packet)) {
291  REDEBUG("Packet is too small (%zd < %zd).", in_len, sizeof(*packet));
293  }
294 
295  if ((packet->prf != EAP_PWD_DEF_PRF) ||
296  (packet->random_function != EAP_PWD_DEF_RAND_FUN) ||
297  (packet->prep != EAP_PWD_PREP_NONE) ||
298  (CRYPTO_memcmp(packet->token, &session->token, 4)) ||
299  (packet->group_num != ntohs(session->group_num))) {
300  REDEBUG("PWD ID response is malformed");
302  }
303 
304  /*
305  * We've agreed on the ciphersuite, record it...
306  */
307  ptr = (uint8_t *)&session->ciphersuite;
308  memcpy(ptr, (char *)&packet->group_num, sizeof(uint16_t));
309  ptr += sizeof(uint16_t);
310  *ptr = EAP_PWD_DEF_RAND_FUN;
311  ptr += sizeof(uint8_t);
312  *ptr = EAP_PWD_DEF_PRF;
313 
314  session->peer_id_len = in_len - sizeof(pwd_id_packet_t);
315  if (session->peer_id_len >= sizeof(session->peer_id)) {
316  REDEBUG("PWD ID response is malformed");
318  }
319 
320  memcpy(session->peer_id, packet->identity, session->peer_id_len);
321  session->peer_id[session->peer_id_len] = '\0';
322 
323  known_good = password_find(&ephemeral, request, request->parent,
324  allowed_passwords, NUM_ELEMENTS(allowed_passwords), false);
325  if (!known_good) {
326  REDEBUG("No \"known good\" password found for user");
328  }
329 
330  ret = compute_password_element(request, session, session->group_num,
331  known_good->vp_strvalue, known_good->vp_length,
332  inst->server_id, strlen(inst->server_id),
333  session->peer_id, strlen(session->peer_id),
334  &session->token, inst->bnctx);
335  if (ephemeral) TALLOC_FREE(known_good);
336  if (ret < 0) {
337  REDEBUG("Failed to obtain password element");
339  }
340 
341  /*
342  * Compute our scalar and element
343  */
344  if (compute_scalar_element(request, session, inst->bnctx)) {
345  REDEBUG("Failed to compute server's scalar and element");
347  }
348 
349  MEM(x = BN_new());
350  MEM(y = BN_new());
351 
352  /*
353  * Element is a point, get both coordinates: x and y
354  */
355  if (!EC_POINT_get_affine_coordinates(session->group, session->my_element, x, y, inst->bnctx)) {
356  REDEBUG("Server point assignment failed");
357  BN_clear_free(x);
358  BN_clear_free(y);
360  }
361 
362  /*
363  * Construct request
364  */
365  session->out_len = BN_num_bytes(session->order) + (2 * BN_num_bytes(session->prime));
366  MEM(session->out = talloc_zero_array(session, uint8_t, session->out_len));
367 
368  ptr = session->out;
369  offset = BN_num_bytes(session->prime) - BN_num_bytes(x);
370  BN_bn2bin(x, ptr + offset);
371  BN_clear_free(x);
372 
373  ptr += BN_num_bytes(session->prime);
374  offset = BN_num_bytes(session->prime) - BN_num_bytes(y);
375  BN_bn2bin(y, ptr + offset);
376  BN_clear_free(y);
377 
378  ptr += BN_num_bytes(session->prime);
379  offset = BN_num_bytes(session->order) - BN_num_bytes(session->my_scalar);
380  BN_bn2bin(session->my_scalar, ptr + offset);
381 
382  session->state = PWD_STATE_COMMIT;
383  rcode = send_pwd_request(request, session, eap_round) < 0 ? RLM_MODULE_FAIL : RLM_MODULE_OK;
384  }
385  break;
386 
387  case PWD_STATE_COMMIT:
389  REDEBUG("PWD exchange is incorrect, not commit!");
391  }
392 
393  /*
394  * Process the peer's commit and generate the shared key, k
395  */
396  if (process_peer_commit(request, session, in, in_len, inst->bnctx)) {
397  REDEBUG("Failed processing peer's commit");
399  }
400 
401  /*
402  * Compute our confirm blob
403  */
404  if (compute_server_confirm(request, session, session->my_confirm, inst->bnctx)) {
405  REDEBUG("Failed computing confirm");
407  }
408 
409  /*
410  * Construct a response...which is just our confirm blob
411  */
412  session->out_len = SHA256_DIGEST_LENGTH;
413  MEM(session->out = talloc_array(session, uint8_t, session->out_len));
414 
415  memset(session->out, 0, session->out_len);
416  memcpy(session->out, session->my_confirm, SHA256_DIGEST_LENGTH);
417 
418  session->state = PWD_STATE_CONFIRM;
419  rcode = send_pwd_request(request, session, eap_round) < 0 ? RLM_MODULE_FAIL : RLM_MODULE_OK;
420  break;
421 
422  case PWD_STATE_CONFIRM:
423  if (in_len < SHA256_DIGEST_LENGTH) {
424  REDEBUG("Peer confirm is too short (%zd < %d)", in_len, SHA256_DIGEST_LENGTH);
426  }
427 
429  REDEBUG("PWD exchange is incorrect, not commit");
431  }
432  if (compute_peer_confirm(request, session, peer_confirm, inst->bnctx)) {
433  REDEBUG("Cannot compute peer's confirm");
435  }
436  if (CRYPTO_memcmp(peer_confirm, in, SHA256_DIGEST_LENGTH)) {
437  REDEBUG("PWD exchange failed, peer confirm is incorrect");
439  }
440  if (compute_keys(request, session, peer_confirm, msk, emsk)) {
441  REDEBUG("Failed generating (E)MSK");
443  }
444  eap_round->request->code = FR_EAP_CODE_SUCCESS;
445 
446  /*
447  * Return the MSK (in halves).
448  */
449  eap_add_reply(request->parent, attr_ms_mppe_recv_key, msk, MPPE_KEY_LEN);
451 
452  rcode = RLM_MODULE_OK;
453  break;
454 
455  default:
456  REDEBUG("Unknown PWD state");
458  }
459 
460  /*
461  * We processed the buffered fragments, get rid of them.
462  */
463  if (session->in) {
464  talloc_free(session->in);
465  session->in = NULL;
466  }
467 
468  RETURN_MODULE_RCODE(rcode);
469 }
470 
471 static int _free_pwd_session(pwd_session_t *session)
472 {
473  BN_clear_free(session->private_value);
474  BN_clear_free(session->peer_scalar);
475  BN_clear_free(session->my_scalar);
476  BN_clear_free(session->k);
477  EC_POINT_clear_free(session->my_element);
478  EC_POINT_clear_free(session->peer_element);
479  EC_GROUP_free(session->group);
480  EC_POINT_clear_free(session->pwe);
481  BN_clear_free(session->order);
482  BN_clear_free(session->prime);
483 
484  return 0;
485 }
486 
487 static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
488 {
489  rlm_eap_pwd_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_eap_pwd_t);
490  eap_session_t *eap_session = eap_session_get(request->parent);
491  pwd_session_t *session;
492  fr_pair_t *vp;
493  pwd_id_packet_t *packet;
494 
495  MEM(session = talloc_zero(eap_session, pwd_session_t));
496  talloc_set_destructor(session, _free_pwd_session);
497  /*
498  * set things up so they can be free'd reliably
499  */
500  session->group_num = inst->group;
501 
502  /*
503  * The admin can dynamically change the MTU.
504  */
505  session->mtu = inst->fragment_size;
506  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_framed_mtu);
507 
508  /*
509  * session->mtu is *our* MTU. We need to subtract off the EAP
510  * overhead.
511  *
512  * 9 = 4 (EAPOL header) + 4 (EAP header) + 1 (EAP type)
513  *
514  * The fragmentation code deals with the included length
515  * so we don't need to subtract that here.
516  */
517  if (vp && (vp->vp_uint32 > 100) && (vp->vp_uint32 < session->mtu)) session->mtu = vp->vp_uint32 - 9;
518 
519  session->state = PWD_STATE_ID_REQ;
520  session->out_pos = 0;
521  eap_session->opaque = session;
522 
523  /*
524  * construct an EAP-pwd-ID/Request
525  */
526  session->out_len = sizeof(pwd_id_packet_t) + strlen(inst->server_id);
527  MEM(session->out = talloc_zero_array(session, uint8_t, session->out_len));
528 
529  packet = (pwd_id_packet_t *)session->out;
530  packet->group_num = htons(session->group_num);
532  packet->prf = EAP_PWD_DEF_PRF;
533  session->token = fr_rand();
534  memcpy(packet->token, (char *)&session->token, 4);
535  packet->prep = EAP_PWD_PREP_NONE;
536  memcpy(packet->identity, inst->server_id, session->out_len - sizeof(pwd_id_packet_t) );
537 
538  if (send_pwd_request(request, session, eap_session->this_round) < 0) RETURN_MODULE_FAIL;
539 
540  eap_session->process = mod_process;
541 
543 }
544 
545 static int mod_detach(module_detach_ctx_t const *mctx)
546 {
547  rlm_eap_pwd_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_eap_pwd_t);
548 
549  if (inst->bnctx) BN_CTX_free(inst->bnctx);
550 
551  return 0;
552 }
553 
554 static int mod_instantiate(module_inst_ctx_t const *mctx)
555 {
556  rlm_eap_pwd_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_eap_pwd_t);
557  CONF_SECTION *conf = mctx->inst->conf;
558 
559  if (inst->fragment_size < 100) {
560  cf_log_err(conf, "Fragment size is too small");
561  return -1;
562  }
563 
564  switch (inst->group) {
565  case 19:
566  case 20:
567  case 21:
568  case 25:
569  case 26:
570  break;
571 
572  default:
573  cf_log_err_by_child(conf, "group", "Group %i is not supported", inst->group);
574  return -1;
575  }
576 
577  inst->bnctx = BN_CTX_new();
578  if (!inst->bnctx) {
579  cf_log_err(conf, "Failed to get BN context");
580  return -1;
581  }
582 
583  return 0;
584 }
585 
588  .common = {
589  .magic = MODULE_MAGIC_INIT,
590  .name = "eap_pwd",
591  .inst_size = sizeof(rlm_eap_pwd_t),
593  .instantiate = mod_instantiate, /* Create new submodule instance */
594  .detach = mod_detach
595  },
596  .provides = { FR_EAP_METHOD_PWD },
597  .session_init = mod_session_init, /* Create the initial request */
598 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define USES_APPLE_DEPRECATED_API
Definition: build.h:431
#define RCSID(id)
Definition: build.h:444
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:406
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define cf_log_err_by_child(_parent, _child, _fmt,...)
Log an error message against a specified child.
Definition: cf_util.h:292
eap_type_data_t type
Definition: compose.h:39
eap_packet_t * response
Packet we received from the peer.
Definition: compose.h:49
eap_code_t code
Definition: compose.h:36
eap_packet_t * request
Packet we will send to the peer.
Definition: compose.h:50
Structure to hold EAP data.
Definition: compose.h:35
Contains a pair of request and response packets.
Definition: compose.h:48
size_t y
Definition: dbuff.c:67
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
static fr_slen_t in
Definition: dict.h:645
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
dl_module_inst_t const * inst
Definition: dl_module.h:87
@ FR_EAP_CODE_REQUEST
Definition: types.h:37
@ FR_EAP_CODE_SUCCESS
Definition: types.h:39
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_PWD
Definition: types.h:98
int compute_scalar_element(request_t *request, pwd_session_t *session, BN_CTX *bn_ctx)
Definition: eap_pwd.c:518
int process_peer_commit(request_t *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx)
Definition: eap_pwd.c:558
int compute_server_confirm(request_t *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
Definition: eap_pwd.c:684
int compute_keys(UNUSED request_t *request, pwd_session_t *session, uint8_t *peer_confirm, uint8_t *msk, uint8_t *emsk)
Definition: eap_pwd.c:889
int compute_password_element(request_t *request, pwd_session_t *session, uint16_t grp_num, char const *password, int password_len, char const *id_server, int id_server_len, char const *id_peer, int id_peer_len, uint32_t *token, BN_CTX *bnctx)
Definition: eap_pwd.c:253
int compute_peer_confirm(request_t *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
Definition: eap_pwd.c:787
#define PWD_STATE_ID_REQ
Definition: eap_pwd.h:81
BIGNUM * private_value
Definition: eap_pwd.h:101
uint8_t token[4]
Definition: eap_pwd.h:71
uint16_t group_num
Definition: eap_pwd.h:84
#define EC_POINT_get_affine_coordinates
copyright holder grants permission for redistribution and use in source and binary forms,...
Definition: eap_pwd.h:45
size_t in_pos
Definition: eap_pwd.h:91
char peer_id[FR_MAX_STRING_LEN]
Definition: eap_pwd.h:87
BIGNUM * my_scalar
Definition: eap_pwd.h:103
uint32_t token
Definition: eap_pwd.h:86
#define PWD_STATE_COMMIT
Definition: eap_pwd.h:82
#define EAP_PWD_EXCH_COMMIT
Definition: eap_pwd.h:52
uint16_t state
Definition: eap_pwd.h:80
uint16_t group_num
Definition: eap_pwd.h:66
#define EAP_PWD_DEF_PRF
Definition: eap_pwd.h:70
#define EAP_PWD_GET_MORE_BIT(x)
Definition: eap_pwd.h:60
uint8_t my_confirm[SHA256_DIGEST_LENGTH]
Definition: eap_pwd.h:106
#define EAP_PWD_DEF_RAND_FUN
Definition: eap_pwd.h:68
size_t out_len
Definition: eap_pwd.h:95
uint8_t data[]
Definition: eap_pwd.h:55
size_t peer_id_len
Definition: eap_pwd.h:88
#define EAP_PWD_GET_LENGTH_BIT(x)
Definition: eap_pwd.h:58
#define EAP_PWD_SET_EXCHANGE(x, y)
Definition: eap_pwd.h:63
char identity[]
Definition: eap_pwd.h:76
BIGNUM * prime
Definition: eap_pwd.h:99
uint8_t prf
Definition: eap_pwd.h:69
uint8_t prep
Definition: eap_pwd.h:72
#define EAP_PWD_GET_EXCHANGE(x)
Definition: eap_pwd.h:62
#define EAP_PWD_SET_LENGTH_BIT(x)
Definition: eap_pwd.h:59
size_t out_pos
Definition: eap_pwd.h:94
EC_GROUP * group
Definition: eap_pwd.h:96
size_t in_len
Definition: eap_pwd.h:92
#define EAP_PWD_EXCH_ID
Definition: eap_pwd.h:51
BIGNUM * peer_scalar
Definition: eap_pwd.h:102
EC_POINT * pwe
Definition: eap_pwd.h:97
BIGNUM * k
Definition: eap_pwd.h:100
size_t mtu
Definition: eap_pwd.h:89
uint8_t * out
Definition: eap_pwd.h:93
#define EAP_PWD_EXCH_CONFIRM
Definition: eap_pwd.h:53
#define PWD_STATE_CONFIRM
Definition: eap_pwd.h:83
uint8_t random_function
Definition: eap_pwd.h:67
uint8_t * in
Definition: eap_pwd.h:90
#define EAP_PWD_SET_MORE_BIT(x)
Definition: eap_pwd.h:61
uint32_t ciphersuite
Definition: eap_pwd.h:85
#define EAP_PWD_PREP_NONE
Definition: eap_pwd.h:73
BIGNUM * order
Definition: eap_pwd.h:98
EC_POINT * peer_element
Definition: eap_pwd.h:105
EC_POINT * my_element
Definition: eap_pwd.h:104
switch(errno)
Definition: fd_errno.h:4
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
Definition: base.c:375
void * opaque
Opaque data used by EAP methods.
Definition: session.h:62
module_method_t process
Callback that should be used to process the next round.
Definition: session.h:64
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition: session.h:59
static eap_session_t * eap_session_get(request_t *request)
Definition: session.h:82
Tracks the progress of a single session of any EAP method.
Definition: session.h:40
talloc_free(reap)
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned int uint32_t
Definition: merged_model.c:33
unsigned char uint8_t
Definition: merged_model.c:30
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition: pair.c:688
fr_pair_t * password_find(bool *ephemeral, TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *allowed_attrs[], size_t allowed_attrs_len, bool normify)
Find a "known good" password in the control list of a request.
Definition: password.c:963
static const conf_parser_t config[]
Definition: base.c:188
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
static rs_t * conf
Definition: radsniff.c:53
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: rand.c:106
#define RETURN_MODULE_RCODE(_rcode)
Definition: rcode.h:64
#define RETURN_MODULE_HANDLED
Definition: rcode.h:58
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
static int send_pwd_request(request_t *request, pwd_session_t *session, eap_round_t *eap_round)
Definition: rlm_eap_pwd.c:85
static int mod_detach(module_detach_ctx_t const *mctx)
Definition: rlm_eap_pwd.c:545
#define MSK_EMSK_LEN
Definition: rlm_eap_pwd.c:52
BN_CTX * bnctx
Definition: rlm_eap_pwd.c:43
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_eap_pwd.c:155
char const * virtual_server
Definition: rlm_eap_pwd.c:48
uint32_t fragment_size
Definition: rlm_eap_pwd.c:46
rlm_eap_submodule_t rlm_eap_pwd
Definition: rlm_eap_pwd.c:587
char const * server_id
Definition: rlm_eap_pwd.c:47
static int _free_pwd_session(pwd_session_t *session)
Definition: rlm_eap_pwd.c:471
static fr_dict_t const * dict_freeradius
Definition: rlm_eap_pwd.c:61
static fr_dict_t const * dict_radius
Definition: rlm_eap_pwd.c:62
uint32_t group
Definition: rlm_eap_pwd.c:45
static fr_dict_attr_t const * attr_ms_mppe_send_key
Definition: rlm_eap_pwd.c:73
fr_dict_attr_autoload_t rlm_eap_pwd_dict_attr[]
Definition: rlm_eap_pwd.c:77
fr_dict_autoload_t rlm_eap_pwd_dict[]
Definition: rlm_eap_pwd.c:65
static fr_dict_attr_t const * attr_cleartext_password
Definition: rlm_eap_pwd.c:71
#define MPPE_KEY_LEN
Definition: rlm_eap_pwd.c:51
static fr_dict_attr_t const * attr_framed_mtu
Definition: rlm_eap_pwd.c:72
static fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition: rlm_eap_pwd.c:74
static conf_parser_t submodule_config[]
Definition: rlm_eap_pwd.c:54
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_eap_pwd.c:554
static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_eap_pwd.c:487
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
RETURN_MODULE_FAIL
if(!subtype_vp) goto fail
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
module_t common
Common fields provided by all modules.
Definition: submodule.h:50
Interface exported by EAP submodules.
Definition: submodule.h:49