Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Kerberos utility functions for GENSEC
5 :
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "system/kerberos.h"
25 : #include "auth/kerberos/kerberos.h"
26 : #include "auth/credentials/credentials.h"
27 : #include "auth/credentials/credentials_krb5.h"
28 : #include "auth/kerberos/kerberos_credentials.h"
29 : #include "auth/kerberos/kerberos_util.h"
30 :
31 : struct principal_container {
32 : struct smb_krb5_context *smb_krb5_context;
33 : krb5_principal principal;
34 : const char *string_form; /* Optional */
35 : };
36 :
37 56398 : static krb5_error_code free_principal(struct principal_container *pc)
38 : {
39 : /* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
40 56398 : krb5_free_principal(pc->smb_krb5_context->krb5_context, pc->principal);
41 :
42 56398 : return 0;
43 : }
44 :
45 :
46 68856 : static krb5_error_code parse_principal(TALLOC_CTX *parent_ctx,
47 : const char *princ_string,
48 : struct smb_krb5_context *smb_krb5_context,
49 : krb5_principal *princ,
50 : const char **error_string)
51 : {
52 : int ret;
53 : struct principal_container *mem_ctx;
54 68856 : if (princ_string == NULL) {
55 12458 : *princ = NULL;
56 12458 : return 0;
57 : }
58 :
59 56398 : ret = krb5_parse_name(smb_krb5_context->krb5_context,
60 : princ_string, princ);
61 :
62 56398 : if (ret) {
63 0 : (*error_string) = smb_get_krb5_error_message(
64 : smb_krb5_context->krb5_context,
65 : ret, parent_ctx);
66 0 : return ret;
67 : }
68 :
69 56398 : mem_ctx = talloc(parent_ctx, struct principal_container);
70 56398 : if (!mem_ctx) {
71 0 : (*error_string) = error_message(ENOMEM);
72 0 : return ENOMEM;
73 : }
74 :
75 : /* This song-and-dance effectivly puts the principal
76 : * into talloc, so we can't loose it. */
77 56398 : mem_ctx->smb_krb5_context = talloc_reference(mem_ctx,
78 : smb_krb5_context);
79 56398 : mem_ctx->principal = *princ;
80 56398 : talloc_set_destructor(mem_ctx, free_principal);
81 56398 : return 0;
82 : }
83 :
84 : /* Obtain the principal set on this context. Requires a
85 : * smb_krb5_context because we are doing krb5 principal parsing with
86 : * the library routines. The returned princ is placed in the talloc
87 : * system by means of a destructor (do *not* free). */
88 :
89 56362 : krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
90 : struct cli_credentials *credentials,
91 : struct smb_krb5_context *smb_krb5_context,
92 : krb5_principal *princ,
93 : enum credentials_obtained *obtained,
94 : const char **error_string)
95 : {
96 : krb5_error_code ret;
97 : const char *princ_string;
98 56362 : TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
99 56362 : *obtained = CRED_UNINITIALISED;
100 :
101 56362 : if (!mem_ctx) {
102 0 : (*error_string) = error_message(ENOMEM);
103 0 : return ENOMEM;
104 : }
105 56362 : princ_string = cli_credentials_get_principal_and_obtained(credentials,
106 : mem_ctx,
107 : obtained);
108 56362 : if (!princ_string) {
109 5 : *princ = NULL;
110 5 : return 0;
111 : }
112 :
113 56357 : ret = parse_principal(parent_ctx, princ_string,
114 : smb_krb5_context, princ, error_string);
115 56357 : talloc_free(mem_ctx);
116 56357 : return ret;
117 : }
118 :
119 : /* Obtain the principal set on this context. Requires a
120 : * smb_krb5_context because we are doing krb5 principal parsing with
121 : * the library routines. The returned princ is placed in the talloc
122 : * system by means of a destructor (do *not* free). */
123 :
124 12204 : static krb5_error_code impersonate_principal_from_credentials(
125 : TALLOC_CTX *parent_ctx,
126 : struct cli_credentials *credentials,
127 : struct smb_krb5_context *smb_krb5_context,
128 : krb5_principal *princ,
129 : const char **error_string)
130 : {
131 12499 : return parse_principal(parent_ctx,
132 : cli_credentials_get_impersonate_principal(credentials),
133 : smb_krb5_context, princ, error_string);
134 : }
135 :
136 326 : krb5_error_code smb_krb5_create_principals_array(TALLOC_CTX *mem_ctx,
137 : krb5_context context,
138 : const char *account_name,
139 : const char *realm,
140 : uint32_t num_spns,
141 : const char *spns[],
142 : uint32_t *pnum_principals,
143 : krb5_principal **pprincipals,
144 : const char **error_string)
145 : {
146 : krb5_error_code code;
147 : TALLOC_CTX *tmp_ctx;
148 326 : uint32_t num_principals = 0;
149 : krb5_principal *principals;
150 : uint32_t i;
151 :
152 326 : tmp_ctx = talloc_new(mem_ctx);
153 326 : if (tmp_ctx == NULL) {
154 0 : *error_string = "Cannot allocate tmp_ctx";
155 0 : return ENOMEM;
156 : }
157 :
158 326 : if (realm == NULL) {
159 0 : *error_string = "Cannot create principal without a realm";
160 0 : code = EINVAL;
161 0 : goto done;
162 : }
163 :
164 326 : if (account_name == NULL && (num_spns == 0 || spns == NULL)) {
165 0 : *error_string = "Cannot create principal without an account or SPN";
166 0 : code = EINVAL;
167 0 : goto done;
168 : }
169 :
170 326 : if (account_name != NULL && account_name[0] != '\0') {
171 326 : num_principals++;
172 : }
173 326 : num_principals += num_spns;
174 :
175 326 : principals = talloc_zero_array(tmp_ctx,
176 : krb5_principal,
177 : num_principals);
178 326 : if (principals == NULL) {
179 0 : *error_string = "Cannot allocate principals";
180 0 : code = ENOMEM;
181 0 : goto done;
182 : }
183 :
184 763 : for (i = 0; i < num_spns; i++) {
185 462 : code = krb5_parse_name(context, spns[i], &(principals[i]));
186 462 : if (code != 0) {
187 0 : *error_string = smb_get_krb5_error_message(context,
188 : code,
189 : mem_ctx);
190 0 : goto done;
191 : }
192 : }
193 :
194 326 : if (account_name != NULL && account_name[0] != '\0') {
195 326 : code = smb_krb5_make_principal(context,
196 326 : &(principals[i]),
197 : realm,
198 : account_name,
199 : NULL);
200 326 : if (code != 0) {
201 0 : *error_string = smb_get_krb5_error_message(context,
202 : code,
203 : mem_ctx);
204 0 : goto done;
205 : }
206 : }
207 :
208 326 : if (pnum_principals != NULL) {
209 326 : *pnum_principals = num_principals;
210 :
211 326 : if (pprincipals != NULL) {
212 326 : *pprincipals = talloc_steal(mem_ctx, principals);
213 : }
214 : }
215 :
216 301 : code = 0;
217 326 : done:
218 326 : talloc_free(tmp_ctx);
219 326 : return code;
220 : }
221 :
222 : /**
223 : * Return a freshly allocated ccache (destroyed by destructor on child
224 : * of parent_ctx), for a given set of client credentials
225 : */
226 :
227 12501 : krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
228 : struct cli_credentials *credentials,
229 : struct smb_krb5_context *smb_krb5_context,
230 : struct tevent_context *event_ctx,
231 : krb5_ccache ccache,
232 : enum credentials_obtained *obtained,
233 : const char **error_string)
234 : {
235 : krb5_error_code ret;
236 : const char *password;
237 : #ifdef SAMBA4_USES_HEIMDAL
238 : const char *self_service;
239 : #endif
240 : const char *target_service;
241 12501 : time_t kdc_time = 0;
242 : krb5_principal princ;
243 : krb5_principal impersonate_principal;
244 : int tries;
245 12501 : TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
246 : krb5_get_init_creds_opt *krb_options;
247 :
248 12501 : if (!mem_ctx) {
249 0 : (*error_string) = strerror(ENOMEM);
250 0 : return ENOMEM;
251 : }
252 :
253 12501 : ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ, obtained, error_string);
254 12501 : if (ret) {
255 0 : talloc_free(mem_ctx);
256 0 : return ret;
257 : }
258 :
259 12501 : if (princ == NULL) {
260 2 : (*error_string) = talloc_asprintf(credentials, "principal, username or realm was not specified in the credentials");
261 2 : talloc_free(mem_ctx);
262 2 : return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
263 : }
264 :
265 12499 : ret = impersonate_principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &impersonate_principal, error_string);
266 12499 : if (ret) {
267 0 : talloc_free(mem_ctx);
268 0 : return ret;
269 : }
270 :
271 : #ifdef SAMBA4_USES_HEIMDAL
272 9675 : self_service = cli_credentials_get_self_service(credentials);
273 : #endif
274 12499 : target_service = cli_credentials_get_target_service(credentials);
275 :
276 12499 : password = cli_credentials_get_password(credentials);
277 :
278 : /* setup the krb5 options we want */
279 12499 : if ((ret = krb5_get_init_creds_opt_alloc(smb_krb5_context->krb5_context, &krb_options))) {
280 0 : (*error_string) = talloc_asprintf(credentials, "krb5_get_init_creds_opt_alloc failed (%s)\n",
281 : smb_get_krb5_error_message(smb_krb5_context->krb5_context,
282 : ret, mem_ctx));
283 0 : talloc_free(mem_ctx);
284 0 : return ret;
285 : }
286 :
287 : #ifdef SAMBA4_USES_HEIMDAL /* Disable for now MIT reads defaults when needed */
288 : /* get the defaults */
289 9675 : krb5_get_init_creds_opt_set_default_flags(smb_krb5_context->krb5_context, NULL, NULL, krb_options);
290 : #endif
291 : /* set if we want a forwardable ticket */
292 12499 : switch (cli_credentials_get_krb_forwardable(credentials)) {
293 12185 : case CRED_AUTO_KRB_FORWARDABLE:
294 12185 : break;
295 19 : case CRED_NO_KRB_FORWARDABLE:
296 19 : krb5_get_init_creds_opt_set_forwardable(krb_options, FALSE);
297 19 : break;
298 0 : case CRED_FORCE_KRB_FORWARDABLE:
299 0 : krb5_get_init_creds_opt_set_forwardable(krb_options, TRUE);
300 0 : break;
301 : }
302 :
303 : #ifdef SAMBA4_USES_HEIMDAL /* FIXME: MIT does not have this yet */
304 : /*
305 : * In order to work against windows KDCs even if we use
306 : * the netbios domain name as realm, we need to add the following
307 : * flags:
308 : * KRB5_INIT_CREDS_NO_C_CANON_CHECK;
309 : * KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK;
310 : *
311 : * On MIT: Set pkinit_eku_checking to none
312 : */
313 9675 : krb5_get_init_creds_opt_set_win2k(smb_krb5_context->krb5_context,
314 : krb_options, true);
315 9675 : krb5_get_init_creds_opt_set_canonicalize(smb_krb5_context->krb5_context,
316 : krb_options, true);
317 : #else /* MIT */
318 2824 : krb5_get_init_creds_opt_set_canonicalize(krb_options, true);
319 : #endif
320 :
321 12499 : tries = 2;
322 21879 : while (tries--) {
323 : #ifdef SAMBA4_USES_HEIMDAL
324 : struct tevent_context *previous_ev;
325 : /* Do this every time, in case we have weird recursive issues here */
326 9675 : ret = smb_krb5_context_set_event_ctx(smb_krb5_context, event_ctx, &previous_ev);
327 9675 : if (ret) {
328 0 : talloc_free(mem_ctx);
329 1 : return ret;
330 : }
331 : #endif
332 12499 : if (password) {
333 12482 : if (impersonate_principal) {
334 : #ifdef SAMBA4_USES_HEIMDAL
335 41 : ret = smb_krb5_kinit_s4u2_ccache(smb_krb5_context->krb5_context,
336 : ccache,
337 : princ,
338 : password,
339 : impersonate_principal,
340 : self_service,
341 : target_service,
342 : krb_options,
343 : NULL,
344 : &kdc_time);
345 : #else
346 0 : talloc_free(mem_ctx);
347 0 : (*error_string) = "INTERNAL error: s4u2 ops "
348 : "are not supported with MIT build yet";
349 0 : return EINVAL;
350 : #endif
351 : } else {
352 12441 : ret = smb_krb5_kinit_password_ccache(smb_krb5_context->krb5_context,
353 : ccache,
354 : princ,
355 : password,
356 : target_service,
357 : krb_options,
358 : NULL,
359 : &kdc_time);
360 : }
361 17 : } else if (impersonate_principal) {
362 0 : talloc_free(mem_ctx);
363 0 : (*error_string) = "INTERNAL error: Cannot impersonate principal with just a keyblock. A password must be specified in the credentials";
364 0 : return EINVAL;
365 : } else {
366 : /* No password available, try to use a keyblock instead */
367 :
368 : krb5_keyblock keyblock;
369 : const struct samr_Password *mach_pwd;
370 17 : mach_pwd = cli_credentials_get_nt_hash(credentials, mem_ctx);
371 17 : if (!mach_pwd) {
372 2 : talloc_free(mem_ctx);
373 2 : (*error_string) = "kinit_to_ccache: No password available for kinit\n";
374 2 : krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
375 : #ifdef SAMBA4_USES_HEIMDAL
376 1 : smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
377 : #endif
378 2 : return EINVAL;
379 : }
380 15 : ret = smb_krb5_keyblock_init_contents(smb_krb5_context->krb5_context,
381 : ENCTYPE_ARCFOUR_HMAC,
382 15 : mach_pwd->hash, sizeof(mach_pwd->hash),
383 : &keyblock);
384 :
385 15 : if (ret == 0) {
386 15 : ret = smb_krb5_kinit_keyblock_ccache(smb_krb5_context->krb5_context,
387 : ccache,
388 : princ,
389 : &keyblock,
390 : target_service,
391 : krb_options,
392 : NULL,
393 : &kdc_time);
394 15 : krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
395 : }
396 : }
397 :
398 : #ifdef SAMBA4_USES_HEIMDAL
399 9674 : smb_krb5_context_remove_event_ctx(smb_krb5_context, previous_ev, event_ctx);
400 : #endif
401 :
402 12497 : if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
403 : /* Perhaps we have been given an invalid skew, so try again without it */
404 0 : time_t t = time(NULL);
405 0 : krb5_set_real_time(smb_krb5_context->krb5_context, t, 0);
406 : } else {
407 : /* not a skew problem */
408 : break;
409 : }
410 : }
411 :
412 12497 : krb5_get_init_creds_opt_free(smb_krb5_context->krb5_context, krb_options);
413 :
414 12497 : if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
415 0 : (*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
416 : cli_credentials_get_principal(credentials, mem_ctx),
417 : smb_get_krb5_error_message(smb_krb5_context->krb5_context,
418 : ret, mem_ctx));
419 0 : talloc_free(mem_ctx);
420 0 : return ret;
421 : }
422 :
423 : /* cope with ticket being in the future due to clock skew */
424 12497 : if ((unsigned)kdc_time > time(NULL)) {
425 0 : time_t t = time(NULL);
426 0 : int time_offset =(unsigned)kdc_time-t;
427 0 : DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
428 0 : krb5_set_real_time(smb_krb5_context->krb5_context, t + time_offset + 1, 0);
429 : }
430 :
431 12497 : if (ret == KRB5KDC_ERR_PREAUTH_FAILED && cli_credentials_wrong_password(credentials)) {
432 0 : ret = kinit_to_ccache(parent_ctx,
433 : credentials,
434 : smb_krb5_context,
435 : event_ctx,
436 : ccache, obtained,
437 : error_string);
438 : }
439 :
440 12497 : if (ret) {
441 1067 : (*error_string) = talloc_asprintf(credentials, "kinit for %s failed (%s)\n",
442 : cli_credentials_get_principal(credentials, mem_ctx),
443 : smb_get_krb5_error_message(smb_krb5_context->krb5_context,
444 : ret, mem_ctx));
445 1067 : talloc_free(mem_ctx);
446 1067 : return ret;
447 : }
448 :
449 11430 : DEBUG(10,("kinit for %s succeeded\n",
450 : cli_credentials_get_principal(credentials, mem_ctx)));
451 :
452 :
453 11430 : talloc_free(mem_ctx);
454 11430 : return 0;
455 : }
456 :
457 53516 : static krb5_error_code free_keytab_container(struct keytab_container *ktc)
458 : {
459 53516 : return krb5_kt_close(ktc->smb_krb5_context->krb5_context, ktc->keytab);
460 : }
461 :
462 53465 : krb5_error_code smb_krb5_get_keytab_container(TALLOC_CTX *mem_ctx,
463 : struct smb_krb5_context *smb_krb5_context,
464 : krb5_keytab opt_keytab,
465 : const char *keytab_name,
466 : struct keytab_container **ktc)
467 : {
468 : krb5_keytab keytab;
469 : krb5_error_code ret;
470 :
471 53465 : if (opt_keytab) {
472 85 : keytab = opt_keytab;
473 : } else {
474 53380 : ret = krb5_kt_resolve(smb_krb5_context->krb5_context,
475 : keytab_name, &keytab);
476 53380 : if (ret) {
477 0 : DEBUG(1,("failed to open krb5 keytab: %s\n",
478 : smb_get_krb5_error_message(
479 : smb_krb5_context->krb5_context,
480 : ret, mem_ctx)));
481 0 : return ret;
482 : }
483 : }
484 :
485 53465 : *ktc = talloc(mem_ctx, struct keytab_container);
486 53465 : if (!*ktc) {
487 0 : return ENOMEM;
488 : }
489 :
490 53465 : (*ktc)->smb_krb5_context = talloc_reference(*ktc, smb_krb5_context);
491 53465 : (*ktc)->keytab = keytab;
492 53465 : (*ktc)->password_based = false;
493 53465 : talloc_set_destructor(*ktc, free_keytab_container);
494 :
495 53465 : return 0;
496 : }
497 :
498 : /*
499 : * Walk the keytab, looking for entries of this principal name,
500 : * with KVNO other than current kvno -1.
501 : *
502 : * These entries are now stale,
503 : * we only keep the current and previous entries around.
504 : *
505 : * Inspired by the code in Samba3 for 'use kerberos keytab'.
506 : */
507 328 : krb5_error_code smb_krb5_remove_obsolete_keytab_entries(TALLOC_CTX *mem_ctx,
508 : krb5_context context,
509 : krb5_keytab keytab,
510 : uint32_t num_principals,
511 : krb5_principal *principals,
512 : krb5_kvno kvno,
513 : bool *found_previous,
514 : const char **error_string)
515 : {
516 : TALLOC_CTX *tmp_ctx;
517 : krb5_error_code code;
518 : krb5_kt_cursor cursor;
519 :
520 328 : tmp_ctx = talloc_new(mem_ctx);
521 328 : if (tmp_ctx == NULL) {
522 0 : *error_string = "Cannot allocate tmp_ctx";
523 0 : return ENOMEM;
524 : }
525 :
526 328 : *found_previous = true;
527 :
528 328 : code = krb5_kt_start_seq_get(context, keytab, &cursor);
529 328 : switch (code) {
530 141 : case 0:
531 141 : break;
532 : #ifdef HEIM_ERR_OPNOTSUPP
533 0 : case HEIM_ERR_OPNOTSUPP:
534 : #endif
535 160 : case ENOENT:
536 : case KRB5_KT_END:
537 : /* no point enumerating if there isn't anything here */
538 160 : code = 0;
539 160 : goto done;
540 0 : default:
541 0 : *error_string = talloc_asprintf(mem_ctx,
542 : "failed to open keytab for read of old entries: %s\n",
543 : smb_get_krb5_error_message(context, code, mem_ctx));
544 0 : goto done;
545 : }
546 :
547 1948 : do {
548 2395 : krb5_kvno old_kvno = kvno - 1;
549 : krb5_keytab_entry entry;
550 2395 : bool matched = false;
551 : uint32_t i;
552 :
553 2395 : code = krb5_kt_next_entry(context, keytab, &entry, &cursor);
554 2395 : if (code) {
555 255 : break;
556 : }
557 :
558 5016 : for (i = 0; i < num_principals; i++) {
559 : krb5_boolean ok;
560 :
561 4684 : ok = smb_krb5_kt_compare(context,
562 : &entry,
563 4684 : principals[i],
564 : 0,
565 : 0);
566 4684 : if (ok) {
567 1563 : matched = true;
568 1563 : break;
569 : }
570 : }
571 :
572 2248 : if (!matched) {
573 : /*
574 : * Free the entry, it wasn't the one we were looking
575 : * for anyway
576 : */
577 528 : krb5_kt_free_entry(context, &entry);
578 : /* Make sure we do not double free */
579 528 : ZERO_STRUCT(entry);
580 528 : continue;
581 : }
582 :
583 : /*
584 : * Delete it, if it is not kvno - 1.
585 : *
586 : * Some keytab files store the kvno only in 8bits. Limit the
587 : * compare to 8bits, so that we don't miss old keys and delete
588 : * them.
589 : */
590 1720 : if ((entry.vno & 0xff) != (old_kvno & 0xff)) {
591 : krb5_error_code rc;
592 :
593 : /* Release the enumeration. We are going to
594 : * have to start this from the top again,
595 : * because deletes during enumeration may not
596 : * always be consistent.
597 : *
598 : * Also, the enumeration locks a FILE: keytab
599 : */
600 369 : krb5_kt_end_seq_get(context, keytab, &cursor);
601 :
602 369 : code = krb5_kt_remove_entry(context, keytab, &entry);
603 369 : krb5_kt_free_entry(context, &entry);
604 :
605 : /* Make sure we do not double free */
606 369 : ZERO_STRUCT(entry);
607 :
608 : /* Deleted: Restart from the top */
609 369 : rc = krb5_kt_start_seq_get(context, keytab, &cursor);
610 369 : if (rc != 0) {
611 0 : krb5_kt_free_entry(context, &entry);
612 :
613 : /* Make sure we do not double free */
614 0 : ZERO_STRUCT(entry);
615 :
616 0 : DEBUG(1, ("failed to restart enumeration of keytab: %s\n",
617 : smb_get_krb5_error_message(context,
618 : code,
619 : tmp_ctx)));
620 :
621 0 : talloc_free(tmp_ctx);
622 0 : return rc;
623 : }
624 :
625 369 : if (code != 0) {
626 0 : break;
627 : }
628 :
629 : } else {
630 1351 : *found_previous = true;
631 : }
632 :
633 : /* Free the entry, we don't need it any more */
634 1720 : krb5_kt_free_entry(context, &entry);
635 : /* Make sure we do not double free */
636 1720 : ZERO_STRUCT(entry);
637 2248 : } while (code == 0);
638 :
639 147 : krb5_kt_end_seq_get(context, keytab, &cursor);
640 :
641 147 : switch (code) {
642 0 : case 0:
643 0 : break;
644 141 : case ENOENT:
645 : case KRB5_KT_END:
646 141 : break;
647 0 : default:
648 0 : *error_string = talloc_asprintf(mem_ctx,
649 : "failed in deleting old entries for principal: %s\n",
650 : smb_get_krb5_error_message(context,
651 : code,
652 : mem_ctx));
653 : }
654 :
655 141 : code = 0;
656 328 : done:
657 328 : talloc_free(tmp_ctx);
658 328 : return code;
659 : }
|