26 RCSID(
"$Id: bf91acbd24b86fb09604e41809fedfe6a11daccd $")
28 #include "rlm_yubikey.h"
60 static char const hextab[] =
"0123456789abcdef";
62 #define is_modhex(x) (memchr(modhextab, tolower(x), 16))
82 for (i = 0; i < len; i++) {
83 if (modhex[i << 1] ==
'\0') {
90 if (modhex[(i << 1) + 1] ==
'\0')
93 if (!(c1 = memchr(modhextab, tolower((
int) modhex[i << 1]), 16)) ||
94 !(c2 = memchr(modhextab, tolower((
int) modhex[(i << 1) + 1]), 16)))
110 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
111 REQUEST *request,
char const *fmt)
115 if (outlen < strlen(fmt))
return 0;
120 len =
modhex2hex(fmt, (uint8_t *) *out, strlen(fmt));
122 REDEBUG(
"Modhex string invalid");
139 cf_log_err_cs(conf,
"Requires libyubikey for OTP decryption");
179 cf_log_err_cs(conf,
"Requires libykclient for OTP validation against Yubicloud servers");
203 for (i = inst->id_len; i < len; i++) {
222 char const *passcode;
232 if (!request->password || (request->password->da->attr != PW_USER_PASSWORD)) {
238 RDEBUG2(
"No cleartext password in the request. Can't do Yubikey authentication");
245 passcode = request->password->vp_strvalue;
246 len = request->password->vp_length;
256 RDEBUG2(
"User-Password value is not the correct length, expected at least %u bytes, got %zu bytes",
262 otp = passcode + password_len;
266 RDMARKER(otp, -ret,
"User-Password (aes-block) value contains non modhex chars");
268 RDEBUG(
"User-Password (aes-block) value contains non modhex chars");
283 REDEBUG(
"Failed creating 'Yubikey-OTP' attribute");
291 MEM(password = talloc_array(request->password,
char, password_len + 1));
292 strlcpy(password, passcode, password_len + 1);
297 RDEBUG3(
"&request:Yubikey-OTP := '%s'", vp->vp_strvalue);
298 RDEBUG3(
"&request:User-Password := '%s'", request->password->vp_strvalue);
300 RDEBUG2(
"&request:Yubikey-OTP := <<< secret >>>");
301 RDEBUG2(
"&request:User-Password := <<< secret >>>");
308 passcode = vp->vp_strvalue;
320 REDEBUG(
"Failed creating Yubikey-Public-ID");
331 vp->vp_integer = dval->
value;
345 char const *passcode = NULL;
353 RDEBUG2(
"No Yubikey-OTP attribute defined, falling back to User-Password");
359 RDEBUG2(
"No Yubikey-OTP attribute found, falling back to User-Password");
364 if (!request->password || (request->password->da->attr != PW_USER_PASSWORD)) {
365 REDEBUG(
"No User-Password in the request. Can't do Yubikey authentication");
369 vp = request->password;
372 passcode = vp->vp_strvalue;
382 REDEBUG(
"%s value is not the correct length, expected bytes %u, got bytes %zu",
390 REMARKER(passcode, -ret,
"Passcode (aes-block) value contains non modhex chars");
392 RERROR(
"Passcode (aes-block) value contains non modhex chars");
430 .config = module_config,
#define RDMARKER(_m, _i, _e)
Output string with error marker, showing where format error occurred.
#define RINDENT()
Indent R* messages by one level.
int xlat_register(void *mod_inst, char const *name, xlat_func_t func, xlat_escape_t escape, xlat_instantiate_t instantiate, size_t inst_size, size_t buf_len)
Register an xlat function.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
RFC2865 - Access-Challenge.
static int mod_instantiate(CONF_SECTION *conf, void *instance)
The module is OK, continue.
char const * name
Instance name.
Metadata exported by the module.
rlm_rcode_t rlm_yubikey_validate(rlm_yubikey_t *inst, REQUEST *request, char const *passcode)
int rlm_yubikey_ykclient_detach(rlm_yubikey_t *inst)
VALUE_PAIR * radius_pair_create(TALLOC_CTX *ctx, VALUE_PAIR **vps, unsigned int attribute, unsigned int vendor)
Create a VALUE_PAIR and add it to a list of VALUE_PAIR s.
static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
Handle authorization requests using Couchbase document data.
#define RLM_TYPE_THREAD_SAFE
Module is threadsafe.
#define REMARKER(_m, _i, _e)
Output string with error marker, showing where format error occurred.
bool validate
Validate the OTP string using the ykclient library.
#define CONF_PARSER_TERMINATOR
static const CONF_PARSER module_config[]
#define pair_make_request(_a, _b, _c)
#define PW_TYPE_SECRET
Only print value if debug level >= 3.
static char const hextab[]
bool split
Split password string into components.
The module considers the request invalid.
#define XLAT_DEFAULT_BUF_LEN
static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) CC_HINT(nonnull)
#define PW_TYPE_SUBSECTION
Defines a CONF_PAIR to C data type mapping.
fr_dict_enum_t * fr_dict_enum_by_name(fr_dict_t *dict, fr_dict_attr_t const *da, char const *val)
void fr_pair_value_strsteal(VALUE_PAIR *vp, char const *src)
Reparent an allocated char buffer to a VALUE_PAIR.
static int CC_HINT(nonnull)
static int mod_bootstrap(CONF_SECTION *conf, void *instance)
int rlm_yubikey_ykclient_init(CONF_SECTION *conf, rlm_yubikey_t *inst)
Stores an attribute, a value and various bits of other data.
void void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
0 methods index for authenticate section.
#define REXDENT()
Exdent (unindent) R* messages by one level.
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
rlm_rcode_t rlm_yubikey_decrypt(rlm_yubikey_t *inst, REQUEST *request, char const *passcode)
CONF_SECTION * cf_section_sub_find(CONF_SECTION const *, char const *name)
Find a sub-section in a section.
struct rlm_yubikey_t rlm_yubikey_t
#define YUBIKEY_TOKEN_LEN
char const * cf_section_name1(CONF_SECTION const *cs)
VALUE_PAIR * fr_pair_find_by_da(VALUE_PAIR *head, fr_dict_attr_t const *da, int8_t tag)
Find the pair with the matching DAs.
Module succeeded without doing anything.
char name[1]
Attribute name.
uint64_t magic
Used to validate module struct.
Module failed, don't reply.
#define FR_CONF_OFFSET(_n, _t, _s, _f)
unsigned int id_len
The length of the Public ID portion of the OTP string.
static ssize_t modhex_to_hex_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Convert Yubikey modhex to standard hex.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
static int mod_detach(void *instance)
Free any memory allocated under the instance.
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
String of printable characters.
#define FR_CONF_POINTER(_n, _t, _p)
1 methods index for authorize section.
bool decrypt
Decrypt the OTP string using the yubikey library.
static char const modhextab[]
VALUE_PAIR * fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps, char const *attribute, char const *value, FR_TOKEN op)
Create a VALUE_PAIR from ASCII strings.
static ssize_t modhex2hex(char const *modhex, uint8_t *hex, size_t len)
Convert yubikey modhex to normal hex.
Value of an enumerated attribute.
char const * cf_section_name2(CONF_SECTION const *cs)
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_t *dict, char const *attr)
Locate a fr_dict_attr_t by its name.