credentials: set GSS_KRB5_CRED_NO_CI_FLAGS_X to avoid GSS_C_CONF_FLAG and GSS_C_INTEG...
[metze/samba/wip.git] / source / auth / credentials / credentials_krb5.c
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, 
33                                               struct event_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, 
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, 
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)
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) {
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, 
131                                         struct event_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, 
207                                       struct event_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, 
258                                         struct event_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, 
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, 
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)
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, 
354                                          struct event_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         if (cred->client_gss_creds_obtained >= cred->client_gss_creds_threshold && 
363             cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
364                 *_gcc = cred->client_gss_creds;
365                 return 0;
366         }
367         ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx, 
368                                          &ccache);
369         if (ret) {
370                 DEBUG(1, ("Failed to get CCACHE for GSSAPI client: %s\n", error_message(ret)));
371                 return ret;
372         }
373
374         gcc = talloc(cred, struct gssapi_creds_container);
375         if (!gcc) {
376                 return ENOMEM;
377         }
378
379         maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL, 
380                                         &gcc->creds);
381         if (maj_stat) {
382                 talloc_free(gcc);
383                 if (min_stat) {
384                         ret = min_stat;
385                 } else {
386                         ret = EINVAL;
387                 }
388                 return ret;
389         }
390
391         /* don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG */
392         maj_stat = gss_set_cred_option(&min_stat, gcc->creds,
393                                        GSS_KRB5_CRED_NO_CI_FLAGS_X,
394                                        GSS_C_NO_BUFFER);
395         if (maj_stat) {
396                 talloc_free(gcc);
397                 if (min_stat) {
398                         ret = min_stat;
399                 } else {
400                         ret = EINVAL;
401                 }
402                 return ret;
403         }
404
405         cred->client_gss_creds_obtained = cred->ccache_obtained;
406         talloc_set_destructor(gcc, free_gssapi_creds);
407         cred->client_gss_creds = gcc;
408         *_gcc = gcc;
409         return 0;
410 }
411
412 /**
413    Set a gssapi cred_id_t into the credentials system. (Client case)
414
415    This grabs the credentials both 'intact' and getting the krb5
416    ccache out of it.  This routine can be generalised in future for
417    the case where we deal with GSSAPI mechs other than krb5.  
418
419    On sucess, the caller must not free gssapi_cred, as it now belongs
420    to the credentials system.
421 */
422
423  int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, 
424                                           struct event_context *event_ctx,
425                                           struct loadparm_context *lp_ctx,
426                                           gss_cred_id_t gssapi_cred,
427                                           enum credentials_obtained obtained) 
428 {
429         int ret;
430         OM_uint32 maj_stat, min_stat;
431         struct ccache_container *ccc;
432         struct gssapi_creds_container *gcc;
433         if (cred->client_gss_creds_obtained > obtained) {
434                 return 0;
435         }
436
437         gcc = talloc(cred, struct gssapi_creds_container);
438         if (!gcc) {
439                 return ENOMEM;
440         }
441
442         ret = cli_credentials_new_ccache(cred, event_ctx, lp_ctx, &ccc);
443         if (ret != 0) {
444                 return ret;
445         }
446
447         maj_stat = gss_krb5_copy_ccache(&min_stat, 
448                                         gssapi_cred, ccc->ccache);
449         if (maj_stat) {
450                 if (min_stat) {
451                         ret = min_stat;
452                 } else {
453                         ret = EINVAL;
454                 }
455         }
456
457         if (ret == 0) {
458                 ret = cli_credentials_set_from_ccache(cred, ccc, obtained);
459         }
460         cred->ccache = ccc;
461         cred->ccache_obtained = obtained;
462         if (ret == 0) {
463                 gcc->creds = gssapi_cred;
464                 talloc_set_destructor(gcc, free_gssapi_creds);
465                 
466                 /* set the clinet_gss_creds_obtained here, as it just 
467                    got set to UNINITIALISED by the calls above */
468                 cred->client_gss_creds_obtained = obtained;
469                 cred->client_gss_creds = gcc;
470         }
471         return ret;
472 }
473
474 /* Get the keytab (actually, a container containing the krb5_keytab)
475  * attached to this context.  If this hasn't been done or set before,
476  * it will be generated from the password.
477  */
478 _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred, 
479                                         struct event_context *event_ctx,
480                                struct loadparm_context *lp_ctx,
481                                struct keytab_container **_ktc)
482 {
483         krb5_error_code ret;
484         struct keytab_container *ktc;
485         struct smb_krb5_context *smb_krb5_context;
486         const char **enctype_strings;
487         TALLOC_CTX *mem_ctx;
488
489         if (cred->keytab_obtained >= (MAX(cred->principal_obtained, 
490                                           cred->username_obtained))) {
491                 *_ktc = cred->keytab;
492                 return 0;
493         }
494
495         if (cli_credentials_is_anonymous(cred)) {
496                 return EINVAL;
497         }
498
499         ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, 
500                                                &smb_krb5_context);
501         if (ret) {
502                 return ret;
503         }
504
505         mem_ctx = talloc_new(cred);
506         if (!mem_ctx) {
507                 return ENOMEM;
508         }
509
510         enctype_strings = cli_credentials_get_enctype_strings(cred);
511         
512         ret = smb_krb5_create_memory_keytab(mem_ctx, cred, 
513                                             smb_krb5_context, 
514                                             enctype_strings, &ktc);
515         if (ret) {
516                 talloc_free(mem_ctx);
517                 return ret;
518         }
519
520         cred->keytab_obtained = (MAX(cred->principal_obtained, 
521                                      cred->username_obtained));
522
523         talloc_steal(cred, ktc);
524         cred->keytab = ktc;
525         *_ktc = cred->keytab;
526         talloc_free(mem_ctx);
527         return ret;
528 }
529
530 /* Given the name of a keytab (presumably in the format
531  * FILE:/etc/krb5.keytab), open it and attach it */
532
533 _PUBLIC_ int cli_credentials_set_keytab_name(struct cli_credentials *cred, 
534                                              struct event_context *event_ctx,
535                                     struct loadparm_context *lp_ctx,
536                                     const char *keytab_name, 
537                                     enum credentials_obtained obtained) 
538 {
539         krb5_error_code ret;
540         struct keytab_container *ktc;
541         struct smb_krb5_context *smb_krb5_context;
542         TALLOC_CTX *mem_ctx;
543
544         if (cred->keytab_obtained >= obtained) {
545                 return 0;
546         }
547
548         ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
549         if (ret) {
550                 return ret;
551         }
552
553         mem_ctx = talloc_new(cred);
554         if (!mem_ctx) {
555                 return ENOMEM;
556         }
557
558         ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, 
559                                    keytab_name, &ktc);
560         if (ret) {
561                 return ret;
562         }
563
564         cred->keytab_obtained = obtained;
565
566         talloc_steal(cred, ktc);
567         cred->keytab = ktc;
568         talloc_free(mem_ctx);
569
570         return ret;
571 }
572
573 _PUBLIC_ int cli_credentials_update_keytab(struct cli_credentials *cred, 
574                                            struct event_context *event_ctx,
575                                   struct loadparm_context *lp_ctx) 
576 {
577         krb5_error_code ret;
578         struct keytab_container *ktc;
579         struct smb_krb5_context *smb_krb5_context;
580         const char **enctype_strings;
581         TALLOC_CTX *mem_ctx;
582         
583         mem_ctx = talloc_new(cred);
584         if (!mem_ctx) {
585                 return ENOMEM;
586         }
587
588         ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
589         if (ret) {
590                 talloc_free(mem_ctx);
591                 return ret;
592         }
593
594         enctype_strings = cli_credentials_get_enctype_strings(cred);
595         
596         ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
597         if (ret != 0) {
598                 talloc_free(mem_ctx);
599                 return ret;
600         }
601
602         ret = smb_krb5_update_keytab(mem_ctx, cred, smb_krb5_context, enctype_strings, ktc);
603
604         talloc_free(mem_ctx);
605         return ret;
606 }
607
608 /* Get server gss credentials (in gsskrb5, this means the keytab) */
609
610 _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred, 
611                                                   struct event_context *event_ctx,
612                                          struct loadparm_context *lp_ctx,
613                                          struct gssapi_creds_container **_gcc) 
614 {
615         int ret = 0;
616         OM_uint32 maj_stat, min_stat;
617         struct gssapi_creds_container *gcc;
618         struct keytab_container *ktc;
619         struct smb_krb5_context *smb_krb5_context;
620         TALLOC_CTX *mem_ctx;
621         krb5_principal princ;
622
623         if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, 
624                                                     MAX(cred->principal_obtained, 
625                                                         cred->username_obtained)))) {
626                 *_gcc = cred->server_gss_creds;
627                 return 0;
628         }
629
630         ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
631         if (ret) {
632                 return ret;
633         }
634
635         ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
636         if (ret) {
637                 DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
638                 return ret;
639         }
640
641         mem_ctx = talloc_new(cred);
642         if (!mem_ctx) {
643                 return ENOMEM;
644         }
645
646         ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ);
647         if (ret) {
648                 DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
649                          smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
650                                                     ret, mem_ctx)));
651                 talloc_free(mem_ctx);
652                 return ret;
653         }
654
655         gcc = talloc(cred, struct gssapi_creds_container);
656         if (!gcc) {
657                 talloc_free(mem_ctx);
658                 return ENOMEM;
659         }
660
661         /* This creates a GSSAPI cred_id_t with the principal and keytab set */
662         maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab, 
663                                         &gcc->creds);
664         if (maj_stat) {
665                 if (min_stat) {
666                         ret = min_stat;
667                 } else {
668                         ret = EINVAL;
669                 }
670         }
671         if (ret == 0) {
672                 cred->server_gss_creds_obtained = cred->keytab_obtained;
673                 talloc_set_destructor(gcc, free_gssapi_creds);
674                 cred->server_gss_creds = gcc;
675                 *_gcc = gcc;
676         }
677         talloc_free(mem_ctx);
678         return ret;
679 }
680
681 /** 
682  * Set Kerberos KVNO
683  */
684
685 _PUBLIC_ void cli_credentials_set_kvno(struct cli_credentials *cred,
686                               int kvno)
687 {
688         cred->kvno = kvno;
689 }
690
691 /**
692  * Return Kerberos KVNO
693  */
694
695 _PUBLIC_ int cli_credentials_get_kvno(struct cli_credentials *cred)
696 {
697         return cred->kvno;
698 }
699
700
701 const char **cli_credentials_get_enctype_strings(struct cli_credentials *cred) 
702 {
703         /* If this is ever made user-configurable, we need to add code
704          * to remove/hide the other entries from the generated
705          * keytab */
706         static const char *default_enctypes[] = {
707                 "des-cbc-md5",
708                 "aes256-cts-hmac-sha1-96",
709                 "des3-cbc-sha1",
710                 "arcfour-hmac-md5",
711                 NULL
712         };
713         return default_enctypes;
714 }
715
716 const char *cli_credentials_get_salt_principal(struct cli_credentials *cred) 
717 {
718         return cred->salt_principal;
719 }
720
721 _PUBLIC_ void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char *principal) 
722 {
723         cred->salt_principal = talloc_strdup(cred, principal);
724 }
725
726