23 RCSID(
"$Id: 04f67c76fb0466a128f2866a210f76a59871b683 $")
25 #include <freeradius-devel/server/dependency.h>
26 #include <freeradius-devel/server/pair.h>
27 #include <freeradius-devel/server/virtual_servers.h>
28 #include <freeradius-devel/unlang/call.h>
29 #include <freeradius-devel/unlang/interpret.h>
30 #include <freeradius-devel/util/base16.h>
31 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/util/rand.h>
111 RDEBUG2(
"Storing attributes for final response");
210 length = htons(length);
219 memcpy(ptr, reply->vp_octets, reply->vp_length);
220 memcpy((ptr + reply->vp_length),
inst->identity, (talloc_array_length(
inst->identity) - 1));
245 length = htons(length);
247 memcpy((eap_round->
request->
type.
data + 4), reply->vp_strvalue + 1, 42);
250 length = 4 + reply->vp_length - 1;
262 length = htons(length);
267 memcpy((eap_round->
request->
type.
data + 4), reply->vp_strvalue + 1, reply->vp_length - 1);
269 RERROR(
"%s: Internal sanity check failed", __FUNCTION__);
313 }
else if (
inst->send_error) {
333 n = sscanf(
vp->vp_strvalue,
"%*cE=%d R=%d C=%32s", &
err, &retry, &buf[0]);
335 RDEBUG2(
"Found new challenge from MS-CHAP-Error: err=%d retry=%d challenge=%s",
340 RDEBUG2(
"Could not parse new challenge from MS-CHAP-Error: %d",
n);
390 REDEBUG(
"Response too short, expected at least 6 bytes, got %zu bytes",
397 switch (
data->code) {
400 RDEBUG2(
"Authentication re-try from client after we sent a failure");
417 RDEBUG2(
"Password change packet received");
429 if (!ms) ms = request->request_ctx;
434 while (copied < 516) {
437 int to_copy = 516 - copied;
438 if (to_copy > 243) to_copy = 243;
452 RDEBUG2(
"Built change password packet");
465 REDEBUG(
"Sent FAILURE expecting FAILURE but got %d", ccode);
492 RDEBUG2(
"Adding stored attributes to parent");
496 RDEBUG2(
"No stored attributes to copy to parent");
505 REDEBUG(
"Sent SUCCESS expecting SUCCESS (or ACK) but got %d", ccode);
515 REDEBUG(
"Sent CHALLENGE expecting RESPONSE but got %d", ccode);
537 REDEBUG(
"Response is too short");
563 if ((length < (5 + 49)) || (length > (256 + 5 + 49))) {
564 REDEBUG(
"Response contains contradictory length %zu %d", length, 5 + 49);
597 length - 49 - 5,
true) == 0);
604 RDEBUG(
"Looking for authenticate %s { ... }",
inst->auth_type->name);
608 RDEBUG2(
"authenticate %s { ... } sub-section not found.",
609 inst->auth_type->name);
629 bool created_auth_challenge;
652 RWDEBUG(
"&parent.control.MS-CHAP-Challenge is incorrect length. Ignoring it");
653 auth_challenge = NULL;
658 RWDEBUG(
"&parent.control.MS-CHAP-Peer-Challenge is incorrect length. Ignoring it");
659 peer_challenge = NULL;
662 created_auth_challenge = (auth_challenge == NULL);
667 if (!auth_challenge) {
679 if (peer_challenge) {
680 data->has_peer_challenge =
true;
691 if (created_auth_challenge) TALLOC_FREE(auth_challenge);
712 if (
inst->identity && (strlen(
inst->identity) > 255)) {
729 .name =
"eap_mschapv2",
737 .clone_parent_lists =
false
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
#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_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
eap_packet_t * response
Packet we received from the peer.
eap_packet_t * request
Packet we will send to the peer.
Contains a pair of request and response packets.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define RADIUSD_VERSION_STRING
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
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.
int fr_dict_enum_add_name_next(fr_dict_attr_t *da, char const *name)
Add an name to an integer attribute hashing the name for the integer value.
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
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.
Value of an enumerated attribute.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define MSCHAPV2_CHALLENGE_LEN
#define MSCHAPV2_HEADER_LEN
#define MSCHAPV2_RESPONSE_LEN
#define FR_EAP_MSCHAPV2_FAILURE
#define FR_EAP_MSCHAPV2_CHALLENGE
#define FR_EAP_MSCHAPV2_SUCCESS
#define FR_EAP_MSCHAPV2_RESPONSE
#define FR_EAP_MSCHAPV2_ACK
#define FR_EAP_MSCHAPV2_CHGPASSWD
rlm_rcode_t unlang_interpret_stack_result(request_t *request)
Get the current rcode for the frame.
void * opaque
Opaque data used by EAP methods.
module_method_t process
Callback that should be used to process the next round.
void const * inst
Instance of the eap module this session was created by.
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.
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RINDENT()
Indent R* messages by one level.
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
void * rctx
Resume ctx that a module previously set.
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.
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
int fr_pair_list_copy_by_da(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *da, unsigned int count)
Duplicate pairs in a list matching the specified da.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_pair_t * fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da)
Create a pair (and all intermediate parents), and append it to the list.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
static const conf_parser_t config[]
#define pair_update_request(_attr, _da)
uint32_t fr_rand(void)
Return a 32-bit random number.
#define RETURN_MODULE_REJECT
#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 fr_dict_attr_t const * attr_microsoft
static int eap_mschapv2_compose(rlm_eap_mschapv2_t const *inst, request_t *request, eap_session_t *eap_session, fr_pair_t *reply)
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static unlang_action_t mschap_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_attr_t const * attr_state
static void mppe_keys_store(request_t *request, mschapv2_opaque_t *data)
static fr_dict_attr_t const * attr_ms_mppe_encryption_type
static fr_dict_t const * dict_freeradius
static int auth_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
fr_dict_enum_value_t * auth_type
static fr_dict_attr_t const * attr_ms_chap2_success
static fr_dict_t const * dict_radius
static fr_dict_attr_t const * attr_ms_chap_challenge
static fr_dict_attr_t const * attr_auth_type
static fr_dict_attr_t const * attr_ms_chap_user_name
static fr_dict_attr_t const * attr_ms_chap_error
static fr_dict_attr_t const * attr_ms_mppe_send_key
static fr_dict_attr_t const * attr_ms_chap2_response
fr_dict_autoload_t rlm_eap_mschapv2_dict[]
static fr_dict_attr_t const * attr_user_name
fr_dict_attr_autoload_t rlm_eap_mschapv2_dict_attr[]
static fr_dict_attr_t const * attr_ms_mppe_recv_key
static conf_parser_t submodule_config[]
static fr_dict_attr_t const * attr_ms_chap_nt_enc_pw
rlm_eap_submodule_t rlm_eap_mschapv2
static fr_dict_attr_t const * attr_ms_chap_peer_challenge
static int mod_instantiate(module_inst_ctx_t const *mctx)
static fr_dict_attr_t const * attr_ms_chap2_cpw
static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_attr_t const * attr_ms_mppe_encryption_policy
static int instantiate(module_inst_ctx_t const *mctx)
#define FR_SBUFF_IN(_start, _len_or_end)
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
unlang_action_t unlang_module_yield_to_section(rlm_rcode_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
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.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
module_t common
Common fields provided by all modules.
Interface exported by EAP submodules.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
static size_t char ** out