Windows: Enable weak crypto by default
[heimdal.git] / lib / krb5 / keytab.c
blob7ba2f977822d795cdf8020ac769c97021171b854
1 /*
2 * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "krb5_locl.h"
36 /**
37 * @page krb5_keytab_intro The keytab handing functions
38 * @section section_krb5_keytab Kerberos Keytabs
40 * See the library functions here: @ref krb5_keytab
42 * Keytabs are long term key storage for servers, their equvalment of
43 * password files.
45 * Normally the only function that useful for server are to specify
46 * what keytab to use to other core functions like krb5_rd_req()
47 * krb5_kt_resolve(), and krb5_kt_close().
49 * @subsection krb5_keytab_names Keytab names
51 * A keytab name is on the form type:residual. The residual part is
52 * specific to each keytab-type.
54 * When a keytab-name is resolved, the type is matched with an internal
55 * list of keytab types. If there is no matching keytab type,
56 * the default keytab is used. The current default type is FILE.
58 * The default value can be changed in the configuration file
59 * /etc/krb5.conf by setting the variable
60 * [defaults]default_keytab_name.
62 * The keytab types that are implemented in Heimdal are:
63 * - file
64 * store the keytab in a file, the type's name is FILE . The
65 * residual part is a filename. For compatibility with other
66 * Kerberos implemtation WRFILE and JAVA14 is also accepted. WRFILE
67 * has the same format as FILE. JAVA14 have a format that is
68 * compatible with older versions of MIT kerberos and SUN's Java
69 * based installation. They store a truncted kvno, so when the knvo
70 * excess 255, they are truncted in this format.
72 * - keytab
73 * store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ),
74 * the type's name is AFSKEYFILE. The residual part is a filename.
76 * - memory
77 * The keytab is stored in a memory segment. This allows sensitive
78 * and/or temporary data not to be stored on disk. The type's name
79 * is MEMORY. Each MEMORY keytab is referenced counted by and
80 * opened by the residual name, so two handles can point to the
81 * same memory area. When the last user closes the entry, it
82 * disappears.
85 * @subsection krb5_keytab_example Keytab example
87 * This is a minimalistic version of ktutil.
89 * @code
90 int
91 main (int argc, char **argv)
93 krb5_context context;
94 krb5_keytab keytab;
95 krb5_kt_cursor cursor;
96 krb5_keytab_entry entry;
97 krb5_error_code ret;
98 char *principal;
100 if (krb5_init_context (&context) != 0)
101 errx(1, "krb5_context");
103 ret = krb5_kt_default (context, &keytab);
104 if (ret)
105 krb5_err(context, 1, ret, "krb5_kt_default");
107 ret = krb5_kt_start_seq_get(context, keytab, &cursor);
108 if (ret)
109 krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
110 while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
111 krb5_unparse_name_short(context, entry.principal, &principal);
112 printf("principal: %s\n", principal);
113 free(principal);
114 krb5_kt_free_entry(context, &entry);
116 ret = krb5_kt_end_seq_get(context, keytab, &cursor);
117 if (ret)
118 krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
119 ret = krb5_kt_close(context, keytab);
120 if (ret)
121 krb5_err(context, 1, ret, "krb5_kt_close");
122 krb5_free_context(context);
123 return 0;
125 * @endcode
131 * Register a new keytab backend.
133 * @param context a Keberos context.
134 * @param ops a backend to register.
136 * @return Return an error code or 0, see krb5_get_error_message().
138 * @ingroup krb5_keytab
141 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
142 krb5_kt_register(krb5_context context,
143 const krb5_kt_ops *ops)
145 struct krb5_keytab_data *tmp;
147 if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) {
148 krb5_set_error_message(context, KRB5_KT_BADNAME,
149 N_("can't register cache type, prefix too long", ""));
150 return KRB5_KT_BADNAME;
153 tmp = realloc(context->kt_types,
154 (context->num_kt_types + 1) * sizeof(*context->kt_types));
155 if(tmp == NULL) {
156 krb5_set_error_message(context, ENOMEM,
157 N_("malloc: out of memory", ""));
158 return ENOMEM;
160 memcpy(&tmp[context->num_kt_types], ops,
161 sizeof(tmp[context->num_kt_types]));
162 context->kt_types = tmp;
163 context->num_kt_types++;
164 return 0;
168 * Resolve the keytab name (of the form `type:residual') in `name'
169 * into a keytab in `id'.
171 * @param context a Keberos context.
172 * @param name name to resolve
173 * @param id resulting keytab, free with krb5_kt_close().
175 * @return Return an error code or 0, see krb5_get_error_message().
177 * @ingroup krb5_keytab
181 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
182 krb5_kt_resolve(krb5_context context,
183 const char *name,
184 krb5_keytab *id)
186 krb5_keytab k;
187 int i;
188 const char *type, *residual;
189 size_t type_len;
190 krb5_error_code ret;
192 residual = strchr(name, ':');
193 if(residual == NULL) {
194 type = "FILE";
195 type_len = strlen(type);
196 residual = name;
197 } else {
198 type = name;
199 type_len = residual - name;
200 residual++;
203 for(i = 0; i < context->num_kt_types; i++) {
204 if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0)
205 break;
207 if(i == context->num_kt_types) {
208 krb5_set_error_message(context, KRB5_KT_UNKNOWN_TYPE,
209 N_("unknown keytab type %.*s", "type"),
210 (int)type_len, type);
211 return KRB5_KT_UNKNOWN_TYPE;
214 k = malloc (sizeof(*k));
215 if (k == NULL) {
216 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
217 return ENOMEM;
219 memcpy(k, &context->kt_types[i], sizeof(*k));
220 k->data = NULL;
221 ret = (*k->resolve)(context, residual, k);
222 if(ret) {
223 free(k);
224 k = NULL;
226 *id = k;
227 return ret;
231 * copy the name of the default keytab into `name'.
233 * @param context a Keberos context.
234 * @param name buffer where the name will be written
235 * @param namesize length of name
237 * @return Return an error code or 0, see krb5_get_error_message().
239 * @ingroup krb5_keytab
242 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
243 krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
245 if (strlcpy (name, context->default_keytab, namesize) >= namesize) {
246 krb5_clear_error_message (context);
247 return KRB5_CONFIG_NOTENUFSPACE;
249 return 0;
253 * Copy the name of the default modify keytab into `name'.
255 * @param context a Keberos context.
256 * @param name buffer where the name will be written
257 * @param namesize length of name
259 * @return Return an error code or 0, see krb5_get_error_message().
261 * @ingroup krb5_keytab
264 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
265 krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
267 const char *kt = NULL;
268 if(context->default_keytab_modify == NULL) {
269 if(strncasecmp(context->default_keytab, "ANY:", 4) != 0)
270 kt = context->default_keytab;
271 else {
272 size_t len = strcspn(context->default_keytab + 4, ",");
273 if(len >= namesize) {
274 krb5_clear_error_message(context);
275 return KRB5_CONFIG_NOTENUFSPACE;
277 strlcpy(name, context->default_keytab + 4, namesize);
278 name[len] = '\0';
279 return 0;
281 } else
282 kt = context->default_keytab_modify;
283 if (strlcpy (name, kt, namesize) >= namesize) {
284 krb5_clear_error_message (context);
285 return KRB5_CONFIG_NOTENUFSPACE;
287 return 0;
291 * Set `id' to the default keytab.
293 * @param context a Keberos context.
294 * @param id the new default keytab.
296 * @return Return an error code or 0, see krb5_get_error_message().
298 * @ingroup krb5_keytab
301 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
302 krb5_kt_default(krb5_context context, krb5_keytab *id)
304 return krb5_kt_resolve (context, context->default_keytab, id);
308 * Read the key identified by `(principal, vno, enctype)' from the
309 * keytab in `keyprocarg' (the default if == NULL) into `*key'.
311 * @param context a Keberos context.
312 * @param keyprocarg
313 * @param principal
314 * @param vno
315 * @param enctype
316 * @param key
318 * @return Return an error code or 0, see krb5_get_error_message().
320 * @ingroup krb5_keytab
323 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
324 krb5_kt_read_service_key(krb5_context context,
325 krb5_pointer keyprocarg,
326 krb5_principal principal,
327 krb5_kvno vno,
328 krb5_enctype enctype,
329 krb5_keyblock **key)
331 krb5_keytab keytab;
332 krb5_keytab_entry entry;
333 krb5_error_code ret;
335 if (keyprocarg)
336 ret = krb5_kt_resolve (context, keyprocarg, &keytab);
337 else
338 ret = krb5_kt_default (context, &keytab);
340 if (ret)
341 return ret;
343 ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
344 krb5_kt_close (context, keytab);
345 if (ret)
346 return ret;
347 ret = krb5_copy_keyblock (context, &entry.keyblock, key);
348 krb5_kt_free_entry(context, &entry);
349 return ret;
353 * Return the type of the `keytab' in the string `prefix of length
354 * `prefixsize'.
356 * @param context a Keberos context.
357 * @param keytab the keytab to get the prefix for
358 * @param prefix prefix buffer
359 * @param prefixsize length of prefix buffer
361 * @return Return an error code or 0, see krb5_get_error_message().
363 * @ingroup krb5_keytab
366 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
367 krb5_kt_get_type(krb5_context context,
368 krb5_keytab keytab,
369 char *prefix,
370 size_t prefixsize)
372 strlcpy(prefix, keytab->prefix, prefixsize);
373 return 0;
377 * Retrieve the name of the keytab `keytab' into `name', `namesize'
379 * @param context a Keberos context.
380 * @param keytab the keytab to get the name for.
381 * @param name name buffer.
382 * @param namesize size of name buffer.
384 * @return Return an error code or 0, see krb5_get_error_message().
386 * @ingroup krb5_keytab
389 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
390 krb5_kt_get_name(krb5_context context,
391 krb5_keytab keytab,
392 char *name,
393 size_t namesize)
395 return (*keytab->get_name)(context, keytab, name, namesize);
399 * Retrieve the full name of the keytab `keytab' and store the name in
400 * `str'.
402 * @param context a Keberos context.
403 * @param keytab keytab to get name for.
404 * @param str the name of the keytab name, usee krb5_xfree() to free
405 * the string. On error, *str is set to NULL.
407 * @return Return an error code or 0, see krb5_get_error_message().
409 * @ingroup krb5_keytab
412 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
413 krb5_kt_get_full_name(krb5_context context,
414 krb5_keytab keytab,
415 char **str)
417 char type[KRB5_KT_PREFIX_MAX_LEN];
418 char name[MAXPATHLEN];
419 krb5_error_code ret;
421 *str = NULL;
423 ret = krb5_kt_get_type(context, keytab, type, sizeof(type));
424 if (ret)
425 return ret;
427 ret = krb5_kt_get_name(context, keytab, name, sizeof(name));
428 if (ret)
429 return ret;
431 if (asprintf(str, "%s:%s", type, name) == -1) {
432 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
433 *str = NULL;
434 return ENOMEM;
437 return 0;
441 * Finish using the keytab in `id'. All resources will be released,
442 * even on errors.
444 * @param context a Keberos context.
445 * @param id keytab to close.
447 * @return Return an error code or 0, see krb5_get_error_message().
449 * @ingroup krb5_keytab
452 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
453 krb5_kt_close(krb5_context context,
454 krb5_keytab id)
456 krb5_error_code ret;
458 ret = (*id->close)(context, id);
459 memset(id, 0, sizeof(*id));
460 free(id);
461 return ret;
465 * Destroy (remove) the keytab in `id'. All resources will be released,
466 * even on errors, does the equvalment of krb5_kt_close() on the resources.
468 * @param context a Keberos context.
469 * @param id keytab to destroy.
471 * @return Return an error code or 0, see krb5_get_error_message().
473 * @ingroup krb5_keytab
476 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
477 krb5_kt_destroy(krb5_context context,
478 krb5_keytab id)
480 krb5_error_code ret;
482 ret = (*id->destroy)(context, id);
483 krb5_kt_close(context, id);
484 return ret;
488 * Match any aliases in keytab `entry' with `principal'.
491 static krb5_boolean
492 compare_aliseses(krb5_context context,
493 krb5_keytab_entry *entry,
494 krb5_const_principal principal)
496 unsigned int i;
497 if (entry->aliases == NULL)
498 return FALSE;
499 for (i = 0; i < entry->aliases->len; i++)
500 if (krb5_principal_compare(context, &entry->aliases->val[i], principal))
501 return TRUE;
502 return FALSE;
506 * Compare `entry' against `principal, vno, enctype'.
507 * Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
508 * Return TRUE if they compare the same, FALSE otherwise.
510 * @param context a Keberos context.
511 * @param entry an entry to match with.
512 * @param principal principal to match, NULL matches all principals.
513 * @param vno key version to match, 0 matches all key version numbers.
514 * @param enctype encryption type to match, 0 matches all encryption types.
516 * @return Return TRUE or match, FALSE if not matched.
518 * @ingroup krb5_keytab
521 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
522 krb5_kt_compare(krb5_context context,
523 krb5_keytab_entry *entry,
524 krb5_const_principal principal,
525 krb5_kvno vno,
526 krb5_enctype enctype)
528 if(principal != NULL &&
529 !(krb5_principal_compare(context, entry->principal, principal) ||
530 compare_aliseses(context, entry, principal)))
531 return FALSE;
532 if(vno && vno != entry->vno)
533 return FALSE;
534 if(enctype && enctype != entry->keyblock.keytype)
535 return FALSE;
536 return TRUE;
539 krb5_error_code
540 _krb5_kt_principal_not_found(krb5_context context,
541 krb5_error_code ret,
542 krb5_keytab id,
543 krb5_const_principal principal,
544 krb5_enctype enctype,
545 int kvno)
547 char princ[256], kvno_str[25], *kt_name;
548 char *enctype_str = NULL;
550 krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
551 krb5_kt_get_full_name (context, id, &kt_name);
552 krb5_enctype_to_string(context, enctype, &enctype_str);
554 if (kvno)
555 snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
556 else
557 kvno_str[0] = '\0';
559 krb5_set_error_message (context, ret,
560 N_("Failed to find %s%s in keytab %s (%s)",
561 "principal, kvno, keytab file, enctype"),
562 princ,
563 kvno_str,
564 kt_name ? kt_name : "unknown keytab",
565 enctype_str ? enctype_str : "unknown enctype");
566 free(kt_name);
567 free(enctype_str);
568 return ret;
573 * Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
574 * from the keytab `id'. Matching is done like krb5_kt_compare().
576 * @param context a Keberos context.
577 * @param id a keytab.
578 * @param principal principal to match, NULL matches all principals.
579 * @param kvno key version to match, 0 matches all key version numbers.
580 * @param enctype encryption type to match, 0 matches all encryption types.
581 * @param entry the returned entry, free with krb5_kt_free_entry().
583 * @return Return an error code or 0, see krb5_get_error_message().
585 * @ingroup krb5_keytab
588 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
589 krb5_kt_get_entry(krb5_context context,
590 krb5_keytab id,
591 krb5_const_principal principal,
592 krb5_kvno kvno,
593 krb5_enctype enctype,
594 krb5_keytab_entry *entry)
596 krb5_keytab_entry tmp;
597 krb5_error_code ret;
598 krb5_kt_cursor cursor;
600 if(id->get)
601 return (*id->get)(context, id, principal, kvno, enctype, entry);
603 ret = krb5_kt_start_seq_get (context, id, &cursor);
604 if (ret) {
605 /* This is needed for krb5_verify_init_creds, but keep error
606 * string from previous error for the human. */
607 context->error_code = KRB5_KT_NOTFOUND;
608 return KRB5_KT_NOTFOUND;
611 entry->vno = 0;
612 while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
613 if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) {
614 /* the file keytab might only store the lower 8 bits of
615 the kvno, so only compare those bits */
616 if (kvno == tmp.vno
617 || (tmp.vno < 256 && kvno % 256 == tmp.vno)) {
618 krb5_kt_copy_entry_contents (context, &tmp, entry);
619 krb5_kt_free_entry (context, &tmp);
620 krb5_kt_end_seq_get(context, id, &cursor);
621 return 0;
622 } else if (kvno == 0 && tmp.vno > entry->vno) {
623 if (entry->vno)
624 krb5_kt_free_entry (context, entry);
625 krb5_kt_copy_entry_contents (context, &tmp, entry);
628 krb5_kt_free_entry(context, &tmp);
630 krb5_kt_end_seq_get (context, id, &cursor);
631 if (entry->vno == 0)
632 return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
633 id, principal, enctype, kvno);
634 return 0;
638 * Copy the contents of `in' into `out'.
640 * @param context a Keberos context.
641 * @param in the keytab entry to copy.
642 * @param out the copy of the keytab entry, free with krb5_kt_free_entry().
644 * @return Return an error code or 0, see krb5_get_error_message().
646 * @ingroup krb5_keytab
649 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
650 krb5_kt_copy_entry_contents(krb5_context context,
651 const krb5_keytab_entry *in,
652 krb5_keytab_entry *out)
654 krb5_error_code ret;
656 memset(out, 0, sizeof(*out));
657 out->vno = in->vno;
659 ret = krb5_copy_principal (context, in->principal, &out->principal);
660 if (ret)
661 goto fail;
662 ret = krb5_copy_keyblock_contents (context,
663 &in->keyblock,
664 &out->keyblock);
665 if (ret)
666 goto fail;
667 out->timestamp = in->timestamp;
668 return 0;
669 fail:
670 krb5_kt_free_entry (context, out);
671 return ret;
675 * Free the contents of `entry'.
677 * @param context a Keberos context.
678 * @param entry the entry to free
680 * @return Return an error code or 0, see krb5_get_error_message().
682 * @ingroup krb5_keytab
685 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
686 krb5_kt_free_entry(krb5_context context,
687 krb5_keytab_entry *entry)
689 krb5_free_principal (context, entry->principal);
690 krb5_free_keyblock_contents (context, &entry->keyblock);
691 memset(entry, 0, sizeof(*entry));
692 return 0;
696 * Set `cursor' to point at the beginning of `id'.
698 * @param context a Keberos context.
699 * @param id a keytab.
700 * @param cursor a newly allocated cursor, free with krb5_kt_end_seq_get().
702 * @return Return an error code or 0, see krb5_get_error_message().
704 * @ingroup krb5_keytab
707 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
708 krb5_kt_start_seq_get(krb5_context context,
709 krb5_keytab id,
710 krb5_kt_cursor *cursor)
712 if(id->start_seq_get == NULL) {
713 krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
714 N_("start_seq_get is not supported "
715 "in the %s keytab type", ""),
716 id->prefix);
717 return HEIM_ERR_OPNOTSUPP;
719 return (*id->start_seq_get)(context, id, cursor);
723 * Get the next entry from keytab, advance the cursor. On last entry
724 * the function will return KRB5_KT_END.
726 * @param context a Keberos context.
727 * @param id a keytab.
728 * @param entry the returned entry, free with krb5_kt_free_entry().
729 * @param cursor the cursor of the iteration.
731 * @return Return an error code or 0, see krb5_get_error_message().
733 * @ingroup krb5_keytab
736 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
737 krb5_kt_next_entry(krb5_context context,
738 krb5_keytab id,
739 krb5_keytab_entry *entry,
740 krb5_kt_cursor *cursor)
742 if(id->next_entry == NULL) {
743 krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
744 N_("next_entry is not supported in the %s "
745 " keytab", ""),
746 id->prefix);
747 return HEIM_ERR_OPNOTSUPP;
749 return (*id->next_entry)(context, id, entry, cursor);
753 * Release all resources associated with `cursor'.
755 * @param context a Keberos context.
756 * @param id a keytab.
757 * @param cursor the cursor to free.
759 * @return Return an error code or 0, see krb5_get_error_message().
761 * @ingroup krb5_keytab
764 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
765 krb5_kt_end_seq_get(krb5_context context,
766 krb5_keytab id,
767 krb5_kt_cursor *cursor)
769 if(id->end_seq_get == NULL) {
770 krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
771 "end_seq_get is not supported in the %s "
772 " keytab", id->prefix);
773 return HEIM_ERR_OPNOTSUPP;
775 return (*id->end_seq_get)(context, id, cursor);
779 * Add the entry in `entry' to the keytab `id'.
781 * @param context a Keberos context.
782 * @param id a keytab.
783 * @param entry the entry to add
785 * @return Return an error code or 0, see krb5_get_error_message().
787 * @ingroup krb5_keytab
790 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
791 krb5_kt_add_entry(krb5_context context,
792 krb5_keytab id,
793 krb5_keytab_entry *entry)
795 if(id->add == NULL) {
796 krb5_set_error_message(context, KRB5_KT_NOWRITE,
797 N_("Add is not supported in the %s keytab", ""),
798 id->prefix);
799 return KRB5_KT_NOWRITE;
801 entry->timestamp = time(NULL);
802 return (*id->add)(context, id,entry);
806 * Remove an entry from the keytab, matching is done using
807 * krb5_kt_compare().
809 * @param context a Keberos context.
810 * @param id a keytab.
811 * @param entry the entry to remove
813 * @return Return an error code or 0, see krb5_get_error_message().
815 * @ingroup krb5_keytab
818 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
819 krb5_kt_remove_entry(krb5_context context,
820 krb5_keytab id,
821 krb5_keytab_entry *entry)
823 if(id->remove == NULL) {
824 krb5_set_error_message(context, KRB5_KT_NOWRITE,
825 N_("Remove is not supported in the %s keytab", ""),
826 id->prefix);
827 return KRB5_KT_NOWRITE;
829 return (*id->remove)(context, id, entry);