2 * This program 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
5 * (at your option) any later version.
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.
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
20 * @brief Context management functions for rlm_krb5
22 * @copyright 2013 The FreeRADIUS server project
23 * @copyright 2013 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
27 #include <freeradius-devel/radiusd.h>
30 #ifdef HAVE_KRB5_GET_ERROR_MESSAGE
31 # define KRB5_STRERROR_BUFSIZE (2048)
33 fr_thread_local_setup(char *, krb5_error_buffer) /* macro */
36 * Explicitly cleanup the memory allocated to the error buffer.
38 static void _krb5_logging_free(void *arg)
43 char const *rlm_krb5_error(krb5_context context, krb5_error_code code)
48 buffer = fr_thread_local_init(krb5_error_buffer, _krb5_logging_free);
53 * malloc is thread safe, talloc is not
55 buffer = malloc(sizeof(char) * KRB5_STRERROR_BUFSIZE);
57 ERROR("Failed allocating memory for krb5 error buffer");
61 ret = fr_thread_local_set(krb5_error_buffer, buffer);
63 ERROR("Failed setting up TLS for krb5 error buffer: %s", fr_syserror(ret));
69 msg = krb5_get_error_message(context, code);
71 strlcpy(buffer, msg, KRB5_STRERROR_BUFSIZE);
72 #ifdef HAVE_KRB5_FREE_ERROR_MESSAGE
73 krb5_free_error_message(context, msg);
74 #elif defined(HAVE_KRB5_FREE_ERROR_STRING)
78 memcpy(&free, &msg, sizeof(free));
79 krb5_free_error_string(context, free);
82 # error "No way to free error strings, missing krb5_free_error_message() and krb5_free_error_string()"
85 strlcpy(buffer, "Unknown error", KRB5_STRERROR_BUFSIZE);
92 /** Frees libkrb5 resources associated with the handle
94 * Must not be called directly.
96 * @param conn to free.
97 * @return 0 (always indicates success).
99 static int _mod_conn_free(rlm_krb5_handle_t *conn) {
100 krb5_free_context(conn->context);
103 krb5_kt_close(conn->context, conn->keytab);
108 krb5_cc_destroy(conn->context, conn->ccache);
115 /** Create and return a new connection
117 * libkrb5(s) can talk to the KDC over TCP. Were assuming something sane is implemented
118 * by libkrb5 and that it does connection caching associated with contexts, so it's
119 * worth using a connection pool to preserve connections when workers die.
121 void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
123 rlm_krb5_t *inst = instance;
124 rlm_krb5_handle_t *conn;
127 MEM(conn = talloc_zero(ctx, rlm_krb5_handle_t));
128 ret = krb5_init_context(&conn->context);
130 ERROR("rlm_krb5 (%s): Context initialisation failed: %s", inst->xlat_name,
131 rlm_krb5_error(NULL, ret));
135 talloc_set_destructor(conn, _mod_conn_free);
137 ret = inst->keytabname ?
138 krb5_kt_resolve(conn->context, inst->keytabname, &conn->keytab) :
139 krb5_kt_default(conn->context, &conn->keytab);
141 ERROR("Resolving keytab failed: %s", rlm_krb5_error(conn->context, ret));
147 ret = krb5_cc_new_unique(conn->context, "MEMORY", NULL, &conn->ccache);
149 ERROR("rlm_krb5 (%s): Credential cache creation failed: %s", inst->xlat_name,
150 rlm_krb5_error(conn->context, ret));
155 krb5_verify_opt_init(&conn->options);
156 krb5_verify_opt_set_ccache(&conn->options, conn->ccache);
158 krb5_verify_opt_set_keytab(&conn->options, conn->keytab);
159 krb5_verify_opt_set_secure(&conn->options, true);
162 krb5_verify_opt_set_service(&conn->options, inst->service);
165 krb5_verify_init_creds_opt_set_ap_req_nofail(inst->vic_options, true);