xref: /freebsd/crypto/heimdal/lib/krb5/keytab.c (revision ed549cb0c53f8438c52593ce811f6fcc812248e9)
1b528cefcSMark Murray /*
2ae771770SStanislav Sedov  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "krb5_locl.h"
35b528cefcSMark Murray 
36ae771770SStanislav Sedov /**
37ae771770SStanislav Sedov  * @page krb5_keytab_intro The keytab handing functions
38ae771770SStanislav Sedov  * @section section_krb5_keytab Kerberos Keytabs
39ae771770SStanislav Sedov  *
40ae771770SStanislav Sedov  * See the library functions here: @ref krb5_keytab
41ae771770SStanislav Sedov  *
42ae771770SStanislav Sedov  * Keytabs are long term key storage for servers, their equvalment of
43ae771770SStanislav Sedov  * password files.
44ae771770SStanislav Sedov  *
45ae771770SStanislav Sedov  * Normally the only function that useful for server are to specify
46ae771770SStanislav Sedov  * what keytab to use to other core functions like krb5_rd_req()
47ae771770SStanislav Sedov  * krb5_kt_resolve(), and krb5_kt_close().
48ae771770SStanislav Sedov  *
49ae771770SStanislav Sedov  * @subsection krb5_keytab_names Keytab names
50ae771770SStanislav Sedov  *
51ae771770SStanislav Sedov  * A keytab name is on the form type:residual. The residual part is
52ae771770SStanislav Sedov  * specific to each keytab-type.
53ae771770SStanislav Sedov  *
54ae771770SStanislav Sedov  * When a keytab-name is resolved, the type is matched with an internal
55ae771770SStanislav Sedov  * list of keytab types. If there is no matching keytab type,
56ae771770SStanislav Sedov  * the default keytab is used. The current default type is FILE.
57ae771770SStanislav Sedov  *
58ae771770SStanislav Sedov  * The default value can be changed in the configuration file
59ae771770SStanislav Sedov  * /etc/krb5.conf by setting the variable
60ae771770SStanislav Sedov  * [defaults]default_keytab_name.
61ae771770SStanislav Sedov  *
62ae771770SStanislav Sedov  * The keytab types that are implemented in Heimdal are:
63ae771770SStanislav Sedov  * - file
64ae771770SStanislav Sedov  *   store the keytab in a file, the type's name is FILE .  The
65ae771770SStanislav Sedov  *   residual part is a filename. For compatibility with other
66ae771770SStanislav Sedov  *   Kerberos implemtation WRFILE and JAVA14 is also accepted.  WRFILE
67ae771770SStanislav Sedov  *   has the same format as FILE. JAVA14 have a format that is
68ae771770SStanislav Sedov  *   compatible with older versions of MIT kerberos and SUN's Java
69ae771770SStanislav Sedov  *   based installation.  They store a truncted kvno, so when the knvo
70ae771770SStanislav Sedov  *   excess 255, they are truncted in this format.
71ae771770SStanislav Sedov  *
72ae771770SStanislav Sedov  * - keytab
73ae771770SStanislav Sedov  *   store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ),
74ae771770SStanislav Sedov  *   the type's name is AFSKEYFILE. The residual part is a filename.
75ae771770SStanislav Sedov  *
76ae771770SStanislav Sedov  * - memory
77ae771770SStanislav Sedov  *   The keytab is stored in a memory segment. This allows sensitive
78ae771770SStanislav Sedov  *   and/or temporary data not to be stored on disk. The type's name
79ae771770SStanislav Sedov  *   is MEMORY. Each MEMORY keytab is referenced counted by and
80ae771770SStanislav Sedov  *   opened by the residual name, so two handles can point to the
81ae771770SStanislav Sedov  *   same memory area.  When the last user closes using krb5_kt_close()
82ae771770SStanislav Sedov  *   the keytab, the keys in they keytab is memset() to zero and freed
83ae771770SStanislav Sedov  *   and can no longer be looked up by name.
84ae771770SStanislav Sedov  *
85ae771770SStanislav Sedov  *
86ae771770SStanislav Sedov  * @subsection krb5_keytab_example Keytab example
87ae771770SStanislav Sedov  *
88ae771770SStanislav Sedov  *  This is a minimalistic version of ktutil.
89ae771770SStanislav Sedov  *
90ae771770SStanislav Sedov  * @code
91ae771770SStanislav Sedov int
92ae771770SStanislav Sedov main (int argc, char **argv)
93ae771770SStanislav Sedov {
94ae771770SStanislav Sedov     krb5_context context;
95ae771770SStanislav Sedov     krb5_keytab keytab;
96ae771770SStanislav Sedov     krb5_kt_cursor cursor;
97ae771770SStanislav Sedov     krb5_keytab_entry entry;
98ae771770SStanislav Sedov     krb5_error_code ret;
99ae771770SStanislav Sedov     char *principal;
100b528cefcSMark Murray 
101ae771770SStanislav Sedov     if (krb5_init_context (&context) != 0)
102ae771770SStanislav Sedov 	errx(1, "krb5_context");
103ae771770SStanislav Sedov 
104ae771770SStanislav Sedov     ret = krb5_kt_default (context, &keytab);
105ae771770SStanislav Sedov     if (ret)
106ae771770SStanislav Sedov 	krb5_err(context, 1, ret, "krb5_kt_default");
107ae771770SStanislav Sedov 
108ae771770SStanislav Sedov     ret = krb5_kt_start_seq_get(context, keytab, &cursor);
109ae771770SStanislav Sedov     if (ret)
110ae771770SStanislav Sedov 	krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
111ae771770SStanislav Sedov     while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
112ae771770SStanislav Sedov 	krb5_unparse_name(context, entry.principal, &principal);
113ae771770SStanislav Sedov 	printf("principal: %s\n", principal);
114ae771770SStanislav Sedov 	free(principal);
115ae771770SStanislav Sedov 	krb5_kt_free_entry(context, &entry);
116ae771770SStanislav Sedov     }
117ae771770SStanislav Sedov     ret = krb5_kt_end_seq_get(context, keytab, &cursor);
118ae771770SStanislav Sedov     if (ret)
119ae771770SStanislav Sedov 	krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
120ae771770SStanislav Sedov     ret = krb5_kt_close(context, keytab);
121ae771770SStanislav Sedov     if (ret)
122ae771770SStanislav Sedov 	krb5_err(context, 1, ret, "krb5_kt_close");
123ae771770SStanislav Sedov     krb5_free_context(context);
124ae771770SStanislav Sedov     return 0;
125ae771770SStanislav Sedov }
126ae771770SStanislav Sedov  * @endcode
127ae771770SStanislav Sedov  *
128b528cefcSMark Murray  */
129b528cefcSMark Murray 
130ae771770SStanislav Sedov 
131ae771770SStanislav Sedov /**
132ae771770SStanislav Sedov  * Register a new keytab backend.
133ae771770SStanislav Sedov  *
134ae771770SStanislav Sedov  * @param context a Keberos context.
135ae771770SStanislav Sedov  * @param ops a backend to register.
136ae771770SStanislav Sedov  *
137ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
138ae771770SStanislav Sedov  *
139ae771770SStanislav Sedov  * @ingroup krb5_keytab
140ae771770SStanislav Sedov  */
141ae771770SStanislav Sedov 
142ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_register(krb5_context context,const krb5_kt_ops * ops)143b528cefcSMark Murray krb5_kt_register(krb5_context context,
144b528cefcSMark Murray 		 const krb5_kt_ops *ops)
145b528cefcSMark Murray {
146b528cefcSMark Murray     struct krb5_keytab_data *tmp;
147b528cefcSMark Murray 
148bbd80c28SJacques Vidrine     if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) {
149ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_KT_BADNAME,
150ae771770SStanislav Sedov 			       N_("can't register cache type, prefix too long", ""));
151c19800e8SDoug Rabson 	return KRB5_KT_BADNAME;
152bbd80c28SJacques Vidrine     }
153bbd80c28SJacques Vidrine 
154b528cefcSMark Murray     tmp = realloc(context->kt_types,
155b528cefcSMark Murray 		  (context->num_kt_types + 1) * sizeof(*context->kt_types));
156adb0ddaeSAssar Westerlund     if(tmp == NULL) {
157ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
158ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
159b528cefcSMark Murray 	return ENOMEM;
160adb0ddaeSAssar Westerlund     }
161b528cefcSMark Murray     memcpy(&tmp[context->num_kt_types], ops,
162b528cefcSMark Murray 	   sizeof(tmp[context->num_kt_types]));
163b528cefcSMark Murray     context->kt_types = tmp;
164b528cefcSMark Murray     context->num_kt_types++;
165b528cefcSMark Murray     return 0;
166b528cefcSMark Murray }
167b528cefcSMark Murray 
168ae771770SStanislav Sedov static const char *
keytab_name(const char * name,const char ** type,size_t * type_len)169ae771770SStanislav Sedov keytab_name(const char *name, const char **type, size_t *type_len)
170ae771770SStanislav Sedov {
171ae771770SStanislav Sedov     const char *residual;
172ae771770SStanislav Sedov 
173ae771770SStanislav Sedov     residual = strchr(name, ':');
174ae771770SStanislav Sedov 
175ae771770SStanislav Sedov     if (residual == NULL ||
176ae771770SStanislav Sedov 	name[0] == '/'
177ae771770SStanislav Sedov #ifdef _WIN32
178ae771770SStanislav Sedov         /* Avoid treating <drive>:<path> as a keytab type
179ae771770SStanislav Sedov          * specification */
180ae771770SStanislav Sedov         || name + 1 == residual
181ae771770SStanislav Sedov #endif
182ae771770SStanislav Sedov         ) {
183ae771770SStanislav Sedov 
184ae771770SStanislav Sedov         *type = "FILE";
185ae771770SStanislav Sedov         *type_len = strlen(*type);
186ae771770SStanislav Sedov         residual = name;
187ae771770SStanislav Sedov     } else {
188ae771770SStanislav Sedov         *type = name;
189ae771770SStanislav Sedov         *type_len = residual - name;
190ae771770SStanislav Sedov         residual++;
191ae771770SStanislav Sedov     }
192ae771770SStanislav Sedov 
193ae771770SStanislav Sedov     return residual;
194ae771770SStanislav Sedov }
195ae771770SStanislav Sedov 
196ae771770SStanislav Sedov /**
197b528cefcSMark Murray  * Resolve the keytab name (of the form `type:residual') in `name'
198b528cefcSMark Murray  * into a keytab in `id'.
199ae771770SStanislav Sedov  *
200ae771770SStanislav Sedov  * @param context a Keberos context.
201ae771770SStanislav Sedov  * @param name name to resolve
202ae771770SStanislav Sedov  * @param id resulting keytab, free with krb5_kt_close().
203ae771770SStanislav Sedov  *
204ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
205ae771770SStanislav Sedov  *
206ae771770SStanislav Sedov  * @ingroup krb5_keytab
207b528cefcSMark Murray  */
208b528cefcSMark Murray 
209ae771770SStanislav Sedov 
210ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_resolve(krb5_context context,const char * name,krb5_keytab * id)211b528cefcSMark Murray krb5_kt_resolve(krb5_context context,
212b528cefcSMark Murray 		const char *name,
213b528cefcSMark Murray 		krb5_keytab *id)
214b528cefcSMark Murray {
215b528cefcSMark Murray     krb5_keytab k;
216b528cefcSMark Murray     int i;
217b528cefcSMark Murray     const char *type, *residual;
218b528cefcSMark Murray     size_t type_len;
219b528cefcSMark Murray     krb5_error_code ret;
220b528cefcSMark Murray 
221ae771770SStanislav Sedov     residual = keytab_name(name, &type, &type_len);
222b528cefcSMark Murray 
223b528cefcSMark Murray     for(i = 0; i < context->num_kt_types; i++) {
2244137ff4cSJacques Vidrine 	if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0)
225b528cefcSMark Murray 	    break;
226b528cefcSMark Murray     }
227adb0ddaeSAssar Westerlund     if(i == context->num_kt_types) {
228ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_KT_UNKNOWN_TYPE,
229ae771770SStanislav Sedov 			       N_("unknown keytab type %.*s", "type"),
230adb0ddaeSAssar Westerlund 			       (int)type_len, type);
231b528cefcSMark Murray 	return KRB5_KT_UNKNOWN_TYPE;
232adb0ddaeSAssar Westerlund     }
233b528cefcSMark Murray 
234b528cefcSMark Murray     k = malloc (sizeof(*k));
235adb0ddaeSAssar Westerlund     if (k == NULL) {
236ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
237b528cefcSMark Murray 	return ENOMEM;
238adb0ddaeSAssar Westerlund     }
239b528cefcSMark Murray     memcpy(k, &context->kt_types[i], sizeof(*k));
240b528cefcSMark Murray     k->data = NULL;
241b528cefcSMark Murray     ret = (*k->resolve)(context, residual, k);
242b528cefcSMark Murray     if(ret) {
243b528cefcSMark Murray 	free(k);
244b528cefcSMark Murray 	k = NULL;
245b528cefcSMark Murray     }
246b528cefcSMark Murray     *id = k;
247b528cefcSMark Murray     return ret;
248b528cefcSMark Murray }
249b528cefcSMark Murray 
250ae771770SStanislav Sedov /**
251b528cefcSMark Murray  * copy the name of the default keytab into `name'.
252ae771770SStanislav Sedov  *
253ae771770SStanislav Sedov  * @param context a Keberos context.
254ae771770SStanislav Sedov  * @param name buffer where the name will be written
255ae771770SStanislav Sedov  * @param namesize length of name
256ae771770SStanislav Sedov  *
257ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
258ae771770SStanislav Sedov  *
259ae771770SStanislav Sedov  * @ingroup krb5_keytab
260b528cefcSMark Murray  */
261b528cefcSMark Murray 
262ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_default_name(krb5_context context,char * name,size_t namesize)263b528cefcSMark Murray krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
264b528cefcSMark Murray {
265adb0ddaeSAssar Westerlund     if (strlcpy (name, context->default_keytab, namesize) >= namesize) {
266ae771770SStanislav Sedov 	krb5_clear_error_message (context);
267b528cefcSMark Murray 	return KRB5_CONFIG_NOTENUFSPACE;
268adb0ddaeSAssar Westerlund     }
269adb0ddaeSAssar Westerlund     return 0;
270adb0ddaeSAssar Westerlund }
271adb0ddaeSAssar Westerlund 
272ae771770SStanislav Sedov /**
273ae771770SStanislav Sedov  * Copy the name of the default modify keytab into `name'.
274ae771770SStanislav Sedov  *
275ae771770SStanislav Sedov  * @param context a Keberos context.
276ae771770SStanislav Sedov  * @param name buffer where the name will be written
277ae771770SStanislav Sedov  * @param namesize length of name
278ae771770SStanislav Sedov  *
279ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
280ae771770SStanislav Sedov  *
281ae771770SStanislav Sedov  * @ingroup krb5_keytab
282adb0ddaeSAssar Westerlund  */
283adb0ddaeSAssar Westerlund 
284ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_default_modify_name(krb5_context context,char * name,size_t namesize)285adb0ddaeSAssar Westerlund krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
286adb0ddaeSAssar Westerlund {
2874137ff4cSJacques Vidrine     const char *kt = NULL;
2884137ff4cSJacques Vidrine     if(context->default_keytab_modify == NULL) {
2894137ff4cSJacques Vidrine 	if(strncasecmp(context->default_keytab, "ANY:", 4) != 0)
2904137ff4cSJacques Vidrine 	    kt = context->default_keytab;
2914137ff4cSJacques Vidrine 	else {
2924137ff4cSJacques Vidrine 	    size_t len = strcspn(context->default_keytab + 4, ",");
2934137ff4cSJacques Vidrine 	    if(len >= namesize) {
294ae771770SStanislav Sedov 		krb5_clear_error_message(context);
2954137ff4cSJacques Vidrine 		return KRB5_CONFIG_NOTENUFSPACE;
2964137ff4cSJacques Vidrine 	    }
2974137ff4cSJacques Vidrine 	    strlcpy(name, context->default_keytab + 4, namesize);
2984137ff4cSJacques Vidrine 	    name[len] = '\0';
2994137ff4cSJacques Vidrine 	    return 0;
3004137ff4cSJacques Vidrine 	}
3014137ff4cSJacques Vidrine     } else
3024137ff4cSJacques Vidrine 	kt = context->default_keytab_modify;
3034137ff4cSJacques Vidrine     if (strlcpy (name, kt, namesize) >= namesize) {
304ae771770SStanislav Sedov 	krb5_clear_error_message (context);
305adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_NOTENUFSPACE;
306adb0ddaeSAssar Westerlund     }
307b528cefcSMark Murray     return 0;
308b528cefcSMark Murray }
309b528cefcSMark Murray 
310ae771770SStanislav Sedov /**
311b528cefcSMark Murray  * Set `id' to the default keytab.
312ae771770SStanislav Sedov  *
313ae771770SStanislav Sedov  * @param context a Keberos context.
314ae771770SStanislav Sedov  * @param id the new default keytab.
315ae771770SStanislav Sedov  *
316ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
317ae771770SStanislav Sedov  *
318ae771770SStanislav Sedov  * @ingroup krb5_keytab
319b528cefcSMark Murray  */
320b528cefcSMark Murray 
321ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_default(krb5_context context,krb5_keytab * id)322b528cefcSMark Murray krb5_kt_default(krb5_context context, krb5_keytab *id)
323b528cefcSMark Murray {
324b528cefcSMark Murray     return krb5_kt_resolve (context, context->default_keytab, id);
325b528cefcSMark Murray }
326b528cefcSMark Murray 
327ae771770SStanislav Sedov /**
328b528cefcSMark Murray  * Read the key identified by `(principal, vno, enctype)' from the
329b528cefcSMark Murray  * keytab in `keyprocarg' (the default if == NULL) into `*key'.
330ae771770SStanislav Sedov  *
331ae771770SStanislav Sedov  * @param context a Keberos context.
332ae771770SStanislav Sedov  * @param keyprocarg
333ae771770SStanislav Sedov  * @param principal
334ae771770SStanislav Sedov  * @param vno
335ae771770SStanislav Sedov  * @param enctype
336ae771770SStanislav Sedov  * @param key
337ae771770SStanislav Sedov  *
338ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
339ae771770SStanislav Sedov  *
340ae771770SStanislav Sedov  * @ingroup krb5_keytab
341b528cefcSMark Murray  */
342b528cefcSMark Murray 
343ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_read_service_key(krb5_context context,krb5_pointer keyprocarg,krb5_principal principal,krb5_kvno vno,krb5_enctype enctype,krb5_keyblock ** key)344b528cefcSMark Murray krb5_kt_read_service_key(krb5_context context,
345b528cefcSMark Murray 			 krb5_pointer keyprocarg,
346b528cefcSMark Murray 			 krb5_principal principal,
347b528cefcSMark Murray 			 krb5_kvno vno,
348b528cefcSMark Murray 			 krb5_enctype enctype,
349b528cefcSMark Murray 			 krb5_keyblock **key)
350b528cefcSMark Murray {
351*ed549cb0SCy Schubert     krb5_keytab keytab = NULL; /* Quiet lint */
352b528cefcSMark Murray     krb5_keytab_entry entry;
353b528cefcSMark Murray     krb5_error_code ret;
354b528cefcSMark Murray 
355*ed549cb0SCy Schubert     memset(&entry, 0, sizeof(entry));
356b528cefcSMark Murray     if (keyprocarg)
357b528cefcSMark Murray 	ret = krb5_kt_resolve (context, keyprocarg, &keytab);
358b528cefcSMark Murray     else
359b528cefcSMark Murray 	ret = krb5_kt_default (context, &keytab);
360b528cefcSMark Murray 
361b528cefcSMark Murray     if (ret)
362b528cefcSMark Murray 	return ret;
363b528cefcSMark Murray 
364b528cefcSMark Murray     ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
365*ed549cb0SCy Schubert     if (ret == 0) {
366b528cefcSMark Murray         ret = krb5_copy_keyblock (context, &entry.keyblock, key);
367b528cefcSMark Murray         krb5_kt_free_entry(context, &entry);
368*ed549cb0SCy Schubert     }
369*ed549cb0SCy Schubert     krb5_kt_close (context, keytab);
370b528cefcSMark Murray     return ret;
371b528cefcSMark Murray }
372b528cefcSMark Murray 
373ae771770SStanislav Sedov /**
374bbd80c28SJacques Vidrine  * Return the type of the `keytab' in the string `prefix of length
375bbd80c28SJacques Vidrine  * `prefixsize'.
376ae771770SStanislav Sedov  *
377ae771770SStanislav Sedov  * @param context a Keberos context.
378ae771770SStanislav Sedov  * @param keytab the keytab to get the prefix for
379ae771770SStanislav Sedov  * @param prefix prefix buffer
380ae771770SStanislav Sedov  * @param prefixsize length of prefix buffer
381ae771770SStanislav Sedov  *
382ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
383ae771770SStanislav Sedov  *
384ae771770SStanislav Sedov  * @ingroup krb5_keytab
385bbd80c28SJacques Vidrine  */
386bbd80c28SJacques Vidrine 
387ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_get_type(krb5_context context,krb5_keytab keytab,char * prefix,size_t prefixsize)388bbd80c28SJacques Vidrine krb5_kt_get_type(krb5_context context,
389bbd80c28SJacques Vidrine 		 krb5_keytab keytab,
390bbd80c28SJacques Vidrine 		 char *prefix,
391bbd80c28SJacques Vidrine 		 size_t prefixsize)
392bbd80c28SJacques Vidrine {
393bbd80c28SJacques Vidrine     strlcpy(prefix, keytab->prefix, prefixsize);
394bbd80c28SJacques Vidrine     return 0;
395bbd80c28SJacques Vidrine }
396bbd80c28SJacques Vidrine 
397ae771770SStanislav Sedov /**
398b528cefcSMark Murray  * Retrieve the name of the keytab `keytab' into `name', `namesize'
399ae771770SStanislav Sedov  *
400ae771770SStanislav Sedov  * @param context a Keberos context.
401ae771770SStanislav Sedov  * @param keytab the keytab to get the name for.
402ae771770SStanislav Sedov  * @param name name buffer.
403ae771770SStanislav Sedov  * @param namesize size of name buffer.
404ae771770SStanislav Sedov  *
405ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
406ae771770SStanislav Sedov  *
407ae771770SStanislav Sedov  * @ingroup krb5_keytab
408b528cefcSMark Murray  */
409b528cefcSMark Murray 
410ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_get_name(krb5_context context,krb5_keytab keytab,char * name,size_t namesize)411b528cefcSMark Murray krb5_kt_get_name(krb5_context context,
412b528cefcSMark Murray 		 krb5_keytab keytab,
413b528cefcSMark Murray 		 char *name,
414b528cefcSMark Murray 		 size_t namesize)
415b528cefcSMark Murray {
416b528cefcSMark Murray     return (*keytab->get_name)(context, keytab, name, namesize);
417b528cefcSMark Murray }
418b528cefcSMark Murray 
419ae771770SStanislav Sedov /**
420c19800e8SDoug Rabson  * Retrieve the full name of the keytab `keytab' and store the name in
421ae771770SStanislav Sedov  * `str'.
422ae771770SStanislav Sedov  *
423ae771770SStanislav Sedov  * @param context a Keberos context.
424ae771770SStanislav Sedov  * @param keytab keytab to get name for.
425ae771770SStanislav Sedov  * @param str the name of the keytab name, usee krb5_xfree() to free
426ae771770SStanislav Sedov  *        the string.  On error, *str is set to NULL.
427ae771770SStanislav Sedov  *
428ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
429ae771770SStanislav Sedov  *
430ae771770SStanislav Sedov  * @ingroup krb5_keytab
431b528cefcSMark Murray  */
432b528cefcSMark Murray 
433ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_get_full_name(krb5_context context,krb5_keytab keytab,char ** str)434c19800e8SDoug Rabson krb5_kt_get_full_name(krb5_context context,
435c19800e8SDoug Rabson 		      krb5_keytab keytab,
436c19800e8SDoug Rabson 		      char **str)
437c19800e8SDoug Rabson {
438c19800e8SDoug Rabson     char type[KRB5_KT_PREFIX_MAX_LEN];
439c19800e8SDoug Rabson     char name[MAXPATHLEN];
440c19800e8SDoug Rabson     krb5_error_code ret;
441c19800e8SDoug Rabson 
442c19800e8SDoug Rabson     *str = NULL;
443c19800e8SDoug Rabson 
444c19800e8SDoug Rabson     ret = krb5_kt_get_type(context, keytab, type, sizeof(type));
445c19800e8SDoug Rabson     if (ret)
446c19800e8SDoug Rabson 	return ret;
447c19800e8SDoug Rabson 
448c19800e8SDoug Rabson     ret = krb5_kt_get_name(context, keytab, name, sizeof(name));
449c19800e8SDoug Rabson     if (ret)
450c19800e8SDoug Rabson 	return ret;
451c19800e8SDoug Rabson 
452c19800e8SDoug Rabson     if (asprintf(str, "%s:%s", type, name) == -1) {
453ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
454c19800e8SDoug Rabson 	*str = NULL;
455c19800e8SDoug Rabson 	return ENOMEM;
456c19800e8SDoug Rabson     }
457c19800e8SDoug Rabson 
458c19800e8SDoug Rabson     return 0;
459c19800e8SDoug Rabson }
460c19800e8SDoug Rabson 
461ae771770SStanislav Sedov /**
462c19800e8SDoug Rabson  * Finish using the keytab in `id'.  All resources will be released,
463ae771770SStanislav Sedov  * even on errors.
464ae771770SStanislav Sedov  *
465ae771770SStanislav Sedov  * @param context a Keberos context.
466ae771770SStanislav Sedov  * @param id keytab to close.
467ae771770SStanislav Sedov  *
468ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
469ae771770SStanislav Sedov  *
470ae771770SStanislav Sedov  * @ingroup krb5_keytab
471c19800e8SDoug Rabson  */
472c19800e8SDoug Rabson 
473ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_close(krb5_context context,krb5_keytab id)474b528cefcSMark Murray krb5_kt_close(krb5_context context,
475b528cefcSMark Murray 	      krb5_keytab id)
476b528cefcSMark Murray {
477*ed549cb0SCy Schubert     krb5_error_code ret = 0;
478b528cefcSMark Murray 
479*ed549cb0SCy Schubert     if (id) {
480*ed549cb0SCy Schubert         ret = (id->close)(context, id);
481c19800e8SDoug Rabson         memset(id, 0, sizeof(*id));
482b528cefcSMark Murray         free(id);
483*ed549cb0SCy Schubert     }
484b528cefcSMark Murray     return ret;
485b528cefcSMark Murray }
486b528cefcSMark Murray 
487ae771770SStanislav Sedov /**
488ae771770SStanislav Sedov  * Destroy (remove) the keytab in `id'.  All resources will be released,
489ae771770SStanislav Sedov  * even on errors, does the equvalment of krb5_kt_close() on the resources.
490ae771770SStanislav Sedov  *
491ae771770SStanislav Sedov  * @param context a Keberos context.
492ae771770SStanislav Sedov  * @param id keytab to destroy.
493ae771770SStanislav Sedov  *
494ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
495ae771770SStanislav Sedov  *
496ae771770SStanislav Sedov  * @ingroup krb5_keytab
497ae771770SStanislav Sedov  */
498ae771770SStanislav Sedov 
499ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_destroy(krb5_context context,krb5_keytab id)500ae771770SStanislav Sedov krb5_kt_destroy(krb5_context context,
501ae771770SStanislav Sedov 		krb5_keytab id)
502ae771770SStanislav Sedov {
503ae771770SStanislav Sedov     krb5_error_code ret;
504ae771770SStanislav Sedov 
505ae771770SStanislav Sedov     ret = (*id->destroy)(context, id);
506ae771770SStanislav Sedov     krb5_kt_close(context, id);
507ae771770SStanislav Sedov     return ret;
508ae771770SStanislav Sedov }
509ae771770SStanislav Sedov 
510b528cefcSMark Murray /*
511ae771770SStanislav Sedov  * Match any aliases in keytab `entry' with `principal'.
512ae771770SStanislav Sedov  */
513ae771770SStanislav Sedov 
514ae771770SStanislav Sedov static krb5_boolean
compare_aliseses(krb5_context context,krb5_keytab_entry * entry,krb5_const_principal principal)515ae771770SStanislav Sedov compare_aliseses(krb5_context context,
516ae771770SStanislav Sedov 		 krb5_keytab_entry *entry,
517ae771770SStanislav Sedov 		 krb5_const_principal principal)
518ae771770SStanislav Sedov {
519ae771770SStanislav Sedov     unsigned int i;
520ae771770SStanislav Sedov     if (entry->aliases == NULL)
521ae771770SStanislav Sedov 	return FALSE;
522ae771770SStanislav Sedov     for (i = 0; i < entry->aliases->len; i++)
523ae771770SStanislav Sedov 	if (krb5_principal_compare(context, &entry->aliases->val[i], principal))
524ae771770SStanislav Sedov 	    return TRUE;
525ae771770SStanislav Sedov     return FALSE;
526ae771770SStanislav Sedov }
527ae771770SStanislav Sedov 
528ae771770SStanislav Sedov /**
529b528cefcSMark Murray  * Compare `entry' against `principal, vno, enctype'.
530b528cefcSMark Murray  * Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
531b528cefcSMark Murray  * Return TRUE if they compare the same, FALSE otherwise.
532ae771770SStanislav Sedov  *
533ae771770SStanislav Sedov  * @param context a Keberos context.
534ae771770SStanislav Sedov  * @param entry an entry to match with.
535ae771770SStanislav Sedov  * @param principal principal to match, NULL matches all principals.
536ae771770SStanislav Sedov  * @param vno key version to match, 0 matches all key version numbers.
537ae771770SStanislav Sedov  * @param enctype encryption type to match, 0 matches all encryption types.
538ae771770SStanislav Sedov  *
539ae771770SStanislav Sedov  * @return Return TRUE or match, FALSE if not matched.
540ae771770SStanislav Sedov  *
541ae771770SStanislav Sedov  * @ingroup krb5_keytab
542b528cefcSMark Murray  */
543b528cefcSMark Murray 
544ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_kt_compare(krb5_context context,krb5_keytab_entry * entry,krb5_const_principal principal,krb5_kvno vno,krb5_enctype enctype)545b528cefcSMark Murray krb5_kt_compare(krb5_context context,
546b528cefcSMark Murray 		krb5_keytab_entry *entry,
547b528cefcSMark Murray 		krb5_const_principal principal,
548b528cefcSMark Murray 		krb5_kvno vno,
549b528cefcSMark Murray 		krb5_enctype enctype)
550b528cefcSMark Murray {
551b528cefcSMark Murray     if(principal != NULL &&
552ae771770SStanislav Sedov        !(krb5_principal_compare(context, entry->principal, principal) ||
553ae771770SStanislav Sedov 	 compare_aliseses(context, entry, principal)))
554b528cefcSMark Murray 	return FALSE;
555b528cefcSMark Murray     if(vno && vno != entry->vno)
556b528cefcSMark Murray 	return FALSE;
557b528cefcSMark Murray     if(enctype && enctype != entry->keyblock.keytype)
558b528cefcSMark Murray 	return FALSE;
559b528cefcSMark Murray     return TRUE;
560b528cefcSMark Murray }
561b528cefcSMark Murray 
562ae771770SStanislav Sedov krb5_error_code
_krb5_kt_principal_not_found(krb5_context context,krb5_error_code ret,krb5_keytab id,krb5_const_principal principal,krb5_enctype enctype,int kvno)563ae771770SStanislav Sedov _krb5_kt_principal_not_found(krb5_context context,
564ae771770SStanislav Sedov 			     krb5_error_code ret,
565ae771770SStanislav Sedov 			     krb5_keytab id,
566ae771770SStanislav Sedov 			     krb5_const_principal principal,
567ae771770SStanislav Sedov 			     krb5_enctype enctype,
568ae771770SStanislav Sedov 			     int kvno)
569ae771770SStanislav Sedov {
570ae771770SStanislav Sedov     char princ[256], kvno_str[25], *kt_name;
571ae771770SStanislav Sedov     char *enctype_str = NULL;
572ae771770SStanislav Sedov 
573ae771770SStanislav Sedov     krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
574ae771770SStanislav Sedov     krb5_kt_get_full_name (context, id, &kt_name);
575ae771770SStanislav Sedov     krb5_enctype_to_string(context, enctype, &enctype_str);
576ae771770SStanislav Sedov 
577ae771770SStanislav Sedov     if (kvno)
578ae771770SStanislav Sedov 	snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
579ae771770SStanislav Sedov     else
580ae771770SStanislav Sedov 	kvno_str[0] = '\0';
581ae771770SStanislav Sedov 
582ae771770SStanislav Sedov     krb5_set_error_message (context, ret,
583ae771770SStanislav Sedov 			    N_("Failed to find %s%s in keytab %s (%s)",
584ae771770SStanislav Sedov 			       "principal, kvno, keytab file, enctype"),
585ae771770SStanislav Sedov 			    princ,
586ae771770SStanislav Sedov 			    kvno_str,
587ae771770SStanislav Sedov 			    kt_name ? kt_name : "unknown keytab",
588ae771770SStanislav Sedov 			    enctype_str ? enctype_str : "unknown enctype");
589ae771770SStanislav Sedov     free(kt_name);
590ae771770SStanislav Sedov     free(enctype_str);
591ae771770SStanislav Sedov     return ret;
592ae771770SStanislav Sedov }
593ae771770SStanislav Sedov 
594ae771770SStanislav Sedov 
595ae771770SStanislav Sedov /**
596b528cefcSMark Murray  * Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
597ae771770SStanislav Sedov  * from the keytab `id'. Matching is done like krb5_kt_compare().
598ae771770SStanislav Sedov  *
599ae771770SStanislav Sedov  * @param context a Keberos context.
600ae771770SStanislav Sedov  * @param id a keytab.
601ae771770SStanislav Sedov  * @param principal principal to match, NULL matches all principals.
602ae771770SStanislav Sedov  * @param kvno key version to match, 0 matches all key version numbers.
603ae771770SStanislav Sedov  * @param enctype encryption type to match, 0 matches all encryption types.
604ae771770SStanislav Sedov  * @param entry the returned entry, free with krb5_kt_free_entry().
605ae771770SStanislav Sedov  *
606ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
607ae771770SStanislav Sedov  *
608ae771770SStanislav Sedov  * @ingroup krb5_keytab
609b528cefcSMark Murray  */
610b528cefcSMark Murray 
611ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_get_entry(krb5_context context,krb5_keytab id,krb5_const_principal principal,krb5_kvno kvno,krb5_enctype enctype,krb5_keytab_entry * entry)612b528cefcSMark Murray krb5_kt_get_entry(krb5_context context,
613b528cefcSMark Murray 		  krb5_keytab id,
614b528cefcSMark Murray 		  krb5_const_principal principal,
615b528cefcSMark Murray 		  krb5_kvno kvno,
616b528cefcSMark Murray 		  krb5_enctype enctype,
617b528cefcSMark Murray 		  krb5_keytab_entry *entry)
618b528cefcSMark Murray {
619b528cefcSMark Murray     krb5_keytab_entry tmp;
620b528cefcSMark Murray     krb5_error_code ret;
621b528cefcSMark Murray     krb5_kt_cursor cursor;
622b528cefcSMark Murray 
623b528cefcSMark Murray     if(id->get)
624b528cefcSMark Murray 	return (*id->get)(context, id, principal, kvno, enctype, entry);
625b528cefcSMark Murray 
626*ed549cb0SCy Schubert     memset(&tmp, 0, sizeof(tmp));
627b528cefcSMark Murray     ret = krb5_kt_start_seq_get (context, id, &cursor);
628c19800e8SDoug Rabson     if (ret) {
629ae771770SStanislav Sedov 	/* This is needed for krb5_verify_init_creds, but keep error
630ae771770SStanislav Sedov 	 * string from previous error for the human. */
631ae771770SStanislav Sedov 	context->error_code = KRB5_KT_NOTFOUND;
632ae771770SStanislav Sedov 	return KRB5_KT_NOTFOUND;
633c19800e8SDoug Rabson     }
634b528cefcSMark Murray 
635b528cefcSMark Murray     entry->vno = 0;
636b528cefcSMark Murray     while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
637b528cefcSMark Murray 	if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) {
6388373020dSJacques Vidrine 	    /* the file keytab might only store the lower 8 bits of
6398373020dSJacques Vidrine 	       the kvno, so only compare those bits */
6408373020dSJacques Vidrine 	    if (kvno == tmp.vno
6418373020dSJacques Vidrine 		|| (tmp.vno < 256 && kvno % 256 == tmp.vno)) {
642b528cefcSMark Murray 		krb5_kt_copy_entry_contents (context, &tmp, entry);
643b528cefcSMark Murray 		krb5_kt_free_entry (context, &tmp);
644b528cefcSMark Murray 		krb5_kt_end_seq_get(context, id, &cursor);
645b528cefcSMark Murray 		return 0;
646b528cefcSMark Murray 	    } else if (kvno == 0 && tmp.vno > entry->vno) {
647b528cefcSMark Murray 		if (entry->vno)
648b528cefcSMark Murray 		    krb5_kt_free_entry (context, entry);
649b528cefcSMark Murray 		krb5_kt_copy_entry_contents (context, &tmp, entry);
650b528cefcSMark Murray 	    }
651b528cefcSMark Murray 	}
652b528cefcSMark Murray 	krb5_kt_free_entry(context, &tmp);
653b528cefcSMark Murray     }
654b528cefcSMark Murray     krb5_kt_end_seq_get (context, id, &cursor);
655ae771770SStanislav Sedov     if (entry->vno == 0)
656ae771770SStanislav Sedov 	return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
657ae771770SStanislav Sedov 					    id, principal, enctype, kvno);
658b528cefcSMark Murray     return 0;
659adb0ddaeSAssar Westerlund }
660b528cefcSMark Murray 
661ae771770SStanislav Sedov /**
662b528cefcSMark Murray  * Copy the contents of `in' into `out'.
663ae771770SStanislav Sedov  *
664ae771770SStanislav Sedov  * @param context a Keberos context.
665ae771770SStanislav Sedov  * @param in the keytab entry to copy.
666ae771770SStanislav Sedov  * @param out the copy of the keytab entry, free with krb5_kt_free_entry().
667ae771770SStanislav Sedov  *
668ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
669ae771770SStanislav Sedov  *
670ae771770SStanislav Sedov  * @ingroup krb5_keytab
671ae771770SStanislav Sedov  */
672b528cefcSMark Murray 
673ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_copy_entry_contents(krb5_context context,const krb5_keytab_entry * in,krb5_keytab_entry * out)674b528cefcSMark Murray krb5_kt_copy_entry_contents(krb5_context context,
675b528cefcSMark Murray 			    const krb5_keytab_entry *in,
676b528cefcSMark Murray 			    krb5_keytab_entry *out)
677b528cefcSMark Murray {
678b528cefcSMark Murray     krb5_error_code ret;
679b528cefcSMark Murray 
680b528cefcSMark Murray     memset(out, 0, sizeof(*out));
681b528cefcSMark Murray 
682b528cefcSMark Murray     ret = krb5_copy_principal (context, in->principal, &out->principal);
683b528cefcSMark Murray     if (ret)
684*ed549cb0SCy Schubert 	return ret;
685b528cefcSMark Murray     ret = krb5_copy_keyblock_contents (context,
686b528cefcSMark Murray 				       &in->keyblock,
687b528cefcSMark Murray 				       &out->keyblock);
688*ed549cb0SCy Schubert     if (ret) {
689*ed549cb0SCy Schubert         krb5_free_principal(context, out->principal);
690*ed549cb0SCy Schubert         memset(out, 0, sizeof(*out));
691*ed549cb0SCy Schubert         return ret;
692*ed549cb0SCy Schubert     }
693*ed549cb0SCy Schubert     out->vno = in->vno;
694b528cefcSMark Murray     out->timestamp = in->timestamp;
695b528cefcSMark Murray     return 0;
696b528cefcSMark Murray }
697b528cefcSMark Murray 
698ae771770SStanislav Sedov /**
699b528cefcSMark Murray  * Free the contents of `entry'.
700ae771770SStanislav Sedov  *
701ae771770SStanislav Sedov  * @param context a Keberos context.
702ae771770SStanislav Sedov  * @param entry the entry to free
703ae771770SStanislav Sedov  *
704ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
705ae771770SStanislav Sedov  *
706ae771770SStanislav Sedov  * @ingroup krb5_keytab
707b528cefcSMark Murray  */
708b528cefcSMark Murray 
709ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_free_entry(krb5_context context,krb5_keytab_entry * entry)710b528cefcSMark Murray krb5_kt_free_entry(krb5_context context,
711b528cefcSMark Murray 		   krb5_keytab_entry *entry)
712b528cefcSMark Murray {
713b528cefcSMark Murray     krb5_free_principal (context, entry->principal);
714b528cefcSMark Murray     krb5_free_keyblock_contents (context, &entry->keyblock);
715c19800e8SDoug Rabson     memset(entry, 0, sizeof(*entry));
716b528cefcSMark Murray     return 0;
717b528cefcSMark Murray }
718b528cefcSMark Murray 
719ae771770SStanislav Sedov /**
720b528cefcSMark Murray  * Set `cursor' to point at the beginning of `id'.
721ae771770SStanislav Sedov  *
722ae771770SStanislav Sedov  * @param context a Keberos context.
723ae771770SStanislav Sedov  * @param id a keytab.
724ae771770SStanislav Sedov  * @param cursor a newly allocated cursor, free with krb5_kt_end_seq_get().
725ae771770SStanislav Sedov  *
726ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
727ae771770SStanislav Sedov  *
728ae771770SStanislav Sedov  * @ingroup krb5_keytab
729b528cefcSMark Murray  */
730b528cefcSMark Murray 
731ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_start_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)732b528cefcSMark Murray krb5_kt_start_seq_get(krb5_context context,
733b528cefcSMark Murray 		      krb5_keytab id,
734b528cefcSMark Murray 		      krb5_kt_cursor *cursor)
735b528cefcSMark Murray {
736adb0ddaeSAssar Westerlund     if(id->start_seq_get == NULL) {
737ae771770SStanislav Sedov 	krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
738ae771770SStanislav Sedov 			       N_("start_seq_get is not supported "
739ae771770SStanislav Sedov 				  "in the %s keytab type", ""),
740ae771770SStanislav Sedov 			       id->prefix);
741b528cefcSMark Murray 	return HEIM_ERR_OPNOTSUPP;
742adb0ddaeSAssar Westerlund     }
743b528cefcSMark Murray     return (*id->start_seq_get)(context, id, cursor);
744b528cefcSMark Murray }
745b528cefcSMark Murray 
746ae771770SStanislav Sedov /**
747ae771770SStanislav Sedov  * Get the next entry from keytab, advance the cursor.  On last entry
748ae771770SStanislav Sedov  * the function will return KRB5_KT_END.
749ae771770SStanislav Sedov  *
750ae771770SStanislav Sedov  * @param context a Keberos context.
751ae771770SStanislav Sedov  * @param id a keytab.
752ae771770SStanislav Sedov  * @param entry the returned entry, free with krb5_kt_free_entry().
753ae771770SStanislav Sedov  * @param cursor the cursor of the iteration.
754ae771770SStanislav Sedov  *
755ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
756ae771770SStanislav Sedov  *
757ae771770SStanislav Sedov  * @ingroup krb5_keytab
758b528cefcSMark Murray  */
759b528cefcSMark Murray 
760ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_next_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry,krb5_kt_cursor * cursor)761b528cefcSMark Murray krb5_kt_next_entry(krb5_context context,
762b528cefcSMark Murray 		   krb5_keytab id,
763b528cefcSMark Murray 		   krb5_keytab_entry *entry,
764b528cefcSMark Murray 		   krb5_kt_cursor *cursor)
765b528cefcSMark Murray {
766adb0ddaeSAssar Westerlund     if(id->next_entry == NULL) {
767ae771770SStanislav Sedov 	krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
768ae771770SStanislav Sedov 			       N_("next_entry is not supported in the %s "
769ae771770SStanislav Sedov 				  " keytab", ""),
770ae771770SStanislav Sedov 			       id->prefix);
771b528cefcSMark Murray 	return HEIM_ERR_OPNOTSUPP;
772adb0ddaeSAssar Westerlund     }
773b528cefcSMark Murray     return (*id->next_entry)(context, id, entry, cursor);
774b528cefcSMark Murray }
775b528cefcSMark Murray 
776ae771770SStanislav Sedov /**
777b528cefcSMark Murray  * Release all resources associated with `cursor'.
778ae771770SStanislav Sedov  *
779ae771770SStanislav Sedov  * @param context a Keberos context.
780ae771770SStanislav Sedov  * @param id a keytab.
781ae771770SStanislav Sedov  * @param cursor the cursor to free.
782ae771770SStanislav Sedov  *
783ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
784ae771770SStanislav Sedov  *
785ae771770SStanislav Sedov  * @ingroup krb5_keytab
786b528cefcSMark Murray  */
787b528cefcSMark Murray 
788ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_end_seq_get(krb5_context context,krb5_keytab id,krb5_kt_cursor * cursor)789b528cefcSMark Murray krb5_kt_end_seq_get(krb5_context context,
790b528cefcSMark Murray 		    krb5_keytab id,
791b528cefcSMark Murray 		    krb5_kt_cursor *cursor)
792b528cefcSMark Murray {
793adb0ddaeSAssar Westerlund     if(id->end_seq_get == NULL) {
794ae771770SStanislav Sedov 	krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
795adb0ddaeSAssar Westerlund 			       "end_seq_get is not supported in the %s "
796adb0ddaeSAssar Westerlund 			       " keytab", id->prefix);
797b528cefcSMark Murray 	return HEIM_ERR_OPNOTSUPP;
798adb0ddaeSAssar Westerlund     }
799b528cefcSMark Murray     return (*id->end_seq_get)(context, id, cursor);
800b528cefcSMark Murray }
801b528cefcSMark Murray 
802ae771770SStanislav Sedov /**
803b528cefcSMark Murray  * Add the entry in `entry' to the keytab `id'.
804ae771770SStanislav Sedov  *
805ae771770SStanislav Sedov  * @param context a Keberos context.
806ae771770SStanislav Sedov  * @param id a keytab.
807ae771770SStanislav Sedov  * @param entry the entry to add
808ae771770SStanislav Sedov  *
809ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
810ae771770SStanislav Sedov  *
811ae771770SStanislav Sedov  * @ingroup krb5_keytab
812b528cefcSMark Murray  */
813b528cefcSMark Murray 
814ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_add_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)815b528cefcSMark Murray krb5_kt_add_entry(krb5_context context,
816b528cefcSMark Murray 		  krb5_keytab id,
817b528cefcSMark Murray 		  krb5_keytab_entry *entry)
818b528cefcSMark Murray {
819adb0ddaeSAssar Westerlund     if(id->add == NULL) {
820ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_KT_NOWRITE,
821ae771770SStanislav Sedov 			       N_("Add is not supported in the %s keytab", ""),
822adb0ddaeSAssar Westerlund 			       id->prefix);
823b528cefcSMark Murray 	return KRB5_KT_NOWRITE;
824adb0ddaeSAssar Westerlund     }
82513e3f4d6SMark Murray     entry->timestamp = time(NULL);
826b528cefcSMark Murray     return (*id->add)(context, id,entry);
827b528cefcSMark Murray }
828b528cefcSMark Murray 
829ae771770SStanislav Sedov /**
830ae771770SStanislav Sedov  * Remove an entry from the keytab, matching is done using
831ae771770SStanislav Sedov  * krb5_kt_compare().
832ae771770SStanislav Sedov 
833ae771770SStanislav Sedov  * @param context a Keberos context.
834ae771770SStanislav Sedov  * @param id a keytab.
835ae771770SStanislav Sedov  * @param entry the entry to remove
836ae771770SStanislav Sedov  *
837ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
838ae771770SStanislav Sedov  *
839ae771770SStanislav Sedov  * @ingroup krb5_keytab
840b528cefcSMark Murray  */
841b528cefcSMark Murray 
842ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_remove_entry(krb5_context context,krb5_keytab id,krb5_keytab_entry * entry)843b528cefcSMark Murray krb5_kt_remove_entry(krb5_context context,
844b528cefcSMark Murray 		     krb5_keytab id,
845b528cefcSMark Murray 		     krb5_keytab_entry *entry)
846b528cefcSMark Murray {
847adb0ddaeSAssar Westerlund     if(id->remove == NULL) {
848ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_KT_NOWRITE,
849ae771770SStanislav Sedov 			       N_("Remove is not supported in the %s keytab", ""),
850adb0ddaeSAssar Westerlund 			       id->prefix);
851b528cefcSMark Murray 	return KRB5_KT_NOWRITE;
852adb0ddaeSAssar Westerlund     }
853b528cefcSMark Murray     return (*id->remove)(context, id, entry);
854b528cefcSMark Murray }
855ae771770SStanislav Sedov 
856ae771770SStanislav Sedov /**
857ae771770SStanislav Sedov  * Return true if the keytab exists and have entries
858ae771770SStanislav Sedov  *
859ae771770SStanislav Sedov  * @param context a Keberos context.
860ae771770SStanislav Sedov  * @param id a keytab.
861ae771770SStanislav Sedov  *
862ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
863ae771770SStanislav Sedov  *
864ae771770SStanislav Sedov  * @ingroup krb5_keytab
865ae771770SStanislav Sedov  */
866ae771770SStanislav Sedov 
867ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_kt_have_content(krb5_context context,krb5_keytab id)868ae771770SStanislav Sedov krb5_kt_have_content(krb5_context context,
869ae771770SStanislav Sedov 		     krb5_keytab id)
870ae771770SStanislav Sedov {
871ae771770SStanislav Sedov     krb5_keytab_entry entry;
872ae771770SStanislav Sedov     krb5_kt_cursor cursor;
873ae771770SStanislav Sedov     krb5_error_code ret;
874ae771770SStanislav Sedov     char *name;
875ae771770SStanislav Sedov 
876*ed549cb0SCy Schubert     memset(&entry, 0, sizeof(entry));
877ae771770SStanislav Sedov     ret = krb5_kt_start_seq_get(context, id, &cursor);
878ae771770SStanislav Sedov     if (ret)
879ae771770SStanislav Sedov 	goto notfound;
880ae771770SStanislav Sedov 
881ae771770SStanislav Sedov     ret = krb5_kt_next_entry(context, id, &entry, &cursor);
882ae771770SStanislav Sedov     krb5_kt_end_seq_get(context, id, &cursor);
883ae771770SStanislav Sedov     if (ret)
884ae771770SStanislav Sedov 	goto notfound;
885ae771770SStanislav Sedov 
886ae771770SStanislav Sedov     krb5_kt_free_entry(context, &entry);
887ae771770SStanislav Sedov 
888ae771770SStanislav Sedov     return 0;
889ae771770SStanislav Sedov 
890ae771770SStanislav Sedov  notfound:
891ae771770SStanislav Sedov     ret = krb5_kt_get_full_name(context, id, &name);
892ae771770SStanislav Sedov     if (ret == 0) {
893ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_KT_NOTFOUND,
894ae771770SStanislav Sedov 			       N_("No entry in keytab: %s", ""), name);
895ae771770SStanislav Sedov 	free(name);
896ae771770SStanislav Sedov     }
897ae771770SStanislav Sedov     return KRB5_KT_NOTFOUND;
898ae771770SStanislav Sedov }
899