33RCSID(
"$Id: 20f7af2f132ea9bc6d3c12a6243f3ebc71d567ea $")
36#include <freeradius-devel/server/base.h>
37#include <freeradius-devel/server/module_rlm.h>
38#include <freeradius-devel/tls/base.h>
55#define MPPE_KEY_LEN 32
56#define MSK_EMSK_LEN (2 * MPPE_KEY_LEN)
103 switch (session->
state) {
117 REDEBUG(
"PWD state is invalid. Can't send request");
132 totlen = ntohs(session->
out_len);
133 memcpy(hdr->
data, (
char *)&totlen,
sizeof(totlen));
176 uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
188 REDEBUG(
"Packet with insufficient data");
199 if (in_len)
REDEBUG(
"PWD got something more than an ACK for a fragment");
211 REDEBUG(
"PWD already alloced buffer for fragments");
216 REDEBUG(
"Invalid packet: length bit set, but no length field");
222 DEBUG(
"EAP-PWD malformed packet (input length)");
239 RDEBUG2(
"Unexpected fragment");
244 REDEBUG(
"Fragment overflows packet");
248 memcpy(session->
in + session->
in_pos,
in, in_len);
249 session->
in_pos += in_len;
272 REDEBUG(
"PWD will overflow a fragment buffer");
275 memcpy(session->
in + session->
in_pos,
in, in_len);
280 switch (session->
state) {
287 BIGNUM *x = NULL, *y = NULL;
290 REDEBUG(
"PWD exchange is incorrect, Not ID");
295 if (in_len <
sizeof(*packet)) {
296 REDEBUG(
"Packet is too small (%zd < %zd).", in_len,
sizeof(*packet));
303 (CRYPTO_memcmp(packet->
token, &session->
token, 4)) ||
305 REDEBUG(
"PWD ID response is malformed");
321 REDEBUG(
"PWD ID response is malformed");
328 known_good =
password_find(&ephemeral, request, request->parent,
329 allowed_passwords,
NUM_ELEMENTS(allowed_passwords),
false);
331 REDEBUG(
"No \"known good\" password found for user");
336 known_good->vp_strvalue, known_good->vp_length,
337 inst->server_id, strlen(
inst->server_id),
340 if (ephemeral) TALLOC_FREE(known_good);
342 REDEBUG(
"Failed to obtain password element");
350 REDEBUG(
"Failed to compute server's scalar and element");
361 REDEBUG(
"Server point assignment failed");
370 session->
out_len = BN_num_bytes(session->
order) + (2 * BN_num_bytes(session->
prime));
374 offset = BN_num_bytes(session->
prime) - BN_num_bytes(x);
375 BN_bn2bin(x, ptr + offset);
378 ptr += BN_num_bytes(session->
prime);
379 offset = BN_num_bytes(session->
prime) - BN_num_bytes(y);
380 BN_bn2bin(y, ptr + offset);
383 ptr += BN_num_bytes(session->
prime);
384 offset = BN_num_bytes(session->
order) - BN_num_bytes(session->
my_scalar);
385 BN_bn2bin(session->
my_scalar, ptr + offset);
394 REDEBUG(
"PWD exchange is incorrect, not commit!");
402 REDEBUG(
"Failed processing peer's commit");
410 REDEBUG(
"Failed computing confirm");
417 session->
out_len = SHA256_DIGEST_LENGTH;
421 memcpy(session->
out, session->
my_confirm, SHA256_DIGEST_LENGTH);
428 if (in_len < SHA256_DIGEST_LENGTH) {
429 REDEBUG(
"Peer confirm is too short (%zd < %d)", in_len, SHA256_DIGEST_LENGTH);
434 REDEBUG(
"PWD exchange is incorrect, not commit");
438 REDEBUG(
"Cannot compute peer's confirm");
441 if (CRYPTO_memcmp(peer_confirm,
in, SHA256_DIGEST_LENGTH)) {
442 REDEBUG(
"PWD exchange failed, peer confirm is incorrect");
445 if (
compute_keys(request, session, peer_confirm, msk, emsk)) {
446 REDEBUG(
"Failed generating (E)MSK");
481 BN_clear_free(session->
k);
484 EC_GROUP_free(session->
group);
485 EC_POINT_clear_free(session->
pwe);
486 BN_clear_free(session->
order);
487 BN_clear_free(session->
prime);
510 session->
mtu =
inst->fragment_size;
522 if (
vp && (
vp->vp_uint32 > 100) && (
vp->vp_uint32 < session->
mtu)) session->
mtu =
vp->vp_uint32 - 9;
526 eap_session->
opaque = session;
539 memcpy(packet->
token, (
char *)&session->
token, 4);
555 if (
inst->fragment_size < 100) {
560 switch (
inst->group) {
585 t->
bnctx = BN_CTX_new();
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define USES_APPLE_DEPRECATED_API
#define CONF_PARSER_TERMINATOR
#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
#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
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_err_by_child(_parent, _child, _fmt,...)
Log an error message against a specified child.
eap_packet_t * response
Packet we received from the peer.
eap_packet_t * request
Packet we will send to the peer.
Structure to hold EAP data.
Contains a pair of request and response packets.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
#define DICT_AUTOLOAD_TERMINATOR
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
int compute_scalar_element(request_t *request, pwd_session_t *session, BN_CTX *bn_ctx)
int process_peer_commit(request_t *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx)
int compute_server_confirm(request_t *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
int compute_keys(UNUSED request_t *request, pwd_session_t *session, uint8_t *peer_confirm, uint8_t *msk, uint8_t *emsk)
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)
int compute_peer_confirm(request_t *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
char peer_id[FR_MAX_STRING_LEN]
#define EAP_PWD_EXCH_COMMIT
#define EAP_PWD_GET_MORE_BIT(x)
uint8_t my_confirm[SHA256_DIGEST_LENGTH]
#define EAP_PWD_DEF_RAND_FUN
#define EAP_PWD_GET_LENGTH_BIT(x)
#define EAP_PWD_SET_EXCHANGE(x, y)
#define EAP_PWD_GET_EXCHANGE(x)
#define EAP_PWD_SET_LENGTH_BIT(x)
#define EAP_PWD_EXCH_CONFIRM
#define PWD_STATE_CONFIRM
#define EAP_PWD_SET_MORE_BIT(x)
#define EAP_PWD_PREP_NONE
copyright holder grants permission for redistribution and use in source and binary forms,...
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
static eap_session_t * eap_session_get(request_t *request)
void * opaque
Opaque data used by EAP methods.
module_method_t process
Callback that should be used to process the next round.
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Tracks the progress of a single session of any EAP method.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
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.
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.
static void thread_detach(UNUSED void *uctx)
Explicitly cleanup module/xlat resources.
static int thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el, UNUSED void *uctx)
Create module and xlat per-thread instances.
uint32_t fr_rand(void)
Return a 32-bit random number.
#define RETURN_UNLANG_HANDLED
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
static int send_pwd_request(request_t *request, pwd_session_t *session, eap_round_t *eap_round)
char const * virtual_server
rlm_eap_submodule_t rlm_eap_pwd
rlm_eap_pwd_t const * inst
static int _free_pwd_session(pwd_session_t *session)
static fr_dict_t const * dict_freeradius
static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_t const * dict_radius
static fr_dict_attr_t const * attr_ms_mppe_send_key
fr_dict_attr_autoload_t rlm_eap_pwd_dict_attr[]
fr_dict_autoload_t rlm_eap_pwd_dict[]
static fr_dict_attr_t const * attr_cleartext_password
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static fr_dict_attr_t const * attr_framed_mtu
static fr_dict_attr_t const * attr_ms_mppe_recv_key
static conf_parser_t submodule_config[]
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static unlang_action_t mod_session_init(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_instantiate(module_inst_ctx_t const *mctx)
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
size_t thread_inst_size
Size of the module's thread-specific instance data.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
module_t common
Common fields provided by all modules.
Interface exported by EAP submodules.