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