* @copyright 2000 Nathan Neulinger <nneul@umr.edu>
* @copyright 2000 Alan DeKok <aland@ox.org>
*/
-#include <freeradius-devel/ident.h>
RCSID("$Id$")
-#include <freeradius-devel/radiusd.h>
-#include <freeradius-devel/modules.h>
-#include <freeradius-devel/rad_assert.h>
-
-/* krb5 includes */
-#include <krb5.h>
-#include <com_err.h>
-
-#define SERVICE_NAME_LEN 64 //!< Maximum length of a service name.
-
-/** Instance configuration for rlm_krb5
- *
- * Holds the configuration and preparsed data for a instance of rlm_krb5.
- */
-typedef struct rlm_krb5_t {
- const char *xlat_name; //!< This module's instance name.
- const char *keytabname; //!< The keytab to resolve the service in.
- const char *service_princ; //!< The service name provided by the
- //!< config parser.
-
- char *hostname; //!< The hostname component of
- //!< service_princ, or NULL.
- char *service; //!< The service component of
- //!< service_princ, or NULL.
-
- krb5_context context; //!< The kerberos context (cloned once per
- //!< request).
-
-#ifndef HEIMDAL_KRB5
- krb5_get_init_creds_opt *gic_options; //!< Options to pass to the
- //!< get_initial_credentials.
- //!< function.
- krb5_verify_init_creds_opt *vic_options; //!< Options to pass to the
- //!< validate_initial_creds
- //!< function.
-
- krb5_principal server; //!< A structure representing the parsed
- //!< service_princ.
-#endif
-
-} rlm_krb5_t;
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+#include "krb5.h"
static const CONF_PARSER module_config[] = {
- { "keytab", PW_TYPE_STRING_PTR,
- offsetof(rlm_krb5_t,keytabname), NULL, NULL },
- { "service_principal", PW_TYPE_STRING_PTR,
- offsetof(rlm_krb5_t,service_princ), NULL, NULL },
+ { "keytab", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_krb5_t, keytabname), NULL },
+ { "service_principal", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_krb5_t, service_princ), NULL },
{ NULL, -1, 0, NULL, NULL }
};
-static int krb5_detach(void *instance)
+static int mod_detach(void *instance)
{
rlm_krb5_t *inst = instance;
-
+
#ifndef HEIMDAL_KRB5
talloc_free(inst->vic_options);
if (inst->gic_options) {
krb5_get_init_creds_opt_free(inst->context, inst->gic_options);
}
+
+ if (inst->server) {
+ krb5_free_principal(inst->context, inst->server);
+ }
#endif
/* Don't free hostname, it's just a pointer into service_princ */
talloc_free(inst->service);
-
+
if (inst->context) {
krb5_free_context(inst->context);
}
+#ifdef KRB5_IS_THREAD_SAFE
+ fr_connection_pool_delete(inst->pool);
+#endif
return 0;
}
-static int krb5_instantiate(CONF_SECTION *conf, void **instance)
+static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
- rlm_krb5_t *inst;
+ rlm_krb5_t *inst = instance;
krb5_error_code ret;
-
+#ifndef HEIMDAL_KRB5
+ krb5_keytab keytab;
+ char keytab_name[200];
char *princ_name;
+#endif
- *instance = inst = talloc_zero(conf, rlm_krb5_t);
- if (cf_section_parse(conf, inst, module_config) < 0) {
- return -1;
- }
-
-
#ifdef HEIMDAL_KRB5
- radlog(L_INFO, "rlm_krb5 (*): Using Heimdal Kerberos library");
+ DEBUG("Using Heimdal Kerberos library");
#else
- radlog(L_INFO, "rlm_krb5 (*): Using MIT Kerberos library");
+ DEBUG("Using MIT Kerberos library");
#endif
-#ifndef KRB5_IS_THREAD_SAFE
if (!krb5_is_thread_safe()) {
- DEBUGW("rlm_krb5 (*): libkrb5 is not threadsafe, recompile it with thread support enabled");
- DEBUGW("rlm_krb5 (*): rlm_krb5 will run in single threaded mode");
+/*
+ * rlm_krb5 was built as threadsafe
+ */
+#ifdef KRB5_IS_THREAD_SAFE
+ ERROR("Build time libkrb5 was threadsafe, but run time library claims not to be");
+ ERROR("Modify runtime linker path (LD_LIBRARY_PATH on most systems), to prefer threadsafe libkrb5");
+ return -1;
+/*
+ * rlm_krb5 was not built as threadsafe
+ */
+#else
+ WARN("libkrb5 is not threadsafe, recompile it with thread support enabled ("
+# ifdef HEIMDAL_KRB5
+ "--enable-pthread-support"
+# else
+ "--disable-thread-support=no"
+# endif
+ ")");
+ WARN("rlm_krb5 will run in single threaded mode, performance may be degraded");
} else {
- DEBUGW("rlm_krb5 (*): Build time krb5 library was not threadsafe, but run time library claims to be");
- DEBUGW("rlm_krb5 (*): Reconfigure and recompile rlm_krb5 to enable thread support");
- }
+ WARN("Build time libkrb5 was not threadsafe, but run time library claims to be");
+ WARN("Reconfigure and recompile rlm_krb5 to enable thread support");
#endif
+ }
inst->xlat_name = cf_section_name2(conf);
if (!inst->xlat_name) {
inst->xlat_name = cf_section_name1(conf);
}
-
+
ret = krb5_init_context(&inst->context);
if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Context initialisation failed: %s", inst->xlat_name, error_message(ret));
+ ERROR("rlm_krb5 (%s): context initialisation failed: %s", inst->xlat_name,
+ rlm_krb5_error(NULL, ret));
return -1;
}
-
- radlog(L_DBG, "rlm_krb5 (%s): Context initialised successfully", inst->xlat_name);
/*
* Split service principal into service and host components
size_t len;
/* Service principal appears to contain a host component */
inst->hostname = strchr(inst->service_princ, '/');
- if (inst->hostname) {
- len = (inst->hostname - inst->service_princ);
+ if (inst->hostname) {
+ len = (inst->hostname - inst->service_princ);
inst->hostname++;
} else {
- len = SERVICE_NAME_LEN;
+ len = strlen(inst->service_princ);
}
-
+
if (len) {
inst->service = talloc_array(inst, char, (len + 1));
- strlcpy(inst->service, inst->service_princ, len);
+ strlcpy(inst->service, inst->service_princ, len + 1);
}
}
-
+
#ifdef HEIMDAL_KRB5
if (inst->hostname) {
- radlog(L_DBG, "rlm_krb5 (%s): Ignoring hostname component of "
- "service principal \"%s\", not needed/supported by "
- "Heimdal", inst->xlat_name, inst->hostname);
+ DEBUG("rlm_krb5 (%s): Ignoring hostname component of service principal \"%s\", not "
+ "needed/supported by Heimdal", inst->xlat_name, inst->hostname);
}
#else
/*
* Convert the service principal string to a krb5 principal.
*/
- ret = krb5_sname_to_principal(inst->context, inst->hostname,
- inst->service, KRB5_NT_SRV_HST,
- &(inst->server));
+ ret = krb5_sname_to_principal(inst->context, inst->hostname, inst->service, KRB5_NT_SRV_HST, &(inst->server));
if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Failed parsing service "
- "principal: %s", inst->xlat_name, error_message(ret));
+ ERROR("rlm_krb5 (%s): Failed parsing service principal: %s", inst->xlat_name,
+ rlm_krb5_error(inst->context, ret));
return -1;
}
-
+
ret = krb5_unparse_name(inst->context, inst->server, &princ_name);
if (ret) {
/* Uh? */
- radlog(L_ERR, "rlm_krb5 (%s): Failed constructing service "
- "principal string: %s", inst->xlat_name,
- error_message(ret));
+ ERROR("rlm_krb5 (%s): Failed constructing service principal string: %s", inst->xlat_name,
+ rlm_krb5_error(inst->context, ret));
return -1;
}
-
+
/*
* Not necessarily the same as the config item
*/
- radlog(L_DBG, "rlm_krb5 (%s): Using service principal \"%s\"",
- inst->xlat_name, princ_name);
-
+ DEBUG("rlm_krb5 (%s): Using service principal \"%s\"", inst->xlat_name, princ_name);
+
krb5_free_unparsed_name(inst->context, princ_name);
-
+
/*
* Setup options for getting credentials and verifying them
*/
-
+
/* For some reason the 'init' version of this function is deprecated */
ret = krb5_get_init_creds_opt_alloc(inst->context, &(inst->gic_options));
if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Couldn't allocated inital "
- "credential options: %s", inst->xlat_name,
- error_message(ret));
-
+ ERROR("rlm_krb5 (%s): Couldn't allocated inital credential options: %s", inst->xlat_name,
+ rlm_krb5_error(inst->context, ret));
+
+ return -1;
+ }
+
+ /*
+ * Perform basic checks on the keytab
+ */
+ ret = inst->keytabname ?
+ krb5_kt_resolve(inst->context, inst->keytabname, &keytab) :
+ krb5_kt_default(inst->context, &keytab);
+ if (ret) {
+ ERROR("rlm_krb5 (%s): Resolving keytab failed: %s", inst->xlat_name,
+ rlm_krb5_error(inst->context, ret));
+
+ return -1;
+ }
+
+ ret = krb5_kt_get_name(inst->context, keytab, keytab_name, sizeof(keytab_name));
+ krb5_kt_close(inst->context, keytab);
+ if (ret) {
+ ERROR("rlm_krb5 (%s): Can't retrieve keytab name: %s", inst->xlat_name,
+ rlm_krb5_error(inst->context, ret));
+
return -1;
}
-
+
+ DEBUG("rlm_krb5 (%s): Using keytab \"%s\"", inst->xlat_name, keytab_name);
+
MEM(inst->vic_options = talloc_zero(inst, krb5_verify_init_creds_opt));
-
krb5_verify_init_creds_opt_init(inst->vic_options);
- krb5_verify_init_creds_opt_set_ap_req_nofail(inst->vic_options, TRUE);
-
#endif
-
+
+#ifdef KRB5_IS_THREAD_SAFE
+ /*
+ * Initialize the socket pool.
+ */
+ inst->pool = fr_connection_pool_init(conf, inst, mod_conn_create, NULL, NULL, NULL);
+ if (!inst->pool) {
+ return -1;
+ }
+#else
+ inst->conn = mod_conn_create(inst, inst);
+ if (!inst->conn) {
+ return -1;
+ }
+#endif
return 0;
}
-static rlm_rcode_t krb5_parse_user(REQUEST *request, krb5_context context, krb5_principal *client)
+/** Common function for transforming a User-Name string into a principal.
+ *
+ * @param[out] client Where to write the client principal.
+ * @param[in] request Current request.
+ * @param[in] context Kerberos context.
+ */
+static rlm_rcode_t krb5_parse_user(krb5_principal *client, REQUEST *request, krb5_context context)
{
krb5_error_code ret;
char *princ_name;
-
+
/*
* We can only authenticate user requests which HAVE
* a User-Name attribute.
*/
if (!request->username) {
- RDEBUG("Attribute \"User-Name\" is required for "
- "authentication");
-
+ REDEBUG("Attribute \"User-Name\" is required for authentication");
+
return RLM_MODULE_INVALID;
}
* a User-Password attribute.
*/
if (!request->password) {
- RDEBUG("Attribute \"User-Password\" is required for "
- "authentication");
-
+ REDEBUG("Attribute \"User-Password\" is required for authentication");
+
return RLM_MODULE_INVALID;
}
* and not anything else.
*/
if (request->password->da->attr != PW_USER_PASSWORD) {
- RDEBUG("Attribute \"User-Password\" is required for "
- "authentication. Cannot use \"%s\".",
- request->password->da->name);
-
+ REDEBUG("Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".",
+ request->password->da->name);
+
return RLM_MODULE_INVALID;
}
-
+
ret = krb5_parse_name(context, request->username->vp_strvalue, client);
if (ret) {
- RDEBUG("Failed parsing username as principal: %s", error_message(ret));
-
+ REDEBUG("Failed parsing username as principal: %s", rlm_krb5_error(context, ret));
+
return RLM_MODULE_FAIL;
}
krb5_unparse_name(context, *client, &princ_name);
RDEBUG("Using client principal \"%s\"", princ_name);
+#ifdef HEIMDAL_KRB5
+ free(princ_name);
+#else
krb5_free_unparsed_name(context, princ_name);
-
+#endif
return RLM_MODULE_OK;
}
+/** Log error message and return appropriate rcode
+ *
+ * Translate kerberos error codes into return codes.
+ * @param request Current request.
+ * @param ret code from kerberos.
+ * @param conn used in the last operation.
+ */
+static rlm_rcode_t krb5_process_error(REQUEST *request, rlm_krb5_handle_t *conn, int ret)
+{
+ rad_assert(ret != 0);
+ rad_assert(conn); /* Silences warnings */
+
+ switch (ret) {
+ case KRB5_LIBOS_BADPWDMATCH:
+ case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+ REDEBUG("Provided password was incorrect (%i): %s", ret, rlm_krb5_error(conn->context, ret));
+ return RLM_MODULE_REJECT;
+
+ case KRB5KDC_ERR_KEY_EXP:
+ case KRB5KDC_ERR_CLIENT_REVOKED:
+ case KRB5KDC_ERR_SERVICE_REVOKED:
+ REDEBUG("Account has been locked out (%i): %s", ret, rlm_krb5_error(conn->context, ret));
+ return RLM_MODULE_USERLOCK;
+
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ RDEBUG("User not found (%i): %s", ret, rlm_krb5_error(conn->context, ret));
+ return RLM_MODULE_NOTFOUND;
+
+ default:
+ REDEBUG("Error verifying credentials (%i): %s", ret, rlm_krb5_error(conn->context, ret));
+ return RLM_MODULE_FAIL;
+ }
+}
+
#ifdef HEIMDAL_KRB5
/*
* Validate user/pass (Heimdal)
*/
-static rlm_rcode_t krb5_auth(void *instance, REQUEST *request)
+static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, REQUEST *request)
{
rlm_krb5_t *inst = instance;
rlm_rcode_t rcode;
-
krb5_error_code ret;
-
+
+ rlm_krb5_handle_t *conn;
+
krb5_principal client;
- krb5_ccache ccache;
- krb5_keytab keytab;
- krb5_verify_opt options;
- krb5_context context;
-
- rad_assert(inst->context);
#ifdef KRB5_IS_THREAD_SAFE
- /*
- * See above in MIT krb5_auth
- */
- ret = krb5_copy_context(inst->context, &context);
- if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s",
- inst->xlat_name, error_message(ret));
-
- return RLM_MODULE_FAIL;
- }
+ conn = fr_connection_get(inst->pool);
+ if (!conn) return RLM_MODULE_FAIL;
#else
- context = inst->context;
+ conn = inst->conn;
#endif
/*
* Zero out local storage
*/
- memset(&keytab, 0, sizeof(keytab));
memset(&client, 0, sizeof(client));
- memset(&init_creds, 0, sizeof(init_creds));
-
+
+ rcode = krb5_parse_user(&client, request, conn->context);
+ if (rcode != RLM_MODULE_OK) goto cleanup;
+
/*
- * Setup krb5_verify_user options
- *
- * Not entirely sure this is necessary, but as we use context
- * to get the cache handle, we probably do have to do this with
- * the cloned context.
+ * Verify the user, using the options we set in instantiate
*/
- krb5_cc_default(context, &ccache);
-
- krb5_verify_opt_init(&options);
- krb5_verify_opt_set_ccache(&options, ccache);
- ret = inst->keytabname ?
- krb5_kt_resolve(context, inst->keytabname, &keytab) :
- krb5_kt_default(context, &keytab);
+ ret = krb5_verify_user_opt(conn->context, client, request->password->vp_strvalue, &conn->options);
if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s",
- inst->xlat_name, error_message(ret));
-
+ rcode = krb5_process_error(request, conn, ret);
goto cleanup;
}
-
- krb5_verify_opt_set_keytab(&options, keytab);
- krb5_verify_opt_set_secure(&options, TRUE);
-
- if (inst->service) {
- krb5_verify_opt_set_service(&options, inst->service);
- }
-
- rcode = krb5_parse_user(request, context, &client);
- if (rcode != RLM_MODULE_OK) goto cleanup;
/*
- * Verify the user, using the options we set in instantiate
+ * krb5_verify_user_opt adds the credentials to the ccache
+ * we specified with krb5_verify_opt_set_ccache.
+ *
+ * To make sure we don't accumulate thousands of sets of
+ * credentials, remove them again here.
+ *
+ * @todo This should definitely be optional, which means writing code for the MIT
+ * variant as well.
*/
- ret = krb5_verify_user_opt(context, client,
- request->password->vp_strvalue,
- &options);
- if (ret) {
- switch (ret) {
- case KRB5_LIBOS_BADPWDMATCH:
- case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- RDEBUG("Provided password was incorrect: %s",
- error_message(ret));
- rcode = RLM_MODULE_REJECT;
-
- break;
- case KRB5KDC_ERR_KEY_EXP:
- case KRB5KDC_ERR_CLIENT_REVOKED:
- case KRB5KDC_ERR_SERVICE_REVOKED:
- RDEBUG("Account has been locked out: %s",
- error_message(ret));
- rcode = RLM_MODULE_USERLOCK;
-
- break;
- case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- RDEBUG("User not found: %s", error_message(ret));
- rcode = RLM_MODULE_NOTFOUND;
-
- default:
- radlog(L_ERR, "rlm_krb5 (%s): Verifying user failed: "
- "%s", inst->xlat_name, error_message(ret));
- rcode = RLM_MODULE_FAIL;
-
- break;
+ {
+ krb5_cc_cursor cursor;
+ krb5_creds cred;
+
+ krb5_cc_start_seq_get(conn->context, conn->ccache, &cursor);
+ for ((ret = krb5_cc_next_cred(conn->context, conn->ccache, &cursor, &cred));
+ ret == 0;
+ (ret = krb5_cc_next_cred(conn->context, conn->ccache, &cursor, &cred))) {
+ krb5_cc_remove_cred(conn->context, conn->ccache, 0, &cred);
}
+ krb5_cc_end_seq_get(conn->context, conn->ccache, &cursor);
+ }
- goto cleanup;
+cleanup:
+ if (client) {
+ krb5_free_principal(conn->context, client);
}
-
- cleanup:
- krb5_free_principal(context, client);
- krb5_kt_close(context, keytab);
+
#ifdef KRB5_IS_THREAD_SAFE
- krb5_free_context(context);
+ fr_connection_release(inst->pool, conn);
#endif
return rcode;
}
-#else
+#else /* HEIMDAL_KRB5 */
/*
* Validate userid/passwd (MIT)
*/
-static rlm_rcode_t krb5_auth(void *instance, REQUEST *request)
+static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, REQUEST *request)
{
rlm_krb5_t *inst = instance;
- rlm_rcode_t rcode;
+ rlm_rcode_t rcode;
krb5_error_code ret;
+ rlm_krb5_handle_t *conn;
+
krb5_principal client;
krb5_creds init_creds;
- krb5_keytab keytab; /* ktid */
- krb5_context context;
-
+ char *password; /* compiler warnings */
+
rad_assert(inst->context);
-#ifdef KRB5_IS_THREAD_SAFE
- /*
- * All the snippets on threadsafety say that individual threads
- * must each use their own copy of context.
- *
- * As we don't have any per thread instantiation, we either have
- * to clone inst->context on every request, or use the connection
- * API.
- *
- * @todo Use the connection API (3.0 only).
- */
- ret = krb5_copy_context(inst->context, &context);
- if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s",
- inst->xlat_name, error_message(ret));
-
- return RLM_MODULE_FAIL;
- }
- rad_assert(context != NULL); /* tell coverity copy context copies it */
+#ifdef KRB5_IS_THREAD_SAFE
+ conn = fr_connection_get(inst->pool);
+ if (!conn) return RLM_MODULE_FAIL;
#else
- context = inst->context;
+ conn = inst->conn;
#endif
/*
* Zero out local storage
*/
- memset(&keytab, 0, sizeof(keytab));
memset(&client, 0, sizeof(client));
memset(&init_creds, 0, sizeof(init_creds));
* Check we have all the required VPs, and convert the username
* into a principal.
*/
- rcode = krb5_parse_user(request, context, &client);
+ rcode = krb5_parse_user(&client, request, conn->context);
if (rcode != RLM_MODULE_OK) goto cleanup;
/*
- * Setup the keytab
- */
- ret = inst->keytabname ?
- krb5_kt_resolve(context, inst->keytabname, &keytab) :
- krb5_kt_default(context, &keytab);
- if (ret) {
- radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s", inst->xlat_name, error_message(ret));
-
- goto cleanup;
- }
-
- /*
* Retrieve the TGT from the TGS/KDC and check we can decrypt it.
*/
- ret = krb5_get_init_creds_password(context, &init_creds, client, request->password->vp_strvalue,
+ memcpy(&password, &request->password->vp_strvalue, sizeof(password));
+ RDEBUG("Retrieving and decrypting TGT");
+ ret = krb5_get_init_creds_password(conn->context, &init_creds, client, password,
NULL, NULL, 0, NULL, inst->gic_options);
if (ret) {
- error:
- switch (ret) {
- case KRB5_LIBOS_BADPWDMATCH:
- case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- RDEBUG("Provided password was incorrect: %s",
- error_message(ret));
- rcode = RLM_MODULE_REJECT;
- break;
-
- case KRB5KDC_ERR_KEY_EXP:
- case KRB5KDC_ERR_CLIENT_REVOKED:
- case KRB5KDC_ERR_SERVICE_REVOKED:
- RDEBUG("Account has been locked out: %s",
- error_message(ret));
- rcode = RLM_MODULE_USERLOCK;
- break;
-
- case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- RDEBUG("User not found: %s", error_message(ret));
- rcode = RLM_MODULE_NOTFOUND;
- break;
-
- default:
- radlog(L_ERR, "rlm_krb5 (%s): Failed getting/verifying "
- "credentials: %s", inst->xlat_name,
- error_message(ret));
- rcode = RLM_MODULE_FAIL;
- break;
- }
-
+ rcode = krb5_process_error(request, conn, ret);
goto cleanup;
}
-
- RDEBUG("Successfully retrieved and decrypted TGT");
- ret = krb5_verify_init_creds(context, &init_creds, inst->server, keytab, NULL, inst->vic_options);
- if (ret) goto error;
+ RDEBUG("Attempting to authenticate against service principal");
+ ret = krb5_verify_init_creds(conn->context, &init_creds, inst->server, conn->keytab, NULL, inst->vic_options);
+ if (ret) {
+ rcode = krb5_process_error(request, conn, ret);
+ }
- cleanup:
+cleanup:
+ if (client) {
+ krb5_free_principal(conn->context, client);
+ }
+ krb5_free_cred_contents(conn->context, &init_creds);
- if (context) {
- krb5_free_principal(context, client);
- krb5_free_cred_contents(context, &init_creds);
- krb5_kt_close(context, keytab);
#ifdef KRB5_IS_THREAD_SAFE
- krb5_free_context(context);
+ fr_connection_release(inst->pool, conn);
#endif
- }
-
return rcode;
}
-#endif /* HEIMDAL_KRB5 */
+#endif /* MIT_KRB5 */
module_t rlm_krb5 = {
RLM_MODULE_INIT,
"krb5",
- RLM_TYPE_CHECK_CONFIG_SAFE | RLM_TYPE_HUP_SAFE
+ RLM_TYPE_HUP_SAFE
#ifdef KRB5_IS_THREAD_SAFE
| RLM_TYPE_THREAD_SAFE
#endif
,
- krb5_instantiate, /* instantiation */
- krb5_detach, /* detach */
+ sizeof(rlm_krb5_t),
+ module_config,
+ mod_instantiate, /* instantiation */
+ mod_detach, /* detach */
{
- krb5_auth, /* authenticate */
+ mod_authenticate, /* authenticate */
NULL, /* authorize */
NULL, /* pre-accounting */
NULL, /* accounting */