/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- cli_credentials_get_krb5_context
- cli_credentials_set_krb5_context
- cli_credentials_set_from_ccache
- free_mccache
- free_dccache
- cli_credentials_set_ccache
- cli_credentials_new_ccache
- cli_credentials_get_ccache
- cli_credentials_invalidate_client_gss_creds
- cli_credentials_invalidate_ccache
- free_gssapi_creds
- cli_credentials_get_client_gss_creds
- cli_credentials_set_client_gss_creds
- cli_credentials_get_keytab
- cli_credentials_set_keytab_name
- cli_credentials_update_keytab
- cli_credentials_get_server_gss_creds
- cli_credentials_set_kvno
- cli_credentials_get_kvno
- cli_credentials_get_enctype_strings
- cli_credentials_get_salt_principal
- cli_credentials_set_salt_principal
1 /*
2 Unix SMB/CIFS implementation.
3
4 Handle user credentials (as regards krb5)
5
6 Copyright (C) Jelmer Vernooij 2005
7 Copyright (C) Tim Potter 2001
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "system/kerberos.h"
26 #include "auth/kerberos/kerberos.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/credentials/credentials_proto.h"
29 #include "auth/credentials/credentials_krb5.h"
30 #include "param/param.h"
31
32 _PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
33 struct tevent_context *event_ctx,
34 struct loadparm_context *lp_ctx,
35 struct smb_krb5_context **smb_krb5_context)
36 {
37 int ret;
38 if (cred->smb_krb5_context) {
39 *smb_krb5_context = cred->smb_krb5_context;
40 return 0;
41 }
42
43 ret = smb_krb5_init_context(cred, event_ctx, lp_ctx, &cred->smb_krb5_context);
44 if (ret) {
45 cred->smb_krb5_context = NULL;
46 return ret;
47 }
48 *smb_krb5_context = cred->smb_krb5_context;
49 return 0;
50 }
51
52 /* This needs to be called directly after the cli_credentials_init(),
53 * otherwise we might have problems with the krb5 context already
54 * being here.
55 */
56 _PUBLIC_ NTSTATUS cli_credentials_set_krb5_context(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
57 struct smb_krb5_context *smb_krb5_context)
58 {
59 if (!talloc_reference(cred, smb_krb5_context)) {
60 return NT_STATUS_NO_MEMORY;
61 }
62 cred->smb_krb5_context = smb_krb5_context;
63 return NT_STATUS_OK;
64 }
65
66 static int cli_credentials_set_from_ccache(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
67 struct ccache_container *ccache,
68 enum credentials_obtained obtained)
69 {
70
71 krb5_principal princ;
72 krb5_error_code ret;
73 char *name;
74 char **realm;
75
76 if (cred->ccache_obtained > obtained) {
77 return 0;
78 }
79
80 ret = krb5_cc_get_principal(ccache->smb_krb5_context->krb5_context,
81 ccache->ccache, &princ);
82
83 if (ret) {
84 char *err_mess = smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context,
85 ret, cred);
86 DEBUG(1,("failed to get principal from ccache: %s\n",
87 err_mess));
88 talloc_free(err_mess);
89 return ret;
90 }
91
92 ret = krb5_unparse_name(ccache->smb_krb5_context->krb5_context, princ, &name);
93 if (ret) {
94 char *err_mess = smb_get_krb5_error_message(ccache->smb_krb5_context->krb5_context, ret, cred);
95 DEBUG(1,("failed to unparse principal from ccache: %s\n",
96 err_mess));
97 talloc_free(err_mess);
98 return ret;
99 }
100
101 realm = krb5_princ_realm(ccache->smb_krb5_context->krb5_context, princ);
102
103 cli_credentials_set_principal(cred, name, obtained);
104
105 free(name);
106
107 krb5_free_principal(ccache->smb_krb5_context->krb5_context, princ);
108
109 /* set the ccache_obtained here, as it just got set to UNINITIALISED by the calls above */
110 cred->ccache_obtained = obtained;
111
112 return 0;
113 }
114
115 /* Free a memory ccache */
116 static int free_mccache(struct ccache_container *ccc)
/* [<][>][^][v][top][bottom][index][help] */
117 {
118 krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache);
119
120 return 0;
121 }
122
123 /* Free a disk-based ccache */
124 static int free_dccache(struct ccache_container *ccc) {
/* [<][>][^][v][top][bottom][index][help] */
125 krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache);
126
127 return 0;
128 }
129
130 _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
131 struct tevent_context *event_ctx,
132 struct loadparm_context *lp_ctx,
133 const char *name,
134 enum credentials_obtained obtained)
135 {
136 krb5_error_code ret;
137 krb5_principal princ;
138 struct ccache_container *ccc;
139 if (cred->ccache_obtained > obtained) {
140 return 0;
141 }
142
143 ccc = talloc(cred, struct ccache_container);
144 if (!ccc) {
145 return ENOMEM;
146 }
147
148 ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx,
149 &ccc->smb_krb5_context);
150 if (ret) {
151 talloc_free(ccc);
152 return ret;
153 }
154 if (!talloc_reference(ccc, ccc->smb_krb5_context)) {
155 talloc_free(ccc);
156 return ENOMEM;
157 }
158
159 if (name) {
160 ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache);
161 if (ret) {
162 DEBUG(1,("failed to read krb5 ccache: %s: %s\n",
163 name,
164 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
165 talloc_free(ccc);
166 return ret;
167 }
168 } else {
169 ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache);
170 if (ret) {
171 DEBUG(3,("failed to read default krb5 ccache: %s\n",
172 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
173 talloc_free(ccc);
174 return ret;
175 }
176 }
177
178 talloc_set_destructor(ccc, free_dccache);
179
180 ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ);
181
182 if (ret) {
183 DEBUG(3,("failed to get principal from default ccache: %s\n",
184 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
185 talloc_free(ccc);
186 return ret;
187 }
188
189 krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ);
190
191 ret = cli_credentials_set_from_ccache(cred, ccc, obtained);
192
193 if (ret) {
194 return ret;
195 }
196
197 cred->ccache = ccc;
198 cred->ccache_obtained = obtained;
199 talloc_steal(cred, ccc);
200
201 cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained);
202 return 0;
203 }
204
205
206 static int cli_credentials_new_ccache(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
207 struct tevent_context *event_ctx,
208 struct loadparm_context *lp_ctx,
209 struct ccache_container **_ccc)
210 {
211 krb5_error_code ret;
212 struct ccache_container *ccc = talloc(cred, struct ccache_container);
213 char *ccache_name;
214 if (!ccc) {
215 return ENOMEM;
216 }
217
218 ccache_name = talloc_asprintf(ccc, "MEMORY:%p",
219 ccc);
220
221 if (!ccache_name) {
222 talloc_free(ccc);
223 return ENOMEM;
224 }
225
226 ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx,
227 &ccc->smb_krb5_context);
228 if (ret) {
229 talloc_free(ccc);
230 return ret;
231 }
232 if (!talloc_reference(ccc, ccc->smb_krb5_context)) {
233 talloc_free(ccc);
234 return ENOMEM;
235 }
236
237 ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name,
238 &ccc->ccache);
239 if (ret) {
240 DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n",
241 ccache_name,
242 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
243 talloc_free(ccache_name);
244 talloc_free(ccc);
245 return ret;
246 }
247
248 talloc_set_destructor(ccc, free_mccache);
249
250 talloc_free(ccache_name);
251
252 *_ccc = ccc;
253
254 return ret;
255 }
256
257 _PUBLIC_ int cli_credentials_get_ccache(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
258 struct tevent_context *event_ctx,
259 struct loadparm_context *lp_ctx,
260 struct ccache_container **ccc)
261 {
262 krb5_error_code ret;
263
264 if (cred->machine_account_pending) {
265 cli_credentials_set_machine_account(cred, lp_ctx);
266 }
267
268 if (cred->ccache_obtained >= cred->ccache_threshold &&
269 cred->ccache_obtained > CRED_UNINITIALISED) {
270 *ccc = cred->ccache;
271 return 0;
272 }
273 if (cli_credentials_is_anonymous(cred)) {
274 return EINVAL;
275 }
276
277 ret = cli_credentials_new_ccache(cred, event_ctx, lp_ctx, ccc);
278 if (ret) {
279 return ret;
280 }
281
282 ret = kinit_to_ccache(cred, cred, (*ccc)->smb_krb5_context, (*ccc)->ccache);
283 if (ret) {
284 return ret;
285 }
286
287 ret = cli_credentials_set_from_ccache(cred, *ccc,
288 (MAX(MAX(cred->principal_obtained,
289 cred->username_obtained),
290 cred->password_obtained)));
291
292 cred->ccache = *ccc;
293 cred->ccache_obtained = cred->principal_obtained;
294 if (ret) {
295 return ret;
296 }
297 cli_credentials_invalidate_client_gss_creds(cred, cred->ccache_obtained);
298 return ret;
299 }
300
301 void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
302 enum credentials_obtained obtained)
303 {
304 /* If the caller just changed the username/password etc, then
305 * any cached credentials are now invalid */
306 if (obtained >= cred->client_gss_creds_obtained) {
307 if (cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
308 talloc_unlink(cred, cred->client_gss_creds);
309 cred->client_gss_creds = NULL;
310 }
311 cred->client_gss_creds_obtained = CRED_UNINITIALISED;
312 }
313 /* Now that we know that the data is 'this specified', then
314 * don't allow something less 'known' to be returned as a
315 * ccache. Ie, if the username is on the commmand line, we
316 * don't want to later guess to use a file-based ccache */
317 if (obtained > cred->client_gss_creds_threshold) {
318 cred->client_gss_creds_threshold = obtained;
319 }
320 }
321
322 _PUBLIC_ void cli_credentials_invalidate_ccache(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
323 enum credentials_obtained obtained)
324 {
325 /* If the caller just changed the username/password etc, then
326 * any cached credentials are now invalid */
327 if (obtained >= cred->ccache_obtained) {
328 if (cred->ccache_obtained > CRED_UNINITIALISED) {
329 talloc_unlink(cred, cred->ccache);
330 cred->ccache = NULL;
331 }
332 cred->ccache_obtained = CRED_UNINITIALISED;
333 }
334 /* Now that we know that the data is 'this specified', then
335 * don't allow something less 'known' to be returned as a
336 * ccache. Ie, if the username is on the commmand line, we
337 * don't want to later guess to use a file-based ccache */
338 if (obtained > cred->ccache_threshold) {
339 cred->ccache_threshold = obtained;
340 }
341
342 cli_credentials_invalidate_client_gss_creds(cred,
343 obtained);
344 }
345
346 static int free_gssapi_creds(struct gssapi_creds_container *gcc)
/* [<][>][^][v][top][bottom][index][help] */
347 {
348 OM_uint32 min_stat, maj_stat;
349 maj_stat = gss_release_cred(&min_stat, &gcc->creds);
350 return 0;
351 }
352
353 _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
354 struct tevent_context *event_ctx,
355 struct loadparm_context *lp_ctx,
356 struct gssapi_creds_container **_gcc)
357 {
358 int ret = 0;
359 OM_uint32 maj_stat, min_stat;
360 struct gssapi_creds_container *gcc;
361 struct ccache_container *ccache;
362 gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
363 krb5_enctype *etypes = NULL;
364
365 if (cred->client_gss_creds_obtained >= cred->client_gss_creds_threshold &&
366 cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
367 *_gcc = cred->client_gss_creds;
368 return 0;
369 }
370
371 ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx,
372 &ccache);
373 if (ret) {
374 DEBUG(1, ("Failed to get CCACHE for GSSAPI client: %s\n", error_message(ret)));
375 return ret;
376 }
377
378 gcc = talloc(cred, struct gssapi_creds_container);
379 if (!gcc) {
380 return ENOMEM;
381 }
382
383 maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL,
384 &gcc->creds);
385 if (maj_stat) {
386 talloc_free(gcc);
387 if (min_stat) {
388 ret = min_stat;
389 } else {
390 ret = EINVAL;
391 }
392 return ret;
393 }
394
395 /*
396 * transfer the enctypes from the smb_krb5_context to the gssapi layer
397 *
398 * We use 'our' smb_krb5_context to do the AS-REQ and it is possible
399 * to configure the enctypes via the krb5.conf.
400 *
401 * And the gss_init_sec_context() creates it's own krb5_context and
402 * the TGS-REQ had all enctypes in it and only the ones configured
403 * and used for the AS-REQ, so it wasn't possible to disable the usage
404 * of AES keys.
405 */
406 min_stat = krb5_get_default_in_tkt_etypes(ccache->smb_krb5_context->krb5_context,
407 &etypes);
408 if (min_stat == 0) {
409 OM_uint32 num_ktypes;
410
411 for (num_ktypes = 0; etypes[num_ktypes]; num_ktypes++);
412
413 maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, gcc->creds,
414 num_ktypes, etypes);
415 krb5_xfree (etypes);
416 if (maj_stat) {
417 talloc_free(gcc);
418 if (min_stat) {
419 ret = min_stat;
420 } else {
421 ret = EINVAL;
422 }
423 return ret;
424 }
425 }
426
427 /* don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG */
428 maj_stat = gss_set_cred_option(&min_stat, &gcc->creds,
429 GSS_KRB5_CRED_NO_CI_FLAGS_X,
430 &empty_buffer);
431 if (maj_stat) {
432 talloc_free(gcc);
433 if (min_stat) {
434 ret = min_stat;
435 } else {
436 ret = EINVAL;
437 }
438 return ret;
439 }
440
441 cred->client_gss_creds_obtained = cred->ccache_obtained;
442 talloc_set_destructor(gcc, free_gssapi_creds);
443 cred->client_gss_creds = gcc;
444 *_gcc = gcc;
445 return 0;
446 }
447
448 /**
449 Set a gssapi cred_id_t into the credentials system. (Client case)
450
451 This grabs the credentials both 'intact' and getting the krb5
452 ccache out of it. This routine can be generalised in future for
453 the case where we deal with GSSAPI mechs other than krb5.
454
455 On sucess, the caller must not free gssapi_cred, as it now belongs
456 to the credentials system.
457 */
458
459 int cli_credentials_set_client_gss_creds(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
460 struct tevent_context *event_ctx,
461 struct loadparm_context *lp_ctx,
462 gss_cred_id_t gssapi_cred,
463 enum credentials_obtained obtained)
464 {
465 int ret;
466 OM_uint32 maj_stat, min_stat;
467 struct ccache_container *ccc;
468 struct gssapi_creds_container *gcc;
469 if (cred->client_gss_creds_obtained > obtained) {
470 return 0;
471 }
472
473 gcc = talloc(cred, struct gssapi_creds_container);
474 if (!gcc) {
475 return ENOMEM;
476 }
477
478 ret = cli_credentials_new_ccache(cred, event_ctx, lp_ctx, &ccc);
479 if (ret != 0) {
480 return ret;
481 }
482
483 maj_stat = gss_krb5_copy_ccache(&min_stat,
484 gssapi_cred, ccc->ccache);
485 if (maj_stat) {
486 if (min_stat) {
487 ret = min_stat;
488 } else {
489 ret = EINVAL;
490 }
491 }
492
493 if (ret == 0) {
494 ret = cli_credentials_set_from_ccache(cred, ccc, obtained);
495 }
496 cred->ccache = ccc;
497 cred->ccache_obtained = obtained;
498 if (ret == 0) {
499 gcc->creds = gssapi_cred;
500 talloc_set_destructor(gcc, free_gssapi_creds);
501
502 /* set the clinet_gss_creds_obtained here, as it just
503 got set to UNINITIALISED by the calls above */
504 cred->client_gss_creds_obtained = obtained;
505 cred->client_gss_creds = gcc;
506 }
507 return ret;
508 }
509
510 /* Get the keytab (actually, a container containing the krb5_keytab)
511 * attached to this context. If this hasn't been done or set before,
512 * it will be generated from the password.
513 */
514 _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
515 struct tevent_context *event_ctx,
516 struct loadparm_context *lp_ctx,
517 struct keytab_container **_ktc)
518 {
519 krb5_error_code ret;
520 struct keytab_container *ktc;
521 struct smb_krb5_context *smb_krb5_context;
522 const char **enctype_strings;
523 TALLOC_CTX *mem_ctx;
524
525 if (cred->keytab_obtained >= (MAX(cred->principal_obtained,
526 cred->username_obtained))) {
527 *_ktc = cred->keytab;
528 return 0;
529 }
530
531 if (cli_credentials_is_anonymous(cred)) {
532 return EINVAL;
533 }
534
535 ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx,
536 &smb_krb5_context);
537 if (ret) {
538 return ret;
539 }
540
541 mem_ctx = talloc_new(cred);
542 if (!mem_ctx) {
543 return ENOMEM;
544 }
545
546 enctype_strings = cli_credentials_get_enctype_strings(cred);
547
548 ret = smb_krb5_create_memory_keytab(mem_ctx, cred,
549 smb_krb5_context,
550 enctype_strings, &ktc);
551 if (ret) {
552 talloc_free(mem_ctx);
553 return ret;
554 }
555
556 cred->keytab_obtained = (MAX(cred->principal_obtained,
557 cred->username_obtained));
558
559 talloc_steal(cred, ktc);
560 cred->keytab = ktc;
561 *_ktc = cred->keytab;
562 talloc_free(mem_ctx);
563 return ret;
564 }
565
566 /* Given the name of a keytab (presumably in the format
567 * FILE:/etc/krb5.keytab), open it and attach it */
568
569 _PUBLIC_ int cli_credentials_set_keytab_name(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
570 struct tevent_context *event_ctx,
571 struct loadparm_context *lp_ctx,
572 const char *keytab_name,
573 enum credentials_obtained obtained)
574 {
575 krb5_error_code ret;
576 struct keytab_container *ktc;
577 struct smb_krb5_context *smb_krb5_context;
578 TALLOC_CTX *mem_ctx;
579
580 if (cred->keytab_obtained >= obtained) {
581 return 0;
582 }
583
584 ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
585 if (ret) {
586 return ret;
587 }
588
589 mem_ctx = talloc_new(cred);
590 if (!mem_ctx) {
591 return ENOMEM;
592 }
593
594 ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context,
595 keytab_name, &ktc);
596 if (ret) {
597 return ret;
598 }
599
600 cred->keytab_obtained = obtained;
601
602 talloc_steal(cred, ktc);
603 cred->keytab = ktc;
604 talloc_free(mem_ctx);
605
606 return ret;
607 }
608
609 _PUBLIC_ int cli_credentials_update_keytab(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
610 struct tevent_context *event_ctx,
611 struct loadparm_context *lp_ctx)
612 {
613 krb5_error_code ret;
614 struct keytab_container *ktc;
615 struct smb_krb5_context *smb_krb5_context;
616 const char **enctype_strings;
617 TALLOC_CTX *mem_ctx;
618
619 mem_ctx = talloc_new(cred);
620 if (!mem_ctx) {
621 return ENOMEM;
622 }
623
624 ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
625 if (ret) {
626 talloc_free(mem_ctx);
627 return ret;
628 }
629
630 enctype_strings = cli_credentials_get_enctype_strings(cred);
631
632 ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
633 if (ret != 0) {
634 talloc_free(mem_ctx);
635 return ret;
636 }
637
638 ret = smb_krb5_update_keytab(mem_ctx, cred, smb_krb5_context, enctype_strings, ktc);
639
640 talloc_free(mem_ctx);
641 return ret;
642 }
643
644 /* Get server gss credentials (in gsskrb5, this means the keytab) */
645
646 _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
647 struct tevent_context *event_ctx,
648 struct loadparm_context *lp_ctx,
649 struct gssapi_creds_container **_gcc)
650 {
651 int ret = 0;
652 OM_uint32 maj_stat, min_stat;
653 struct gssapi_creds_container *gcc;
654 struct keytab_container *ktc;
655 struct smb_krb5_context *smb_krb5_context;
656 TALLOC_CTX *mem_ctx;
657 krb5_principal princ;
658
659 if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained,
660 MAX(cred->principal_obtained,
661 cred->username_obtained)))) {
662 *_gcc = cred->server_gss_creds;
663 return 0;
664 }
665
666 ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
667 if (ret) {
668 return ret;
669 }
670
671 ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
672 if (ret) {
673 DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
674 return ret;
675 }
676
677 mem_ctx = talloc_new(cred);
678 if (!mem_ctx) {
679 return ENOMEM;
680 }
681
682 ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ);
683 if (ret) {
684 DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
685 smb_get_krb5_error_message(smb_krb5_context->krb5_context,
686 ret, mem_ctx)));
687 talloc_free(mem_ctx);
688 return ret;
689 }
690
691 gcc = talloc(cred, struct gssapi_creds_container);
692 if (!gcc) {
693 talloc_free(mem_ctx);
694 return ENOMEM;
695 }
696
697 /* This creates a GSSAPI cred_id_t with the principal and keytab set */
698 maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab,
699 &gcc->creds);
700 if (maj_stat) {
701 if (min_stat) {
702 ret = min_stat;
703 } else {
704 ret = EINVAL;
705 }
706 }
707 if (ret == 0) {
708 cred->server_gss_creds_obtained = cred->keytab_obtained;
709 talloc_set_destructor(gcc, free_gssapi_creds);
710 cred->server_gss_creds = gcc;
711 *_gcc = gcc;
712 }
713 talloc_free(mem_ctx);
714 return ret;
715 }
716
717 /**
718 * Set Kerberos KVNO
719 */
720
721 _PUBLIC_ void cli_credentials_set_kvno(struct cli_credentials *cred,
/* [<][>][^][v][top][bottom][index][help] */
722 int kvno)
723 {
724 cred->kvno = kvno;
725 }
726
727 /**
728 * Return Kerberos KVNO
729 */
730
731 _PUBLIC_ int cli_credentials_get_kvno(struct cli_credentials *cred)
/* [<][>][^][v][top][bottom][index][help] */
732 {
733 return cred->kvno;
734 }
735
736
737 const char **cli_credentials_get_enctype_strings(struct cli_credentials *cred)
/* [<][>][^][v][top][bottom][index][help] */
738 {
739 /* If this is ever made user-configurable, we need to add code
740 * to remove/hide the other entries from the generated
741 * keytab */
742 static const char *default_enctypes[] = {
743 "des-cbc-md5",
744 "aes256-cts-hmac-sha1-96",
745 "des3-cbc-sha1",
746 "arcfour-hmac-md5",
747 NULL
748 };
749 return default_enctypes;
750 }
751
752 const char *cli_credentials_get_salt_principal(struct cli_credentials *cred)
/* [<][>][^][v][top][bottom][index][help] */
753 {
754 return cred->salt_principal;
755 }
756
757 _PUBLIC_ void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char *principal)
/* [<][>][^][v][top][bottom][index][help] */
758 {
759 cred->salt_principal = talloc_strdup(cred, principal);
760 }
761
762