26 RCSID(
"$Id: 4877b1e167a48f69db89a00cd1bb32ce84fd5f3b $")
28 #include <freeradius-devel/radius/radius.h>
29 #include <freeradius-devel/unlang/xlat_func.h>
86 static char const hextab[] =
"0123456789abcdef";
88 #define is_modhex(x) (memchr(modhextab, tolower(x), 16))
108 for (i = 0; i < len; i += 2) {
109 if (modhex[i] ==
'\0') {
116 if (modhex[i + 1] ==
'\0')
146 fr_value_box_list_t *
in)
150 char *p =
UNCONST(
char *, arg->vb_strvalue);
157 REDEBUG(
"Modhex string invalid");
171 PERROR(
"%s", __FUNCTION__);
176 PERROR(
"%s", __FUNCTION__);
225 if (!
inst->auth_type) {
226 WARN(
"Failed to find 'authenticate %s {...}' section. Yubikey authentication will likely not work",
230 if (
inst->validate) {
244 cf_log_err(
conf,
"Requires libykclient for OTP validation against Yubicloud servers");
264 for (i =
inst->id_len; i < len; i++) {
281 char const *passcode;
298 RDEBUG2(
"No cleartext password in the request. Can't do Yubikey authentication");
304 passcode = password->vp_strvalue;
305 len = password->vp_length;
315 RDEBUG2(
"User-Password value is not the correct length, expected at least %u bytes, got %zu bytes",
321 otp = passcode + password_len;
325 RDMARKER(otp, -(ret),
"User-Password (aes-block) value contains non modhex chars");
327 RDEBUG2(
"User-Password (aes-block) value contains non modhex chars");
348 RDEBUG2(
"&request.%pP", password);
353 passcode =
vp->vp_strvalue;
368 if (!
inst->auth_type) {
369 WARN(
"No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup Yubikey authentication",
387 char const *passcode = NULL;
394 RDEBUG2(
"No Yubikey-OTP attribute found, falling back to User-Password");
400 REDEBUG(
"No User-Password in the request. Can't do Yubikey authentication");
405 passcode =
vp->vp_strvalue;
415 REDEBUG(
"%s value is not the correct length, expected bytes %u, got bytes %zu",
423 REMARKER(passcode, -ret,
"Passcode (aes-block) value contains non modhex chars");
425 RERROR(
"Passcode (aes-block) value contains non modhex chars");
473 { .name1 =
"recv", .name2 =
"access-request", .method =
mod_authorize },
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#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_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#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_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple 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.
#define cf_log_err(_cf, _fmt,...)
static int split(char **input, char **output, bool syntax_string)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
#define fr_dict_autofree(_to_free)
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_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
#define fr_dict_autoload(_to_load)
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.
char const *_CONST name
Instance name.
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
static xlat_action_t modhex_to_hex_xlat(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat to convert Yubikey modhex to standard hex.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
#define RDMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
@ 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.
Specifies a module method identifier.
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
module_t common
Common fields presented by all modules.
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.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
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.
int fr_pair_value_bstr_realloc(fr_pair_t *vp, char **out, size_t size)
Change the length of a buffer for 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.
static const conf_parser_t config[]
#define pair_update_request(_attr, _da)
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
#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_NOOP
Module succeeded without doing anything.
static int mod_detach(module_detach_ctx_t const *mctx)
Cleanup a cache_rbtree instance.
static int instantiate(module_inst_ctx_t const *mctx)
static int mod_load(void)
fr_dict_attr_t const * attr_user_password
static xlat_arg_parser_t const modhex_to_hex_xlat_arg[]
fr_dict_attr_t const * attr_yubikey_random
fr_dict_attr_t const * attr_yubikey_counter
static ssize_t modhex2hex(char const *modhex, char *hex, size_t len)
Convert yubikey modhex to normal hex.
static char const modhextab[]
static fr_dict_t const * dict_freeradius
fr_dict_attr_t const * attr_yubikey_public_id
static fr_dict_t const * dict_radius
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_bootstrap(module_inst_ctx_t const *mctx)
fr_dict_attr_t const * attr_yubikey_key
fr_dict_attr_t const * attr_auth_type
fr_dict_attr_t const * attr_yubikey_timestamp
fr_dict_attr_t const * attr_yubikey_otp
static void mod_unload(void)
fr_dict_attr_autoload_t rlm_yubikey_dict_attr[]
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static char const hextab[]
fr_dict_attr_t const * attr_yubikey_private_id
static const conf_parser_t module_config[]
fr_dict_autoload_t rlm_yubikey_dict[]
static int otp_string_valid(rlm_yubikey_t const *inst, char const *otp, size_t len)
static int mod_instantiate(module_inst_ctx_t const *mctx)
int rlm_yubikey_ykclient_init(CONF_SECTION *conf, rlm_yubikey_t *inst)
#define YUBIKEY_TOKEN_LEN
int rlm_yubikey_ykclient_detach(rlm_yubikey_t *inst)
unlang_action_t rlm_yubikey_decrypt(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
unlang_action_t rlm_yubikey_validate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
#define MODULE_NAME_TERMINATOR
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.
#define talloc_get_type_abort_const
bool required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
static size_t char ** out
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
int xlat_func_mono_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the argument of an xlat.
void xlat_func_unregister(char const *name)
Unregister an xlat function.