63
* Report a Kerberos error and bail out.
66
bail_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
68
const char *k5_msg = NULL;
73
k5_msg = krb5_get_error_message(ctx, code);
74
va_start(args, format);
75
bvasprintf(&message, format, args);
80
bail("%s: %s", message, k5_msg);
85
* Report a Kerberos error as a diagnostic to stderr.
88
diag_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
90
const char *k5_msg = NULL;
95
k5_msg = krb5_get_error_message(ctx, code);
96
va_start(args, format);
97
bvasprintf(&message, format, args);
102
diag("%s: %s", message, k5_msg);
105
krb5_free_error_message(ctx, k5_msg);
110
* Clean up at the end of a test. This removes the ticket cache and resets
111
* and frees the memory allocated for the environment variables so that
112
* valgrind output on test suites is cleaner.
115
kerberos_cleanup(void)
119
if (tmpdir_ticket != NULL) {
120
basprintf(&path, "%s/krb5cc_test", tmpdir_ticket);
123
test_tmpdir_free(tmpdir_ticket);
124
tmpdir_ticket = NULL;
126
if (principal != NULL) {
130
putenv((char *) "KRB5CCNAME=");
131
putenv((char *) "KRB5_KTNAME=");
132
if (krb5ccname != NULL) {
136
if (krb5_ktname != NULL) {
144
* Obtain Kerberos tickets for the principal specified in config/principal
145
* using the keytab specified in config/keytab, both of which are presumed to
146
* be in tests in either the build or the source tree. Also sets KRB5_KTNAME
76
* Obtain Kerberos tickets and fill in the principal config entry.
149
* Returns the contents of config/principal in newly allocated memory or NULL
150
* if Kerberos tests are apparently not configured. If Kerberos tests are
151
* configured but something else fails, calls bail.
78
* There are two implementations of this function, one if we have native
79
* Kerberos libraries available and one if we don't. Uses keytab to obtain
80
* credentials, and fills in the cache member of the provided config struct.
156
char *path, *name, *krbtgt;
158
88
krb5_error_code code;
160
90
krb5_ccache ccache;
180
102
code = krb5_init_context(&ctx);
182
104
bail_krb5(ctx, code, "error initializing Kerberos");
183
kprinc = kerberos_keytab_principal(ctx, path);
105
kprinc = kerberos_keytab_principal(ctx, config->keytab);
184
106
code = krb5_unparse_name(ctx, kprinc, &name);
186
108
bail_krb5(ctx, code, "error unparsing name");
187
109
krb5_free_principal(ctx, kprinc);
188
principal = bstrdup(name);
110
config->principal = bstrdup(name);
189
111
krb5_free_unparsed_name(ctx, name);
191
/* Set the KRB5CCNAME and KRB5_KTNAME environment variables. */
192
tmpdir_ticket = test_tmpdir();
193
basprintf(&krb5ccname, "KRB5CCNAME=%s/krb5cc_test", tmpdir_ticket);
194
basprintf(&krb5_ktname, "KRB5_KTNAME=%s", path);
198
113
/* Now do the Kerberos initialization. */
199
114
code = krb5_cc_default(ctx, &ccache);
201
116
bail_krb5(ctx, code, "error setting ticket cache");
202
code = krb5_parse_name(ctx, principal, &kprinc);
117
code = krb5_parse_name(ctx, config->principal, &kprinc);
204
bail_krb5(ctx, code, "error parsing principal %s", principal);
119
bail_krb5(ctx, code, "error parsing principal %s", config->principal);
205
120
realm = krb5_principal_get_realm(ctx, kprinc);
206
121
basprintf(&krbtgt, "krbtgt/%s@%s", realm, realm);
207
code = krb5_kt_resolve(ctx, path, &keytab);
122
code = krb5_kt_resolve(ctx, config->keytab, &keytab);
209
bail_krb5(ctx, code, "cannot open keytab %s", path);
124
bail_krb5(ctx, code, "cannot open keytab %s", config->keytab);
210
125
code = krb5_get_init_creds_opt_alloc(ctx, &opts);
212
127
bail_krb5(ctx, code, "cannot allocate credential options");
230
145
krb5_get_init_creds_opt_free(ctx, opts);
231
146
krb5_free_context(ctx);
233
test_file_path_free(path);
236
* Register the cleanup function as an atexit handler so that the caller
237
* doesn't have to worry about cleanup.
239
if (atexit(kerberos_cleanup) != 0)
240
sysdiag("cannot register cleanup function");
242
/* Return the principal. */
150
#else /* !HAVE_KERBEROS */
248
* Read a principal and password from config/password in the test suite
249
* configuration and return it as a newly allocated kerberos_password struct.
250
* Returns NULL if no configuration is present, and calls bail if there are
251
* errors reading the configuration. Free the result with
252
* kerberos_config_password_free.
254
struct kerberos_password *
255
kerberos_config_password(void)
259
struct kerberos_password *config;
155
static const char * const format[] = {
156
"kinit --no-afslog -k -t %s %s >/dev/null 2>&1 </dev/null",
157
"kinit -k -t %s %s >/dev/null 2>&1 </dev/null",
158
"kinit -t %s %s >/dev/null 2>&1 </dev/null",
159
"kinit -k -K %s %s >/dev/null 2>&1 </dev/null"
163
char principal[BUFSIZ], *command;
262
config = bmalloc(sizeof(struct kerberos_password));
263
path = test_file_path("config/password");
167
/* Read the principal corresponding to the keytab. */
168
path = test_file_path("config/principal");
170
test_file_path_free(config->keytab);
171
config->keytab = NULL;
266
174
file = fopen(path, "r");
268
sysbail("cannot open %s", path);
269
if (fgets(buffer, sizeof(buffer), file) == NULL)
176
test_file_path_free(path);
179
test_file_path_free(path);
180
if (fgets(principal, sizeof(principal), file) == NULL)
270
181
bail("cannot read %s", path);
271
if (buffer[strlen(buffer) - 1] != '\n')
183
if (principal[strlen(principal) - 1] != '\n')
272
184
bail("no newline in %s", path);
273
buffer[strlen(buffer) - 1] = '\0';
274
config->principal = bstrdup(buffer);
275
if (fgets(buffer, sizeof(buffer), file) == NULL)
276
bail("cannot read password from %s", path);
278
if (buffer[strlen(buffer) - 1] != '\n')
279
bail("password too long in %s", path);
280
buffer[strlen(buffer) - 1] = '\0';
281
config->password = bstrdup(buffer);
282
test_file_path_free(path);
285
* Strip the realm from the principal and set realm and username. This
286
* is not strictly correct; it doesn't cope with escaped @-signs. But
287
* it's rather unlikely someone would use such a thing as a test
290
config->username = bstrdup(config->principal);
291
config->realm = strchr(config->username, '@');
292
if (config->realm == NULL)
293
bail("test principal has no realm");
294
*config->realm = '\0';
185
principal[strlen(principal) - 1] = '\0';
186
config->principal = bstrdup(principal);
188
/* Now do the Kerberos initialization. */
189
for (i = 0; i < ARRAY_SIZE(format); i++) {
190
basprintf(&command, format[i], config->keytab, principal);
191
status = system(command);
193
if (status != -1 && WEXITSTATUS(status) == 0)
196
if (status == -1 || WEXITSTATUS(status) != 0)
197
bail("cannot get Kerberos tickets");
200
#endif /* !HAVE_KERBEROS */
204
* Clean up at the end of a test. This removes the ticket cache and resets
205
* and frees the memory allocated for the environment variables so that
206
* valgrind output on test suites is cleaner.
209
kerberos_cleanup(void)
213
if (tmpdir_ticket != NULL) {
214
basprintf(&path, "%s/krb5cc_test", tmpdir_ticket);
217
test_tmpdir_free(tmpdir_ticket);
218
tmpdir_ticket = NULL;
220
if (config != NULL) {
221
if (config->keytab != NULL) {
222
test_file_path_free(config->keytab);
223
free(config->principal);
226
if (config->userprinc != NULL) {
227
free(config->userprinc);
228
free(config->username);
229
free(config->password);
234
if (krb5ccname != NULL) {
235
putenv((char *) "KRB5CCNAME=");
239
if (krb5_ktname != NULL) {
240
putenv((char *) "KRB5_KTNAME=");
248
* Obtain Kerberos tickets for the principal specified in config/principal
249
* using the keytab specified in config/keytab, both of which are presumed to
250
* be in tests in either the build or the source tree. Also sets KRB5_KTNAME
253
* Returns the contents of config/principal in newly allocated memory or NULL
254
* if Kerberos tests are apparently not configured. If Kerberos tests are
255
* configured but something else fails, calls bail.
257
struct kerberos_config *
258
kerberos_setup(enum kerberos_needs needs)
264
/* If we were called before, clean up after the previous run. */
267
config = bcalloc(1, sizeof(struct kerberos_config));
270
* If we have a config/keytab file, set the KRB5CCNAME and KRB5_KTNAME
271
* environment variables and obtain initial tickets.
273
config->keytab = test_file_path("config/keytab");
274
if (config->keytab == NULL) {
275
if (needs == TAP_KRB_NEEDS_KEYTAB || needs == TAP_KRB_NEEDS_BOTH)
276
skip_all("Kerberos tests not configured");
278
tmpdir_ticket = test_tmpdir();
279
basprintf(&config->cache, "%s/krb5cc_test", tmpdir_ticket);
280
basprintf(&krb5ccname, "KRB5CCNAME=%s/krb5cc_test", tmpdir_ticket);
281
basprintf(&krb5_ktname, "KRB5_KTNAME=%s", config->keytab);
288
* If we have a config/password file, read it and fill out the relevant
289
* members of our config struct.
291
path = test_file_path("config/password");
293
file = fopen(path, "r");
295
if (needs == TAP_KRB_NEEDS_PASSWORD || needs == TAP_KRB_NEEDS_BOTH)
296
skip_all("Kerberos tests not configured");
298
if (fgets(buffer, sizeof(buffer), file) == NULL)
299
bail("cannot read %s", path);
300
if (buffer[strlen(buffer) - 1] != '\n')
301
bail("no newline in %s", path);
302
buffer[strlen(buffer) - 1] = '\0';
303
config->userprinc = bstrdup(buffer);
304
if (fgets(buffer, sizeof(buffer), file) == NULL)
305
bail("cannot read password from %s", path);
307
if (buffer[strlen(buffer) - 1] != '\n')
308
bail("password too long in %s", path);
309
buffer[strlen(buffer) - 1] = '\0';
310
config->password = bstrdup(buffer);
313
* Strip the realm from the principal and set realm and username.
314
* This is not strictly correct; it doesn't cope with escaped @-signs
315
* or enterprise names.
317
config->username = bstrdup(config->userprinc);
318
config->realm = strchr(config->username, '@');
319
if (config->realm == NULL)
320
bail("test principal has no realm");
321
*config->realm = '\0';
325
test_file_path_free(path);
328
* Register the cleanup function as an atexit handler so that the caller
329
* doesn't have to worry about cleanup.
331
if (atexit(kerberos_cleanup) != 0)
332
sysdiag("cannot register cleanup function");
334
/* Return the configuration. */
301
* Free a kerberos_password struct. This knows about the allocation strategy
302
* used by kerberos_config_password and frees accordingly.
305
kerberos_config_password_free(struct kerberos_password *config)
307
free(config->principal);
308
free(config->username);
309
free(config->password);
315
* Find the principal of the first entry of a keytab and return it. The
316
* caller is responsible for freeing the result with krb5_free_principal.
320
kerberos_keytab_principal(krb5_context ctx, const char *path)
323
krb5_kt_cursor cursor;
324
krb5_keytab_entry entry;
325
krb5_principal princ;
326
krb5_error_code status;
328
status = krb5_kt_resolve(ctx, path, &keytab);
330
bail_krb5(ctx, status, "error opening %s", path);
331
status = krb5_kt_start_seq_get(ctx, keytab, &cursor);
333
bail_krb5(ctx, status, "error reading %s", path);
334
status = krb5_kt_next_entry(ctx, keytab, &entry, &cursor);
336
status = krb5_copy_principal(ctx, entry.principal, &princ);
338
bail_krb5(ctx, status, "error copying principal from %s", path);
339
krb5_kt_free_entry(ctx, &entry);
342
bail("no principal found in keytab file %s", path);
343
krb5_kt_end_seq_get(ctx, keytab, &cursor);
344
krb5_kt_close(ctx, keytab);
350
340
* Clean up the krb5.conf file generated by kerberos_generate_conf and free
351
341
* the memory used to set the environment variable. This doesn't fail if the
352
342
* file and variable are already gone, allowing it to be harmlessly run
403
395
if (atexit(kerberos_cleanup_conf) != 0)
404
396
sysdiag("cannot register cleanup function");
401
* The remaining functions in this file are only available if Kerberos
402
* libraries are available.
408
* Report a Kerberos error and bail out.
411
bail_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
413
const char *k5_msg = NULL;
418
k5_msg = krb5_get_error_message(ctx, code);
419
va_start(args, format);
420
bvasprintf(&message, format, args);
425
bail("%s: %s", message, k5_msg);
430
* Report a Kerberos error as a diagnostic to stderr.
433
diag_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...)
435
const char *k5_msg = NULL;
440
k5_msg = krb5_get_error_message(ctx, code);
441
va_start(args, format);
442
bvasprintf(&message, format, args);
447
diag("%s: %s", message, k5_msg);
450
krb5_free_error_message(ctx, k5_msg);
455
* Find the principal of the first entry of a keytab and return it. The
456
* caller is responsible for freeing the result with krb5_free_principal.
460
kerberos_keytab_principal(krb5_context ctx, const char *path)
463
krb5_kt_cursor cursor;
464
krb5_keytab_entry entry;
465
krb5_principal princ;
466
krb5_error_code status;
468
status = krb5_kt_resolve(ctx, path, &keytab);
470
bail_krb5(ctx, status, "error opening %s", path);
471
status = krb5_kt_start_seq_get(ctx, keytab, &cursor);
473
bail_krb5(ctx, status, "error reading %s", path);
474
status = krb5_kt_next_entry(ctx, keytab, &entry, &cursor);
476
status = krb5_copy_principal(ctx, entry.principal, &princ);
478
bail_krb5(ctx, status, "error copying principal from %s", path);
479
krb5_kt_free_entry(ctx, &entry);
482
bail("no principal found in keytab file %s", path);
483
krb5_kt_end_seq_get(ctx, keytab, &cursor);
484
krb5_kt_close(ctx, keytab);
488
#endif /* HAVE_KERBEROS */