The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
validate.c
Go to the documentation of this file.
1/**
2 * $Id: 0f5825c50d0720b5db701248432c80023b3fea32 $
3 * @file rlm_yubikey/validate.c
4 * @brief Authentication for yubikey OTP tokens using the ykclient library.
5 *
6 * @author Arran Cudbard-Bell (a.cudbardb@networkradius.com)
7 * @copyright 2013 The FreeRADIUS server project
8 * @copyright 2013 Network RADIUS (legal@networkradius.com)
9 */
10#define LOG_PREFIX inst->name
11
12#include "rlm_yubikey.h"
13
14#ifdef HAVE_YKCLIENT
15#include <freeradius-devel/server/pool.h>
16
17/** Frees a ykclient handle
18 *
19 * @param[in] yandle rlm_yubikey_handle_t to close and free.
20 * @return returns 0.
21 */
22static int _mod_conn_free(ykclient_handle_t **yandle)
23{
24 ykclient_handle_done(yandle);
25
26 return 0;
27}
28
29/** Creates a new connection handle for use by the FR connection API.
30 *
31 * Matches the fr_pool_connection_create_t function prototype, is passed to
32 * fr_pool_init, and called when a new connection is required by the
33 * connection pool API.
34 *
35 * @see fr_pool_init
36 * @see fr_pool_connection_create_t
37 * @see connection.c
38 */
39static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, UNUSED fr_time_delta_t timeout)
40{
42 ykclient_rc status;
43 ykclient_handle_t *yandle, **marker;
44
45 status = ykclient_handle_init(inst->ykc, &yandle);
46 if (status != YKCLIENT_OK) {
47 ERROR("%s", ykclient_strerror(status));
48
49 return NULL;
50 }
51 marker = talloc(ctx, ykclient_handle_t *);
52 talloc_set_destructor(marker, _mod_conn_free);
53 *marker = yandle;
54
55 return yandle;
56}
57
59{
60 ykclient_rc status;
61 CONF_SECTION *servers;
62
63 int count = 0;
64
65 if (!inst->client_id) {
66 ERROR("validation.client_id must be set (to a valid id) when validation is enabled");
67
68 return -1;
69 }
70
71 if (!inst->api_key || !*inst->api_key || is_zero(inst->api_key)) {
72 ERROR("validation.api_key must be set (to a valid key) when validation is enabled");
73
74 return -1;
75 }
76
77 DEBUG("Initialising ykclient");
78
79 status = ykclient_global_init();
80 if (status != YKCLIENT_OK) {
81yk_error:
82 ERROR("%s", ykclient_strerror(status));
83
84 return -1;
85 }
86
87 status = ykclient_init(&inst->ykc);
88 if (status != YKCLIENT_OK) goto yk_error;
89
90 servers = cf_section_find(conf, "servers", CF_IDENT_ANY);
91 if (servers) {
92 CONF_PAIR *uri, *first;
93 /*
94 * If there were no uris configured we just use the default
95 * ykclient uris which point to the yubico servers.
96 */
97 first = uri = cf_pair_find(servers, "uri");
98 if (!uri) {
99 goto init;
100 }
101
102 while (uri) {
103 count++;
104 uri = cf_pair_find_next(servers, uri, "uri");
105 }
106 inst->uris = talloc_zero_array(inst, char const *, count);
107
108 uri = first;
109 count = 0;
110 while (uri) {
111 inst->uris[count++] = cf_pair_value(uri);
112 uri = cf_pair_find_next(servers, uri, "uri");
113 }
114 if (count) {
115 status = ykclient_set_url_templates(inst->ykc, count, inst->uris);
116 if (status != YKCLIENT_OK) {
117 goto yk_error;
118 }
119 }
120 }
121
122init:
123 status = ykclient_set_client_b64(inst->ykc, inst->client_id, inst->api_key);
124 if (status != YKCLIENT_OK) {
125 ERROR("%s", ykclient_strerror(status));
126
127 return -1;
128 }
129
130 inst->pool = module_rlm_connection_pool_init(conf, inst, mod_conn_create, NULL, inst->name, NULL, NULL);
131 if (!inst->pool) {
132 ykclient_done(&inst->ykc);
133
134 return -1;
135 }
136
137 return 0;
138}
139
141{
142 fr_pool_free(inst->pool);
143 ykclient_done(&inst->ykc);
144 ykclient_global_done();
145
146 return 0;
147}
148
150 request_t *request, char const *passcode)
151{
152 rlm_yubikey_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_yubikey_t);
154 ykclient_rc status;
155 ykclient_handle_t *yandle;
156
157 yandle = fr_pool_connection_get(inst->pool, request);
158 if (!yandle) RETURN_MODULE_FAIL;
159
160 /*
161 * The libcurl multi-handle interface will tear down the TCP sockets for any partially completed
162 * requests when their easy handle is removed from the multistack.
163 *
164 * For performance reasons ykclient will stop processing the request immediately after receiving
165 * a response from one of the servers. If we then immediately call ykclient_handle_cleanup
166 * the connections are destroyed and will need to be re-established the next time the handle
167 * is used.
168 *
169 * To try and prevent this from happening, we leave cleanup until the *next* time
170 * the handle is used, by which time the requests will of hopefully completed and the connections
171 * can be re-used.
172 *
173 */
174 ykclient_handle_cleanup(yandle);
175
176 status = ykclient_request_process(inst->ykc, yandle, passcode);
177 if (status != YKCLIENT_OK) {
178 REDEBUG("%s", ykclient_strerror(status));
179 switch (status) {
180 case YKCLIENT_BAD_OTP:
181 case YKCLIENT_REPLAYED_OTP:
182 rcode = RLM_MODULE_REJECT;
183 break;
184
185 case YKCLIENT_NO_SUCH_CLIENT:
186 rcode = RLM_MODULE_NOTFOUND;
187 break;
188
189 default:
190 rcode = RLM_MODULE_FAIL;
191 }
192 }
193
194 fr_pool_connection_release(inst->pool, request, yandle);
195
196 RETURN_MODULE_RCODE(rcode);
197}
198#endif
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
static bool init
Definition fuzzer.c:41
#define UNUSED
Definition build.h:315
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
Definition cf_util.c:1453
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:1028
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1439
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
#define CF_IDENT_ANY
Definition cf_util.h:78
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
static bool is_zero(char const *value)
Check whether the string is all zeros.
Definition misc.h:146
void * mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
Create a new connection pool handle.
Definition mod.c:154
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
fr_pool_t * module_rlm_connection_pool_init(CONF_SECTION *module, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific connection pool.
Definition module_rlm.c:308
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
Definition pool.c:1407
void fr_pool_free(fr_pool_t *pool)
Delete a connection pool.
Definition pool.c:1329
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
Definition pool.c:1392
#define REDEBUG(fmt,...)
Definition radclient.h:52
static rs_t * conf
Definition radsniff.c:53
#define RETURN_MODULE_RCODE(_rcode)
Definition rcode.h:64
#define RETURN_MODULE_FAIL
Definition rcode.h:56
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_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:47
static int _mod_conn_free(rlm_cache_memcached_handle_t *mandle)
Free a connection handle.
int rlm_yubikey_ykclient_init(CONF_SECTION *conf, rlm_yubikey_t *inst)
int rlm_yubikey_ykclient_detach(rlm_yubikey_t *inst)
unlang_action_t rlm_yubikey_validate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, char const *passcode)
void * data
Module's instance data.
Definition module.h:271
return count
Definition module.c:163
eap_aka_sim_process_conf_t * inst
#define talloc_get_type_abort_const
Definition talloc.h:282
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80