xref: /freebsd/crypto/krb5/src/kadmin/ktutil/ktutil_funcs.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* kadmin/ktutil/ktutil_funcs.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert  *(C) Copyright 1995, 1996 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  *   require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  *   It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  *   export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert /*
28*7f2fe78bSCy Schubert  * Utility functions for ktutil.
29*7f2fe78bSCy Schubert  */
30*7f2fe78bSCy Schubert 
31*7f2fe78bSCy Schubert #include "k5-int.h"
32*7f2fe78bSCy Schubert #include "k5-hex.h"
33*7f2fe78bSCy Schubert #include "ktutil.h"
34*7f2fe78bSCy Schubert #include <string.h>
35*7f2fe78bSCy Schubert #include <ctype.h>
36*7f2fe78bSCy Schubert 
37*7f2fe78bSCy Schubert /*
38*7f2fe78bSCy Schubert  * Free a kt_list
39*7f2fe78bSCy Schubert  */
ktutil_free_kt_list(context,list)40*7f2fe78bSCy Schubert krb5_error_code ktutil_free_kt_list(context, list)
41*7f2fe78bSCy Schubert     krb5_context context;
42*7f2fe78bSCy Schubert     krb5_kt_list list;
43*7f2fe78bSCy Schubert {
44*7f2fe78bSCy Schubert     krb5_kt_list lp, prev;
45*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
46*7f2fe78bSCy Schubert 
47*7f2fe78bSCy Schubert     for (lp = list; lp;) {
48*7f2fe78bSCy Schubert         retval = krb5_kt_free_entry(context, lp->entry);
49*7f2fe78bSCy Schubert         free(lp->entry);
50*7f2fe78bSCy Schubert         if (retval)
51*7f2fe78bSCy Schubert             break;
52*7f2fe78bSCy Schubert         prev = lp;
53*7f2fe78bSCy Schubert         lp = lp->next;
54*7f2fe78bSCy Schubert         free(prev);
55*7f2fe78bSCy Schubert     }
56*7f2fe78bSCy Schubert     return retval;
57*7f2fe78bSCy Schubert }
58*7f2fe78bSCy Schubert 
59*7f2fe78bSCy Schubert /*
60*7f2fe78bSCy Schubert  * Delete a numbered entry in a kt_list.  Takes a pointer to a kt_list
61*7f2fe78bSCy Schubert  * in case head gets deleted.
62*7f2fe78bSCy Schubert  */
ktutil_delete(context,list,idx)63*7f2fe78bSCy Schubert krb5_error_code ktutil_delete(context, list, idx)
64*7f2fe78bSCy Schubert     krb5_context context;
65*7f2fe78bSCy Schubert     krb5_kt_list *list;
66*7f2fe78bSCy Schubert     int idx;
67*7f2fe78bSCy Schubert {
68*7f2fe78bSCy Schubert     krb5_kt_list lp, prev;
69*7f2fe78bSCy Schubert     int i;
70*7f2fe78bSCy Schubert 
71*7f2fe78bSCy Schubert     for (lp = *list, i = 1; lp; prev = lp, lp = lp->next, i++) {
72*7f2fe78bSCy Schubert         if (i == idx) {
73*7f2fe78bSCy Schubert             if (i == 1)
74*7f2fe78bSCy Schubert                 *list = lp->next;
75*7f2fe78bSCy Schubert             else
76*7f2fe78bSCy Schubert                 prev->next = lp->next;
77*7f2fe78bSCy Schubert             lp->next = NULL;
78*7f2fe78bSCy Schubert             return ktutil_free_kt_list(context, lp);
79*7f2fe78bSCy Schubert         }
80*7f2fe78bSCy Schubert     }
81*7f2fe78bSCy Schubert     return EINVAL;
82*7f2fe78bSCy Schubert }
83*7f2fe78bSCy Schubert 
84*7f2fe78bSCy Schubert /*
85*7f2fe78bSCy Schubert  * Determine the enctype, salt, and s2kparams for princ based on the presence
86*7f2fe78bSCy Schubert  * of the -f flag (fetch), the optionally specified salt string, and the
87*7f2fe78bSCy Schubert  * optionally specified enctype.  If the fetch flag is used, salt_str must not
88*7f2fe78bSCy Schubert  * be given; if the fetch flag is not used, the enctype must be given.
89*7f2fe78bSCy Schubert  */
90*7f2fe78bSCy Schubert static krb5_error_code
get_etype_info(krb5_context context,krb5_principal princ,int fetch,char * salt_str,krb5_enctype * enctype_inout,krb5_data * salt_out,krb5_data * s2kparams_out)91*7f2fe78bSCy Schubert get_etype_info(krb5_context context, krb5_principal princ, int fetch,
92*7f2fe78bSCy Schubert                char *salt_str, krb5_enctype *enctype_inout,
93*7f2fe78bSCy Schubert                krb5_data *salt_out, krb5_data *s2kparams_out)
94*7f2fe78bSCy Schubert {
95*7f2fe78bSCy Schubert     krb5_error_code retval;
96*7f2fe78bSCy Schubert     krb5_enctype enctype;
97*7f2fe78bSCy Schubert     krb5_get_init_creds_opt *opt = NULL;
98*7f2fe78bSCy Schubert     krb5_data salt;
99*7f2fe78bSCy Schubert 
100*7f2fe78bSCy Schubert     *salt_out = empty_data();
101*7f2fe78bSCy Schubert     *s2kparams_out = empty_data();
102*7f2fe78bSCy Schubert 
103*7f2fe78bSCy Schubert     if (!fetch) {
104*7f2fe78bSCy Schubert         /* Use the specified enctype and either the specified or default salt.
105*7f2fe78bSCy Schubert          * Do not produce s2kparams. */
106*7f2fe78bSCy Schubert         assert(*enctype_inout != ENCTYPE_NULL);
107*7f2fe78bSCy Schubert         if (salt_str != NULL) {
108*7f2fe78bSCy Schubert             salt = string2data(salt_str);
109*7f2fe78bSCy Schubert             return krb5int_copy_data_contents(context, &salt, salt_out);
110*7f2fe78bSCy Schubert         } else {
111*7f2fe78bSCy Schubert             return krb5_principal2salt(context, princ, salt_out);
112*7f2fe78bSCy Schubert         }
113*7f2fe78bSCy Schubert     }
114*7f2fe78bSCy Schubert 
115*7f2fe78bSCy Schubert     /* Get etype-info from the KDC. */
116*7f2fe78bSCy Schubert     assert(salt_str == NULL);
117*7f2fe78bSCy Schubert     if (*enctype_inout != ENCTYPE_NULL) {
118*7f2fe78bSCy Schubert         retval = krb5_get_init_creds_opt_alloc(context, &opt);
119*7f2fe78bSCy Schubert         if (retval)
120*7f2fe78bSCy Schubert             return retval;
121*7f2fe78bSCy Schubert         krb5_get_init_creds_opt_set_etype_list(opt, enctype_inout, 1);
122*7f2fe78bSCy Schubert     }
123*7f2fe78bSCy Schubert     retval = krb5_get_etype_info(context, princ, opt, &enctype, salt_out,
124*7f2fe78bSCy Schubert                                  s2kparams_out);
125*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_free(context, opt);
126*7f2fe78bSCy Schubert     if (retval)
127*7f2fe78bSCy Schubert         return retval;
128*7f2fe78bSCy Schubert     if (enctype == ENCTYPE_NULL)
129*7f2fe78bSCy Schubert         return KRB5KDC_ERR_ETYPE_NOSUPP;
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert     *enctype_inout = enctype;
132*7f2fe78bSCy Schubert     return 0;
133*7f2fe78bSCy Schubert }
134*7f2fe78bSCy Schubert 
135*7f2fe78bSCy Schubert /*
136*7f2fe78bSCy Schubert  * Create a new keytab entry and add it to the keytab list.
137*7f2fe78bSCy Schubert  * Based on the value of use_pass, either prompt the user for a
138*7f2fe78bSCy Schubert  * password or key.  If the keytab list is NULL, allocate a new
139*7f2fe78bSCy Schubert  * one first.
140*7f2fe78bSCy Schubert  */
ktutil_add(context,list,princ_str,fetch,kvno,enctype_str,use_pass,salt_str)141*7f2fe78bSCy Schubert krb5_error_code ktutil_add(context, list, princ_str, fetch, kvno,
142*7f2fe78bSCy Schubert                            enctype_str, use_pass, salt_str)
143*7f2fe78bSCy Schubert     krb5_context context;
144*7f2fe78bSCy Schubert     krb5_kt_list *list;
145*7f2fe78bSCy Schubert     char *princ_str;
146*7f2fe78bSCy Schubert     int fetch;
147*7f2fe78bSCy Schubert     krb5_kvno kvno;
148*7f2fe78bSCy Schubert     char *enctype_str;
149*7f2fe78bSCy Schubert     int use_pass;
150*7f2fe78bSCy Schubert     char *salt_str;
151*7f2fe78bSCy Schubert {
152*7f2fe78bSCy Schubert     krb5_keytab_entry *entry = NULL;
153*7f2fe78bSCy Schubert     krb5_kt_list lp, *last;
154*7f2fe78bSCy Schubert     krb5_principal princ;
155*7f2fe78bSCy Schubert     krb5_enctype enctype = ENCTYPE_NULL;
156*7f2fe78bSCy Schubert     krb5_timestamp now;
157*7f2fe78bSCy Schubert     krb5_error_code retval;
158*7f2fe78bSCy Schubert     krb5_data password = empty_data(), salt = empty_data();
159*7f2fe78bSCy Schubert     krb5_data params = empty_data(), *s2kparams;
160*7f2fe78bSCy Schubert     krb5_keyblock key;
161*7f2fe78bSCy Schubert     char buf[BUFSIZ];
162*7f2fe78bSCy Schubert     char promptstr[1024];
163*7f2fe78bSCy Schubert     char *princ_full = NULL;
164*7f2fe78bSCy Schubert     uint8_t *keybytes;
165*7f2fe78bSCy Schubert     size_t keylen;
166*7f2fe78bSCy Schubert     unsigned int pwsize = BUFSIZ;
167*7f2fe78bSCy Schubert 
168*7f2fe78bSCy Schubert     retval = krb5_parse_name(context, princ_str, &princ);
169*7f2fe78bSCy Schubert     if (retval)
170*7f2fe78bSCy Schubert         goto cleanup;
171*7f2fe78bSCy Schubert     /* now unparse in order to get the default realm appended
172*7f2fe78bSCy Schubert        to princ_str, if no realm was specified */
173*7f2fe78bSCy Schubert     retval = krb5_unparse_name(context, princ, &princ_full);
174*7f2fe78bSCy Schubert     if (retval)
175*7f2fe78bSCy Schubert         goto cleanup;
176*7f2fe78bSCy Schubert     if (enctype_str != NULL) {
177*7f2fe78bSCy Schubert         retval = krb5_string_to_enctype(enctype_str, &enctype);
178*7f2fe78bSCy Schubert         if (retval) {
179*7f2fe78bSCy Schubert             retval = KRB5_BAD_ENCTYPE;
180*7f2fe78bSCy Schubert             goto cleanup;
181*7f2fe78bSCy Schubert         }
182*7f2fe78bSCy Schubert     }
183*7f2fe78bSCy Schubert     retval = krb5_timeofday(context, &now);
184*7f2fe78bSCy Schubert     if (retval)
185*7f2fe78bSCy Schubert         goto cleanup;
186*7f2fe78bSCy Schubert 
187*7f2fe78bSCy Schubert     entry = k5alloc(sizeof(*entry), &retval);
188*7f2fe78bSCy Schubert     if (entry == NULL)
189*7f2fe78bSCy Schubert         goto cleanup;
190*7f2fe78bSCy Schubert 
191*7f2fe78bSCy Schubert     if (use_pass) {
192*7f2fe78bSCy Schubert         retval = alloc_data(&password, pwsize);
193*7f2fe78bSCy Schubert         if (retval)
194*7f2fe78bSCy Schubert             goto cleanup;
195*7f2fe78bSCy Schubert 
196*7f2fe78bSCy Schubert         snprintf(promptstr, sizeof(promptstr), _("Password for %.1000s"),
197*7f2fe78bSCy Schubert                  princ_full);
198*7f2fe78bSCy Schubert         retval = krb5_read_password(context, promptstr, NULL, password.data,
199*7f2fe78bSCy Schubert                                     &password.length);
200*7f2fe78bSCy Schubert         if (retval)
201*7f2fe78bSCy Schubert             goto cleanup;
202*7f2fe78bSCy Schubert 
203*7f2fe78bSCy Schubert         retval = get_etype_info(context, princ, fetch, salt_str,
204*7f2fe78bSCy Schubert                                 &enctype, &salt, &params);
205*7f2fe78bSCy Schubert         if (retval)
206*7f2fe78bSCy Schubert             goto cleanup;
207*7f2fe78bSCy Schubert         s2kparams = (params.length > 0) ? &params : NULL;
208*7f2fe78bSCy Schubert         retval = krb5_c_string_to_key_with_params(context, enctype, &password,
209*7f2fe78bSCy Schubert                                                   &salt, s2kparams, &key);
210*7f2fe78bSCy Schubert         if (retval)
211*7f2fe78bSCy Schubert             goto cleanup;
212*7f2fe78bSCy Schubert         entry->key = key;
213*7f2fe78bSCy Schubert     } else {
214*7f2fe78bSCy Schubert         printf(_("Key for %s (hex): "), princ_full);
215*7f2fe78bSCy Schubert         fgets(buf, BUFSIZ, stdin);
216*7f2fe78bSCy Schubert         /*
217*7f2fe78bSCy Schubert          * We need to get rid of the trailing '\n' from fgets.
218*7f2fe78bSCy Schubert          * If we have an even number of hex digits (as we should),
219*7f2fe78bSCy Schubert          * write a '\0' over the '\n'.  If for some reason we have
220*7f2fe78bSCy Schubert          * an odd number of hex digits, force an even number of hex
221*7f2fe78bSCy Schubert          * digits by writing a '0' into the last position (the string
222*7f2fe78bSCy Schubert          * will still be null-terminated).
223*7f2fe78bSCy Schubert          */
224*7f2fe78bSCy Schubert         buf[strlen(buf) - 1] = strlen(buf) % 2 ? '\0' : '0';
225*7f2fe78bSCy Schubert         if (strlen(buf) == 0) {
226*7f2fe78bSCy Schubert             fprintf(stderr, _("addent: Error reading key.\n"));
227*7f2fe78bSCy Schubert             retval = 0;
228*7f2fe78bSCy Schubert             goto cleanup;
229*7f2fe78bSCy Schubert         }
230*7f2fe78bSCy Schubert 
231*7f2fe78bSCy Schubert         retval = k5_hex_decode(buf, &keybytes, &keylen);
232*7f2fe78bSCy Schubert         if (retval) {
233*7f2fe78bSCy Schubert             if (retval == EINVAL) {
234*7f2fe78bSCy Schubert                 fprintf(stderr, _("addent: Illegal character in key.\n"));
235*7f2fe78bSCy Schubert                 retval = 0;
236*7f2fe78bSCy Schubert             }
237*7f2fe78bSCy Schubert             goto cleanup;
238*7f2fe78bSCy Schubert         }
239*7f2fe78bSCy Schubert 
240*7f2fe78bSCy Schubert         entry->key.enctype = enctype;
241*7f2fe78bSCy Schubert         entry->key.contents = keybytes;
242*7f2fe78bSCy Schubert         entry->key.length = keylen;
243*7f2fe78bSCy Schubert     }
244*7f2fe78bSCy Schubert     entry->principal = princ;
245*7f2fe78bSCy Schubert     entry->vno = kvno;
246*7f2fe78bSCy Schubert     entry->timestamp = now;
247*7f2fe78bSCy Schubert 
248*7f2fe78bSCy Schubert     /* Add entry to the end of the list (or create a new list if empty). */
249*7f2fe78bSCy Schubert     lp = k5alloc(sizeof(*lp), &retval);
250*7f2fe78bSCy Schubert     if (lp == NULL)
251*7f2fe78bSCy Schubert         goto cleanup;
252*7f2fe78bSCy Schubert     lp->next = NULL;
253*7f2fe78bSCy Schubert     lp->entry = entry;
254*7f2fe78bSCy Schubert     entry = NULL;
255*7f2fe78bSCy Schubert     for (last = list; *last != NULL; last = &(*last)->next);
256*7f2fe78bSCy Schubert     *last = lp;
257*7f2fe78bSCy Schubert 
258*7f2fe78bSCy Schubert cleanup:
259*7f2fe78bSCy Schubert     krb5_free_keytab_entry_contents(context, entry);
260*7f2fe78bSCy Schubert     free(entry);
261*7f2fe78bSCy Schubert     zapfree(password.data, password.length);
262*7f2fe78bSCy Schubert     krb5_free_data_contents(context, &salt);
263*7f2fe78bSCy Schubert     krb5_free_data_contents(context, &params);
264*7f2fe78bSCy Schubert     krb5_free_unparsed_name(context, princ_full);
265*7f2fe78bSCy Schubert     return retval;
266*7f2fe78bSCy Schubert }
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert /*
269*7f2fe78bSCy Schubert  * Read in a keytab and append it to list.  If list starts as NULL,
270*7f2fe78bSCy Schubert  * allocate a new one if necessary.
271*7f2fe78bSCy Schubert  */
ktutil_read_keytab(context,name,list)272*7f2fe78bSCy Schubert krb5_error_code ktutil_read_keytab(context, name, list)
273*7f2fe78bSCy Schubert     krb5_context context;
274*7f2fe78bSCy Schubert     char *name;
275*7f2fe78bSCy Schubert     krb5_kt_list *list;
276*7f2fe78bSCy Schubert {
277*7f2fe78bSCy Schubert     krb5_kt_list lp = NULL, tail = NULL, back = NULL;
278*7f2fe78bSCy Schubert     krb5_keytab kt;
279*7f2fe78bSCy Schubert     krb5_keytab_entry *entry;
280*7f2fe78bSCy Schubert     krb5_kt_cursor cursor;
281*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
282*7f2fe78bSCy Schubert 
283*7f2fe78bSCy Schubert     if (*list) {
284*7f2fe78bSCy Schubert         /* point lp at the tail of the list */
285*7f2fe78bSCy Schubert         for (lp = *list; lp->next; lp = lp->next);
286*7f2fe78bSCy Schubert         back = lp;
287*7f2fe78bSCy Schubert     }
288*7f2fe78bSCy Schubert     retval = krb5_kt_resolve(context, name, &kt);
289*7f2fe78bSCy Schubert     if (retval)
290*7f2fe78bSCy Schubert         return retval;
291*7f2fe78bSCy Schubert     retval = krb5_kt_start_seq_get(context, kt, &cursor);
292*7f2fe78bSCy Schubert     if (retval)
293*7f2fe78bSCy Schubert         goto close_kt;
294*7f2fe78bSCy Schubert     for (;;) {
295*7f2fe78bSCy Schubert         entry = (krb5_keytab_entry *)malloc(sizeof (krb5_keytab_entry));
296*7f2fe78bSCy Schubert         if (!entry) {
297*7f2fe78bSCy Schubert             retval = ENOMEM;
298*7f2fe78bSCy Schubert             break;
299*7f2fe78bSCy Schubert         }
300*7f2fe78bSCy Schubert         memset(entry, 0, sizeof (*entry));
301*7f2fe78bSCy Schubert         retval = krb5_kt_next_entry(context, kt, entry, &cursor);
302*7f2fe78bSCy Schubert         if (retval)
303*7f2fe78bSCy Schubert             break;
304*7f2fe78bSCy Schubert 
305*7f2fe78bSCy Schubert         if (!lp) {              /* if list is empty, start one */
306*7f2fe78bSCy Schubert             lp = (krb5_kt_list)malloc(sizeof (*lp));
307*7f2fe78bSCy Schubert             if (!lp) {
308*7f2fe78bSCy Schubert                 retval = ENOMEM;
309*7f2fe78bSCy Schubert                 break;
310*7f2fe78bSCy Schubert             }
311*7f2fe78bSCy Schubert         } else {
312*7f2fe78bSCy Schubert             lp->next = (krb5_kt_list)malloc(sizeof (*lp));
313*7f2fe78bSCy Schubert             if (!lp->next) {
314*7f2fe78bSCy Schubert                 retval = ENOMEM;
315*7f2fe78bSCy Schubert                 break;
316*7f2fe78bSCy Schubert             }
317*7f2fe78bSCy Schubert             lp = lp->next;
318*7f2fe78bSCy Schubert         }
319*7f2fe78bSCy Schubert         if (!tail)
320*7f2fe78bSCy Schubert             tail = lp;
321*7f2fe78bSCy Schubert         lp->next = NULL;
322*7f2fe78bSCy Schubert         lp->entry = entry;
323*7f2fe78bSCy Schubert     }
324*7f2fe78bSCy Schubert     if (entry)
325*7f2fe78bSCy Schubert         free(entry);
326*7f2fe78bSCy Schubert     if (retval) {
327*7f2fe78bSCy Schubert         if (retval == KRB5_KT_END)
328*7f2fe78bSCy Schubert             retval = 0;
329*7f2fe78bSCy Schubert         else {
330*7f2fe78bSCy Schubert             ktutil_free_kt_list(context, tail);
331*7f2fe78bSCy Schubert             tail = NULL;
332*7f2fe78bSCy Schubert             if (back)
333*7f2fe78bSCy Schubert                 back->next = NULL;
334*7f2fe78bSCy Schubert         }
335*7f2fe78bSCy Schubert     }
336*7f2fe78bSCy Schubert     if (!*list)
337*7f2fe78bSCy Schubert         *list = tail;
338*7f2fe78bSCy Schubert     krb5_kt_end_seq_get(context, kt, &cursor);
339*7f2fe78bSCy Schubert close_kt:
340*7f2fe78bSCy Schubert     krb5_kt_close(context, kt);
341*7f2fe78bSCy Schubert     return retval;
342*7f2fe78bSCy Schubert }
343*7f2fe78bSCy Schubert 
344*7f2fe78bSCy Schubert /*
345*7f2fe78bSCy Schubert  * Takes a kt_list and writes it to the named keytab.
346*7f2fe78bSCy Schubert  */
ktutil_write_keytab(context,list,name)347*7f2fe78bSCy Schubert krb5_error_code ktutil_write_keytab(context, list, name)
348*7f2fe78bSCy Schubert     krb5_context context;
349*7f2fe78bSCy Schubert     krb5_kt_list list;
350*7f2fe78bSCy Schubert     char *name;
351*7f2fe78bSCy Schubert {
352*7f2fe78bSCy Schubert     krb5_kt_list lp;
353*7f2fe78bSCy Schubert     krb5_keytab kt;
354*7f2fe78bSCy Schubert     char ktname[MAXPATHLEN+sizeof("WRFILE:")+1];
355*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
356*7f2fe78bSCy Schubert     int result;
357*7f2fe78bSCy Schubert 
358*7f2fe78bSCy Schubert     result = snprintf(ktname, sizeof(ktname), "WRFILE:%s", name);
359*7f2fe78bSCy Schubert     if (SNPRINTF_OVERFLOW(result, sizeof(ktname)))
360*7f2fe78bSCy Schubert         return ENAMETOOLONG;
361*7f2fe78bSCy Schubert     retval = krb5_kt_resolve(context, ktname, &kt);
362*7f2fe78bSCy Schubert     if (retval)
363*7f2fe78bSCy Schubert         return retval;
364*7f2fe78bSCy Schubert     for (lp = list; lp; lp = lp->next) {
365*7f2fe78bSCy Schubert         retval = krb5_kt_add_entry(context, kt, lp->entry);
366*7f2fe78bSCy Schubert         if (retval)
367*7f2fe78bSCy Schubert             break;
368*7f2fe78bSCy Schubert     }
369*7f2fe78bSCy Schubert     krb5_kt_close(context, kt);
370*7f2fe78bSCy Schubert     return retval;
371*7f2fe78bSCy Schubert }
372