All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
krb5.c
Go to the documentation of this file.
1 /*
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.
6  *
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.
11  *
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
15  */
16 
17 /**
18  * $Id: 2b1d9f7ac1f057c59c86b707916877d234004a66 $
19  * @file krb5.h
20  * @brief Context management functions for rlm_krb5
21  *
22  * @copyright 2013 The FreeRADIUS server project
23  * @copyright 2013 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
24  */
25 RCSID("$Id: 2b1d9f7ac1f057c59c86b707916877d234004a66 $")
26 
27 #include <freeradius-devel/radiusd.h>
28 #include "krb5.h"
29 
30 #ifdef HAVE_KRB5_GET_ERROR_MESSAGE
31 # define KRB5_STRERROR_BUFSIZE (2048)
32 
33 fr_thread_local_setup(char *, krb5_error_buffer) /* macro */
34 
35 /*
36  * Explicitly cleanup the memory allocated to the error buffer.
37  */
38 static void _krb5_logging_free(void *arg)
39 {
40  free(arg);
41 }
42 
43 char const *rlm_krb5_error(krb5_context context, krb5_error_code code)
44 {
45  char const *msg;
46  char *buffer;
47 
48  buffer = fr_thread_local_init(krb5_error_buffer, _krb5_logging_free);
49  if (!buffer) {
50  int ret;
51 
52  /*
53  * malloc is thread safe, talloc is not
54  */
55  buffer = malloc(sizeof(char) * KRB5_STRERROR_BUFSIZE);
56  if (!buffer) {
57  ERROR("Failed allocating memory for krb5 error buffer");
58  return NULL;
59  }
60 
61  ret = fr_thread_local_set(krb5_error_buffer, buffer);
62  if (ret != 0) {
63  ERROR("Failed setting up TLS for krb5 error buffer: %s", fr_syserror(ret));
64  free(buffer);
65  return NULL;
66  }
67  }
68 
69  msg = krb5_get_error_message(context, code);
70  if (msg) {
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)
75  {
76  char *free;
77 
78  memcpy(&free, &msg, sizeof(free));
79  krb5_free_error_string(context, free);
80  }
81 # else
82 # error "No way to free error strings, missing krb5_free_error_message() and krb5_free_error_string()"
83 # endif
84  } else {
85  strlcpy(buffer, "Unknown error", KRB5_STRERROR_BUFSIZE);
86  }
87 
88  return buffer;
89 }
90 #endif
91 
92 /** Frees libkrb5 resources associated with the handle
93  *
94  * Must not be called directly.
95  *
96  * @param conn to free.
97  * @return 0 (always indicates success).
98  */
99 static int _mod_conn_free(rlm_krb5_handle_t *conn) {
100  krb5_free_context(conn->context);
101 
102  if (conn->keytab) krb5_kt_close(conn->context, conn->keytab);
103 
104 #ifdef HEIMDAL_KRB5
105  if (conn->ccache) krb5_cc_destroy(conn->context, conn->ccache);
106 #endif
107 
108  return 0;
109 }
110 
111 /** Create and return a new connection
112  *
113  * libkrb5(s) can talk to the KDC over TCP. Were assuming something sane is implemented
114  * by libkrb5 and that it does connection caching associated with contexts, so it's
115  * worth using a connection pool to preserve connections when workers die.
116  */
117 void *mod_conn_create(TALLOC_CTX *ctx, void *instance, UNUSED struct timeval const *timeout)
118 {
119  rlm_krb5_t *inst = instance;
120  rlm_krb5_handle_t *conn;
121  krb5_error_code ret;
122 
123  MEM(conn = talloc_zero(ctx, rlm_krb5_handle_t));
124  ret = krb5_init_context(&conn->context);
125  if (ret) {
126  ERROR("rlm_krb5 (%s): Context initialisation failed: %s", inst->xlat_name,
127  rlm_krb5_error(NULL, ret));
128 
129  return NULL;
130  }
131  talloc_set_destructor(conn, _mod_conn_free);
132 
133  ret = inst->keytabname ?
134  krb5_kt_resolve(conn->context, inst->keytabname, &conn->keytab) :
135  krb5_kt_default(conn->context, &conn->keytab);
136  if (ret) {
137  ERROR("Resolving keytab failed: %s", rlm_krb5_error(conn->context, ret));
138 
139  goto cleanup;
140  }
141 
142 #ifdef HEIMDAL_KRB5
143  ret = krb5_cc_new_unique(conn->context, "MEMORY", NULL, &conn->ccache);
144  if (ret) {
145  ERROR("rlm_krb5 (%s): Credential cache creation failed: %s", inst->xlat_name,
146  rlm_krb5_error(conn->context, ret));
147 
148  return NULL;
149  }
150 
151  krb5_verify_opt_init(&conn->options);
152  krb5_verify_opt_set_ccache(&conn->options, conn->ccache);
153 
154  krb5_verify_opt_set_keytab(&conn->options, conn->keytab);
155  krb5_verify_opt_set_secure(&conn->options, true);
156 
157  if (inst->service) krb5_verify_opt_set_service(&conn->options, inst->service);
158 #else
159  krb5_verify_init_creds_opt_set_ap_req_nofail(inst->vic_options, true);
160 #endif
161  return conn;
162 
163 cleanup:
164  talloc_free(conn);
165  return NULL;
166 }
Instance configuration for rlm_krb5.
Definition: krb5.h:49
#define MEM(x)
Definition: radiusd.h:396
#define UNUSED
Definition: libradius.h:134
static int _mod_conn_free(rlm_krb5_handle_t *conn)
Frees libkrb5 resources associated with the handle.
Definition: krb5.c:99
static float timeout
Definition: radclient.c:43
#define inst
#define rlm_krb5_error(_x, _y)
Definition: krb5.h:88
char const * keytabname
The keytab to resolve the service in.
Definition: krb5.h:57
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
void * mod_conn_create(TALLOC_CTX *ctx, void *instance, UNUSED struct timeval const *timeout)
Create and return a new connection.
Definition: krb5.c:117
static bool cleanup
Definition: radsniff.c:53
char * service
The service component of service_princ, or NULL.
Definition: krb5.h:63
fr_thread_local_setup(char *, fr_strerror_buffer)
POSIX-2008 errno macros.
Definition: log.c:37
char const * xlat_name
This module's instance name.
Definition: krb5.h:56
Context management functions for rlm_krb5.
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
#define RCSID(id)
Definition: build.h:135
krb5_verify_init_creds_opt * vic_options
Options to pass to the validate_initial_creds function.
Definition: krb5.h:70
#define ERROR(fmt,...)
Definition: log.h:145
USES_APPLE_DEPRECATED_API struct rlm_krb5_handle rlm_krb5_handle_t