33 RCSID(
"$Id: 047a13e40ec13370add8a7da2c36dc9c4d1f6cc3 $")
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.
#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)
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.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Module instance to detach.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach 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)
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
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.