33 RCSID(
"$Id: febcab0c3e1f75aa4bedf07ca091d8bc7017d8e8 $")
36 #include <freeradius-devel/server/base.h>
37 #include <freeradius-devel/server/module_rlm.h>
38 #include <freeradius-devel/tls/base.h>
51 #define MPPE_KEY_LEN 32
52 #define MSK_EMSK_LEN (2 * MPPE_KEY_LEN)
113 REDEBUG(
"PWD state is invalid. Can't send request");
128 totlen = ntohs(session->
out_len);
129 memcpy(hdr->
data, (
char *)&totlen,
sizeof(totlen));
171 uint8_t peer_confirm[SHA256_DIGEST_LENGTH];
183 REDEBUG(
"Packet with insufficient data");
194 if (in_len)
REDEBUG(
"PWD got something more than an ACK for a fragment");
206 REDEBUG(
"PWD already alloced buffer for fragments");
211 REDEBUG(
"Invalid packet: length bit set, but no length field");
217 DEBUG(
"EAP-PWD malformed packet (input length)");
234 RDEBUG2(
"Unexpected fragment");
239 REDEBUG(
"Fragment overflows packet");
243 memcpy(session->
in + session->
in_pos,
in, in_len);
244 session->
in_pos += in_len;
267 REDEBUG(
"PWD will overflow a fragment buffer");
270 memcpy(session->
in + session->
in_pos,
in, in_len);
275 switch (session->
state) {
282 BIGNUM *x = NULL, *
y = NULL;
285 REDEBUG(
"PWD exchange is incorrect, Not ID");
290 if (in_len <
sizeof(*packet)) {
291 REDEBUG(
"Packet is too small (%zd < %zd).", in_len,
sizeof(*packet));
298 (CRYPTO_memcmp(packet->
token, &session->
token, 4)) ||
300 REDEBUG(
"PWD ID response is malformed");
316 REDEBUG(
"PWD ID response is malformed");
323 known_good =
password_find(&ephemeral, request, request->parent,
324 allowed_passwords,
NUM_ELEMENTS(allowed_passwords),
false);
326 REDEBUG(
"No \"known good\" password found for user");
331 known_good->vp_strvalue, known_good->vp_length,
332 inst->server_id, strlen(
inst->server_id),
335 if (ephemeral) TALLOC_FREE(known_good);
337 REDEBUG(
"Failed to obtain password element");
345 REDEBUG(
"Failed to compute server's scalar and element");
356 REDEBUG(
"Server point assignment failed");
365 session->
out_len = BN_num_bytes(session->
order) + (2 * BN_num_bytes(session->
prime));
369 offset = BN_num_bytes(session->
prime) - BN_num_bytes(x);
370 BN_bn2bin(x, ptr + offset);
373 ptr += BN_num_bytes(session->
prime);
374 offset = BN_num_bytes(session->
prime) - BN_num_bytes(
y);
375 BN_bn2bin(
y, ptr + offset);
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);
389 REDEBUG(
"PWD exchange is incorrect, not commit!");
397 REDEBUG(
"Failed processing peer's commit");
405 REDEBUG(
"Failed computing confirm");
412 session->
out_len = SHA256_DIGEST_LENGTH;
416 memcpy(session->
out, session->
my_confirm, SHA256_DIGEST_LENGTH);
423 if (in_len < SHA256_DIGEST_LENGTH) {
424 REDEBUG(
"Peer confirm is too short (%zd < %d)", in_len, SHA256_DIGEST_LENGTH);
429 REDEBUG(
"PWD exchange is incorrect, not commit");
433 REDEBUG(
"Cannot compute peer's confirm");
436 if (CRYPTO_memcmp(peer_confirm,
in, SHA256_DIGEST_LENGTH)) {
437 REDEBUG(
"PWD exchange failed, peer confirm is incorrect");
440 if (
compute_keys(request, session, peer_confirm, msk, emsk)) {
441 REDEBUG(
"Failed generating (E)MSK");
476 BN_clear_free(session->
k);
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);
505 session->
mtu =
inst->fragment_size;
517 if (
vp && (
vp->vp_uint32 > 100) && (
vp->vp_uint32 < session->
mtu)) session->
mtu =
vp->vp_uint32 - 9;
521 eap_session->
opaque = session;
534 memcpy(packet->
token, (
char *)&session->
token, 4);
549 if (
inst->bnctx) BN_CTX_free(
inst->bnctx);
559 if (
inst->fragment_size < 100) {
564 switch (
inst->group) {
577 inst->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.
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.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_inst_t const * inst
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)
#define EC_POINT_get_affine_coordinates
copyright holder grants permission for redistribution and use in source and binary forms,...
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
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
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.
static eap_session_t * eap_session_get(request_t *request)
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.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for 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 const conf_parser_t config[]
uint32_t fr_rand(void)
Return a 32-bit random number.
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_HANDLED
#define RETURN_MODULE_INVALID
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)
static int mod_detach(module_detach_ctx_t const *mctx)
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
char const * virtual_server
rlm_eap_submodule_t rlm_eap_pwd
static int _free_pwd_session(pwd_session_t *session)
static fr_dict_t const * dict_freeradius
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 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_instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int instantiate(module_inst_ctx_t const *mctx)
if(!subtype_vp) goto fail
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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.