1 #include "utils/includes.h"
2 #include "utils/common.h"
3 #include "utils/eloop.h"
4 #include "crypto/crypto.h"
5 #include "crypto/tls.h"
7 #include "ap/ap_config.h"
8 #include "eap_server/eap.h"
9 #include "radius/radius.h"
10 #include "radius/radius_server.h"
11 #include "eap_register.h"
13 #include <libubox/blobmsg_json.h>
14 #include <libubox/blobmsg.h>
15 #include <libubox/avl.h>
16 #include <libubox/avl-cmp.h>
17 #include <libubox/kvlist.h>
22 #define VENDOR_ID_WISPR 14122
23 #define VENDOR_ATTR_SIZE 6
25 struct radius_parse_attr_data
{
33 struct radius_parse_attr_state
{
34 struct hostapd_radius_attr
*prev
;
35 struct hostapd_radius_attr
*attr
;
40 struct radius_user_state
{
45 struct radius_user_data
{
47 struct avl_tree user_state
;
48 struct blob_attr
*wildcard
;
52 struct radius_server_data
*radius
;
53 struct eap_config eap
;
55 struct radius_user_data phase1
, phase2
;
56 const char *user_file
;
60 struct hostapd_radius_attr
*attrs
;
63 struct radius_config
{
64 struct tls_connection_params tls
;
65 struct radius_server_conf radius
;
75 USER_ATTR_MAX_RATE_UP
,
76 USER_ATTR_MAX_RATE_DOWN
,
80 static void radius_tls_event(void *ctx
, enum tls_event ev
,
81 union tls_event_data
*data
)
84 case TLS_CERT_CHAIN_SUCCESS
:
85 wpa_printf(MSG_DEBUG
, "radius: remote certificate verification success");
87 case TLS_CERT_CHAIN_FAILURE
:
88 wpa_printf(MSG_INFO
, "radius: certificate chain failure: reason=%d depth=%d subject='%s' err='%s'",
89 data
->cert_fail
.reason
,
90 data
->cert_fail
.depth
,
91 data
->cert_fail
.subject
,
92 data
->cert_fail
.reason_txt
);
94 case TLS_PEER_CERTIFICATE
:
95 wpa_printf(MSG_DEBUG
, "radius: peer certificate: depth=%d serial_num=%s subject=%s",
96 data
->peer_cert
.depth
,
97 data
->peer_cert
.serial_num
? data
->peer_cert
.serial_num
: "N/A",
98 data
->peer_cert
.subject
);
101 if (data
->alert
.is_local
)
102 wpa_printf(MSG_DEBUG
, "radius: local TLS alert: %s",
103 data
->alert
.description
);
105 wpa_printf(MSG_DEBUG
, "radius: remote TLS alert: %s",
106 data
->alert
.description
);
108 case TLS_UNSAFE_RENEGOTIATION_DISABLED
:
109 /* Not applicable to TLS server */
114 static void radius_userdata_init(struct radius_user_data
*u
)
116 kvlist_init(&u
->users
, kvlist_blob_len
);
117 avl_init(&u
->user_state
, avl_strcmp
, false, NULL
);
120 static void radius_userdata_free(struct radius_user_data
*u
)
122 struct radius_user_state
*s
, *tmp
;
124 kvlist_free(&u
->users
);
127 avl_remove_all_elements(&u
->user_state
, s
, node
, tmp
)
132 radius_userdata_load(struct radius_user_data
*u
, struct blob_attr
*data
)
139 static const struct blobmsg_policy policy
[__USERSTATE_MAX
] = {
140 [USERSTATE_USERS
] = { "users", BLOBMSG_TYPE_TABLE
},
141 [USERSTATE_WILDCARD
] = { "wildcard", BLOBMSG_TYPE_ARRAY
},
143 struct blob_attr
*tb
[__USERSTATE_MAX
], *cur
;
149 blobmsg_parse(policy
, __USERSTATE_MAX
, tb
, blobmsg_data(data
), blobmsg_len(data
));
151 blobmsg_for_each_attr(cur
, tb
[USERSTATE_USERS
], rem
)
152 kvlist_set(&u
->users
, blobmsg_name(cur
), cur
);
154 if (tb
[USERSTATE_WILDCARD
])
155 u
->wildcard
= blob_memdup(tb
[USERSTATE_WILDCARD
]);
159 load_userfile(struct radius_state
*s
)
166 static const struct blobmsg_policy policy
[__USERDATA_MAX
] = {
167 [USERDATA_PHASE1
] = { "phase1", BLOBMSG_TYPE_TABLE
},
168 [USERDATA_PHASE2
] = { "phase2", BLOBMSG_TYPE_TABLE
},
170 struct blob_attr
*tb
[__USERDATA_MAX
], *cur
;
171 static struct blob_buf b
;
175 if (stat(s
->user_file
, &st
))
178 if (s
->user_file_ts
== st
.st_mtime
)
181 s
->user_file_ts
= st
.st_mtime
;
182 radius_userdata_free(&s
->phase1
);
183 radius_userdata_free(&s
->phase2
);
185 blob_buf_init(&b
, 0);
186 blobmsg_add_json_from_file(&b
, s
->user_file
);
187 blobmsg_parse(policy
, __USERDATA_MAX
, tb
, blob_data(b
.head
), blob_len(b
.head
));
188 radius_userdata_load(&s
->phase1
, tb
[USERDATA_PHASE1
]);
189 radius_userdata_load(&s
->phase2
, tb
[USERDATA_PHASE2
]);
194 static struct blob_attr
*
195 radius_user_get(struct radius_user_data
*s
, const char *name
)
197 struct blob_attr
*cur
;
200 cur
= kvlist_get(&s
->users
, name
);
204 blobmsg_for_each_attr(cur
, s
->wildcard
, rem
) {
205 static const struct blobmsg_policy policy
= {
206 "name", BLOBMSG_TYPE_STRING
208 struct blob_attr
*pattern
;
210 if (blobmsg_type(cur
) != BLOBMSG_TYPE_TABLE
)
213 blobmsg_parse(&policy
, 1, &pattern
, blobmsg_data(cur
), blobmsg_len(cur
));
217 if (!fnmatch(blobmsg_get_string(pattern
), name
, 0))
224 static struct radius_parse_attr_data
*
225 radius_parse_attr(struct blob_attr
*attr
)
227 static const struct blobmsg_policy policy
[4] = {
228 { .type
= BLOBMSG_TYPE_INT32
},
229 { .type
= BLOBMSG_TYPE_INT32
},
230 { .type
= BLOBMSG_TYPE_STRING
},
231 { .type
= BLOBMSG_TYPE_STRING
},
233 static struct radius_parse_attr_data data
;
234 struct blob_attr
*tb
[4];
237 blobmsg_parse_array(policy
, ARRAY_SIZE(policy
), tb
, blobmsg_data(attr
), blobmsg_len(attr
));
239 if (!tb
[0] || !tb
[1] || !tb
[2] || !tb
[3])
242 format
= blobmsg_get_string(tb
[2]);
243 if (strlen(format
) != 1)
246 data
.vendor
= blobmsg_get_u32(tb
[0]);
247 data
.type
= blobmsg_get_u32(tb
[1]);
248 data
.format
= format
[0];
249 data
.data
= blobmsg_get_string(tb
[3]);
250 data
.size
= strlen(data
.data
);
252 switch (data
.format
) {
271 radius_count_attrs(struct blob_attr
**tb
, int *n_attr
, size_t *attr_size
)
273 struct blob_attr
*data
= tb
[USER_ATTR_RADIUS
];
274 struct blob_attr
*cur
;
277 blobmsg_for_each_attr(cur
, data
, rem
) {
278 struct radius_parse_attr_data
*data
;
279 size_t prev
= *attr_size
;
281 data
= radius_parse_attr(cur
);
285 *attr_size
+= data
->size
;
287 *attr_size
+= VENDOR_ATTR_SIZE
;
292 *n_attr
+= !!tb
[USER_ATTR_VLAN
] * 3 +
293 !!tb
[USER_ATTR_MAX_RATE_UP
] +
294 !!tb
[USER_ATTR_MAX_RATE_DOWN
];
295 *attr_size
+= !!tb
[USER_ATTR_VLAN
] * (4 + 4 + 5) +
296 !!tb
[USER_ATTR_MAX_RATE_UP
] * (4 + VENDOR_ATTR_SIZE
) +
297 !!tb
[USER_ATTR_MAX_RATE_DOWN
] * (4 + VENDOR_ATTR_SIZE
);
301 radius_add_attr(struct radius_parse_attr_state
*state
,
302 u32 vendor
, u8 type
, u8 len
)
304 struct hostapd_radius_attr
*attr
;
308 val
= state
->attrdata
;
313 attr
= state
->attr
++;
318 state
->prev
->next
= attr
;
322 u8
*vendor_hdr
= val
+ 4;
324 WPA_PUT_BE32(val
, vendor
);
325 vendor_hdr
[0] = type
;
326 vendor_hdr
[1] = len
+ 2;
328 len
+= VENDOR_ATTR_SIZE
;
329 val
+= VENDOR_ATTR_SIZE
;
330 attr
->type
= RADIUS_ATTR_VENDOR_SPECIFIC
;
333 buf
->size
= buf
->used
= len
;
334 state
->attrdata
+= len
;
340 radius_parse_attrs(struct blob_attr
**tb
, struct radius_parse_attr_state
*state
)
342 struct blob_attr
*data
= tb
[USER_ATTR_RADIUS
];
343 struct hostapd_radius_attr
*prev
= NULL
;
344 struct blob_attr
*cur
;
348 if ((cur
= tb
[USER_ATTR_VLAN
]) != NULL
&& blobmsg_get_u32(cur
) < 4096) {
351 val
= radius_add_attr(state
, 0, RADIUS_ATTR_TUNNEL_TYPE
, 4);
352 WPA_PUT_BE32(val
, RADIUS_TUNNEL_TYPE_VLAN
);
354 val
= radius_add_attr(state
, 0, RADIUS_ATTR_TUNNEL_MEDIUM_TYPE
, 4);
355 WPA_PUT_BE32(val
, RADIUS_TUNNEL_MEDIUM_TYPE_802
);
357 len
= snprintf(buf
, sizeof(buf
), "%d", blobmsg_get_u32(cur
));
358 val
= radius_add_attr(state
, 0, RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID
, len
);
359 memcpy(val
, buf
, len
);
362 if ((cur
= tb
[USER_ATTR_MAX_RATE_UP
]) != NULL
) {
363 val
= radius_add_attr(state
, VENDOR_ID_WISPR
, 7, 4);
364 WPA_PUT_BE32(val
, blobmsg_get_u32(cur
));
367 if ((cur
= tb
[USER_ATTR_MAX_RATE_DOWN
]) != NULL
) {
368 val
= radius_add_attr(state
, VENDOR_ID_WISPR
, 8, 4);
369 WPA_PUT_BE32(val
, blobmsg_get_u32(cur
));
372 blobmsg_for_each_attr(cur
, data
, rem
) {
373 struct radius_parse_attr_data
*data
;
377 data
= radius_parse_attr(cur
);
381 val
= radius_add_attr(state
, data
->vendor
, data
->type
, data
->size
);
382 switch (data
->format
) {
384 memcpy(val
, data
->data
, data
->size
);
387 hexstr2bin(data
->data
, val
, data
->size
);
390 WPA_PUT_BE32(val
, atoi(data
->data
));
397 radius_user_parse_methods(struct eap_user
*eap
, struct blob_attr
*data
)
399 struct blob_attr
*cur
;
405 blobmsg_for_each_attr(cur
, data
, rem
) {
408 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
411 if (n
== EAP_MAX_METHODS
)
414 method
= blobmsg_get_string(cur
);
415 eap
->methods
[n
].method
= eap_server_get_type(method
, &eap
->methods
[n
].vendor
);
416 if (eap
->methods
[n
].vendor
== EAP_VENDOR_IETF
&&
417 eap
->methods
[n
].method
== EAP_TYPE_NONE
) {
418 if (!strcmp(method
, "TTLS-PAP")) {
419 eap
->ttls_auth
|= EAP_TTLS_AUTH_PAP
;
422 if (!strcmp(method
, "TTLS-CHAP")) {
423 eap
->ttls_auth
|= EAP_TTLS_AUTH_CHAP
;
426 if (!strcmp(method
, "TTLS-MSCHAP")) {
427 eap
->ttls_auth
|= EAP_TTLS_AUTH_MSCHAP
;
430 if (!strcmp(method
, "TTLS-MSCHAPV2")) {
431 eap
->ttls_auth
|= EAP_TTLS_AUTH_MSCHAPV2
;
439 static struct eap_user
*
440 radius_user_get_state(struct radius_user_data
*u
, struct blob_attr
*data
,
443 static const struct blobmsg_policy policy
[__USER_ATTR_MAX
] = {
444 [USER_ATTR_PASSWORD
] = { "password", BLOBMSG_TYPE_STRING
},
445 [USER_ATTR_HASH
] = { "hash", BLOBMSG_TYPE_STRING
},
446 [USER_ATTR_SALT
] = { "salt", BLOBMSG_TYPE_STRING
},
447 [USER_ATTR_METHODS
] = { "methods", BLOBMSG_TYPE_ARRAY
},
448 [USER_ATTR_RADIUS
] = { "radius", BLOBMSG_TYPE_ARRAY
},
449 [USER_ATTR_VLAN
] = { "vlan-id", BLOBMSG_TYPE_INT32
},
450 [USER_ATTR_MAX_RATE_UP
] = { "max-rate-up", BLOBMSG_TYPE_INT32
},
451 [USER_ATTR_MAX_RATE_DOWN
] = { "max-rate-down", BLOBMSG_TYPE_INT32
},
453 struct blob_attr
*tb
[__USER_ATTR_MAX
], *cur
;
454 char *password_buf
, *salt_buf
, *name_buf
;
455 struct radius_parse_attr_state astate
= {};
456 struct hostapd_radius_attr
*attr
;
457 struct radius_user_state
*state
;
458 int pw_len
= 0, salt_len
= 0;
459 struct eap_user
*eap
;
465 state
= avl_find_element(&u
->user_state
, id
, state
, node
);
469 blobmsg_parse(policy
, __USER_ATTR_MAX
, tb
, blobmsg_data(data
), blobmsg_len(data
));
471 if ((cur
= tb
[USER_ATTR_SALT
]) != NULL
)
472 salt_len
= strlen(blobmsg_get_string(cur
)) / 2;
473 if ((cur
= tb
[USER_ATTR_HASH
]) != NULL
)
474 pw_len
= strlen(blobmsg_get_string(cur
)) / 2;
475 else if ((cur
= tb
[USER_ATTR_PASSWORD
]) != NULL
)
476 pw_len
= blobmsg_len(cur
) - 1;
477 radius_count_attrs(tb
, &n_attr
, &attrsize
);
479 state
= calloc_a(sizeof(*state
), &name_buf
, strlen(id
) + 1,
480 &password_buf
, pw_len
,
482 &astate
.attr
, n_attr
* sizeof(*astate
.attr
),
483 &astate
.buf
, n_attr
* sizeof(*astate
.buf
),
484 &astate
.attrdata
, attrsize
);
486 eap
->salt
= salt_len
? salt_buf
: NULL
;
487 eap
->salt_len
= salt_len
;
488 eap
->password
= pw_len
? password_buf
: NULL
;
489 eap
->password_len
= pw_len
;
490 eap
->force_version
= -1;
492 if ((cur
= tb
[USER_ATTR_SALT
]) != NULL
)
493 hexstr2bin(blobmsg_get_string(cur
), salt_buf
, salt_len
);
494 if ((cur
= tb
[USER_ATTR_PASSWORD
]) != NULL
)
495 memcpy(password_buf
, blobmsg_get_string(cur
), pw_len
);
496 else if ((cur
= tb
[USER_ATTR_HASH
]) != NULL
) {
497 hexstr2bin(blobmsg_get_string(cur
), password_buf
, pw_len
);
498 eap
->password_hash
= 1;
500 radius_user_parse_methods(eap
, tb
[USER_ATTR_METHODS
]);
503 cur
= tb
[USER_ATTR_RADIUS
];
504 eap
->accept_attr
= astate
.attr
;
505 radius_parse_attrs(tb
, &astate
);
508 state
->node
.key
= strcpy(name_buf
, id
);
509 avl_insert(&u
->user_state
, &state
->node
);
518 static int radius_get_eap_user(void *ctx
, const u8
*identity
,
519 size_t identity_len
, int phase2
,
520 struct eap_user
*user
)
522 struct radius_state
*s
= ctx
;
523 struct radius_user_data
*u
= phase2
? &s
->phase2
: &s
->phase1
;
524 struct blob_attr
*entry
;
525 struct eap_user
*data
;
528 if (identity_len
> 512)
533 id
= alloca(identity_len
+ 1);
534 memcpy(id
, identity
, identity_len
);
535 id
[identity_len
] = 0;
537 entry
= radius_user_get(u
, id
);
544 data
= radius_user_get_state(u
, entry
, id
);
549 if (user
->password_len
> 0)
550 user
->password
= os_memdup(user
->password
, user
->password_len
);
551 if (user
->salt_len
> 0)
552 user
->salt
= os_memdup(user
->salt
, user
->salt_len
);
553 user
->phase2
= phase2
;
558 static int radius_setup(struct radius_state
*s
, struct radius_config
*c
)
560 struct eap_config
*eap
= &s
->eap
;
561 struct tls_config conf
= {
562 .event_cb
= radius_tls_event
,
563 .tls_flags
= TLS_CONN_DISABLE_TLSv1_3
,
568 eap
->max_auth_rounds
= 100;
569 eap
->max_auth_rounds_short
= 50;
570 eap
->ssl_ctx
= tls_init(&conf
);
572 wpa_printf(MSG_INFO
, "TLS init failed\n");
576 if (tls_global_set_params(eap
->ssl_ctx
, &c
->tls
)) {
577 wpa_printf(MSG_INFO
, "failed to set TLS parameters\n");
581 c
->radius
.eap_cfg
= eap
;
582 c
->radius
.conf_ctx
= s
;
583 c
->radius
.get_eap_user
= radius_get_eap_user
;
584 s
->radius
= radius_server_init(&c
->radius
);
586 wpa_printf(MSG_INFO
, "failed to initialize radius server\n");
593 static int radius_init(struct radius_state
*s
)
595 memset(s
, 0, sizeof(*s
));
596 radius_userdata_init(&s
->phase1
);
597 radius_userdata_init(&s
->phase2
);
600 static void radius_deinit(struct radius_state
*s
)
603 radius_server_deinit(s
->radius
);
606 tls_deinit(s
->eap
.ssl_ctx
);
608 radius_userdata_free(&s
->phase1
);
609 radius_userdata_free(&s
->phase2
);
612 static int usage(const char *progname
)
614 fprintf(stderr
, "Usage: %s <options>\n",
618 int radius_main(int argc
, char **argv
)
620 static struct radius_state state
= {};
621 static struct radius_config config
= {};
622 const char *progname
= argv
[0];
626 wpa_debug_setup_stdout();
630 wpa_printf(MSG_ERROR
, "Failed to initialize event loop");
634 eap_server_register_methods();
637 while ((ch
= getopt(argc
, argv
, "6C:c:d:i:k:K:p:P:s:u:")) != -1) {
640 config
.radius
.ipv6
= 1;
643 config
.tls
.ca_cert
= optarg
;
646 if (config
.tls
.client_cert2
)
647 return usage(progname
);
649 if (config
.tls
.client_cert
)
650 config
.tls
.client_cert2
= optarg
;
652 config
.tls
.client_cert
= optarg
;
655 config
.tls
.dh_file
= optarg
;
658 state
.eap
.server_id
= optarg
;
659 state
.eap
.server_id_len
= strlen(optarg
);
662 if (config
.tls
.private_key2
)
663 return usage(progname
);
665 if (config
.tls
.private_key
)
666 config
.tls
.private_key2
= optarg
;
668 config
.tls
.private_key
= optarg
;
671 if (config
.tls
.private_key_passwd2
)
672 return usage(progname
);
674 if (config
.tls
.private_key_passwd
)
675 config
.tls
.private_key_passwd2
= optarg
;
677 config
.tls
.private_key_passwd
= optarg
;
680 config
.radius
.auth_port
= atoi(optarg
);
683 config
.radius
.acct_port
= atoi(optarg
);
686 config
.radius
.client_file
= optarg
;
689 state
.user_file
= optarg
;
692 return usage(progname
);
696 if (!config
.tls
.client_cert
|| !config
.tls
.private_key
||
697 !config
.radius
.client_file
|| !state
.eap
.server_id
||
699 wpa_printf(MSG_INFO
, "missing options\n");
703 ret
= radius_setup(&state
, &config
);
707 load_userfile(&state
);
711 radius_deinit(&state
);