The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 4877b1e167a48f69db89a00cd1bb32ce84fd5f3b $
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  */
26 RCSID("$Id: 4877b1e167a48f69db89a00cd1bb32ce84fd5f3b $")
27 
28 #include <freeradius-devel/radius/radius.h>
29 #include <freeradius-devel/unlang/xlat_func.h>
30 #include "rlm_yubikey.h"
31 
32 #ifdef HAVE_YKCLIENT
33 static const conf_parser_t validation_config[] = {
34  { FR_CONF_OFFSET("client_id", rlm_yubikey_t, client_id), .dflt = 0 },
35  { FR_CONF_OFFSET_FLAGS("api_key", CONF_FLAG_SECRET, rlm_yubikey_t, api_key) },
37 };
38 #endif
39 
40 static const conf_parser_t module_config[] = {
41  { FR_CONF_OFFSET("id_length", rlm_yubikey_t, id_len), .dflt = "12" },
42  { FR_CONF_OFFSET("split", rlm_yubikey_t, split), .dflt = "yes" },
43  { FR_CONF_OFFSET("decrypt", rlm_yubikey_t, decrypt), .dflt = "no" },
44  { FR_CONF_OFFSET("validate", rlm_yubikey_t, validate), .dflt = "no" },
45 #ifdef HAVE_YKCLIENT
46  { FR_CONF_POINTER("validation", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) validation_config },
47 #endif
49 };
50 
51 static fr_dict_t const *dict_freeradius;
52 static fr_dict_t const *dict_radius;
53 
56  { .out = &dict_freeradius, .proto = "freeradius" },
57  { .out = &dict_radius, .proto = "radius" },
58  { NULL }
59 };
60 
70 
73  { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
74  { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius },
75  { .out = &attr_yubikey_key, .name = "Vendor-Specific.Yubico.Yubikey-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
76  { .out = &attr_yubikey_public_id, .name = "Vendor-Specific.Yubico.Yubikey-Public-ID", .type = FR_TYPE_STRING, .dict = &dict_radius },
77  { .out = &attr_yubikey_private_id, .name = "Vendor-Specific.Yubico.Yubikey-Private-ID", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
78  { .out = &attr_yubikey_counter, .name = "Vendor-Specific.Yubico.Yubikey-Counter", .type = FR_TYPE_UINT32, .dict = &dict_radius },
79  { .out = &attr_yubikey_timestamp, .name = "Vendor-Specific.Yubico.Yubikey-Timestamp", .type = FR_TYPE_UINT32, .dict = &dict_radius },
80  { .out = &attr_yubikey_random, .name = "Vendor-Specific.Yubico.Yubikey-Random", .type = FR_TYPE_UINT32, .dict = &dict_radius },
81  { .out = &attr_yubikey_otp, .name = "Vendor-Specific.Yubico.Yubikey-OTP", .type = FR_TYPE_STRING, .dict = &dict_radius },
82  { NULL }
83 };
84 
85 static char const modhextab[] = "cbdefghijklnrtuv";
86 static char const hextab[] = "0123456789abcdef";
87 
88 #define is_modhex(x) (memchr(modhextab, tolower(x), 16))
89 
90 /** Convert yubikey modhex to normal hex
91  *
92  * The same buffer may be passed as modhex and hex to convert the modhex in place.
93  *
94  * Modhex and hex must be the same size.
95  *
96  * @param[in] modhex data.
97  * @param[in] len of input and output buffers.
98  * @param[out] hex where to write the standard hexits.
99  * @return
100  * - The number of bytes written to the output buffer.
101  * - -1 on failure.
102  */
103 static ssize_t modhex2hex(char const *modhex, char *hex, size_t len)
104 {
105  size_t i;
106  char *c1, *c2;
107 
108  for (i = 0; i < len; i += 2) {
109  if (modhex[i] == '\0') {
110  break;
111  }
112 
113  /*
114  * We only deal with whole bytes
115  */
116  if (modhex[i + 1] == '\0')
117  return -1;
118 
119  if (!(c1 = memchr(modhextab, tolower((uint8_t) modhex[i]), 16)) ||
120  !(c2 = memchr(modhextab, tolower((uint8_t) modhex[i + 1]), 16)))
121  return -1;
122 
123  hex[i] = hextab[c1 - modhextab];
124  hex[i + 1] = hextab[c2 - modhextab];
125  }
126 
127  return i;
128 }
129 
131  { .required = true, .concat = true, .type = FR_TYPE_STRING },
133 };
134 
135 /** Xlat to convert Yubikey modhex to standard hex
136  *
137  * Example:
138 @verbatim
139 %modhextohex('vvrbuctetdhc') == "ffc1e0d3d260"
140 @endverbatim
141  *
142  * @ingroup xlat_functions
143  */
145  UNUSED xlat_ctx_t const *xctx, request_t *request,
146  fr_value_box_list_t *in)
147 {
148  ssize_t len;
149  fr_value_box_t *arg = fr_value_box_list_pop_head(in);
150  char *p = UNCONST(char *, arg->vb_strvalue);
151 
152  /*
153  * mod2hex allows conversions in place
154  */
155  len = modhex2hex(p, p, arg->vb_length);
156  if (len <= 0) {
157  REDEBUG("Modhex string invalid");
158  talloc_free(arg);
159  return XLAT_ACTION_FAIL;
160  }
161 
162  fr_dcursor_append(out, arg);
163  return XLAT_ACTION_DONE;
164 }
165 
166 static int mod_load(void)
167 {
168  xlat_t *xlat;
169 
171  PERROR("%s", __FUNCTION__);
172  return -1;
173  }
174 
176  PERROR("%s", __FUNCTION__);
178  return -1;
179  }
180 
181  if (unlikely(!(xlat = xlat_func_register(NULL, "modhextohex", modhex_to_hex_xlat, FR_TYPE_STRING)))) return -1;
184 
185  return 0;
186 }
187 
188 static void mod_unload(void)
189 {
190  xlat_func_unregister("modhextohex");
192 }
193 
194 #ifndef HAVE_YUBIKEY
195 static int mod_bootstrap(module_inst_ctx_t const *mctx)
196 {
197  rlm_yubikey_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_yubikey_t);
198 
199  if (inst->decrypt) {
200  cf_log_err(mctx->inst->conf, "Requires libyubikey for OTP decryption");
201  return -1;
202  }
203  return 0;
204 }
205 #endif
206 
207 /*
208  * Do any per-module initialization that is separate to each
209  * configured instance of the module. e.g. set up connections
210  * to external databases, read configuration files, set up
211  * dictionary entries, etc.
212  *
213  * If configuration information is given in the config section
214  * that must be referenced in later calls, store a handle to it
215  * in *instance otherwise put a null pointer there.
216  */
217 static int mod_instantiate(module_inst_ctx_t const *mctx)
218 {
219  rlm_yubikey_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_yubikey_t);
220  CONF_SECTION *conf = mctx->inst->conf;
221 
222  inst->name = mctx->inst->name;
223 
224  inst->auth_type = fr_dict_enum_by_name(attr_auth_type, inst->name, -1);
225  if (!inst->auth_type) {
226  WARN("Failed to find 'authenticate %s {...}' section. Yubikey authentication will likely not work",
227  mctx->inst->name);
228  }
229 
230  if (inst->validate) {
231 #ifdef HAVE_YKCLIENT
232  CONF_SECTION *cs;
233 
234  cs = cf_section_find(conf, "validation", CF_IDENT_ANY);
235  if (!cs) {
236  cf_log_err(conf, "Missing validation section");
237  return -1;
238  }
239 
240  if (rlm_yubikey_ykclient_init(cs, inst) < 0) {
241  return -1;
242  }
243 #else
244  cf_log_err(conf, "Requires libykclient for OTP validation against Yubicloud servers");
245  return -1;
246 #endif
247  }
248 
249  return 0;
250 }
251 
252 #ifdef HAVE_YKCLIENT
253 static int mod_detach(module_detach_ctx_t const *mctx)
254 {
255  rlm_yubikey_ykclient_detach(talloc_get_type_abort(mctx->inst->data, rlm_yubikey_t));
256  return 0;
257 }
258 #endif
259 
260 static int CC_HINT(nonnull) otp_string_valid(rlm_yubikey_t const *inst, char const *otp, size_t len)
261 {
262  size_t i;
263 
264  for (i = inst->id_len; i < len; i++) {
265  if (!is_modhex(otp[i])) return -i;
266  }
267 
268  return 1;
269 }
270 
271 
272 /*
273  * Find the named user in this modules database. Create the set
274  * of attribute-value pairs to check and reply with for this user
275  * from the database. The authentication code only needs to check
276  * the password, the rest is done here.
277  */
278 static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
279 {
281  char const *passcode;
282  size_t len;
283  fr_pair_t *vp, *password;
284  char const *otp;
285  size_t password_len;
286  int ret;
287 
288  /*
289  * Can't do yubikey auth if there's no password.
290  */
291  password = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password);
292  if (!password) {
293  /*
294  * Don't print out debugging messages if we know
295  * they're useless.
296  */
297  if ((request->dict == dict_radius) && request->packet->code != FR_RADIUS_CODE_ACCESS_CHALLENGE) {
298  RDEBUG2("No cleartext password in the request. Can't do Yubikey authentication");
299  }
300 
302  }
303 
304  passcode = password->vp_strvalue;
305  len = password->vp_length;
306 
307  /*
308  * Now see if the passcode is the correct length (in its raw
309  * modhex encoded form).
310  *
311  * <public_id (6-16 bytes)> + <aes-block (32 bytes)>
312  *
313  */
314  if (len < (inst->id_len + YUBIKEY_TOKEN_LEN)) {
315  RDEBUG2("User-Password value is not the correct length, expected at least %u bytes, got %zu bytes",
316  inst->id_len + YUBIKEY_TOKEN_LEN, len);
318  }
319 
320  password_len = (len - (inst->id_len + YUBIKEY_TOKEN_LEN));
321  otp = passcode + password_len;
322  ret = otp_string_valid(inst, otp, (inst->id_len + YUBIKEY_TOKEN_LEN));
323  if (ret <= 0) {
324  if (RDEBUG_ENABLED3) {
325  RDMARKER(otp, -(ret), "User-Password (aes-block) value contains non modhex chars");
326  } else {
327  RDEBUG2("User-Password (aes-block) value contains non modhex chars");
328  }
330  }
331 
332  /* May be a concatenation, check the last 32 bytes are modhex */
333  if (inst->split) {
334  /*
335  * Insert a new request attribute just containing the OTP
336  * portion.
337  */
339  fr_pair_value_strdup(vp, otp, password->vp_tainted);
340 
341  /*
342  * Replace the existing string buffer for the password
343  * attribute with one just containing the password portion.
344  */
345  MEM(fr_pair_value_bstr_realloc(password, NULL, password_len) == 0);
346 
347  RDEBUG2("&request.%pP", vp);
348  RDEBUG2("&request.%pP", password);
349 
350  /*
351  * So the ID split code works on the non password portion.
352  */
353  passcode = vp->vp_strvalue;
354  }
355 
356  /*
357  * Split out the Public ID in case another module in authorize
358  * needs to verify it's associated with the user.
359  *
360  * It's left up to the user if they want to decode it or not.
361  */
362  if (inst->id_len) {
364  fr_pair_value_bstrndup(vp, passcode, inst->id_len, true);
365  RDEBUG2("&request.%pP", vp);
366  }
367 
368  if (!inst->auth_type) {
369  WARN("No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup Yubikey authentication",
370  mctx->inst->name, mctx->inst->name);
372  }
373 
375 
377 }
378 
379 
380 /*
381  * Authenticate the user with the given password.
382  */
383 static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
384 {
387  char const *passcode = NULL;
388  fr_pair_t const *vp;
389  size_t len;
390  int ret;
391 
392  vp = fr_pair_find_by_da_nested(&request->request_pairs, NULL, attr_yubikey_otp);
393  if (!vp) {
394  RDEBUG2("No Yubikey-OTP attribute found, falling back to User-Password");
395  /*
396  * Can't do yubikey auth if there's no password.
397  */
398  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_user_password);
399  if (!vp) {
400  REDEBUG("No User-Password in the request. Can't do Yubikey authentication");
402  }
403  }
404 
405  passcode = vp->vp_strvalue;
406  len = vp->vp_length;
407 
408  /*
409  * Verify the passcode is the correct length (in its raw
410  * modhex encoded form).
411  *
412  * <public_id (6-16 bytes)> + <aes-block (32 bytes)>
413  */
414  if (len != (inst->id_len + YUBIKEY_TOKEN_LEN)) {
415  REDEBUG("%s value is not the correct length, expected bytes %u, got bytes %zu",
416  vp->da->name, inst->id_len + YUBIKEY_TOKEN_LEN, len);
418  }
419 
420  ret = otp_string_valid(inst, passcode, (inst->id_len + YUBIKEY_TOKEN_LEN));
421  if (ret <= 0) {
422  if (RDEBUG_ENABLED3) {
423  REMARKER(passcode, -ret, "Passcode (aes-block) value contains non modhex chars");
424  } else {
425  RERROR("Passcode (aes-block) value contains non modhex chars");
426  }
428  }
429 
430 #ifdef HAVE_YUBIKEY
431  if (inst->decrypt) {
432 
433  rlm_yubikey_decrypt(&rcode, mctx, request, passcode);
434  if (rcode != RLM_MODULE_OK) RETURN_MODULE_RCODE(rcode);
435  /* Fall-Through to doing ykclient auth in addition to local auth */
436  }
437 #endif
438 
439 #ifdef HAVE_YKCLIENT
440  if (inst->validate) return rlm_yubikey_validate(p_result, mctx, request, passcode);
441 #endif
442  RETURN_MODULE_RCODE(rcode);
443 }
444 
445 /*
446  * The module name should be the only globally exported symbol.
447  * That is, everything else should be 'static'.
448  *
449  * If the module needs to temporarily modify it's instantiation
450  * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
451  * The server will then take care of ensuring that the module
452  * is single-threaded.
453  */
456  .common = {
457  .magic = MODULE_MAGIC_INIT,
458  .name = "yubikey",
459  .flags = MODULE_TYPE_THREAD_SAFE,
460  .inst_size = sizeof(rlm_yubikey_t),
461  .onload = mod_load,
462  .unload = mod_unload,
464 #ifndef HAVE_YUBIKEY
465  .bootstrap = mod_bootstrap,
466 #endif
468 #ifdef HAVE_YKCLIENT
469  .detach = mod_detach,
470 #endif
471  },
472  .method_names = (module_method_name_t[]){
473  { .name1 = "recv", .name2 = "access-request", .method = mod_authorize },
474  { .name1 = "authenticate", .name2 = CF_IDENT_ANY, .method = mod_authenticate },
476  }
477 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:444
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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:268
#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:310
#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:256
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition: cf_parse.h:410
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:400
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
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:970
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define CF_IDENT_ANY
Definition: cf_util.h:78
static int split(char **input, char **output, bool syntax_string)
Definition: command.c:385
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:405
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition: defs.h:43
#define fr_dict_autofree(_to_free)
Definition: dict.h:674
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
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:3647
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition: dict_util.c:2992
#define fr_dict_autoload(_to_load)
Definition: dict.h:671
static fr_slen_t in
Definition: dict.h:645
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
char const *_CONST name
Instance name.
Definition: dl_module.h:163
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
dl_module_inst_t const * inst
Definition: dl_module.h:87
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.
Definition: rlm_yubikey.c:144
#define PERROR(_fmt,...)
Definition: log.h:228
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition: log.h:335
#define RERROR(fmt,...)
Definition: log.h:298
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition: log.h:498
#define RDMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition: log.h:516
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
Specifies a module method identifier.
Definition: module_method.c:36
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:397
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
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:688
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition: pair.c:2631
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:2781
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:2752
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:765
static const conf_parser_t config[]
Definition: base.c:188
#define pair_update_request(_attr, _da)
Definition: radclient-ng.c:60
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define WARN(fmt,...)
Definition: radclient.h:47
static rs_t * conf
Definition: radsniff.c:53
#define RETURN_MODULE_NOOP
Definition: rcode.h:62
#define RETURN_MODULE_RCODE(_rcode)
Definition: rcode.h:64
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
static int mod_detach(module_detach_ctx_t const *mctx)
Cleanup a cache_rbtree instance.
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
static int mod_load(void)
Definition: rlm_yubikey.c:166
fr_dict_attr_t const * attr_user_password
Definition: rlm_yubikey.c:62
static xlat_arg_parser_t const modhex_to_hex_xlat_arg[]
Definition: rlm_yubikey.c:130
fr_dict_attr_t const * attr_yubikey_random
Definition: rlm_yubikey.c:68
fr_dict_attr_t const * attr_yubikey_counter
Definition: rlm_yubikey.c:66
static ssize_t modhex2hex(char const *modhex, char *hex, size_t len)
Convert yubikey modhex to normal hex.
Definition: rlm_yubikey.c:103
static char const modhextab[]
Definition: rlm_yubikey.c:85
#define is_modhex(x)
Definition: rlm_yubikey.c:88
static fr_dict_t const * dict_freeradius
Definition: rlm_yubikey.c:51
fr_dict_attr_t const * attr_yubikey_public_id
Definition: rlm_yubikey.c:64
module_rlm_t rlm_yubikey
Definition: rlm_yubikey.c:455
static fr_dict_t const * dict_radius
Definition: rlm_yubikey.c:52
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_yubikey.c:383
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: rlm_yubikey.c:195
fr_dict_attr_t const * attr_yubikey_key
Definition: rlm_yubikey.c:63
fr_dict_attr_t const * attr_auth_type
Definition: rlm_yubikey.c:61
fr_dict_attr_t const * attr_yubikey_timestamp
Definition: rlm_yubikey.c:67
fr_dict_attr_t const * attr_yubikey_otp
Definition: rlm_yubikey.c:69
static void mod_unload(void)
Definition: rlm_yubikey.c:188
fr_dict_attr_autoload_t rlm_yubikey_dict_attr[]
Definition: rlm_yubikey.c:72
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_yubikey.c:278
static char const hextab[]
Definition: rlm_yubikey.c:86
fr_dict_attr_t const * attr_yubikey_private_id
Definition: rlm_yubikey.c:65
static const conf_parser_t module_config[]
Definition: rlm_yubikey.c:40
fr_dict_autoload_t rlm_yubikey_dict[]
Definition: rlm_yubikey.c:55
static int otp_string_valid(rlm_yubikey_t const *inst, char const *otp, size_t len)
Definition: rlm_yubikey.c:260
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_yubikey.c:217
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)
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.
Definition: module.h:49
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
static char const hex[]
Definition: smbencrypt.c:35
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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:270
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition: xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984
An xlat calling ctx.
Definition: xlat_ctx.h:42
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:415
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:195
int xlat_func_mono_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the argument of an xlat.
Definition: xlat_func.c:392
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition: xlat_func.c:531
@ XLAT_FUNC_FLAG_PURE
Definition: xlat_func.h:38