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