27 RCSID(
"$Id: 0cb5c2bb861a2228022eb93616f3da40e4333c1f $")
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/modules.h>
31 #include <freeradius-devel/rad_assert.h>
55 #ifdef KRB5_IS_THREAD_SAFE
68 char keytab_name[200];
73 DEBUG(
"Using Heimdal Kerberos library");
75 DEBUG(
"Using MIT Kerberos library");
79 if (!krb5_is_thread_safe()) {
83 #ifdef KRB5_IS_THREAD_SAFE
84 ERROR(
"Build time libkrb5 was threadsafe, but run time library claims not to be");
85 ERROR(
"Modify runtime linker path (LD_LIBRARY_PATH on most systems), to prefer threadsafe libkrb5");
91 radlog(
L_WARN,
"libkrb5 is not threadsafe, recompile it with thread support enabled ("
93 "--enable-pthread-support"
95 "--disable-thread-support=no"
98 WARN(
"rlm_krb5 will run in single threaded mode, performance may be degraded");
100 WARN(
"Build time libkrb5 was not threadsafe, but run time library claims to be");
101 WARN(
"Reconfigure and recompile rlm_krb5 to enable thread support");
108 ret = krb5_init_context(&inst->
context);
110 ERROR(
"rlm_krb5 (%s): context initialisation failed: %s", inst->
xlat_name,
133 inst->
service = talloc_array(inst,
char, (len + 1));
139 if (inst->
hostname)
DEBUG(
"rlm_krb5 (%s): Ignoring hostname component of service principal \"%s\", not "
148 ERROR(
"rlm_krb5 (%s): Failed parsing service principal: %s", inst->
xlat_name,
154 ret = krb5_unparse_name(inst->
context, inst->
server, &princ_name);
157 ERROR(
"rlm_krb5 (%s): Failed constructing service principal string: %s", inst->
xlat_name,
166 DEBUG(
"rlm_krb5 (%s): Using service principal \"%s\"", inst->
xlat_name, princ_name);
167 krb5_free_unparsed_name(inst->
context, princ_name);
175 ERROR(
"rlm_krb5 (%s): Couldn't allocated inital credential options: %s", inst->
xlat_name,
186 krb5_kt_default(inst->
context, &keytab);
188 ERROR(
"rlm_krb5 (%s): Resolving keytab failed: %s", inst->
xlat_name,
194 ret = krb5_kt_get_name(inst->
context, keytab, keytab_name,
sizeof(keytab_name));
195 krb5_kt_close(inst->
context, keytab);
197 ERROR(
"rlm_krb5 (%s): Can't retrieve keytab name: %s", inst->
xlat_name,
203 DEBUG(
"rlm_krb5 (%s): Using keytab \"%s\"", inst->
xlat_name, keytab_name);
205 MEM(inst->
vic_options = talloc_zero(inst, krb5_verify_init_creds_opt));
206 krb5_verify_init_creds_opt_init(inst->
vic_options);
209 #ifdef KRB5_IS_THREAD_SAFE
214 if (!inst->pool)
return -1;
217 if (!inst->
conn)
return -1;
238 REDEBUG(
"Attribute \"User-Name\" is required for authentication");
248 REDEBUG(
"Attribute \"User-Password\" is required for authentication");
258 REDEBUG(
"Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".",
264 ret = krb5_parse_name(context, request->
username->vp_strvalue, client);
271 krb5_unparse_name(context, *client, &princ_name);
272 RDEBUG(
"Using client principal \"%s\"", princ_name);
276 krb5_free_unparsed_name(context, princ_name);
294 case KRB5_LIBOS_BADPWDMATCH:
295 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
299 case KRB5KDC_ERR_KEY_EXP:
300 case KRB5KDC_ERR_CLIENT_REVOKED:
301 case KRB5KDC_ERR_SERVICE_REVOKED:
305 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
328 krb5_principal client;
330 # ifdef KRB5_IS_THREAD_SAFE
340 memset(&client, 0,
sizeof(client));
348 ret = krb5_verify_user_opt(conn->context, client, request->password->vp_strvalue, &conn->options);
365 krb5_cc_cursor cursor;
368 krb5_cc_start_seq_get(conn->context, conn->ccache, &cursor);
369 for (ret = krb5_cc_next_cred(conn->context, conn->ccache, &cursor, &cred);
371 ret = krb5_cc_next_cred(conn->context, conn->ccache, &cursor, &cred)) {
372 krb5_cc_remove_cred(conn->context, conn->ccache, 0, &cred);
374 krb5_cc_end_seq_get(conn->context, conn->ccache, &cursor);
379 krb5_free_principal(conn->context, client);
382 # ifdef KRB5_IS_THREAD_SAFE
401 krb5_principal client;
402 krb5_creds init_creds;
407 # ifdef KRB5_IS_THREAD_SAFE
417 memset(&client, 0,
sizeof(client));
418 memset(&init_creds, 0,
sizeof(init_creds));
430 memcpy(&password, &request->password->vp_strvalue,
sizeof(password));
431 RDEBUG(
"Retrieving and decrypting TGT");
432 ret = krb5_get_init_creds_password(conn->context, &init_creds, client, password,
439 RDEBUG(
"Attempting to authenticate against service principal");
440 ret = krb5_verify_init_creds(conn->context, &init_creds, inst->
server, conn->keytab, NULL, inst->
vic_options);
444 if (client) krb5_free_principal(conn->context, client);
445 krb5_free_cred_contents(conn->context, &init_creds);
447 # ifdef KRB5_IS_THREAD_SAFE
460 #ifdef KRB5_IS_THREAD_SAFE
465 .config = module_config,
The module is OK, continue.
Instance configuration for rlm_krb5.
Metadata exported by the module.
int radlog(log_type_t lvl, char const *fmt,...) CC_HINT(format(printf
krb5_context context
The kerberos context (cloned once per request).
#define RLM_TYPE_THREAD_SAFE
Module is threadsafe.
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
krb5_get_init_creds_opt * gic_options
Options to pass to the get_initial_credentials function.
#define CONF_PARSER_TERMINATOR
VALUE_PAIR * password
Cached password VALUE_PAIR from request RADIUS_PACKET.
static int mod_instantiate(CONF_SECTION *conf, void *instance)
struct rlm_krb5_t rlm_krb5_t
Instance configuration for rlm_krb5.
The module considers the request invalid.
#define RLM_TYPE_HUP_SAFE
Will be restarted on HUP.
#define rlm_krb5_error(_x, _y)
static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) CC_HINT(nonnull)
Defines a CONF_PAIR to C data type mapping.
Reject the request (user is locked out).
char const * keytabname
The keytab to resolve the service in.
static rlm_rcode_t krb5_parse_user(krb5_principal *client, REQUEST *request, krb5_context context)
Common function for transforming a User-Name string into a principal.
fr_connection_pool_t * module_connection_pool_init(CONF_SECTION *module, void *opaque, fr_connection_create_t c, fr_connection_alive_t a, char const *prefix)
Initialise a module specific connection pool.
static void * mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *timeout)
Create a new memcached handle.
static const CONF_PARSER module_config[]
unsigned int attr
Attribute number.
Immediately reject the request.
0 methods index for authenticate section.
char * hostname
The hostname component of service_princ, or NULL.
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
char const * cf_section_name1(CONF_SECTION const *cs)
char * service
The service component of service_princ, or NULL.
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)
static int mod_detach(void *instance)
char const * xlat_name
This module's instance name.
void * fr_connection_get(fr_connection_pool_t *pool)
Reserve a connection in the connection pool.
krb5_principal server
A structure representing the parsed service_princ.
Context management functions for rlm_krb5.
char const * service_princ
The service name provided by the config parser.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
void fr_connection_release(fr_connection_pool_t *pool, void *conn)
Release a connection.
String of printable characters.
krb5_verify_init_creds_opt * vic_options
Options to pass to the validate_initial_creds function.
USES_APPLE_DEPRECATED_API struct rlm_krb5_handle rlm_krb5_handle_t
static rlm_rcode_t krb5_process_error(REQUEST *request, rlm_krb5_handle_t *conn, int ret)
Log error message and return appropriate rcode.
char const * cf_section_name2(CONF_SECTION const *cs)
static rlm_rcode_t CC_HINT(nonnull)
void fr_connection_pool_free(fr_connection_pool_t *pool)
Delete a connection pool.