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