Branch data Line data Source code
1 : : /*
2 : : Authors:
3 : : Sumit Bose <sbose@redhat.com>
4 : :
5 : : Copyright (C) 2009-2010 Red Hat
6 : :
7 : : This program is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3 of the License, or
10 : : (at your option) any later version.
11 : :
12 : : This program is distributed in the hope that it will be useful,
13 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : GNU General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : : #include <stdio.h>
21 : : #include <errno.h>
22 : : #include <talloc.h>
23 : :
24 : : #include "config.h"
25 : :
26 : : #include "util/util.h"
27 : : #include "util/sss_krb5.h"
28 : :
29 : 0 : errno_t select_principal_from_keytab(TALLOC_CTX *mem_ctx,
30 : : const char *hostname,
31 : : const char *desired_realm,
32 : : const char *keytab_name,
33 : : char **_principal,
34 : : char **_primary,
35 : : char **_realm)
36 : : {
37 : 0 : krb5_error_code kerr = 0;
38 : 0 : krb5_context krb_ctx = NULL;
39 : 0 : krb5_keytab keytab = NULL;
40 : 0 : krb5_principal client_princ = NULL;
41 : : TALLOC_CTX *tmp_ctx;
42 : 0 : char *primary = NULL;
43 : 0 : char *realm = NULL;
44 : 0 : int i = 0;
45 : : errno_t ret;
46 : : char *principal_string;
47 : : const char *realm_name;
48 : : int realm_len;
49 : :
50 : : /**
51 : : * Priority of lookup:
52 : : * - foobar$@REALM (AD domain)
53 : : * - host/our.hostname@REALM
54 : : * - host/foobar@REALM
55 : : * - host/foo@BAR
56 : : * - pick the first principal in the keytab
57 : : */
58 : 0 : const char *primary_patterns[] = {"%s$", "*$", "host/%s", "host/*", "host/*", NULL};
59 : 0 : const char *realm_patterns[] = {"%s", "%s", "%s", "%s", NULL, NULL};
60 : :
61 [ # # ][ # # ]: 0 : DEBUG(5, ("trying to select the most appropriate principal from keytab\n"));
[ # # ][ # # ]
[ # # ]
62 : 0 : tmp_ctx = talloc_new(NULL);
63 [ # # ]: 0 : if (!tmp_ctx) {
64 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_new failed\n"));
[ # # ][ # # ]
[ # # ]
65 : : return ENOMEM;
66 : : }
67 : :
68 : 0 : kerr = krb5_init_context(&krb_ctx);
69 [ # # ]: 0 : if (kerr) {
70 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to init kerberos context\n"));
[ # # ][ # # ]
[ # # ]
71 : : ret = EFAULT;
72 : : goto done;
73 : : }
74 : :
75 [ # # ]: 0 : if (keytab_name != NULL) {
76 : 0 : kerr = krb5_kt_resolve(krb_ctx, keytab_name, &keytab);
77 : : } else {
78 : 0 : kerr = krb5_kt_default(krb_ctx, &keytab);
79 : : }
80 [ # # ]: 0 : if (kerr) {
81 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE,
[ # # ][ # # ]
[ # # ][ # # ]
82 : : ("Failed to read keytab [%s]: %s\n",
83 : : KEYTAB_CLEAN_NAME,
84 : : sss_krb5_get_error_message(krb_ctx, kerr)));
85 : : ret = EFAULT;
86 : : goto done;
87 : : }
88 : :
89 [ # # ]: 0 : if (!desired_realm) {
90 : 0 : desired_realm = "*";
91 : : }
92 [ # # ]: 0 : if (!hostname) {
93 : 0 : hostname = "*";
94 : : }
95 : :
96 : : do {
97 [ # # ]: 0 : if (primary_patterns[i]) {
98 : 0 : primary = talloc_asprintf(tmp_ctx, primary_patterns[i], hostname);
99 [ # # ]: 0 : if (primary == NULL) {
100 : : ret = ENOMEM;
101 : : goto done;
102 : : }
103 : : } else {
104 : : primary = NULL;
105 : : }
106 [ # # ]: 0 : if (realm_patterns[i]) {
107 : 0 : realm = talloc_asprintf(tmp_ctx, realm_patterns[i], desired_realm);
108 [ # # ]: 0 : if (realm == NULL) {
109 : : ret = ENOMEM;
110 : : goto done;
111 : : }
112 : : } else {
113 : : realm = NULL;
114 : : }
115 : :
116 : 0 : kerr = find_principal_in_keytab(krb_ctx, keytab, primary, realm,
117 : : &client_princ);
118 : 0 : talloc_zfree(primary);
119 : 0 : talloc_zfree(realm);
120 [ # # ]: 0 : if (kerr == 0) {
121 : : break;
122 : : }
123 [ # # ]: 0 : if (client_princ != NULL) {
124 : 0 : krb5_free_principal(krb_ctx, client_princ);
125 : 0 : client_princ = NULL;
126 : : }
127 : 0 : i++;
128 [ # # ][ # # ]: 0 : } while(primary_patterns[i-1] != NULL || realm_patterns[i-1] != NULL);
129 : :
130 [ # # ]: 0 : if (kerr == 0) {
131 [ # # ]: 0 : if (_principal) {
132 : 0 : kerr = krb5_unparse_name(krb_ctx, client_princ, &principal_string);
133 [ # # ]: 0 : if (kerr) {
134 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_unparse_name failed"));
[ # # ][ # # ]
[ # # ]
135 : : ret = EFAULT;
136 : : goto done;
137 : : }
138 : :
139 : 0 : *_principal = talloc_strdup(mem_ctx, principal_string);
140 : 0 : free(principal_string);
141 [ # # ]: 0 : if (!*_principal) {
142 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_strdup failed"));
[ # # ][ # # ]
[ # # ]
143 : : ret = ENOMEM;
144 : : goto done;
145 : : }
146 [ # # ][ # # ]: 0 : DEBUG(5, ("Selected principal: %s\n", *_principal));
[ # # ][ # # ]
[ # # ]
147 : : }
148 : :
149 [ # # ]: 0 : if (_primary) {
150 : 0 : kerr = sss_krb5_unparse_name_flags(krb_ctx, client_princ,
151 : : KRB5_PRINCIPAL_UNPARSE_NO_REALM,
152 : : &principal_string);
153 [ # # ]: 0 : if (kerr) {
154 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_unparse_name failed"));
[ # # ][ # # ]
[ # # ]
155 : : ret = EFAULT;
156 : : goto done;
157 : : }
158 : :
159 : 0 : *_primary = talloc_strdup(mem_ctx, principal_string);
160 : 0 : free(principal_string);
161 [ # # ]: 0 : if (!*_primary) {
162 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_strdup failed"));
[ # # ][ # # ]
[ # # ]
163 [ # # ]: 0 : if (_principal) talloc_zfree(*_principal);
164 : : ret = ENOMEM;
165 : : goto done;
166 : : }
167 [ # # ][ # # ]: 0 : DEBUG(5, ("Selected primary: %s\n", *_primary));
[ # # ][ # # ]
[ # # ]
168 : : }
169 : :
170 [ # # ]: 0 : if (_realm) {
171 : 0 : sss_krb5_princ_realm(krb_ctx, client_princ,
172 : : &realm_name,
173 : : &realm_len);
174 : 0 : *_realm = talloc_asprintf(mem_ctx, "%.*s",
175 : : realm_len, realm_name);
176 [ # # ]: 0 : if (!*_realm) {
177 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_asprintf failed"));
[ # # ][ # # ]
[ # # ]
178 [ # # ]: 0 : if (_principal) talloc_zfree(*_principal);
179 [ # # ]: 0 : if (_primary) talloc_zfree(*_primary);
180 : : ret = ENOMEM;
181 : : goto done;
182 : : }
183 [ # # ][ # # ]: 0 : DEBUG(5, ("Selected realm: %s\n", *_realm));
[ # # ][ # # ]
[ # # ]
184 : : }
185 : :
186 : : ret = EOK;
187 : : } else {
188 [ # # ][ # # ]: 0 : DEBUG(3, ("No suitable principal found in keytab\n"));
[ # # ][ # # ]
[ # # ]
189 : : ret = ENOENT;
190 : : }
191 : :
192 : : done:
193 [ # # ]: 0 : if (keytab) krb5_kt_close(krb_ctx, keytab);
194 [ # # ]: 0 : if (krb_ctx) krb5_free_context(krb_ctx);
195 [ # # ]: 0 : if (client_princ != NULL) {
196 : 0 : krb5_free_principal(krb_ctx, client_princ);
197 : 0 : client_princ = NULL;
198 : : }
199 : 0 : talloc_free(tmp_ctx);
200 : : return ret;
201 : : }
202 : :
203 : 0 : int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
204 : : krb5_context context, krb5_keytab keytab)
205 : : {
206 : : bool found;
207 : : char *kt_principal;
208 : : krb5_error_code krberr;
209 : : krb5_kt_cursor cursor;
210 : : krb5_keytab_entry entry;
211 : :
212 : 0 : krberr = krb5_kt_start_seq_get(context, keytab, &cursor);
213 [ # # ]: 0 : if (krberr) {
214 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE,
[ # # ][ # # ]
[ # # ][ # # ]
215 : : ("Cannot read keytab [%s].\n", KEYTAB_CLEAN_NAME));
216 : :
217 [ # # ]: 0 : sss_log(SSS_LOG_ERR, "Error reading keytab file [%s]: [%d][%s]. "
218 : : "Unable to create GSSAPI-encrypted LDAP "
219 : : "connection.",
220 : : KEYTAB_CLEAN_NAME, krberr,
221 : : sss_krb5_get_error_message(context, krberr));
222 : :
223 : : return EIO;
224 : : }
225 : :
226 : : found = false;
227 [ # # ]: 0 : while((krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
228 : 0 : krberr = krb5_unparse_name(context, entry.principal, &kt_principal);
229 [ # # ]: 0 : if (krberr) {
230 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE,
[ # # ][ # # ]
[ # # ]
231 : : ("Could not parse keytab entry\n"));
232 : 0 : sss_log(SSS_LOG_ERR, "Could not parse keytab entry\n");
233 : : return EIO;
234 : : }
235 : :
236 [ # # ]: 0 : if (strcmp(principal, kt_principal) == 0) {
237 : 0 : found = true;
238 : : }
239 : 0 : free(kt_principal);
240 : 0 : krberr = sss_krb5_free_keytab_entry_contents(context, &entry);
241 [ # # ]: 0 : if (krberr) {
242 : : /* This should never happen. The API docs for this function
243 : : * specify only success for this function
244 : : */
245 [ # # ][ # # ]: 0 : DEBUG(1,("Could not free keytab entry contents\n"));
[ # # ][ # # ]
[ # # ]
246 : : /* This is non-fatal, so we'll continue here */
247 : : }
248 : :
249 [ # # ]: 0 : if (found) {
250 : : break;
251 : : }
252 : : }
253 : :
254 : 0 : krberr = krb5_kt_end_seq_get(context, keytab, &cursor);
255 [ # # ]: 0 : if (krberr) {
256 [ # # ][ # # ]: 0 : DEBUG(0, ("Could not close keytab.\n"));
[ # # ][ # # ]
[ # # ]
257 [ # # ]: 0 : sss_log(SSS_LOG_ERR, "Could not close keytab file [%s].",
258 : : KEYTAB_CLEAN_NAME);
259 : : return EIO;
260 : : }
261 : :
262 [ # # ]: 0 : if (!found) {
263 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_FATAL_FAILURE,
[ # # ][ # # ]
[ # # ][ # # ]
264 : : ("Principal [%s] not found in keytab [%s]\n",
265 : : principal,
266 : : KEYTAB_CLEAN_NAME));
267 [ # # ]: 0 : sss_log(SSS_LOG_ERR, "Error processing keytab file [%s]: "
268 : : "Principal [%s] was not found. "
269 : : "Unable to create GSSAPI-encrypted LDAP connection.",
270 : : KEYTAB_CLEAN_NAME, principal);
271 : :
272 : : return EFAULT;
273 : : }
274 : :
275 : : return EOK;
276 : : }
277 : :
278 : :
279 : : enum matching_mode {MODE_NORMAL, MODE_PREFIX, MODE_POSTFIX};
280 : : /**
281 : : * We only have primary and instances stored separately, we need to
282 : : * join them to one string and compare that string.
283 : : *
284 : : * @param ctx kerberos context
285 : : * @param principal principal we want to match
286 : : * @param pattern_primary primary part of the principal we want to
287 : : * perform matching against. It is possible to use * wildcard
288 : : * at the beginning or at the end of the string. If NULL, it
289 : : * will act as "*"
290 : : * @param pattern_realm realm part of the principal we want to perform
291 : : * the matching against. If NULL, it will act as "*"
292 : : */
293 : 0 : static bool match_principal(krb5_context ctx,
294 : : krb5_principal principal,
295 : : const char *pattern_primary,
296 : : const char *pattern_realm)
297 : : {
298 : 0 : char *primary = NULL;
299 : 0 : char *primary_str = NULL;
300 : 0 : int primary_str_len = 0;
301 : : int tmp_len;
302 : : int len_diff;
303 : : const char *realm_name;
304 : : int realm_len;
305 : :
306 : 0 : enum matching_mode mode = MODE_NORMAL;
307 : : TALLOC_CTX *tmp_ctx;
308 : 0 : bool ret = false;
309 : :
310 : : sss_krb5_princ_realm(ctx, principal, &realm_name, &realm_len);
311 : :
312 : 0 : tmp_ctx = talloc_new(NULL);
313 [ # # ]: 0 : if (!tmp_ctx) {
314 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_new failed\n"));
[ # # ][ # # ]
[ # # ]
315 : : return false;
316 : : }
317 : :
318 [ # # ]: 0 : if (pattern_primary) {
319 : 0 : tmp_len = strlen(pattern_primary);
320 [ # # ]: 0 : if (pattern_primary[tmp_len-1] == '*') {
321 : 0 : mode = MODE_PREFIX;
322 : 0 : primary_str = talloc_strdup(tmp_ctx, pattern_primary);
323 : 0 : primary_str[tmp_len-1] = '\0';
324 : 0 : primary_str_len = tmp_len-1;
325 [ # # ]: 0 : } else if (pattern_primary[0] == '*') {
326 : 0 : mode = MODE_POSTFIX;
327 : 0 : primary_str = talloc_strdup(tmp_ctx, pattern_primary+1);
328 : 0 : primary_str_len = tmp_len-1;
329 : : }
330 : :
331 : 0 : sss_krb5_unparse_name_flags(ctx, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM,
332 : : &primary);
333 : :
334 : 0 : len_diff = strlen(primary)-primary_str_len;
335 : :
336 [ # # ][ # # ]: 0 : if ((mode == MODE_NORMAL &&
337 [ # # ]: 0 : strcmp(primary, pattern_primary) != 0) ||
338 [ # # ]: 0 : (mode == MODE_PREFIX &&
339 [ # # ]: 0 : strncmp(primary, primary_str, primary_str_len) != 0) ||
340 [ # # ]: 0 : (mode == MODE_POSTFIX &&
341 : 0 : strcmp(primary+len_diff, primary_str) != 0)) {
342 : : goto done;
343 : : }
344 : : }
345 : :
346 [ # # ][ # # ]: 0 : if (!pattern_realm || (realm_len == strlen(pattern_realm) &&
[ # # ]
347 : 0 : strncmp(realm_name, pattern_realm, realm_len) == 0)) {
348 [ # # ][ # # ]: 0 : DEBUG(7, ("Principal matched to the sample (%s@%s).\n", pattern_primary,
[ # # ][ # # ]
[ # # ]
349 : : pattern_realm));
350 : : ret = true;
351 : : }
352 : :
353 : : done:
354 : 0 : free(primary);
355 : 0 : talloc_free(tmp_ctx);
356 : : return ret;
357 : : }
358 : :
359 : 0 : krb5_error_code find_principal_in_keytab(krb5_context ctx,
360 : : krb5_keytab keytab,
361 : : const char *pattern_primary,
362 : : const char *pattern_realm,
363 : : krb5_principal *princ)
364 : : {
365 : : krb5_error_code kerr;
366 : : krb5_error_code kt_err;
367 : : krb5_error_code kerr_d;
368 : : krb5_kt_cursor cursor;
369 : : krb5_keytab_entry entry;
370 : 0 : bool principal_found = false;
371 : :
372 : 0 : memset(&cursor, 0, sizeof(cursor));
373 : 0 : kerr = krb5_kt_start_seq_get(ctx, keytab, &cursor);
374 [ # # ]: 0 : if (kerr != 0) {
375 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_kt_start_seq_get failed.\n"));
[ # # ][ # # ]
[ # # ]
376 : : return kerr;
377 : : }
378 : :
379 [ # # ][ # # ]: 0 : DEBUG(9, ("Trying to find principal %s@%s in keytab.\n", pattern_primary, pattern_realm));
[ # # ][ # # ]
[ # # ]
380 : 0 : memset(&entry, 0, sizeof(entry));
381 [ # # ]: 0 : while ((kt_err = krb5_kt_next_entry(ctx, keytab, &entry, &cursor)) == 0) {
382 : 0 : principal_found = match_principal(ctx, entry.principal, pattern_primary, pattern_realm);
383 [ # # ]: 0 : if (principal_found) {
384 : : break;
385 : : }
386 : :
387 : 0 : kerr = sss_krb5_free_keytab_entry_contents(ctx, &entry);
388 [ # # ]: 0 : if (kerr != 0) {
389 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to free keytab entry.\n"));
[ # # ][ # # ]
[ # # ]
390 : : }
391 : 0 : memset(&entry, 0, sizeof(entry));
392 : : }
393 : :
394 : : /* Close the keytab here. Even though we're using cursors, the file
395 : : * handle is stored in the krb5_keytab structure, and it gets
396 : : * overwritten by other keytab calls, creating a leak. */
397 : 0 : kerr = krb5_kt_end_seq_get(ctx, keytab, &cursor);
398 [ # # ]: 0 : if (kerr != 0) {
399 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_kt_end_seq_get failed.\n"));
[ # # ][ # # ]
[ # # ]
400 : : goto done;
401 : : }
402 : :
403 [ # # ]: 0 : if (!principal_found) {
404 : 0 : kerr = KRB5_KT_NOTFOUND;
405 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC,
[ # # ][ # # ]
[ # # ]
406 : : ("No principal matching %s@%s found in keytab.\n",
407 : : pattern_primary, pattern_realm));
408 : : goto done;
409 : : }
410 : :
411 : : /* check if we got any errors from krb5_kt_next_entry */
412 [ # # ]: 0 : if (kt_err != 0 && kt_err != KRB5_KT_END) {
413 [ # # ][ # # ]: 0 : DEBUG(1, ("Error while reading keytab.\n"));
[ # # ][ # # ]
[ # # ]
414 : : goto done;
415 : : }
416 : :
417 : 0 : kerr = krb5_copy_principal(ctx, entry.principal, princ);
418 [ # # ]: 0 : if (kerr != 0) {
419 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_copy_principal failed.\n"));
[ # # ][ # # ]
[ # # ]
420 : : goto done;
421 : : }
422 : :
423 : : kerr = 0;
424 : :
425 : : done:
426 : 0 : kerr_d = sss_krb5_free_keytab_entry_contents(ctx, &entry);
427 [ # # ]: 0 : if (kerr_d != 0) {
428 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to free keytab entry.\n"));
[ # # ][ # # ]
[ # # ]
429 : : }
430 : :
431 : : return kerr;
432 : : }
433 : :
434 : 0 : const char *KRB5_CALLCONV sss_krb5_get_error_message(krb5_context ctx,
435 : : krb5_error_code ec)
436 : : {
437 : : #ifdef HAVE_KRB5_GET_ERROR_MESSAGE
438 : 0 : return krb5_get_error_message(ctx, ec);
439 : : #else
440 : : int ret;
441 : : char *s = NULL;
442 : : int size = sizeof("Kerberos error [XXXXXXXXXXXX]");
443 : :
444 : : s = malloc(sizeof(char) * (size));
445 : : if (s == NULL) {
446 : : return NULL;
447 : : }
448 : :
449 : : ret = snprintf(s, size, "Kerberos error [%12d]", ec);
450 : :
451 : : if (ret < 0 || ret >= size) {
452 : : return NULL;
453 : : }
454 : :
455 : : return s;
456 : : #endif
457 : : }
458 : :
459 : 0 : void KRB5_CALLCONV sss_krb5_free_error_message(krb5_context ctx, const char *s)
460 : : {
461 : : #ifdef HAVE_KRB5_GET_ERROR_MESSAGE
462 : 0 : krb5_free_error_message(ctx, s);
463 : : #else
464 : : free(s);
465 : : #endif
466 : :
467 : 0 : return;
468 : : }
469 : :
470 : 0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_alloc(
471 : : krb5_context context,
472 : : krb5_get_init_creds_opt **opt)
473 : : {
474 : : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
475 : 0 : return krb5_get_init_creds_opt_alloc(context, opt);
476 : : #else
477 : : *opt = calloc(1, sizeof(krb5_get_init_creds_opt));
478 : : if (*opt == NULL) {
479 : : return ENOMEM;
480 : : }
481 : : krb5_get_init_creds_opt_init(*opt);
482 : :
483 : : return 0;
484 : : #endif
485 : : }
486 : :
487 : 0 : void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
488 : : krb5_get_init_creds_opt *opt)
489 : : {
490 : : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
491 : 0 : krb5_get_init_creds_opt_free(context, opt);
492 : : #else
493 : : free(opt);
494 : : #endif
495 : :
496 : 0 : return;
497 : : }
498 : :
499 : 0 : void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
500 : : {
501 : : #ifdef HAVE_KRB5_FREE_UNPARSED_NAME
502 : 0 : krb5_free_unparsed_name(context, name);
503 : : #else
504 : : if (name != NULL) {
505 : : memset(name, 0, strlen(name));
506 : : free(name);
507 : : }
508 : : #endif
509 : 0 : }
510 : :
511 : :
512 : 0 : krb5_error_code check_for_valid_tgt(krb5_context context,
513 : : krb5_ccache ccache, const char *realm,
514 : : const char *client_princ_str, bool *result)
515 : : {
516 : : krb5_error_code krberr;
517 : 0 : TALLOC_CTX *tmp_ctx = NULL;
518 : : krb5_creds mcred;
519 : : krb5_creds cred;
520 : 0 : char *server_name = NULL;
521 : 0 : krb5_principal client_principal = NULL;
522 : 0 : krb5_principal server_principal = NULL;
523 : :
524 : 0 : *result = false;
525 : :
526 : 0 : tmp_ctx = talloc_new(NULL);
527 [ # # ]: 0 : if (tmp_ctx == NULL) {
528 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_new failed.\n"));
[ # # ][ # # ]
[ # # ]
529 : : return ENOMEM;
530 : : }
531 : :
532 : 0 : server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
533 [ # # ]: 0 : if (server_name == NULL) {
534 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_asprintf failed.\n"));
[ # # ][ # # ]
[ # # ]
535 : : krberr = ENOMEM;
536 : : goto done;
537 : : }
538 : :
539 : 0 : krberr = krb5_parse_name(context, server_name, &server_principal);
540 [ # # ]: 0 : if (krberr != 0) {
541 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_parse_name failed.\n"));
[ # # ][ # # ]
[ # # ]
542 : : goto done;
543 : : }
544 : :
545 : 0 : krberr = krb5_parse_name(context, client_princ_str, &client_principal);
546 [ # # ]: 0 : if (krberr != 0) {
547 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_parse_name failed.\n"));
[ # # ][ # # ]
[ # # ]
548 : : goto done;
549 : : }
550 : :
551 : 0 : memset(&mcred, 0, sizeof(mcred));
552 : 0 : memset(&cred, 0, sizeof(mcred));
553 : 0 : mcred.client = client_principal;
554 : 0 : mcred.server = server_principal;
555 : :
556 : 0 : krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
557 [ # # ]: 0 : if (krberr != 0) {
558 [ # # ][ # # ]: 0 : DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
[ # # ][ # # ]
[ # # ]
559 : : krberr = 0;
560 : : goto done;
561 : : }
562 : :
563 [ # # ][ # # ]: 0 : DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
[ # # ][ # # ]
[ # # ]
564 : :
565 [ # # ]: 0 : if (cred.times.endtime > time(NULL)) {
566 [ # # ][ # # ]: 0 : DEBUG(3, ("TGT is valid.\n"));
[ # # ][ # # ]
[ # # ]
567 : 0 : *result = true;
568 : : }
569 : 0 : krb5_free_cred_contents(context, &cred);
570 : :
571 : : krberr = 0;
572 : :
573 : : done:
574 [ # # ]: 0 : if (client_principal != NULL) {
575 : 0 : krb5_free_principal(context, client_principal);
576 : : }
577 [ # # ]: 0 : if (server_principal != NULL) {
578 : 0 : krb5_free_principal(context, server_principal);
579 : : }
580 : 0 : talloc_free(tmp_ctx);
581 : : return krberr;
582 : : }
583 : :
584 : 0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback(
585 : : krb5_context context,
586 : : krb5_get_init_creds_opt *opt,
587 : : krb5_expire_callback_func cb,
588 : : void *data)
589 : : {
590 : : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_EXPIRE_CALLBACK
591 : 0 : return krb5_get_init_creds_opt_set_expire_callback(context, opt, cb, data);
592 : : #else
593 : : DEBUG(5, ("krb5_get_init_creds_opt_set_expire_callback not available.\n"));
594 : : return 0;
595 : : #endif
596 : : }
597 : :
598 : 0 : errno_t check_fast(const char *str, bool *use_fast)
599 : : {
600 : : #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS
601 [ # # ]: 0 : if (strcasecmp(str, "never") == 0 ) {
602 : 0 : *use_fast = false;
603 [ # # ][ # # ]: 0 : } else if (strcasecmp(str, "try") == 0 || strcasecmp(str, "demand") == 0) {
604 : 0 : *use_fast = true;
605 : : } else {
606 : 0 : sss_log(SSS_LOG_ALERT, "Unsupported value [%s] for option krb5_use_fast,"
607 : : "please use never, try, or demand.\n");
608 : 0 : return EINVAL;
609 : : }
610 : :
611 : : return EOK;
612 : : #else
613 : : sss_log(SSS_LOG_ALERT, "This build of sssd done not support FAST. "
614 : : "Please remove option krb5_use_fast.\n");
615 : : return EINVAL;
616 : : #endif
617 : : }
618 : :
619 : 0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_ccache_name(
620 : : krb5_context context,
621 : : krb5_get_init_creds_opt *opt,
622 : : const char *fast_ccache_name)
623 : : {
624 : : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME
625 : 0 : return krb5_get_init_creds_opt_set_fast_ccache_name(context, opt,
626 : : fast_ccache_name);
627 : : #else
628 : : DEBUG(5, ("krb5_get_init_creds_opt_set_fast_ccache_name not available.\n"));
629 : : return 0;
630 : : #endif
631 : : }
632 : :
633 : 0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags(
634 : : krb5_context context,
635 : : krb5_get_init_creds_opt *opt,
636 : : krb5_flags flags)
637 : : {
638 : : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS
639 : 0 : return krb5_get_init_creds_opt_set_fast_flags(context, opt, flags);
640 : : #else
641 : : DEBUG(5, ("krb5_get_init_creds_opt_set_fast_flags not available.\n"));
642 : : return 0;
643 : : #endif
644 : : }
645 : :
646 : :
647 : : #ifndef HAVE_KRB5_UNPARSE_NAME_FLAGS
648 : : #ifndef REALM_SEP
649 : : #define REALM_SEP '@'
650 : : #endif
651 : : #ifndef COMPONENT_SEP
652 : : #define COMPONENT_SEP '/'
653 : : #endif
654 : :
655 : : static int
656 : : sss_krb5_copy_component_quoting(char *dest, const krb5_data *src, int flags)
657 : : {
658 : : int j;
659 : : const char *cp = src->data;
660 : : char *q = dest;
661 : : int length = src->length;
662 : :
663 : : if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) {
664 : : memcpy(dest, src->data, src->length);
665 : : return src->length;
666 : : }
667 : :
668 : : for (j=0; j < length; j++,cp++) {
669 : : int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
670 : : !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
671 : :
672 : : switch (*cp) {
673 : : case REALM_SEP:
674 : : if (no_realm) {
675 : : *q++ = *cp;
676 : : break;
677 : : }
678 : : case COMPONENT_SEP:
679 : : case '\\':
680 : : *q++ = '\\';
681 : : *q++ = *cp;
682 : : break;
683 : : case '\t':
684 : : *q++ = '\\';
685 : : *q++ = 't';
686 : : break;
687 : : case '\n':
688 : : *q++ = '\\';
689 : : *q++ = 'n';
690 : : break;
691 : : case '\b':
692 : : *q++ = '\\';
693 : : *q++ = 'b';
694 : : break;
695 : : case '\0':
696 : : *q++ = '\\';
697 : : *q++ = '0';
698 : : break;
699 : : default:
700 : : *q++ = *cp;
701 : : }
702 : : }
703 : : return q - dest;
704 : : }
705 : :
706 : : static int
707 : : sss_krb5_component_length_quoted(const krb5_data *src, int flags)
708 : : {
709 : : const char *cp = src->data;
710 : : int length = src->length;
711 : : int j;
712 : : int size = length;
713 : :
714 : : if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) {
715 : : int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
716 : : !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
717 : :
718 : : for (j = 0; j < length; j++,cp++)
719 : : if ((!no_realm && *cp == REALM_SEP) ||
720 : : *cp == COMPONENT_SEP ||
721 : : *cp == '\0' || *cp == '\\' || *cp == '\t' ||
722 : : *cp == '\n' || *cp == '\b')
723 : : size++;
724 : : }
725 : :
726 : : return size;
727 : : }
728 : :
729 : : #endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
730 : :
731 : :
732 : : krb5_error_code
733 : 0 : sss_krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal,
734 : : int flags, char **name)
735 : : {
736 : : #ifdef HAVE_KRB5_UNPARSE_NAME_FLAGS
737 : 0 : return krb5_unparse_name_flags(context, principal, flags, name);
738 : : #else
739 : : char *cp, *q;
740 : : int i;
741 : : int length;
742 : : krb5_int32 nelem;
743 : : unsigned int totalsize = 0;
744 : : char *default_realm = NULL;
745 : : krb5_error_code ret = 0;
746 : :
747 : : if (name != NULL)
748 : : *name = NULL;
749 : :
750 : : if (!principal || !name)
751 : : return KRB5_PARSE_MALFORMED;
752 : :
753 : : if (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) {
754 : : /* omit realm if local realm */
755 : : krb5_principal_data p;
756 : :
757 : : ret = krb5_get_default_realm(context, &default_realm);
758 : : if (ret != 0)
759 : : goto cleanup;
760 : :
761 : : krb5_princ_realm(context, &p)->length = strlen(default_realm);
762 : : krb5_princ_realm(context, &p)->data = default_realm;
763 : :
764 : : if (krb5_realm_compare(context, &p, principal))
765 : : flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
766 : : }
767 : :
768 : : if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
769 : : totalsize += sss_krb5_component_length_quoted(krb5_princ_realm(context,
770 : : principal),
771 : : flags);
772 : : totalsize++;
773 : : }
774 : :
775 : : nelem = krb5_princ_size(context, principal);
776 : : for (i = 0; i < (int) nelem; i++) {
777 : : cp = krb5_princ_component(context, principal, i)->data;
778 : : totalsize += sss_krb5_component_length_quoted(krb5_princ_component(context, principal, i), flags);
779 : : totalsize++;
780 : : }
781 : : if (nelem == 0)
782 : : totalsize++;
783 : :
784 : : *name = malloc(totalsize);
785 : :
786 : : if (!*name) {
787 : : ret = ENOMEM;
788 : : goto cleanup;
789 : : }
790 : :
791 : : q = *name;
792 : :
793 : : for (i = 0; i < (int) nelem; i++) {
794 : : cp = krb5_princ_component(context, principal, i)->data;
795 : : length = krb5_princ_component(context, principal, i)->length;
796 : : q += sss_krb5_copy_component_quoting(q,
797 : : krb5_princ_component(context,
798 : : principal,
799 : : i),
800 : : flags);
801 : : *q++ = COMPONENT_SEP;
802 : : }
803 : :
804 : : if (i > 0)
805 : : q--;
806 : : if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
807 : : *q++ = REALM_SEP;
808 : : q += sss_krb5_copy_component_quoting(q, krb5_princ_realm(context, principal), flags);
809 : : }
810 : : *q++ = '\0';
811 : :
812 : : cleanup:
813 : : free(default_realm);
814 : :
815 : : return ret;
816 : : #endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
817 : : }
818 : :
819 : 0 : void sss_krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opts,
820 : : int canonicalize)
821 : : {
822 : : /* FIXME: The extra check for HAVE_KRB5_TICKET_TIMES is a workaround due to Heimdal
823 : : * defining krb5_get_init_creds_opt_set_canonicalize() with a different set of
824 : : * arguments. We should use a better configure check in the future.
825 : : */
826 : : #if defined(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CANONICALIZE) && defined(HAVE_KRB5_TICKET_TIMES)
827 : 0 : krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize);
828 : : #else
829 : : DEBUG(SSSDBG_OP_FAILURE, ("Kerberos principal canonicalization is not available!\n"));
830 : : #endif
831 : 0 : }
832 : :
833 : : #ifdef HAVE_KRB5_PRINCIPAL_GET_REALM
834 : : void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
835 : : const char **realm, int *len)
836 : : {
837 : : *realm = krb5_principal_get_realm(context, princ);
838 : : *len = strlen(*realm);
839 : : }
840 : : #else
841 : 0 : void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
842 : : const char **realm, int *len)
843 : : {
844 : : const krb5_data *data;
845 : :
846 : 0 : data = krb5_princ_realm(context, princ);
847 [ # # ][ # # ]: 0 : if (data) {
[ # # ]
848 : 0 : *realm = data->data;
849 : 0 : *len = data->length;
850 : : } else {
851 : 0 : *realm = NULL;
852 : 0 : *len = 0;
853 : : }
854 : 0 : }
855 : : #endif
856 : :
857 : : #ifdef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS
858 : : krb5_error_code
859 : 0 : sss_krb5_free_keytab_entry_contents(krb5_context context,
860 : : krb5_keytab_entry *entry)
861 : : {
862 : 0 : return krb5_free_keytab_entry_contents(context, entry);
863 : : }
864 : : #else
865 : : krb5_error_code
866 : : sss_krb5_free_keytab_entry_contents(krb5_context context,
867 : : krb5_keytab_entry *entry)
868 : : {
869 : : return krb5_kt_free_entry(context, entry);
870 : : }
871 : : #endif
872 : :
873 : : #define SSS_KRB5_FILE "FILE:"
874 : : #define SSS_KRB5_DIR "DIR:"
875 : :
876 : : enum sss_krb5_cc_type
877 : 2 : sss_krb5_get_type(const char *full_location)
878 : : {
879 [ + - ]: 2 : if (!full_location) {
880 : : return SSS_KRB5_TYPE_UNKNOWN;
881 : : }
882 : :
883 [ + - ]: 2 : if (strncmp(full_location, SSS_KRB5_FILE,
884 : : sizeof(SSS_KRB5_FILE)-1) == 0) {
885 : : return SSS_KRB5_TYPE_FILE;
886 : : }
887 : : #ifdef HAVE_KRB5_DIRCACHE
888 [ - + ]: 2 : else if (strncmp(full_location, SSS_KRB5_DIR,
889 : : sizeof(SSS_KRB5_DIR)-1) == 0) {
890 : : return SSS_KRB5_TYPE_DIR;
891 : : }
892 : : #endif /* HAVE_KRB5_DIRCACHE */
893 [ # # ]: 0 : else if (full_location[0] == '/') {
894 : : return SSS_KRB5_TYPE_FILE;
895 : : }
896 : :
897 : 2 : return SSS_KRB5_TYPE_UNKNOWN;
898 : : }
899 : :
900 : : const char *
901 : 0 : sss_krb5_residual_by_type(const char *full_location,
902 : : enum sss_krb5_cc_type type)
903 : : {
904 : : size_t offset;
905 : :
906 [ + - # # ]: 2 : if (full_location == NULL) return NULL;
[ # # ]
907 : :
908 [ - + - ]: 2 : switch (type) {
[ # # # ]
[ # # # ]
909 : : case SSS_KRB5_TYPE_FILE:
910 [ # # ][ # # ]: 0 : if (full_location[0] == '/') {
[ # # ]
911 : : offset = 0;
912 : : } else {
913 : 0 : offset = sizeof(SSS_KRB5_FILE)-1;
914 : : }
915 : : break;
916 : : #ifdef HAVE_KRB5_DIRCACHE
917 : : case SSS_KRB5_TYPE_DIR:
918 : : offset = sizeof(SSS_KRB5_DIR)-1;
919 : : break;
920 : : #endif /* HAVE_KRB5_DIRCACHE */
921 : : default:
922 : : return NULL;
923 : : }
924 : :
925 : 2 : return full_location + offset;
926 : : }
927 : :
928 : : const char *
929 : 0 : sss_krb5_cc_file_path(const char *full_location)
930 : : {
931 : : enum sss_krb5_cc_type cc_type;
932 : : const char *residual;
933 : :
934 : 0 : cc_type = sss_krb5_get_type(full_location);
935 : 0 : residual = sss_krb5_residual_by_type(full_location, cc_type);
936 : :
937 [ # # # ]: 0 : switch(cc_type) {
938 : : case SSS_KRB5_TYPE_FILE:
939 : 0 : return residual;
940 : : #ifdef HAVE_KRB5_DIRCACHE
941 : : case SSS_KRB5_TYPE_DIR:
942 : : /* DIR::/run/user/tkt_foo */
943 [ # # ]: 0 : if (residual[0] == ':') return residual+1;
944 : : #endif
945 : : case SSS_KRB5_TYPE_UNKNOWN:
946 : : break;
947 : : }
948 : :
949 : : return NULL;
950 : : }
951 : :
952 : : const char *
953 : 2 : sss_krb5_residual_check_type(const char *full_location,
954 : : enum sss_krb5_cc_type expected_type)
955 : : {
956 : : enum sss_krb5_cc_type type;
957 : :
958 : 2 : type = sss_krb5_get_type(full_location);
959 [ - + ]: 2 : if (type != expected_type) {
960 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Unexpected ccache type\n"));
[ # # ][ # # ]
[ # # ]
961 : : return NULL;
962 : : }
963 : :
964 : 2 : return sss_krb5_residual_by_type(full_location, type);
965 : : }
966 : :
967 : : #ifdef HAVE_KRB5_SET_TRACE_CALLBACK
968 : : static void
969 : 0 : sss_child_krb5_trace_cb(krb5_context context,
970 : : const struct krb5_trace_info *info, void *data)
971 : : {
972 [ # # ]: 0 : if (info == NULL) {
973 : : /* Null info means destroy the callback data. */
974 : 0 : return;
975 : : }
976 : :
977 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_ALL, ("%s\n", info->message));
[ # # ][ # # ]
[ # # ]
978 : : }
979 : :
980 : : errno_t
981 : 0 : sss_child_set_krb5_tracing(krb5_context ctx)
982 : : {
983 : 0 : return krb5_set_trace_callback(ctx, sss_child_krb5_trace_cb, NULL);
984 : : }
985 : : #else /* HAVE_KRB5_SET_TRACE_CALLBACK */
986 : : errno_t
987 : : sss_child_set_krb5_tracing(krb5_context ctx)
988 : : {
989 : : DEBUG(SSSDBG_CONF_SETTINGS, ("krb5 tracing is not available\n"));
990 : : return 0;
991 : : }
992 : : #endif /* HAVE_KRB5_SET_TRACE_CALLBACK */
993 : :
994 : 0 : krb5_error_code sss_krb5_find_authdata(krb5_context context,
995 : : krb5_authdata *const *ticket_authdata,
996 : : krb5_authdata *const *ap_req_authdata,
997 : : krb5_authdatatype ad_type,
998 : : krb5_authdata ***results)
999 : : {
1000 : : #ifdef HAVE_KRB5_FIND_AUTHDATA
1001 : 0 : return krb5_find_authdata(context, ticket_authdata, ap_req_authdata,
1002 : : ad_type, results);
1003 : : #else
1004 : : return ENOTSUP;
1005 : : #endif
1006 : : }
1007 : :
1008 : 0 : krb5_error_code sss_extract_pac(krb5_context ctx,
1009 : : krb5_ccache ccache,
1010 : : krb5_principal server_principal,
1011 : : krb5_principal client_principal,
1012 : : krb5_keytab keytab,
1013 : : krb5_authdata ***_pac_authdata)
1014 : : {
1015 : : #ifdef HAVE_PAC_RESPONDER
1016 : : krb5_error_code kerr;
1017 : : krb5_creds mcred;
1018 : : krb5_creds cred;
1019 : : krb5_authdata **pac_authdata = NULL;
1020 : : krb5_pac pac = NULL;
1021 : : int ret;
1022 : : krb5_ticket *ticket = NULL;
1023 : : krb5_keytab_entry entry;
1024 : :
1025 : : memset(&entry, 0, sizeof(entry));
1026 : : memset(&mcred, 0, sizeof(mcred));
1027 : : memset(&cred, 0, sizeof(mcred));
1028 : :
1029 : : mcred.server = server_principal;
1030 : : mcred.client = client_principal;
1031 : :
1032 : : kerr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred);
1033 : : if (kerr != 0) {
1034 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_cc_retrieve_cred failed.\n"));
1035 : : goto done;
1036 : : }
1037 : :
1038 : : kerr = krb5_decode_ticket(&cred.ticket, &ticket);
1039 : : if (kerr != 0) {
1040 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_decode_ticket failed.\n"));
1041 : : goto done;
1042 : : }
1043 : :
1044 : : kerr = krb5_server_decrypt_ticket_keytab(ctx, keytab, ticket);
1045 : : if (kerr != 0) {
1046 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_server_decrypt_ticket_keytab failed.\n"));
1047 : : goto done;
1048 : : }
1049 : :
1050 : : kerr = sss_krb5_find_authdata(ctx,
1051 : : ticket->enc_part2->authorization_data, NULL,
1052 : : KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata);
1053 : : if (kerr != 0) {
1054 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_find_authdata failed.\n"));
1055 : : goto done;
1056 : : }
1057 : :
1058 : : if (pac_authdata == NULL || pac_authdata[0] == NULL) {
1059 : : DEBUG(SSSDBG_OP_FAILURE, ("No PAC authdata available.\n"));
1060 : : kerr = ENOENT;
1061 : : goto done;
1062 : : }
1063 : :
1064 : : if (pac_authdata[1] != NULL) {
1065 : : DEBUG(SSSDBG_OP_FAILURE, ("More than one PAC autdata found.\n"));
1066 : : kerr = EINVAL;
1067 : : goto done;
1068 : : }
1069 : :
1070 : : kerr = krb5_pac_parse(ctx, pac_authdata[0]->contents,
1071 : : pac_authdata[0]->length, &pac);
1072 : : if (kerr != 0) {
1073 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_pac_parse failed.\n"));
1074 : : goto done;
1075 : : }
1076 : :
1077 : : kerr = krb5_kt_get_entry(ctx, keytab, ticket->server,
1078 : : ticket->enc_part.kvno, ticket->enc_part.enctype,
1079 : : &entry);
1080 : : if (kerr != 0) {
1081 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_kt_get_entry failed.\n"));
1082 : : goto done;
1083 : : }
1084 : :
1085 : : kerr = krb5_pac_verify(ctx, pac, 0, NULL, &entry.key, NULL);
1086 : : if (kerr != 0) {
1087 : : DEBUG(SSSDBG_OP_FAILURE, ("krb5_pac_verify failed.\n"));
1088 : : goto done;
1089 : : }
1090 : :
1091 : : ret = unsetenv("_SSS_LOOPS");
1092 : : if (ret != EOK) {
1093 : : DEBUG(1, ("Failed to unset _SSS_LOOPS, "
1094 : : "sss_pac_make_request will most certainly fail.\n"));
1095 : : }
1096 : :
1097 : : *_pac_authdata = pac_authdata;
1098 : : kerr = 0;
1099 : :
1100 : : done:
1101 : : if (kerr != 0) {
1102 : : krb5_free_authdata(ctx, pac_authdata);
1103 : : }
1104 : : if (entry.magic != 0) {
1105 : : krb5_free_keytab_entry_contents(ctx, &entry);
1106 : : }
1107 : : krb5_pac_free(ctx, pac);
1108 : : if (ticket != NULL) {
1109 : : krb5_free_ticket(ctx, ticket);
1110 : : }
1111 : :
1112 : : krb5_free_cred_contents(ctx, &cred);
1113 : : return kerr;
1114 : : #else
1115 : 0 : return ENOTSUP;
1116 : : #endif
1117 : : }
|