The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_yubikey.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 74c01429bc276dba88842e11693f03ab8f49f3f8 $
19 * @file rlm_yubikey.c
20 * @brief Authentication for yubikey OTP tokens.
21 *
22 * @author Arran Cudbard-Bell (a.cudbardb@networkradius.com)
23 * @copyright 2013 The FreeRADIUS server project
24 * @copyright 2013 Network RADIUS (legal@networkradius.com)
25 */
26RCSID("$Id: 74c01429bc276dba88842e11693f03ab8f49f3f8 $")
27
28#include <freeradius-devel/radius/radius.h>
29#include <freeradius-devel/unlang/xlat_func.h>
30#include <freeradius-devel/server/rcode.h>
31#include "rlm_yubikey.h"
32
33#ifdef HAVE_YKCLIENT
34static const conf_parser_t validation_config[] = {
35 { FR_CONF_OFFSET("client_id", rlm_yubikey_t, client_id), .dflt = 0 },
36 { FR_CONF_OFFSET_FLAGS("api_key", CONF_FLAG_SECRET, rlm_yubikey_t, api_key) },
38};
39#endif
40
41static const conf_parser_t module_config[] = {
42 { FR_CONF_OFFSET("id_length", rlm_yubikey_t, id_len), .dflt = "12" },
43 { FR_CONF_OFFSET("split", rlm_yubikey_t, split), .dflt = "yes" },
44 { FR_CONF_OFFSET("decrypt", rlm_yubikey_t, decrypt), .dflt = "no" },
45 { FR_CONF_OFFSET("validate", rlm_yubikey_t, validate), .dflt = "no" },
46#ifdef HAVE_YKCLIENT
47 { FR_CONF_POINTER("validation", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) validation_config },
48#endif
50};
51
53static fr_dict_t const *dict_radius;
54
57 { .out = &dict_freeradius, .proto = "freeradius" },
58 { .out = &dict_radius, .proto = "radius" },
60};
61
71
74 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
75 { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius },
76 { .out = &attr_yubikey_key, .name = "Vendor-Specific.Yubico.Yubikey-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
77 { .out = &attr_yubikey_public_id, .name = "Vendor-Specific.Yubico.Yubikey-Public-ID", .type = FR_TYPE_STRING, .dict = &dict_radius },
78 { .out = &attr_yubikey_private_id, .name = "Vendor-Specific.Yubico.Yubikey-Private-ID", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
79 { .out = &attr_yubikey_counter, .name = "Vendor-Specific.Yubico.Yubikey-Counter", .type = FR_TYPE_UINT32, .dict = &dict_radius },
80 { .out = &attr_yubikey_timestamp, .name = "Vendor-Specific.Yubico.Yubikey-Timestamp", .type = FR_TYPE_UINT32, .dict = &dict_radius },
81 { .out = &attr_yubikey_random, .name = "Vendor-Specific.Yubico.Yubikey-Random", .type = FR_TYPE_UINT32, .dict = &dict_radius },
82 { .out = &attr_yubikey_otp, .name = "Vendor-Specific.Yubico.Yubikey-OTP", .type = FR_TYPE_STRING, .dict = &dict_radius },
84};
85
86static char const modhextab[] = "cbdefghijklnrtuv";
87static char const hextab[] = "0123456789abcdef";
88
89#define is_modhex(x) (memchr(modhextab, tolower(x), 16))
90
91/** Convert yubikey modhex to normal hex
92 *
93 * The same buffer may be passed as modhex and hex to convert the modhex in place.
94 *
95 * Modhex and hex must be the same size.
96 *
97 * @param[in] modhex data.
98 * @param[in] len of input and output buffers.
99 * @param[out] hex where to write the standard hexits.
100 * @return
101 * - The number of bytes written to the output buffer.
102 * - -1 on failure.
103 */
104static ssize_t modhex2hex(char const *modhex, char *hex, size_t len)
105{
106 size_t i;
107 char *c1, *c2;
108
109 for (i = 0; i < len; i += 2) {
110 if (modhex[i] == '\0') {
111 break;
112 }
113
114 /*
115 * We only deal with whole bytes
116 */
117 if (modhex[i + 1] == '\0')
118 return -1;
119
120 if (!(c1 = memchr(modhextab, tolower((uint8_t) modhex[i]), 16)) ||
121 !(c2 = memchr(modhextab, tolower((uint8_t) modhex[i + 1]), 16)))
122 return -1;
123
124 hex[i] = hextab[c1 - modhextab];
125 hex[i + 1] = hextab[c2 - modhextab];
126 }
127
128 return i;
129}
130
132 { .required = true, .concat = true, .type = FR_TYPE_STRING },
134};
135
136/** Xlat to convert Yubikey modhex to standard hex
137 *
138 * Example:
139@verbatim
140%modhextohex('vvrbuctetdhc') == "ffc1e0d3d260"
141@endverbatim
142 *
143 * @ingroup xlat_functions
144 */
146 UNUSED xlat_ctx_t const *xctx, request_t *request,
147 fr_value_box_list_t *in)
148{
149 ssize_t len;
150 fr_value_box_t *arg = fr_value_box_list_pop_head(in);
151 char *p = UNCONST(char *, arg->vb_strvalue);
152
153 /*
154 * mod2hex allows conversions in place
155 */
156 len = modhex2hex(p, p, arg->vb_length);
157 if (len <= 0) {
158 REDEBUG("Modhex string invalid");
159 talloc_free(arg);
160 return XLAT_ACTION_FAIL;
161 }
162
164 return XLAT_ACTION_DONE;
165}
166
167static int mod_load(void)
168{
169 xlat_t *xlat;
170
172 PERROR("%s", __FUNCTION__);
173 return -1;
174 }
175
177 PERROR("%s", __FUNCTION__);
179 return -1;
180 }
181
182 if (unlikely(!(xlat = xlat_func_register(NULL, "modhextohex", modhex_to_hex_xlat, FR_TYPE_STRING)))) return -1;
185
186 return 0;
187}
188
189static void mod_unload(void)
190{
191 xlat_func_unregister("modhextohex");
193}
194
195#ifndef HAVE_YUBIKEY
196static int mod_bootstrap(module_inst_ctx_t const *mctx)
197{
198 rlm_yubikey_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_yubikey_t);
199
200 if (inst->decrypt) {
201 cf_log_err(mctx->mi->conf, "Requires libyubikey for OTP decryption");
202 return -1;
203 }
204 return 0;
205}
206#endif
207
208/*
209 * Do any per-module initialization that is separate to each
210 * configured instance of the module. e.g. set up connections
211 * to external databases, read configuration files, set up
212 * dictionary entries, etc.
213 *
214 * If configuration information is given in the config section
215 * that must be referenced in later calls, store a handle to it
216 * in *instance otherwise put a null pointer there.
217 */
218static int mod_instantiate(module_inst_ctx_t const *mctx)
219{
220 rlm_yubikey_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_yubikey_t);
221 CONF_SECTION *conf = mctx->mi->conf;
222
223 inst->name = mctx->mi->name;
224
225 inst->auth_type = fr_dict_enum_by_name(attr_auth_type, inst->name, -1);
226 if (!inst->auth_type) {
227 WARN("Failed to find 'authenticate %s {...}' section. Yubikey authentication will likely not work",
228 mctx->mi->name);
229 }
230
231 if (inst->validate) {
232#ifdef HAVE_YKCLIENT
233 CONF_SECTION *cs;
234
235 cs = cf_section_find(conf, "validation", CF_IDENT_ANY);
236 if (!cs) {
237 cf_log_err(conf, "Missing validation section");
238 return -1;
239 }
240
241 if (rlm_yubikey_ykclient_init(cs, inst) < 0) {
242 return -1;
243 }
244#else
245 cf_log_err(conf, "Requires libykclient for OTP validation against Yubicloud servers");
246 return -1;
247#endif
248 }
249
250 return 0;
251}
252
253#ifdef HAVE_YKCLIENT
254static int mod_detach(module_detach_ctx_t const *mctx)
255{
256 rlm_yubikey_ykclient_detach(talloc_get_type_abort(mctx->mi->data, rlm_yubikey_t));
257 return 0;
258}
259#endif
260
261static int CC_HINT(nonnull) otp_string_valid(rlm_yubikey_t const *inst, char const *otp, size_t len)
262{
263 size_t i;
264
265 for (i = inst->id_len; i < len; i++) {
266 if (!is_modhex(otp[i])) return -i;
267 }
268
269 return 1;
270}
271
272
273/*
274 * Find the named user in this modules database. Create the set
275 * of attribute-value pairs to check and reply with for this user
276 * from the database. The authentication code only needs to check
277 * the password, the rest is done here.
278 */
279static unlang_action_t CC_HINT(nonnull) mod_authorize(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
280{
282 char const *passcode;
283 size_t len;
284 fr_pair_t *vp, *password;
285 char const *otp;
286 size_t password_len;
287 int ret;
288
289 /*
290 * Can't do yubikey auth if there's no password.
291 */
292 password = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password);
293 if (!password) {
294 /*
295 * Don't print out debugging messages if we know
296 * they're useless.
297 */
298 if ((request->proto_dict == dict_radius) && request->packet->code != FR_RADIUS_CODE_ACCESS_CHALLENGE) {
299 RDEBUG2("No cleartext password in the request. Can't do Yubikey authentication");
300 }
301
303 }
304
305 passcode = password->vp_strvalue;
306 len = password->vp_length;
307
308 /*
309 * Now see if the passcode is the correct length (in its raw
310 * modhex encoded form).
311 *
312 * <public_id (6-16 bytes)> + <aes-block (32 bytes)>
313 *
314 */
315 if (len < (inst->id_len + YUBIKEY_TOKEN_LEN)) {
316 RDEBUG2("User-Password value is not the correct length, expected at least %u bytes, got %zu bytes",
317 inst->id_len + YUBIKEY_TOKEN_LEN, len);
319 }
320
321 password_len = (len - (inst->id_len + YUBIKEY_TOKEN_LEN));
322 otp = passcode + password_len;
323 ret = otp_string_valid(inst, otp, (inst->id_len + YUBIKEY_TOKEN_LEN));
324 if (ret <= 0) {
325 if (RDEBUG_ENABLED3) {
326 RDMARKER(otp, -(ret), "User-Password (aes-block) value contains non modhex chars");
327 } else {
328 RDEBUG2("User-Password (aes-block) value contains non modhex chars");
329 }
331 }
332
333 /* May be a concatenation, check the last 32 bytes are modhex */
334 if (inst->split) {
335 /*
336 * Insert a new request attribute just containing the OTP
337 * portion.
338 */
340 fr_pair_value_strdup(vp, otp, password->vp_tainted);
341
342 /*
343 * Replace the existing string buffer for the password
344 * attribute with one just containing the password portion.
345 */
346 MEM(fr_pair_value_bstr_realloc(password, NULL, password_len) == 0);
347
348 RDEBUG2("request.%pP", vp);
349 RDEBUG2("request.%pP", password);
350
351 /*
352 * So the ID split code works on the non password portion.
353 */
354 passcode = vp->vp_strvalue;
355 }
356
357 /*
358 * Split out the Public ID in case another module in authorize
359 * needs to verify it's associated with the user.
360 *
361 * It's left up to the user if they want to decode it or not.
362 */
363 if (inst->id_len) {
365 fr_pair_value_bstrndup(vp, passcode, inst->id_len, true);
366 RDEBUG2("request.%pP", vp);
367 }
368
369 if (!inst->auth_type) {
370 WARN("No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup Yubikey authentication",
371 mctx->mi->name, mctx->mi->name);
373 }
374
376
378}
379
380
381/*
382 * Authenticate the user with the given password.
383 */
384static unlang_action_t CC_HINT(nonnull) mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
385{
387 char const *passcode = NULL;
388 fr_pair_t const *vp;
389 size_t len;
390 int ret;
391
392 p_result->rcode = RLM_MODULE_NOOP;
393
394 vp = fr_pair_find_by_da_nested(&request->request_pairs, NULL, attr_yubikey_otp);
395 if (!vp) {
396 RDEBUG2("No Yubikey-OTP attribute found, falling back to User-Password");
397 /*
398 * Can't do yubikey auth if there's no password.
399 */
400 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password);
401 if (!vp) {
402 REDEBUG("No User-Password in the request. Can't do Yubikey authentication");
404 }
405 }
406
407 passcode = vp->vp_strvalue;
408 len = vp->vp_length;
409
410 /*
411 * Verify the passcode is the correct length (in its raw
412 * modhex encoded form).
413 *
414 * <public_id (6-16 bytes)> + <aes-block (32 bytes)>
415 */
416 if (len != (inst->id_len + YUBIKEY_TOKEN_LEN)) {
417 REDEBUG("%s value is not the correct length, expected bytes %u, got bytes %zu",
418 vp->da->name, inst->id_len + YUBIKEY_TOKEN_LEN, len);
420 }
421
422 ret = otp_string_valid(inst, passcode, (inst->id_len + YUBIKEY_TOKEN_LEN));
423 if (ret <= 0) {
424 if (RDEBUG_ENABLED3) {
425 REMARKER(passcode, -ret, "Passcode (aes-block) value contains non modhex chars");
426 } else {
427 RERROR("Passcode (aes-block) value contains non modhex chars");
428 }
430 }
431
432#ifdef HAVE_YUBIKEY
433 if (inst->decrypt) {
434
435 rlm_yubikey_decrypt(p_result, mctx, request, passcode);
436 if (p_result->rcode != RLM_MODULE_OK) return UNLANG_ACTION_CALCULATE_RESULT;
437 /* Fall-Through to doing ykclient auth in addition to local auth */
438 }
439#endif
440
441#ifdef HAVE_YKCLIENT
442 if (inst->validate) return rlm_yubikey_validate(p_result, mctx, request, passcode);
443#endif
445}
446
447/*
448 * The module name should be the only globally exported symbol.
449 * That is, everything else should be 'static'.
450 *
451 * If the module needs to temporarily modify it's instantiation
452 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
453 * The server will then take care of ensuring that the module
454 * is single-threaded.
455 */
458 .common = {
459 .magic = MODULE_MAGIC_INIT,
460 .name = "yubikey",
461 .inst_size = sizeof(rlm_yubikey_t),
462 .onload = mod_load,
463 .unload = mod_unload,
465#ifndef HAVE_YUBIKEY
466 .bootstrap = mod_bootstrap,
467#endif
468 .instantiate = mod_instantiate,
469#ifdef HAVE_YKCLIENT
470 .detach = mod_detach,
471#endif
472 },
473 .method_group = {
474 .bindings = (module_method_binding_t[]){
475 { .section = SECTION_NAME("authenticate", CF_IDENT_ANY), .method = mod_authenticate },
476 { .section = SECTION_NAME("recv", "Access-Request"), .method = mod_authorize },
478 }
479 }
480};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:506
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:657
#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
Definition cf_parse.h:280
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition cf_parse.h:334
#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
Definition cf_parse.h:268
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition cf_parse.h:433
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:423
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:594
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
#define CF_IDENT_ANY
Definition cf_util.h:75
static int split(char **input, char **output, bool syntax_string)
Definition command.c:393
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:46
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition defs.h:43
#define fr_dict_autofree(_to_free)
Definition dict.h:915
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:292
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:305
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.
Definition dict_util.c:4395
#define fr_dict_autoload(_to_load)
Definition dict.h:912
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:311
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3701
static fr_slen_t in
Definition dict.h:882
Specifies an attribute which must be present for the module to function.
Definition dict.h:291
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:304
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
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.
talloc_free(hp)
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
Definition interpret.h:134
#define PERROR(_fmt,...)
Definition log.h:228
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition log.h:347
#define RERROR(fmt,...)
Definition log.h:310
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:510
#define RDMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:528
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
unsigned char uint8_t
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for detach calls.
Definition module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
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.
Definition module_rlm.c:418
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
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.
Definition pair.c:784
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2663
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.
Definition pair.c:707
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.
Definition pair.c:2812
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.
Definition pair.c:2784
static const conf_parser_t config[]
Definition base.c:163
#define pair_update_request(_attr, _da)
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define WARN(fmt,...)
static rs_t * conf
Definition radsniff.c:52
#define RETURN_UNLANG_INVALID
Definition rcode.h:66
#define RETURN_UNLANG_OK
Definition rcode.h:64
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:54
#define RETURN_UNLANG_NOOP
Definition rcode.h:69
static int mod_detach(module_detach_ctx_t const *mctx)
Definition rlm_always.c:136
static int mod_load(void)
fr_dict_attr_t const * attr_user_password
Definition rlm_yubikey.c:63
static xlat_arg_parser_t const modhex_to_hex_xlat_arg[]
fr_dict_attr_t const * attr_yubikey_random
Definition rlm_yubikey.c:69
fr_dict_attr_t const * attr_yubikey_counter
Definition rlm_yubikey.c:67
static ssize_t modhex2hex(char const *modhex, char *hex, size_t len)
Convert yubikey modhex to normal hex.
static char const modhextab[]
Definition rlm_yubikey.c:86
#define is_modhex(x)
Definition rlm_yubikey.c:89
static fr_dict_t const * dict_freeradius
Definition rlm_yubikey.c:52
fr_dict_attr_t const * attr_yubikey_public_id
Definition rlm_yubikey.c:65
module_rlm_t rlm_yubikey
static fr_dict_t const * dict_radius
Definition rlm_yubikey.c:53
static int mod_bootstrap(module_inst_ctx_t const *mctx)
fr_dict_attr_t const * attr_yubikey_key
Definition rlm_yubikey.c:64
fr_dict_attr_t const * attr_auth_type
Definition rlm_yubikey.c:62
fr_dict_attr_t const * attr_yubikey_timestamp
Definition rlm_yubikey.c:68
static unlang_action_t mod_authorize(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_attr_t const * attr_yubikey_otp
Definition rlm_yubikey.c:70
static void mod_unload(void)
fr_dict_attr_autoload_t rlm_yubikey_dict_attr[]
Definition rlm_yubikey.c:73
static char const hextab[]
Definition rlm_yubikey.c:87
static unlang_action_t mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_attr_t const * attr_yubikey_private_id
Definition rlm_yubikey.c:66
static const conf_parser_t module_config[]
Definition rlm_yubikey.c:41
fr_dict_autoload_t rlm_yubikey_dict[]
Definition rlm_yubikey.c:56
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)
unlang_action_t rlm_yubikey_validate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
unlang_action_t rlm_yubikey_decrypt(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
int rlm_yubikey_ykclient_init(CONF_SECTION *conf, rlm_yubikey_t *inst)
#define YUBIKEY_TOKEN_LEN
Definition rlm_yubikey.h:31
int rlm_yubikey_ykclient_detach(rlm_yubikey_t *inst)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:39
char const * name
Instance name e.g. user_database.
Definition module.h:357
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:293
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:152
Named methods exported by a module.
Definition module.h:174
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define talloc_get_type_abort_const
Definition talloc.h:110
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumed by an xlat function.
Definition xlat.h:145
int nonnull(2, 5))
static size_t char ** out
Definition value.h:1030
An xlat calling ctx.
Definition xlat_ctx.h:49
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
Definition xlat_func.c:399
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:216
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:516
@ XLAT_FUNC_FLAG_PURE
Definition xlat_func.h:38