aboutsummaryrefslogtreecommitdiff
path: root/lib/krb5/keytab.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/krb5/keytab.c')
-rw-r--r--lib/krb5/keytab.c687
1 files changed, 526 insertions, 161 deletions
diff --git a/lib/krb5/keytab.c b/lib/krb5/keytab.c
index f6c7858c12ec..8ca515f2133d 100644
--- a/lib/krb5/keytab.c
+++ b/lib/krb5/keytab.c
@@ -1,60 +1,161 @@
/*
- * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#include "krb5_locl.h"
-RCSID("$Id: keytab.c 20211 2007-02-09 07:11:03Z lha $");
+/**
+ * @page krb5_keytab_intro The keytab handing functions
+ * @section section_krb5_keytab Kerberos Keytabs
+ *
+ * See the library functions here: @ref krb5_keytab
+ *
+ * Keytabs are long term key storage for servers, their equvalment of
+ * password files.
+ *
+ * Normally the only function that useful for server are to specify
+ * what keytab to use to other core functions like krb5_rd_req()
+ * krb5_kt_resolve(), and krb5_kt_close().
+ *
+ * @subsection krb5_keytab_names Keytab names
+ *
+ * A keytab name is on the form type:residual. The residual part is
+ * specific to each keytab-type.
+ *
+ * When a keytab-name is resolved, the type is matched with an internal
+ * list of keytab types. If there is no matching keytab type,
+ * the default keytab is used. The current default type is FILE.
+ *
+ * The default value can be changed in the configuration file
+ * /etc/krb5.conf by setting the variable
+ * [defaults]default_keytab_name.
+ *
+ * The keytab types that are implemented in Heimdal are:
+ * - file
+ * store the keytab in a file, the type's name is FILE . The
+ * residual part is a filename. For compatibility with other
+ * Kerberos implemtation WRFILE and JAVA14 is also accepted. WRFILE
+ * has the same format as FILE. JAVA14 have a format that is
+ * compatible with older versions of MIT kerberos and SUN's Java
+ * based installation. They store a truncted kvno, so when the knvo
+ * excess 255, they are truncted in this format.
+ *
+ * - keytab
+ * store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ),
+ * the type's name is AFSKEYFILE. The residual part is a filename.
+ *
+ * - memory
+ * The keytab is stored in a memory segment. This allows sensitive
+ * and/or temporary data not to be stored on disk. The type's name
+ * is MEMORY. Each MEMORY keytab is referenced counted by and
+ * opened by the residual name, so two handles can point to the
+ * same memory area. When the last user closes using krb5_kt_close()
+ * the keytab, the keys in they keytab is memset() to zero and freed
+ * and can no longer be looked up by name.
+ *
+ *
+ * @subsection krb5_keytab_example Keytab example
+ *
+ * This is a minimalistic version of ktutil.
+ *
+ * @code
+int
+main (int argc, char **argv)
+{
+ krb5_context context;
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+ krb5_error_code ret;
+ char *principal;
+
+ if (krb5_init_context (&context) != 0)
+ errx(1, "krb5_context");
-/*
- * Register a new keytab in `ops'
- * Return 0 or an error.
+ ret = krb5_kt_default (context, &keytab);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_default");
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
+ while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
+ krb5_unparse_name(context, entry.principal, &principal);
+ printf("principal: %s\n", principal);
+ free(principal);
+ krb5_kt_free_entry(context, &entry);
+ }
+ ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
+ ret = krb5_kt_close(context, keytab);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_close");
+ krb5_free_context(context);
+ return 0;
+}
+ * @endcode
+ *
*/
-krb5_error_code KRB5_LIB_FUNCTION
+
+/**
+ * Register a new keytab backend.
+ *
+ * @param context a Keberos context.
+ * @param ops a backend to register.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_register(krb5_context context,
const krb5_kt_ops *ops)
{
struct krb5_keytab_data *tmp;
if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) {
- krb5_set_error_string(context, "krb5_kt_register; prefix too long");
+ krb5_set_error_message(context, KRB5_KT_BADNAME,
+ N_("can't register cache type, prefix too long", ""));
return KRB5_KT_BADNAME;
}
tmp = realloc(context->kt_types,
(context->num_kt_types + 1) * sizeof(*context->kt_types));
if(tmp == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
return ENOMEM;
}
memcpy(&tmp[context->num_kt_types], ops,
@@ -64,13 +165,49 @@ krb5_kt_register(krb5_context context,
return 0;
}
-/*
+static const char *
+keytab_name(const char *name, const char **type, size_t *type_len)
+{
+ const char *residual;
+
+ residual = strchr(name, ':');
+
+ if (residual == NULL ||
+ name[0] == '/'
+#ifdef _WIN32
+ /* Avoid treating <drive>:<path> as a keytab type
+ * specification */
+ || name + 1 == residual
+#endif
+ ) {
+
+ *type = "FILE";
+ *type_len = strlen(*type);
+ residual = name;
+ } else {
+ *type = name;
+ *type_len = residual - name;
+ residual++;
+ }
+
+ return residual;
+}
+
+/**
* Resolve the keytab name (of the form `type:residual') in `name'
* into a keytab in `id'.
- * Return 0 or an error
+ *
+ * @param context a Keberos context.
+ * @param name name to resolve
+ * @param id resulting keytab, free with krb5_kt_close().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_resolve(krb5_context context,
const char *name,
krb5_keytab *id)
@@ -81,30 +218,22 @@ krb5_kt_resolve(krb5_context context,
size_t type_len;
krb5_error_code ret;
- residual = strchr(name, ':');
- if(residual == NULL) {
- type = "FILE";
- type_len = strlen(type);
- residual = name;
- } else {
- type = name;
- type_len = residual - name;
- residual++;
- }
-
+ residual = keytab_name(name, &type, &type_len);
+
for(i = 0; i < context->num_kt_types; i++) {
if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0)
break;
}
if(i == context->num_kt_types) {
- krb5_set_error_string(context, "unknown keytab type %.*s",
- (int)type_len, type);
+ krb5_set_error_message(context, KRB5_KT_UNKNOWN_TYPE,
+ N_("unknown keytab type %.*s", "type"),
+ (int)type_len, type);
return KRB5_KT_UNKNOWN_TYPE;
}
-
+
k = malloc (sizeof(*k));
if (k == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
return ENOMEM;
}
memcpy(k, &context->kt_types[i], sizeof(*k));
@@ -118,27 +247,41 @@ krb5_kt_resolve(krb5_context context,
return ret;
}
-/*
+/**
* copy the name of the default keytab into `name'.
- * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+ *
+ * @param context a Keberos context.
+ * @param name buffer where the name will be written
+ * @param namesize length of name
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
{
if (strlcpy (name, context->default_keytab, namesize) >= namesize) {
- krb5_clear_error_string (context);
+ krb5_clear_error_message (context);
return KRB5_CONFIG_NOTENUFSPACE;
}
return 0;
}
-/*
- * copy the name of the default modify keytab into `name'.
- * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+/**
+ * Copy the name of the default modify keytab into `name'.
+ *
+ * @param context a Keberos context.
+ * @param name buffer where the name will be written
+ * @param namesize length of name
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
{
const char *kt = NULL;
@@ -148,40 +291,56 @@ krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
else {
size_t len = strcspn(context->default_keytab + 4, ",");
if(len >= namesize) {
- krb5_clear_error_string(context);
+ krb5_clear_error_message(context);
return KRB5_CONFIG_NOTENUFSPACE;
}
strlcpy(name, context->default_keytab + 4, namesize);
name[len] = '\0';
return 0;
- }
+ }
} else
kt = context->default_keytab_modify;
if (strlcpy (name, kt, namesize) >= namesize) {
- krb5_clear_error_string (context);
+ krb5_clear_error_message (context);
return KRB5_CONFIG_NOTENUFSPACE;
}
return 0;
}
-/*
+/**
* Set `id' to the default keytab.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id the new default keytab.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_default(krb5_context context, krb5_keytab *id)
{
return krb5_kt_resolve (context, context->default_keytab, id);
}
-/*
+/**
* Read the key identified by `(principal, vno, enctype)' from the
* keytab in `keyprocarg' (the default if == NULL) into `*key'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param keyprocarg
+ * @param principal
+ * @param vno
+ * @param enctype
+ * @param key
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_read_service_key(krb5_context context,
krb5_pointer keyprocarg,
krb5_principal principal,
@@ -210,12 +369,21 @@ krb5_kt_read_service_key(krb5_context context,
return ret;
}
-/*
+/**
* Return the type of the `keytab' in the string `prefix of length
* `prefixsize'.
+ *
+ * @param context a Keberos context.
+ * @param keytab the keytab to get the prefix for
+ * @param prefix prefix buffer
+ * @param prefixsize length of prefix buffer
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_get_type(krb5_context context,
krb5_keytab keytab,
char *prefix,
@@ -225,13 +393,21 @@ krb5_kt_get_type(krb5_context context,
return 0;
}
-/*
+/**
* Retrieve the name of the keytab `keytab' into `name', `namesize'
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param keytab the keytab to get the name for.
+ * @param name name buffer.
+ * @param namesize size of name buffer.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_kt_get_name(krb5_context context,
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_kt_get_name(krb5_context context,
krb5_keytab keytab,
char *name,
size_t namesize)
@@ -239,21 +415,29 @@ krb5_kt_get_name(krb5_context context,
return (*keytab->get_name)(context, keytab, name, namesize);
}
-/*
+/**
* Retrieve the full name of the keytab `keytab' and store the name in
- * `str'. `str' needs to be freed by the caller using free(3).
- * Returns 0 or an error. On error, *str is set to NULL.
+ * `str'.
+ *
+ * @param context a Keberos context.
+ * @param keytab keytab to get name for.
+ * @param str the name of the keytab name, usee krb5_xfree() to free
+ * the string. On error, *str is set to NULL.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_kt_get_full_name(krb5_context context,
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_kt_get_full_name(krb5_context context,
krb5_keytab keytab,
char **str)
{
char type[KRB5_KT_PREFIX_MAX_LEN];
char name[MAXPATHLEN];
krb5_error_code ret;
-
+
*str = NULL;
ret = krb5_kt_get_type(context, keytab, type, sizeof(type));
@@ -265,7 +449,7 @@ krb5_kt_get_full_name(krb5_context context,
return ret;
if (asprintf(str, "%s:%s", type, name) == -1) {
- krb5_set_error_string(context, "malloc - out of memory");
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
*str = NULL;
return ENOMEM;
}
@@ -273,13 +457,20 @@ krb5_kt_get_full_name(krb5_context context,
return 0;
}
-/*
+/**
* Finish using the keytab in `id'. All resources will be released,
- * even on errors. Return 0 or an error.
+ * even on errors.
+ *
+ * @param context a Keberos context.
+ * @param id keytab to close.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_kt_close(krb5_context context,
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_kt_close(krb5_context context,
krb5_keytab id)
{
krb5_error_code ret;
@@ -290,21 +481,73 @@ krb5_kt_close(krb5_context context,
return ret;
}
+/**
+ * Destroy (remove) the keytab in `id'. All resources will be released,
+ * even on errors, does the equvalment of krb5_kt_close() on the resources.
+ *
+ * @param context a Keberos context.
+ * @param id keytab to destroy.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_kt_destroy(krb5_context context,
+ krb5_keytab id)
+{
+ krb5_error_code ret;
+
+ ret = (*id->destroy)(context, id);
+ krb5_kt_close(context, id);
+ return ret;
+}
+
/*
+ * Match any aliases in keytab `entry' with `principal'.
+ */
+
+static krb5_boolean
+compare_aliseses(krb5_context context,
+ krb5_keytab_entry *entry,
+ krb5_const_principal principal)
+{
+ unsigned int i;
+ if (entry->aliases == NULL)
+ return FALSE;
+ for (i = 0; i < entry->aliases->len; i++)
+ if (krb5_principal_compare(context, &entry->aliases->val[i], principal))
+ return TRUE;
+ return FALSE;
+}
+
+/**
* Compare `entry' against `principal, vno, enctype'.
* Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
* Return TRUE if they compare the same, FALSE otherwise.
+ *
+ * @param context a Keberos context.
+ * @param entry an entry to match with.
+ * @param principal principal to match, NULL matches all principals.
+ * @param vno key version to match, 0 matches all key version numbers.
+ * @param enctype encryption type to match, 0 matches all encryption types.
+ *
+ * @return Return TRUE or match, FALSE if not matched.
+ *
+ * @ingroup krb5_keytab
*/
-krb5_boolean KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_kt_compare(krb5_context context,
- krb5_keytab_entry *entry,
+ krb5_keytab_entry *entry,
krb5_const_principal principal,
krb5_kvno vno,
krb5_enctype enctype)
{
- if(principal != NULL &&
- !krb5_principal_compare(context, entry->principal, principal))
+ if(principal != NULL &&
+ !(krb5_principal_compare(context, entry->principal, principal) ||
+ compare_aliseses(context, entry, principal)))
return FALSE;
if(vno && vno != entry->vno)
return FALSE;
@@ -313,14 +556,56 @@ krb5_kt_compare(krb5_context context,
return TRUE;
}
-/*
+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)
+{
+ char princ[256], kvno_str[25], *kt_name;
+ char *enctype_str = NULL;
+
+ krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
+ krb5_kt_get_full_name (context, id, &kt_name);
+ krb5_enctype_to_string(context, enctype, &enctype_str);
+
+ if (kvno)
+ snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
+ else
+ kvno_str[0] = '\0';
+
+ krb5_set_error_message (context, ret,
+ N_("Failed to find %s%s in keytab %s (%s)",
+ "principal, kvno, keytab file, enctype"),
+ princ,
+ kvno_str,
+ kt_name ? kt_name : "unknown keytab",
+ enctype_str ? enctype_str : "unknown enctype");
+ free(kt_name);
+ free(enctype_str);
+ return ret;
+}
+
+
+/**
* Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
- * from the keytab `id'.
- * kvno == 0 is a wildcard and gives the keytab with the highest vno.
- * Return 0 or an error.
+ * from the keytab `id'. Matching is done like krb5_kt_compare().
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param principal principal to match, NULL matches all principals.
+ * @param kvno key version to match, 0 matches all key version numbers.
+ * @param enctype encryption type to match, 0 matches all encryption types.
+ * @param entry the returned entry, free with krb5_kt_free_entry().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_get_entry(krb5_context context,
krb5_keytab id,
krb5_const_principal principal,
@@ -337,8 +622,10 @@ krb5_kt_get_entry(krb5_context context,
ret = krb5_kt_start_seq_get (context, id, &cursor);
if (ret) {
- krb5_clear_error_string(context);
- return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */
+ /* This is needed for krb5_verify_init_creds, but keep error
+ * string from previous error for the human. */
+ context->error_code = KRB5_KT_NOTFOUND;
+ return KRB5_KT_NOTFOUND;
}
entry->vno = 0;
@@ -361,38 +648,25 @@ krb5_kt_get_entry(krb5_context context,
krb5_kt_free_entry(context, &tmp);
}
krb5_kt_end_seq_get (context, id, &cursor);
- if (entry->vno) {
- return 0;
- } else {
- char princ[256], kvno_str[25], *kt_name;
- char *enctype_str = NULL;
-
- krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
- krb5_kt_get_full_name (context, id, &kt_name);
- krb5_enctype_to_string(context, enctype, &enctype_str);
-
- if (kvno)
- snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
- else
- kvno_str[0] = '\0';
-
- krb5_set_error_string (context,
- "Failed to find %s%s in keytab %s (%s)",
- princ,
- kvno_str,
- kt_name ? kt_name : "unknown keytab",
- enctype_str ? enctype_str : "unknown enctype");
- free(kt_name);
- free(enctype_str);
- return KRB5_KT_NOTFOUND;
- }
+ if (entry->vno == 0)
+ return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
+ id, principal, enctype, kvno);
+ return 0;
}
-/*
+/**
* Copy the contents of `in' into `out'.
- * Return 0 or an error. */
+ *
+ * @param context a Keberos context.
+ * @param in the keytab entry to copy.
+ * @param out the copy of the keytab entry, free with krb5_kt_free_entry().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
-krb5_error_code KRB5_LIB_FUNCTION
+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)
@@ -417,11 +691,18 @@ fail:
return ret;
}
-/*
+/**
* Free the contents of `entry'.
+ *
+ * @param context a Keberos context.
+ * @param entry the entry to free
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_free_entry(krb5_context context,
krb5_keytab_entry *entry)
{
@@ -431,98 +712,182 @@ krb5_kt_free_entry(krb5_context context,
return 0;
}
-/*
+/**
* Set `cursor' to point at the beginning of `id'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param cursor a newly allocated cursor, free with krb5_kt_end_seq_get().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
if(id->start_seq_get == NULL) {
- krb5_set_error_string(context,
- "start_seq_get is not supported in the %s "
- " keytab", id->prefix);
+ krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
+ N_("start_seq_get is not supported "
+ "in the %s keytab type", ""),
+ id->prefix);
return HEIM_ERR_OPNOTSUPP;
}
return (*id->start_seq_get)(context, id, cursor);
}
-/*
- * Get the next entry from `id' pointed to by `cursor' and advance the
- * `cursor'.
- * Return 0 or an error.
+/**
+ * Get the next entry from keytab, advance the cursor. On last entry
+ * the function will return KRB5_KT_END.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the returned entry, free with krb5_kt_free_entry().
+ * @param cursor the cursor of the iteration.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+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)
{
if(id->next_entry == NULL) {
- krb5_set_error_string(context,
- "next_entry is not supported in the %s "
- " keytab", id->prefix);
+ krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
+ N_("next_entry is not supported in the %s "
+ " keytab", ""),
+ id->prefix);
return HEIM_ERR_OPNOTSUPP;
}
return (*id->next_entry)(context, id, entry, cursor);
}
-/*
+/**
* Release all resources associated with `cursor'.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param cursor the cursor to free.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
if(id->end_seq_get == NULL) {
- krb5_set_error_string(context,
- "end_seq_get is not supported in the %s "
- " keytab", id->prefix);
+ krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP,
+ "end_seq_get is not supported in the %s "
+ " keytab", id->prefix);
return HEIM_ERR_OPNOTSUPP;
}
return (*id->end_seq_get)(context, id, cursor);
}
-/*
+/**
* Add the entry in `entry' to the keytab `id'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the entry to add
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
if(id->add == NULL) {
- krb5_set_error_string(context, "Add is not supported in the %s keytab",
- id->prefix);
+ krb5_set_error_message(context, KRB5_KT_NOWRITE,
+ N_("Add is not supported in the %s keytab", ""),
+ id->prefix);
return KRB5_KT_NOWRITE;
}
entry->timestamp = time(NULL);
return (*id->add)(context, id,entry);
}
-/*
- * Remove the entry `entry' from the keytab `id'.
- * Return 0 or an error.
+/**
+ * Remove an entry from the keytab, matching is done using
+ * krb5_kt_compare().
+
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the entry to remove
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
-krb5_error_code KRB5_LIB_FUNCTION
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_remove_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
if(id->remove == NULL) {
- krb5_set_error_string(context,
- "Remove is not supported in the %s keytab",
- id->prefix);
+ krb5_set_error_message(context, KRB5_KT_NOWRITE,
+ N_("Remove is not supported in the %s keytab", ""),
+ id->prefix);
return KRB5_KT_NOWRITE;
}
return (*id->remove)(context, id, entry);
}
+
+/**
+ * Return true if the keytab exists and have entries
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
+
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
+krb5_kt_have_content(krb5_context context,
+ krb5_keytab id)
+{
+ krb5_keytab_entry entry;
+ krb5_kt_cursor cursor;
+ krb5_error_code ret;
+ char *name;
+
+ ret = krb5_kt_start_seq_get(context, id, &cursor);
+ if (ret)
+ goto notfound;
+
+ ret = krb5_kt_next_entry(context, id, &entry, &cursor);
+ krb5_kt_end_seq_get(context, id, &cursor);
+ if (ret)
+ goto notfound;
+
+ krb5_kt_free_entry(context, &entry);
+
+ return 0;
+
+ notfound:
+ ret = krb5_kt_get_full_name(context, id, &name);
+ if (ret == 0) {
+ krb5_set_error_message(context, KRB5_KT_NOTFOUND,
+ N_("No entry in keytab: %s", ""), name);
+ free(name);
+ }
+ return KRB5_KT_NOTFOUND;
+}