2013-10-02 18:46:20 +00:00
|
|
|
Pared down from the git commits, with a local copy of k5memdup0() added in
|
|
|
|
to cc_keyring, and a wrapper 'run' in to k5test.py.
|
|
|
|
|
2013-09-06 18:12:24 +00:00
|
|
|
diff --git a/src/aclocal.m4 b/src/aclocal.m4
|
2013-10-02 18:46:20 +00:00
|
|
|
index 2c17e46..7be77c2 100644
|
2013-09-06 18:12:24 +00:00
|
|
|
--- a/src/aclocal.m4
|
|
|
|
+++ b/src/aclocal.m4
|
|
|
|
@@ -89,6 +89,7 @@ KRB5_AC_INITFINI
|
|
|
|
KRB5_AC_ENABLE_THREADS
|
|
|
|
KRB5_AC_FIND_DLOPEN
|
|
|
|
KRB5_AC_KEYRING_CCACHE
|
|
|
|
+KRB5_AC_PERSISTENT_KEYRING
|
|
|
|
])dnl
|
|
|
|
|
|
|
|
dnl Maintainer mode, akin to what automake provides, 'cept we don't
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1664,3 +1659,12 @@ AC_DEFUN(KRB5_AC_KEYRING_CCACHE,[
|
2013-09-06 18:12:24 +00:00
|
|
|
]))
|
|
|
|
])dnl
|
|
|
|
dnl
|
|
|
|
+dnl If libkeyutils supports persistent keyrings, use them
|
|
|
|
+AC_DEFUN(KRB5_AC_PERSISTENT_KEYRING,[
|
|
|
|
+ AC_CHECK_HEADERS([keyutils.h],
|
2013-10-02 18:46:20 +00:00
|
|
|
+ AC_CHECK_LIB(keyutils, keyctl_get_persistent,
|
|
|
|
+ [AC_DEFINE(HAVE_PERSISTENT_KEYRING, 1,
|
|
|
|
+ [Define if persistent keyrings are supported])
|
2013-09-06 18:12:24 +00:00
|
|
|
+ ]))
|
|
|
|
+])dnl
|
|
|
|
+dnl
|
2013-10-02 18:46:20 +00:00
|
|
|
diff --git a/src/lib/krb5/error_tables/k5e1_err.et b/src/lib/krb5/error_tables/k5e1_err.et
|
|
|
|
index 98374ed..071b7f2 100644
|
|
|
|
--- a/src/lib/krb5/error_tables/k5e1_err.et
|
|
|
|
+++ b/src/lib/krb5/error_tables/k5e1_err.et
|
|
|
|
@@ -35,4 +35,7 @@ error_code KRB5_PLUGIN_BAD_MODULE_SPEC, "Invalid module specifier"
|
|
|
|
error_code KRB5_PLUGIN_NAME_NOTFOUND, "Plugin module name not found"
|
|
|
|
error_code KRB5KDC_ERR_DISCARD, "The KDC should discard this request"
|
|
|
|
error_code KRB5_DCC_CANNOT_CREATE, "Can't create new subsidiary cache"
|
|
|
|
+error_code KRB5_KCC_INVALID_ANCHOR, "Invalid keyring anchor name"
|
|
|
|
+error_code KRB5_KCC_UNKNOWN_VERSION, "Unknown keyring collection version"
|
|
|
|
+error_code KRB5_KCC_INVALID_UID, "Invalid UID in persistent keyring name"
|
|
|
|
end
|
2013-09-06 18:12:24 +00:00
|
|
|
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
|
2013-10-02 18:46:20 +00:00
|
|
|
index fd1bcec..795ccd6 100644
|
2013-09-06 18:12:24 +00:00
|
|
|
--- a/src/lib/krb5/ccache/cc_keyring.c
|
|
|
|
+++ b/src/lib/krb5/ccache/cc_keyring.c
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -56,17 +56,42 @@
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
- * Implementation of a credentials cache stored in the Linux keyring facility
|
|
|
|
+ * This file implements a collection-enabled credential cache type where the
|
|
|
|
+ * credentials are stored in the Linux keyring facility.
|
|
|
|
*
|
|
|
|
- * Some assumptions:
|
|
|
|
+ * A residual of this type can have three forms:
|
|
|
|
+ * anchor:collection:subsidiary
|
|
|
|
+ * anchor:collection
|
|
|
|
+ * collection
|
|
|
|
*
|
|
|
|
- * - A credentials cache "file" == a keyring with separate keys
|
|
|
|
- * for the information in the ccache (see below)
|
|
|
|
- * - A credentials cache keyring will contain only keys,
|
|
|
|
- * not other keyrings
|
|
|
|
- * - Each Kerberos ticket will have its own key within the ccache keyring
|
|
|
|
- * - The principal information for the ccache is stored in a
|
2013-09-06 18:12:24 +00:00
|
|
|
- * special key, which is not counted in the 'numkeys' count
|
2013-10-02 18:46:20 +00:00
|
|
|
+ * The anchor name is "process", "thread", or "legacy" and determines where we
|
|
|
|
+ * search for keyring collections. In the third form, the anchor name is
|
|
|
|
+ * presumed to be "legacy". The anchor keyring for legacy caches is the
|
|
|
|
+ * session keyring.
|
|
|
|
+ *
|
|
|
|
+ * If the subsidiary name is present, the residual identifies a single cache
|
|
|
|
+ * within a collection. Otherwise, the residual identifies the collection
|
|
|
|
+ * itself. When a residual identifying a collection is resolved, the
|
|
|
|
+ * collection's primary key is looked up (or initialized, using the collection
|
|
|
|
+ * name as the subsidiary name), and the resulting cache's name will use the
|
|
|
|
+ * first name form and will identify the primary cache.
|
|
|
|
+ *
|
|
|
|
+ * Keyring collections are named "_krb_<collection>" and are linked from the
|
|
|
|
+ * anchor keyring. The keys within a keyring collection are links to cache
|
|
|
|
+ * keyrings, plus a link to one user key named "krb_ccache:primary" which
|
|
|
|
+ * contains a serialized representation of the collection version (currently 1)
|
|
|
|
+ * and the primary name of the collection.
|
2013-09-06 18:12:24 +00:00
|
|
|
+ *
|
2013-10-02 18:46:20 +00:00
|
|
|
+ * Cache keyrings contain one user key per credential which contains a
|
|
|
|
+ * serialized representation of the credential. There is also one user key
|
|
|
|
+ * named "__krb5_princ__" which contains a serialized representation of the
|
|
|
|
+ * cache's default principal.
|
|
|
|
+ *
|
|
|
|
+ * If the anchor name is "legacy", then the initial primary cache (the one
|
|
|
|
+ * named with the collection name) is also linked to the session keyring, and
|
|
|
|
+ * we look for a cache in that location when initializing the collection. This
|
|
|
|
+ * extra link allows that cache to be visible to old versions of the KEYRING
|
|
|
|
+ * cache type, and allows us to see caches created by that code.
|
2013-09-06 18:12:24 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cc-int.h"
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -101,7 +126,20 @@ debug_print(char *fmt, ...)
|
2013-09-06 18:12:24 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
- * We always use "user" key type
|
2013-10-02 18:46:20 +00:00
|
|
|
+ * We try to use the big_key key type for credentials except in legacy caches.
|
|
|
|
+ * We fall back to the user key type if the kernel does not support big_key.
|
|
|
|
+ * If the library doesn't support keyctl_get_persistent(), we don't even try
|
|
|
|
+ * big_key since the two features were added at the same time.
|
|
|
|
+ */
|
|
|
|
+#ifdef HAVE_PERSISTENT_KEYRING
|
|
|
|
+#define KRCC_CRED_KEY_TYPE "big_key"
|
|
|
|
+#else
|
|
|
|
+#define KRCC_CRED_KEY_TYPE "user"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * We use the "user" key type for collection primary names, for cache principal
|
|
|
|
+ * names, and for credentials in legacy caches.
|
2013-09-06 18:12:24 +00:00
|
|
|
*/
|
|
|
|
#define KRCC_KEY_TYPE_USER "user"
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -117,20 +155,6 @@ debug_print(char *fmt, ...)
|
2013-09-06 18:12:24 +00:00
|
|
|
#define KRCC_SPEC_PRINC_KEYNAME "__krb5_princ__"
|
|
|
|
|
|
|
|
/*
|
|
|
|
- * XXX The following two really belong in some external
|
|
|
|
- * header since outside programs will need to use these
|
|
|
|
- * same names.
|
|
|
|
- */
|
|
|
|
-/*
|
|
|
|
- * Special name for key to communicate key serial numbers
|
|
|
|
- * This is used by the Linux gssd process to pass the
|
|
|
|
- * user's keyring values it gets in an upcall.
|
|
|
|
- * The format of the contents should be
|
|
|
|
- * <session_key>:<process_key>:<thread_key>
|
|
|
|
- */
|
|
|
|
-#define KRCC_SPEC_IDS_KEYNAME "_gssd_keyring_ids_"
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
* Special name for the key to communicate the name(s)
|
|
|
|
* of credentials caches to be used for requests.
|
|
|
|
* This should currently contain a single name, but
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -139,26 +163,55 @@ debug_print(char *fmt, ...)
|
2013-09-06 18:12:24 +00:00
|
|
|
*/
|
|
|
|
#define KRCC_SPEC_CCACHE_SET_KEYNAME "__krb5_cc_set__"
|
|
|
|
|
|
|
|
+/*
|
2013-10-02 18:46:20 +00:00
|
|
|
+ * This name identifies the key containing the name of the current primary
|
|
|
|
+ * cache within a collection.
|
2013-09-06 18:12:24 +00:00
|
|
|
+ */
|
|
|
|
+#define KRCC_COLLECTION_PRIMARY "krb_ccache:primary"
|
|
|
|
+
|
|
|
|
+/*
|
2013-10-02 18:46:20 +00:00
|
|
|
+ * If the library context does not specify a keyring collection, unique ccaches
|
|
|
|
+ * will be created within this collection.
|
|
|
|
+ */
|
|
|
|
+#define KRCC_DEFAULT_UNIQUE_COLLECTION "session:__krb5_unique__"
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Collection keyring names begin with this prefix. We use a prefix so that a
|
|
|
|
+ * cache keyring with the collection name itself can be linked directly into
|
|
|
|
+ * the anchor, for legacy session keyring compatibility.
|
|
|
|
+ */
|
|
|
|
+#define KRCC_CCCOL_PREFIX "_krb_"
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * For the "persistent" anchor type, we look up or create this fixed keyring
|
|
|
|
+ * name within the per-UID persistent keyring.
|
|
|
|
+ */
|
|
|
|
+#define KRCC_PERSISTENT_KEYRING_NAME "_krb"
|
|
|
|
+
|
|
|
|
+/*
|
2013-09-06 18:12:24 +00:00
|
|
|
+ * Keyring name prefix and length of random name part
|
|
|
|
+ */
|
|
|
|
+#define KRCC_NAME_PREFIX "krb_ccache_"
|
|
|
|
+#define KRCC_NAME_RAND_CHARS 8
|
|
|
|
+
|
|
|
|
+#define KRCC_COLLECTION_VERSION 1
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+#define KRCC_PERSISTENT_ANCHOR "persistent"
|
|
|
|
+#define KRCC_PROCESS_ANCHOR "process"
|
|
|
|
+#define KRCC_THREAD_ANCHOR "thread"
|
|
|
|
+#define KRCC_SESSION_ANCHOR "session"
|
|
|
|
+#define KRCC_USER_ANCHOR "user"
|
|
|
|
+#define KRCC_LEGACY_ANCHOR "legacy"
|
2013-09-06 18:12:24 +00:00
|
|
|
+
|
|
|
|
#define KRB5_OK 0
|
|
|
|
|
|
|
|
/* Hopefully big enough to hold a serialized credential */
|
|
|
|
-#define GUESS_CRED_SIZE 4096
|
|
|
|
-
|
|
|
|
-#define ALLOC(NUM,TYPE) \
|
|
|
|
- (((NUM) <= (((size_t)0-1)/ sizeof(TYPE))) \
|
|
|
|
- ? (TYPE *) calloc((NUM), sizeof(TYPE)) \
|
|
|
|
- : (errno = ENOMEM,(TYPE *) 0))
|
|
|
|
+#define MAX_CRED_SIZE (1024*1024)
|
|
|
|
|
|
|
|
#define CHECK_N_GO(ret, errdest) if (ret != KRB5_OK) goto errdest
|
|
|
|
#define CHECK(ret) if (ret != KRB5_OK) goto errout
|
|
|
|
#define CHECK_OUT(ret) if (ret != KRB5_OK) return ret
|
|
|
|
|
|
|
|
-typedef struct krb5_krcc_ring_ids {
|
|
|
|
- key_serial_t session;
|
|
|
|
- key_serial_t process;
|
|
|
|
- key_serial_t thread;
|
|
|
|
-} krb5_krcc_ring_ids_t;
|
|
|
|
-
|
|
|
|
typedef struct _krb5_krcc_cursor
|
|
|
|
{
|
|
|
|
int numkeys;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -169,7 +222,7 @@ typedef struct _krb5_krcc_cursor
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This represents a credentials cache "file"
|
|
|
|
- * where ring_id is the keyring serial number for
|
|
|
|
+ * where cache_id is the keyring serial number for
|
|
|
|
* this credentials cache "file". Each key
|
|
|
|
* in the keyring contains a separate key.
|
|
|
|
*/
|
|
|
|
@@ -177,12 +230,11 @@ typedef struct _krb5_krcc_data
|
|
|
|
{
|
|
|
|
char *name; /* Name for this credentials cache */
|
|
|
|
k5_cc_mutex lock; /* synchronization */
|
|
|
|
- key_serial_t parent_id; /* parent keyring of this ccache keyring */
|
|
|
|
- key_serial_t ring_id; /* keyring representing ccache */
|
|
|
|
+ key_serial_t collection_id; /* collection containing this cache keyring */
|
|
|
|
+ key_serial_t cache_id; /* keyring representing ccache */
|
2013-09-06 18:12:24 +00:00
|
|
|
key_serial_t princ_id; /* key holding principal info */
|
|
|
|
- int numkeys; /* # of keys in this ring
|
|
|
|
- * (does NOT include principal info) */
|
|
|
|
krb5_timestamp changetime;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_boolean is_legacy_type;
|
2013-09-06 18:12:24 +00:00
|
|
|
} krb5_krcc_data;
|
|
|
|
|
|
|
|
/* Passed internally to assure we don't go past the bounds of our buffer */
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -190,6 +242,7 @@ typedef struct _krb5_krcc_buffer_cursor
|
2013-09-06 18:12:24 +00:00
|
|
|
{
|
|
|
|
char *bpp;
|
|
|
|
char *endp;
|
|
|
|
+ size_t size; /* For dry-run length calculation */
|
|
|
|
} krb5_krcc_bc;
|
|
|
|
|
|
|
|
/* Global mutex */
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -258,6 +311,29 @@ static krb5_error_code KRB5_CALLCONV krb5_krcc_lock
|
2013-09-06 18:12:24 +00:00
|
|
|
static krb5_error_code KRB5_CALLCONV krb5_krcc_unlock
|
|
|
|
(krb5_context context, krb5_ccache id);
|
|
|
|
|
|
|
|
+static krb5_error_code KRB5_CALLCONV krb5_krcc_ptcursor_new
|
|
|
|
+(krb5_context context, krb5_cc_ptcursor *cursor_out);
|
|
|
|
+
|
|
|
|
+static krb5_error_code KRB5_CALLCONV krb5_krcc_ptcursor_next
|
|
|
|
+(krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *cache_out);
|
|
|
|
+
|
|
|
|
+static krb5_error_code KRB5_CALLCONV krb5_krcc_ptcursor_free
|
|
|
|
+(krb5_context context, krb5_cc_ptcursor *cursor);
|
|
|
|
+
|
|
|
|
+static krb5_error_code KRB5_CALLCONV krb5_krcc_switch_to
|
|
|
|
+(krb5_context context, krb5_ccache cache);
|
2013-10-02 18:46:20 +00:00
|
|
|
+
|
|
|
|
+/* Like k5memdup, but add a final null byte. */
|
|
|
|
+static inline void *
|
|
|
|
+k5memdup0(const void *in, size_t len, krb5_error_code *code)
|
|
|
|
+{
|
|
|
|
+ void *ptr = k5alloc(len + 1, code);
|
|
|
|
+
|
|
|
|
+ if (ptr != NULL && len > 0)
|
|
|
|
+ memcpy(ptr, in, len);
|
|
|
|
+ return ptr;
|
|
|
|
+}
|
2013-09-06 18:12:24 +00:00
|
|
|
+
|
|
|
|
/*
|
|
|
|
* Internal utility functions
|
|
|
|
*/
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -266,8 +331,9 @@ static krb5_error_code krb5_krcc_clearcache
|
|
|
|
(krb5_context context, krb5_ccache id);
|
|
|
|
|
|
|
|
static krb5_error_code krb5_krcc_new_data
|
|
|
|
-(const char *, key_serial_t ring, key_serial_t parent_ring,
|
|
|
|
- krb5_krcc_data **);
|
|
|
|
+(const char *anchor_name, const char *collection_name,
|
|
|
|
+ const char *subsidiary_name, key_serial_t cache_id,
|
|
|
|
+ key_serial_t collection_id, krb5_krcc_data **datapp);
|
|
|
|
|
|
|
|
static krb5_error_code krb5_krcc_save_principal
|
|
|
|
(krb5_context context, krb5_ccache id, krb5_principal princ);
|
|
|
|
@@ -275,100 +341,480 @@ static krb5_error_code krb5_krcc_save_principal
|
2013-09-06 18:12:24 +00:00
|
|
|
static krb5_error_code krb5_krcc_retrieve_principal
|
|
|
|
(krb5_context context, krb5_ccache id, krb5_principal * princ);
|
|
|
|
|
|
|
|
-static int krb5_krcc_get_ring_ids(krb5_krcc_ring_ids_t *p);
|
2013-10-02 18:46:20 +00:00
|
|
|
-
|
2013-09-06 18:12:24 +00:00
|
|
|
/* Routines to parse a key from a keyring into a cred structure */
|
|
|
|
static krb5_error_code krb5_krcc_parse
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_pointer buf, unsigned int len,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_pointer buf, unsigned int len, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_cred
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_creds * creds,
|
|
|
|
- char *payload, int psize);
|
|
|
|
+(krb5_context context, krb5_creds * creds, char *payload, int psize);
|
|
|
|
static krb5_error_code krb5_krcc_parse_principal
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_principal * princ,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_principal * princ, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_keyblock
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_keyblock * keyblock,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_keyblock * keyblock, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_times
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_ticket_times * t,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_ticket_times * t, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_krb5data
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_data * data,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_data * data, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_int32
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_int32 * i, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_int32 * i, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_octet
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_octet * octet,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_octet * octet, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_addrs
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_address *** a,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_address *** a, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_addr
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_address * a,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_address * a, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_authdata
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_authdata *** ad,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_authdata *** ad, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_authdatum
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_authdata * ad,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context context, krb5_authdata * ad, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_parse_ui_2
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_ui_2 * i, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_ui_2 * i, krb5_krcc_bc * bc);
|
|
|
|
|
|
|
|
/* Routines to unparse a cred structure into keyring key */
|
|
|
|
static krb5_error_code krb5_krcc_unparse
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_pointer buf, unsigned int len,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
-static krb5_error_code krb5_krcc_unparse_cred
|
|
|
|
-(krb5_context context, krb5_ccache id, krb5_creds * creds,
|
|
|
|
+(krb5_context, krb5_pointer buf, unsigned int len, krb5_krcc_bc * bc);
|
|
|
|
+static krb5_error_code krb5_krcc_unparse_cred_alloc
|
|
|
|
+(krb5_context context, krb5_creds * creds,
|
|
|
|
char **datapp, unsigned int *lenptr);
|
|
|
|
+static krb5_error_code krb5_krcc_unparse_cred
|
|
|
|
+(krb5_context context, krb5_creds * creds, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_principal
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_principal princ, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_principal princ, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_keyblock
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_keyblock * keyblock,
|
|
|
|
- krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_keyblock * keyblock, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_times
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_ticket_times * t, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_ticket_times * t, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_krb5data
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_data * data, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_data * data, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_int32
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_int32 i, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_octet
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_int32 i, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_addrs
|
|
|
|
-(krb5_context, krb5_ccache, krb5_address ** a, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_address ** a, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_addr
|
|
|
|
-(krb5_context, krb5_ccache, krb5_address * a, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_address * a, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_authdata
|
|
|
|
-(krb5_context, krb5_ccache, krb5_authdata ** ad, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_authdata ** ad, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_authdatum
|
|
|
|
-(krb5_context, krb5_ccache, krb5_authdata * ad, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_authdata * ad, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_ui_4
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_ui_4 i, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_ui_4 i, krb5_krcc_bc * bc);
|
|
|
|
static krb5_error_code krb5_krcc_unparse_ui_2
|
|
|
|
-(krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
|
|
|
|
+(krb5_context, krb5_int32 i, krb5_krcc_bc * bc);
|
|
|
|
static void krb5_krcc_update_change_time
|
|
|
|
(krb5_krcc_data *);
|
|
|
|
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_parse_index(krb5_context context, krb5_int32 *version,
|
|
|
|
+ char **primary, void *payload, int psize);
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_unparse_index(krb5_context context, krb5_int32 version,
|
|
|
|
+ const char *primary, void **datapp, int *lenptr);
|
|
|
|
+
|
|
|
|
/* Note the following is a stub function for Linux */
|
|
|
|
extern krb5_error_code krb5_change_cache(void);
|
|
|
|
|
|
|
|
/*
|
|
|
|
- * Determine how many keys exist in a ccache keyring.
|
|
|
|
- * Subtracts out the "hidden" key holding the principal information.
|
2013-10-02 18:46:20 +00:00
|
|
|
+ * GET_PERSISTENT(uid) acquires the persistent keyring for uid, or falls back
|
|
|
|
+ * to the user keyring if uid matches the current effective uid.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static key_serial_t
|
|
|
|
+get_persistent_fallback(uid_t uid)
|
|
|
|
+{
|
|
|
|
+ return (uid == geteuid()) ? KEY_SPEC_USER_KEYRING : -1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#ifdef HAVE_PERSISTENT_KEYRING
|
|
|
|
+#define GET_PERSISTENT get_persistent_real
|
|
|
|
+static key_serial_t
|
|
|
|
+get_persistent_real(uid_t uid)
|
|
|
|
+{
|
|
|
|
+ key_serial_t key;
|
|
|
|
+
|
|
|
|
+ key = keyctl_get_persistent(uid, KEY_SPEC_PROCESS_KEYRING);
|
|
|
|
+ return (key == -1 && errno == ENOTSUP) ? get_persistent_fallback(uid) :
|
|
|
|
+ key;
|
|
|
|
+}
|
|
|
|
+#else
|
|
|
|
+#define GET_PERSISTENT get_persistent_fallback
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Find or create a keyring within parent with the given name. If possess is
|
|
|
|
+ * nonzero, also make sure the key is linked from possess. This is necessary
|
|
|
|
+ * to ensure that we have possession rights on the key when the parent is the
|
|
|
|
+ * user or persistent keyring.
|
|
|
|
+ */
|
|
|
|
+static krb5_error_code
|
|
|
|
+find_or_create_keyring(key_serial_t parent, key_serial_t possess,
|
|
|
|
+ const char *name, key_serial_t *key_out)
|
|
|
|
+{
|
|
|
|
+ key_serial_t key;
|
|
|
|
+
|
|
|
|
+ *key_out = -1;
|
|
|
|
+ key = keyctl_search(parent, KRCC_KEY_TYPE_KEYRING, name, possess);
|
|
|
|
+ if (key == -1) {
|
|
|
|
+ if (possess != 0) {
|
|
|
|
+ key = add_key(KRCC_KEY_TYPE_KEYRING, name, NULL, 0, possess);
|
|
|
|
+ if (key == -1)
|
|
|
|
+ return errno;
|
|
|
|
+ if (keyctl_link(key, parent) == -1)
|
|
|
|
+ return errno;
|
|
|
|
+ } else {
|
|
|
|
+ key = add_key(KRCC_KEY_TYPE_KEYRING, name, NULL, 0, parent);
|
|
|
|
+ if (key == -1)
|
|
|
|
+ return errno;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ *key_out = key;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Parse a residual name into an anchor name, a collection name, and possibly a
|
|
|
|
+ * subsidiary name. */
|
|
|
|
+static krb5_error_code
|
|
|
|
+parse_residual(const char *residual, char **anchor_name_out,
|
|
|
|
+ char **collection_name_out, char **subsidiary_name_out)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL;
|
|
|
|
+ const char *sep;
|
|
|
|
+
|
|
|
|
+ *anchor_name_out = 0;
|
|
|
|
+ *collection_name_out = NULL;
|
|
|
|
+ *subsidiary_name_out = NULL;
|
|
|
|
+
|
|
|
|
+ /* Parse out the anchor name. Use the legacy anchor if not present. */
|
|
|
|
+ sep = strchr(residual, ':');
|
|
|
|
+ if (sep == NULL) {
|
|
|
|
+ anchor_name = strdup(KRCC_LEGACY_ANCHOR);
|
|
|
|
+ if (anchor_name == NULL)
|
|
|
|
+ goto oom;
|
|
|
|
+ } else {
|
|
|
|
+ anchor_name = k5memdup0(residual, sep - residual, &ret);
|
|
|
|
+ if (anchor_name == NULL)
|
|
|
|
+ goto oom;
|
|
|
|
+ residual = sep + 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Parse out the collection and subsidiary name. */
|
|
|
|
+ sep = strchr(residual, ':');
|
|
|
|
+ if (sep == NULL) {
|
|
|
|
+ collection_name = strdup(residual);
|
|
|
|
+ if (collection_name == NULL)
|
|
|
|
+ goto oom;
|
|
|
|
+ subsidiary_name = NULL;
|
|
|
|
+ } else {
|
|
|
|
+ collection_name = k5memdup0(residual, sep - residual, &ret);
|
|
|
|
+ if (collection_name == NULL)
|
|
|
|
+ goto oom;
|
|
|
|
+ subsidiary_name = strdup(sep + 1);
|
|
|
|
+ if (subsidiary_name == NULL)
|
|
|
|
+ goto oom;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *anchor_name_out = anchor_name;
|
|
|
|
+ *collection_name_out = collection_name;
|
|
|
|
+ *subsidiary_name_out = subsidiary_name;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+oom:
|
|
|
|
+ free(anchor_name);
|
|
|
|
+ free(collection_name);
|
|
|
|
+ free(subsidiary_name);
|
|
|
|
+ return ENOMEM;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Return true if residual identifies a subsidiary cache which should be linked
|
|
|
|
+ * into the anchor so it can be visible to old code. This is the case if the
|
|
|
|
+ * residual has the legacy anchor and the subsidiary name matches the
|
|
|
|
+ * collection name.
|
|
|
|
+ */
|
|
|
|
+static krb5_boolean
|
|
|
|
+is_legacy_cache_name(const char *residual)
|
|
|
|
+{
|
|
|
|
+ const char *sep, *aname, *cname, *sname;
|
|
|
|
+ size_t alen, clen, legacy_len = sizeof(KRCC_LEGACY_ANCHOR) - 1;
|
|
|
|
+
|
|
|
|
+ /* Get pointers to the anchor, collection, and subsidiary names. */
|
|
|
|
+ aname = residual;
|
|
|
|
+ sep = strchr(residual, ':');
|
|
|
|
+ if (sep == NULL)
|
|
|
|
+ return FALSE;
|
|
|
|
+ alen = sep - aname;
|
|
|
|
+ cname = sep + 1;
|
|
|
|
+ sep = strchr(cname, ':');
|
|
|
|
+ if (sep == NULL)
|
|
|
|
+ return FALSE;
|
|
|
|
+ clen = sep - cname;
|
|
|
|
+ sname = sep + 1;
|
|
|
|
+
|
|
|
|
+ return alen == legacy_len && clen == strlen(sname) &&
|
|
|
|
+ strncmp(aname, KRCC_LEGACY_ANCHOR, alen) == 0 &&
|
|
|
|
+ strncmp(cname, sname, clen) == 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* If the default cache name for context is a KEYRING cache, parse its residual
|
|
|
|
+ * string. Otherwise set all outputs to NULL. */
|
|
|
|
+static krb5_error_code
|
|
|
|
+get_default(krb5_context context, char **anchor_name_out,
|
|
|
|
+ char **collection_name_out, char **subsidiary_name_out)
|
|
|
|
+{
|
|
|
|
+ const char *defname;
|
|
|
|
+
|
|
|
|
+ *anchor_name_out = *collection_name_out = *subsidiary_name_out = NULL;
|
|
|
|
+ defname = krb5_cc_default_name(context);
|
|
|
|
+ if (defname == NULL || strncmp(defname, "KEYRING:", 8) != 0)
|
|
|
|
+ return 0;
|
|
|
|
+ return parse_residual(defname + 8, anchor_name_out, collection_name_out,
|
|
|
|
+ subsidiary_name_out);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Create a residual identifying a subsidiary cache. */
|
|
|
|
+static krb5_error_code
|
|
|
|
+make_subsidiary_residual(const char *anchor_name, const char *collection_name,
|
|
|
|
+ const char *subsidiary_name, char **residual_out)
|
|
|
|
+{
|
|
|
|
+ if (asprintf(residual_out, "%s:%s:%s", anchor_name, collection_name,
|
|
|
|
+ subsidiary_name) < 0) {
|
|
|
|
+ *residual_out = NULL;
|
|
|
|
+ return ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Retrieve or create a keyring for collection_name within the anchor, and set
|
|
|
|
+ * *collection_id_out to its serial number. */
|
|
|
|
+static krb5_error_code
|
|
|
|
+get_collection(const char *anchor_name, const char *collection_name,
|
|
|
|
+ key_serial_t *collection_id_out)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ key_serial_t persistent_id, anchor_id, possess_id = 0;
|
|
|
|
+ char *ckname;
|
|
|
|
+ long uidnum;
|
|
|
|
+
|
|
|
|
+ *collection_id_out = 0;
|
|
|
|
+
|
|
|
|
+ if (strcmp(anchor_name, KRCC_PERSISTENT_ANCHOR) == 0) {
|
|
|
|
+ /*
|
|
|
|
+ * The collection name is a uid (or empty for the current effective
|
|
|
|
+ * uid), and we look up a fixed keyring name within the persistent
|
|
|
|
+ * keyring for that uid. We link it to the process keyring to ensure
|
|
|
|
+ * that we have possession rights on the collection key.
|
|
|
|
+ */
|
|
|
|
+ if (*collection_name != '\0') {
|
|
|
|
+ errno = 0;
|
|
|
|
+ uidnum = strtol(collection_name, NULL, 10);
|
|
|
|
+ if (errno)
|
|
|
|
+ return KRB5_KCC_INVALID_UID;
|
|
|
|
+ } else {
|
|
|
|
+ uidnum = geteuid();
|
|
|
|
+ }
|
|
|
|
+ persistent_id = GET_PERSISTENT(uidnum);
|
|
|
|
+ if (persistent_id == -1)
|
|
|
|
+ return KRB5_KCC_INVALID_UID;
|
|
|
|
+ return find_or_create_keyring(persistent_id, KEY_SPEC_PROCESS_KEYRING,
|
|
|
|
+ KRCC_PERSISTENT_KEYRING_NAME,
|
|
|
|
+ collection_id_out);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (strcmp(anchor_name, KRCC_PROCESS_ANCHOR) == 0) {
|
|
|
|
+ anchor_id = KEY_SPEC_PROCESS_KEYRING;
|
|
|
|
+ } else if (strcmp(anchor_name, KRCC_THREAD_ANCHOR) == 0) {
|
|
|
|
+ anchor_id = KEY_SPEC_THREAD_KEYRING;
|
|
|
|
+ } else if (strcmp(anchor_name, KRCC_SESSION_ANCHOR) == 0) {
|
|
|
|
+ anchor_id = KEY_SPEC_SESSION_KEYRING;
|
|
|
|
+ } else if (strcmp(anchor_name, KRCC_USER_ANCHOR) == 0) {
|
|
|
|
+ /* The user keyring does not confer possession, so we need to link the
|
|
|
|
+ * collection to the process keyring to maintain possession rights. */
|
|
|
|
+ anchor_id = KEY_SPEC_USER_KEYRING;
|
|
|
|
+ possess_id = KEY_SPEC_PROCESS_KEYRING;
|
|
|
|
+ } else if (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0) {
|
|
|
|
+ anchor_id = KEY_SPEC_SESSION_KEYRING;
|
|
|
|
+ } else {
|
|
|
|
+ return KRB5_KCC_INVALID_ANCHOR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Look up the collection keyring name within the anchor keyring. */
|
|
|
|
+ if (asprintf(&ckname, "%s%s", KRCC_CCCOL_PREFIX, collection_name) == -1)
|
|
|
|
+ return ENOMEM;
|
|
|
|
+ ret = find_or_create_keyring(anchor_id, possess_id, ckname,
|
|
|
|
+ collection_id_out);
|
|
|
|
+ free(ckname);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Store subsidiary_name into the primary index key for collection_id. */
|
|
|
|
+static krb5_error_code
|
|
|
|
+set_primary_name(krb5_context context, key_serial_t collection_id,
|
|
|
|
+ const char *subsidiary_name)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ key_serial_t key;
|
|
|
|
+ void *payload = NULL;
|
|
|
|
+ int payloadlen;
|
|
|
|
+
|
|
|
|
+ ret = krb5_krcc_unparse_index(context, KRCC_COLLECTION_VERSION,
|
|
|
|
+ subsidiary_name, &payload, &payloadlen);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ key = add_key(KRCC_KEY_TYPE_USER, KRCC_COLLECTION_PRIMARY,
|
|
|
|
+ payload, payloadlen, collection_id);
|
|
|
|
+ free(payload);
|
|
|
|
+ return (key == -1) ? errno : 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Get or initialize the primary name within collection_id and set
|
|
|
|
+ * *subsidiary_out to its value. If initializing a legacy collection, look
|
|
|
|
+ * for a legacy cache and add it to the collection.
|
|
|
|
+ */
|
|
|
|
+static krb5_error_code
|
|
|
|
+get_primary_name(krb5_context context, const char *anchor_name,
|
|
|
|
+ const char *collection_name, key_serial_t collection_id,
|
|
|
|
+ char **subsidiary_out)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ key_serial_t primary_id, legacy;
|
|
|
|
+ void *payload = NULL;
|
|
|
|
+ int payloadlen;
|
|
|
|
+ krb5_int32 version;
|
|
|
|
+ char *subsidiary_name = NULL;
|
|
|
|
+
|
|
|
|
+ *subsidiary_out = NULL;
|
|
|
|
+
|
|
|
|
+ primary_id = keyctl_search(collection_id, KRCC_KEY_TYPE_USER,
|
|
|
|
+ KRCC_COLLECTION_PRIMARY, 0);
|
|
|
|
+ if (primary_id == -1) {
|
|
|
|
+ /* Initialize the primary key using the collection name. We can't name
|
|
|
|
+ * a key with the empty string, so map that to an arbitrary string. */
|
|
|
|
+ subsidiary_name = strdup((*collection_name == '\0') ? "tkt" :
|
|
|
|
+ collection_name);
|
|
|
|
+ if (subsidiary_name == NULL) {
|
|
|
|
+ ret = ENOMEM;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ ret = set_primary_name(context, collection_id, subsidiary_name);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+
|
|
|
|
+ if (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0) {
|
|
|
|
+ /* Look for a cache created by old code. If we find one, add it to
|
|
|
|
+ * the collection. */
|
|
|
|
+ legacy = keyctl_search(KEY_SPEC_SESSION_KEYRING,
|
|
|
|
+ KRCC_KEY_TYPE_KEYRING, subsidiary_name, 0);
|
|
|
|
+ if (legacy != -1 && keyctl_link(legacy, collection_id) == -1) {
|
|
|
|
+ ret = errno;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ /* Read, parse, and free the primary key's payload. */
|
|
|
|
+ payloadlen = keyctl_read_alloc(primary_id, &payload);
|
|
|
|
+ if (payloadlen == -1) {
|
|
|
|
+ ret = errno;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ ret = krb5_krcc_parse_index(context, &version, &subsidiary_name,
|
|
|
|
+ payload, payloadlen);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+
|
|
|
|
+ if (version != KRCC_COLLECTION_VERSION) {
|
|
|
|
+ ret = KRB5_KCC_UNKNOWN_VERSION;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *subsidiary_out = subsidiary_name;
|
|
|
|
+ subsidiary_name = NULL;
|
|
|
|
+
|
|
|
|
+cleanup:
|
|
|
|
+ free(payload);
|
|
|
|
+ free(subsidiary_name);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Create a keyring with a unique random name within collection_id. Set
|
|
|
|
+ * *subsidiary to its name and *cache_id_out to its key serial number.
|
|
|
|
*/
|
2013-09-06 18:12:24 +00:00
|
|
|
-static int KRB5_CALLCONV
|
|
|
|
-krb5_krcc_getkeycount(key_serial_t cred_ring)
|
2013-10-02 18:46:20 +00:00
|
|
|
+static krb5_error_code
|
|
|
|
+unique_keyring(krb5_context context, key_serial_t collection_id,
|
|
|
|
+ char **subsidiary_out, key_serial_t *cache_id_out)
|
|
|
|
{
|
2013-09-06 18:12:24 +00:00
|
|
|
- int res, nkeys;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ key_serial_t key;
|
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ char uniquename[sizeof(KRCC_NAME_PREFIX) + KRCC_NAME_RAND_CHARS];
|
|
|
|
+ int prefixlen = sizeof(KRCC_NAME_PREFIX) - 1;
|
|
|
|
+ int tries;
|
|
|
|
+
|
|
|
|
+ *subsidiary_out = NULL;
|
|
|
|
+ *cache_id_out = 0;
|
|
|
|
+
|
|
|
|
+ memcpy(uniquename, KRCC_NAME_PREFIX, sizeof(KRCC_NAME_PREFIX));
|
|
|
|
+ k5_cc_mutex_lock(context, &krb5int_krcc_mutex);
|
|
|
|
+
|
|
|
|
+ /* Loop until we successfully create a new ccache keyring with
|
|
|
|
+ * a unique name, or we get an error. Limit to 100 tries. */
|
|
|
|
+ tries = 100;
|
|
|
|
+ while (tries-- > 0) {
|
|
|
|
+ ret = krb5int_random_string(context, uniquename + prefixlen,
|
|
|
|
+ KRCC_NAME_RAND_CHARS);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+
|
|
|
|
+ key = keyctl_search(collection_id, KRCC_KEY_TYPE_KEYRING, uniquename,
|
|
|
|
+ 0);
|
|
|
|
+ if (key < 0) {
|
|
|
|
+ /* Name does not already exist. Create it to reserve the name. */
|
|
|
|
+ key = add_key(KRCC_KEY_TYPE_KEYRING, uniquename, NULL, 0,
|
|
|
|
+ collection_id);
|
|
|
|
+ if (key < 0) {
|
|
|
|
+ ret = errno;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
2013-09-06 18:12:24 +00:00
|
|
|
- res = keyctl_read(cred_ring, NULL, 0);
|
|
|
|
- if (res > 0)
|
|
|
|
- nkeys = (res / sizeof(key_serial_t)) - 1;
|
|
|
|
- else
|
|
|
|
- nkeys = 0;
|
|
|
|
- return(nkeys);
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (tries <= 0) {
|
|
|
|
+ ret = KRB5_CC_BADNAME;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *subsidiary_out = strdup(uniquename);
|
|
|
|
+ if (*subsidiary_out == NULL) {
|
|
|
|
+ ret = ENOMEM;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ *cache_id_out = key;
|
|
|
|
+ ret = KRB5_OK;
|
|
|
|
+cleanup:
|
|
|
|
+ k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static krb5_error_code
|
|
|
|
+add_cred_key(const char *name, const void *payload, size_t plen,
|
|
|
|
+ key_serial_t cache_id, krb5_boolean legacy_type)
|
|
|
|
+{
|
|
|
|
+ key_serial_t key;
|
|
|
|
+
|
|
|
|
+ if (!legacy_type) {
|
|
|
|
+ /* Try the preferred cred key type; fall back if no kernel support. */
|
|
|
|
+ key = add_key(KRCC_CRED_KEY_TYPE, name, payload, plen, cache_id);
|
|
|
|
+ if (key != -1)
|
|
|
|
+ return 0;
|
|
|
|
+ else if (errno != EINVAL && errno != ENODEV)
|
|
|
|
+ return errno;
|
|
|
|
+ }
|
|
|
|
+ /* Use the user key type. */
|
|
|
|
+ key = add_key(KRCC_KEY_TYPE_USER, name, payload, plen, cache_id);
|
|
|
|
+ return (key == -1) ? errno : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -388,24 +834,40 @@ static krb5_error_code KRB5_CALLCONV
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_initialize(krb5_context context, krb5_ccache id,
|
|
|
|
krb5_principal princ)
|
|
|
|
{
|
|
|
|
+ krb5_krcc_data *data = (krb5_krcc_data *)id->data;
|
|
|
|
krb5_error_code kret;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ const char *cache_name, *p;
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
DEBUG_PRINT(("krb5_krcc_initialize: entered\n"));
|
|
|
|
|
|
|
|
- kret = k5_cc_mutex_lock(context, &((krb5_krcc_data *) id->data)->lock);
|
|
|
|
- if (kret)
|
|
|
|
- return kret;
|
|
|
|
+ k5_cc_mutex_lock(context, &data->lock);
|
|
|
|
|
|
|
|
kret = krb5_krcc_clearcache(context, id);
|
|
|
|
if (kret != KRB5_OK)
|
|
|
|
goto out;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (!data->cache_id) {
|
|
|
|
+ /* The key didn't exist at resolve time. Check again and create the
|
|
|
|
+ * key if it still isn't there. */
|
|
|
|
+ p = strrchr(data->name, ':');
|
|
|
|
+ cache_name = (p != NULL) ? p + 1 : data->name;
|
|
|
|
+ kret = find_or_create_keyring(data->collection_id, 0, cache_name,
|
|
|
|
+ &data->cache_id);
|
|
|
|
+ if (kret)
|
|
|
|
+ goto out;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* If this is the legacy cache in a legacy session collection, link it
|
|
|
|
+ * directly to the session keyring so that old code can see it. */
|
|
|
|
+ if (is_legacy_cache_name(data->name))
|
|
|
|
+ (void)keyctl_link(data->cache_id, KEY_SPEC_SESSION_KEYRING);
|
2013-09-06 18:12:24 +00:00
|
|
|
+
|
|
|
|
kret = krb5_krcc_save_principal(context, id, princ);
|
|
|
|
if (kret == KRB5_OK)
|
|
|
|
krb5_change_cache();
|
|
|
|
|
|
|
|
out:
|
|
|
|
- k5_cc_mutex_unlock(context, &((krb5_krcc_data *) id->data)->lock);
|
|
|
|
+ k5_cc_mutex_unlock(context, &data->lock);
|
|
|
|
return kret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -460,14 +922,14 @@ krb5_krcc_clearcache(krb5_context context, krb5_ccache id)
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
d = (krb5_krcc_data *) id->data;
|
|
|
|
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_clearcache: ring_id %d, princ_id %d, "
|
|
|
|
- "numkeys is %d\n", d->ring_id, d->princ_id, d->numkeys));
|
2013-10-02 18:46:20 +00:00
|
|
|
+ DEBUG_PRINT(("krb5_krcc_clearcache: cache_id %d, princ_id %d\n",
|
|
|
|
+ d->cache_id, d->princ_id));
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
- res = keyctl_clear(d->ring_id);
|
|
|
|
- if (res != 0) {
|
|
|
|
- return errno;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (d->cache_id) {
|
|
|
|
+ res = keyctl_clear(d->cache_id);
|
2013-09-06 18:12:24 +00:00
|
|
|
+ if (res != 0)
|
|
|
|
+ return errno;
|
|
|
|
}
|
|
|
|
- d->numkeys = 0;
|
|
|
|
d->princ_id = 0;
|
|
|
|
krb5_krcc_update_change_time(d);
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -484,7 +946,7 @@ krb5_krcc_clearcache(krb5_context context, krb5_ccache id)
|
2013-09-06 18:12:24 +00:00
|
|
|
static krb5_error_code KRB5_CALLCONV
|
|
|
|
krb5_krcc_destroy(krb5_context context, krb5_ccache id)
|
|
|
|
{
|
|
|
|
- krb5_error_code kret;
|
|
|
|
+ krb5_error_code kret = 0;
|
|
|
|
krb5_krcc_data *d;
|
|
|
|
int res;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -492,30 +954,67 @@ krb5_krcc_destroy(krb5_context context, krb5_ccache id)
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
d = (krb5_krcc_data *) id->data;
|
|
|
|
|
|
|
|
- kret = k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
- if (kret)
|
|
|
|
- return kret;
|
|
|
|
+ k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
|
|
|
|
krb5_krcc_clearcache(context, id);
|
2013-10-02 18:46:20 +00:00
|
|
|
- free(d->name);
|
|
|
|
- res = keyctl_unlink(d->ring_id, d->parent_id);
|
2013-09-06 18:12:24 +00:00
|
|
|
- if (res < 0) {
|
|
|
|
- kret = errno;
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_destroy: unlinking key %d from ring %d: %s",
|
|
|
|
- d->ring_id, d->parent_id, error_message(errno)));
|
|
|
|
- goto cleanup;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (d->cache_id) {
|
|
|
|
+ res = keyctl_unlink(d->cache_id, d->collection_id);
|
|
|
|
+ if (res < 0) {
|
2013-09-06 18:12:24 +00:00
|
|
|
+ kret = errno;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ DEBUG_PRINT(("unlinking key %d from ring %d: %s",
|
|
|
|
+ d->cache_id, d->collection_id, error_message(errno)));
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* If this is a legacy cache, unlink it from the session anchor. */
|
|
|
|
+ if (is_legacy_cache_name(d->name))
|
|
|
|
+ (void)keyctl_unlink(d->cache_id, KEY_SPEC_SESSION_KEYRING);
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
-cleanup:
|
|
|
|
+
|
|
|
|
k5_cc_mutex_unlock(context, &d->lock);
|
|
|
|
k5_cc_mutex_destroy(&d->lock);
|
2013-10-02 18:46:20 +00:00
|
|
|
+ free(d->name);
|
2013-09-06 18:12:24 +00:00
|
|
|
free(d);
|
2013-10-02 18:46:20 +00:00
|
|
|
free(id);
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
krb5_change_cache();
|
|
|
|
|
|
|
|
- return KRB5_OK;
|
|
|
|
+ return kret;
|
2013-10-02 18:46:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+/* Create a cache handle for a cache ID. */
|
2013-09-06 18:12:24 +00:00
|
|
|
+static krb5_error_code
|
2013-10-02 18:46:20 +00:00
|
|
|
+make_cache(key_serial_t collection_id, key_serial_t cache_id,
|
|
|
|
+ const char *anchor_name, const char *collection_name,
|
|
|
|
+ const char *subsidiary_name, krb5_ccache *cache_out)
|
2013-09-06 18:12:24 +00:00
|
|
|
+{
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_error_code ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ krb5_ccache ccache = NULL;
|
|
|
|
+ krb5_krcc_data *d;
|
|
|
|
+ key_serial_t pkey = 0;
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* Determine the key containing principal information, if present. */
|
|
|
|
+ pkey = keyctl_search(cache_id, KRCC_KEY_TYPE_USER, KRCC_SPEC_PRINC_KEYNAME,
|
|
|
|
+ 0);
|
|
|
|
+ if (pkey < 0)
|
2013-09-06 18:12:24 +00:00
|
|
|
+ pkey = 0;
|
|
|
|
+
|
|
|
|
+ ccache = malloc(sizeof(struct _krb5_ccache));
|
|
|
|
+ if (!ccache)
|
|
|
|
+ return ENOMEM;
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ ret = krb5_krcc_new_data(anchor_name, collection_name, subsidiary_name,
|
|
|
|
+ cache_id, collection_id, &d);
|
|
|
|
+ if (ret) {
|
|
|
|
+ free(ccache);
|
|
|
|
+ return ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ d->princ_id = pkey;
|
|
|
|
+ ccache->ops = &krb5_krcc_ops;
|
|
|
|
+ ccache->data = d;
|
|
|
|
+ ccache->magic = KV5M_CCACHE;
|
|
|
|
+ *cache_out = ccache;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ return 0;
|
2013-09-06 18:12:24 +00:00
|
|
|
+}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Requires:
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -538,101 +1037,42 @@ cleanup:
|
2013-09-06 18:12:24 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static krb5_error_code KRB5_CALLCONV
|
2013-10-02 18:46:20 +00:00
|
|
|
-krb5_krcc_resolve(krb5_context context, krb5_ccache * id, const char *full_residual)
|
|
|
|
+krb5_krcc_resolve(krb5_context context, krb5_ccache *id, const char *residual)
|
2013-09-06 18:12:24 +00:00
|
|
|
{
|
|
|
|
- krb5_ccache lid;
|
2013-10-02 18:46:20 +00:00
|
|
|
- krb5_error_code kret;
|
2013-09-06 18:12:24 +00:00
|
|
|
- krb5_krcc_data *d;
|
2013-10-02 18:46:20 +00:00
|
|
|
- key_serial_t key;
|
2013-09-06 18:12:24 +00:00
|
|
|
- key_serial_t pkey = 0;
|
|
|
|
- int nkeys = 0;
|
|
|
|
- int res;
|
|
|
|
- krb5_krcc_ring_ids_t ids;
|
2013-10-02 18:46:20 +00:00
|
|
|
- key_serial_t ring_id;
|
2013-09-06 18:12:24 +00:00
|
|
|
- const char *residual;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ key_serial_t collection_id, cache_id;
|
|
|
|
+ char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL;
|
|
|
|
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: entered with name '%s'\n",
|
|
|
|
- full_residual));
|
|
|
|
+ ret = parse_residual(residual, &anchor_name, &collection_name,
|
|
|
|
+ &subsidiary_name);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+ ret = get_collection(anchor_name, collection_name, &collection_id);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
- res = krb5_krcc_get_ring_ids(&ids);
|
|
|
|
- if (res) {
|
|
|
|
- kret = EINVAL;
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: Error getting ring id values!\n"));
|
2013-10-02 18:46:20 +00:00
|
|
|
- return kret;
|
|
|
|
+ if (subsidiary_name == NULL) {
|
|
|
|
+ /* Retrieve or initialize the primary name for the collection. */
|
|
|
|
+ ret = get_primary_name(context, anchor_name, collection_name,
|
|
|
|
+ collection_id, &subsidiary_name);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-09-06 18:12:24 +00:00
|
|
|
- if (strncmp(full_residual, "thread:", 7) == 0) {
|
|
|
|
- residual = full_residual + 7;
|
|
|
|
- ring_id = ids.thread;
|
|
|
|
- } else if (strncmp(full_residual, "process:", 8) == 0) {
|
|
|
|
- residual = full_residual + 8;
|
|
|
|
- ring_id = ids.process;
|
|
|
|
- } else {
|
|
|
|
- residual = full_residual;
|
|
|
|
- ring_id = ids.session;
|
|
|
|
- }
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* Look up the cache keyring ID, if the cache is already initialized. */
|
|
|
|
+ cache_id = keyctl_search(collection_id, KRCC_KEY_TYPE_KEYRING,
|
|
|
|
+ subsidiary_name, 0);
|
|
|
|
+ if (cache_id < 0)
|
|
|
|
+ cache_id = 0;
|
2013-09-06 18:12:24 +00:00
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: searching ring %d for residual '%s'\n",
|
|
|
|
- ring_id, residual));
|
|
|
|
+ ret = make_cache(collection_id, cache_id, anchor_name, collection_name,
|
|
|
|
+ subsidiary_name, id);
|
|
|
|
|
|
|
|
- /*
|
|
|
|
- * Use keyctl_search instead of request_key. If we're supposed
|
|
|
|
- * to be looking for a process ccache, we shouldn't find a
|
|
|
|
- * thread ccache.
|
|
|
|
- * XXX But should we look in the session ring if we don't find it
|
|
|
|
- * in the process ring? Same goes for thread. Should we look in
|
|
|
|
- * the process and session rings if not found in the thread ring?
|
|
|
|
- *
|
|
|
|
- */
|
2013-09-06 18:12:24 +00:00
|
|
|
- key = keyctl_search(ring_id, KRCC_KEY_TYPE_KEYRING, residual, 0);
|
|
|
|
- if (key < 0) {
|
|
|
|
- key = add_key(KRCC_KEY_TYPE_KEYRING, residual, NULL, 0, ring_id);
|
|
|
|
- if (key < 0) {
|
|
|
|
- kret = errno;
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: Error adding new "
|
|
|
|
- "keyring '%s': %s\n", residual, strerror(errno)));
|
|
|
|
- return kret;
|
|
|
|
- }
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: new keyring '%s', "
|
|
|
|
- "key %d, added to keyring %d\n",
|
|
|
|
- residual, key, ring_id));
|
2013-10-02 18:46:20 +00:00
|
|
|
- } else {
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: found existing "
|
|
|
|
- "key %d, with name '%s' in keyring %d\n",
|
2013-09-06 18:12:24 +00:00
|
|
|
- key, residual, ring_id));
|
|
|
|
- /* Determine key containing principal information */
|
|
|
|
- pkey = keyctl_search(key, KRCC_KEY_TYPE_USER,
|
|
|
|
- KRCC_SPEC_PRINC_KEYNAME, 0);
|
|
|
|
- if (pkey < 0) {
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: Error locating principal "
|
|
|
|
- "info for existing ccache in ring %d: %s\n",
|
|
|
|
- key, strerror(errno)));
|
|
|
|
- pkey = 0;
|
|
|
|
- }
|
|
|
|
- /* Determine how many keys exist */
|
|
|
|
- nkeys = krb5_krcc_getkeycount(key);
|
2013-10-02 18:46:20 +00:00
|
|
|
- }
|
|
|
|
-
|
2013-09-06 18:12:24 +00:00
|
|
|
- lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
|
|
|
|
- if (lid == NULL)
|
|
|
|
- return KRB5_CC_NOMEM;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- kret = krb5_krcc_new_data(residual, key, ring_id, &d);
|
|
|
|
- if (kret) {
|
|
|
|
- free(lid);
|
|
|
|
- return kret;
|
|
|
|
- }
|
2013-10-02 18:46:20 +00:00
|
|
|
-
|
2013-09-06 18:12:24 +00:00
|
|
|
- DEBUG_PRINT(("krb5_krcc_resolve: ring_id %d, princ_id %d, "
|
|
|
|
- "nkeys %d\n", key, pkey, nkeys));
|
|
|
|
- d->princ_id = pkey;
|
|
|
|
- d->numkeys = nkeys;
|
|
|
|
- lid->ops = &krb5_krcc_ops;
|
|
|
|
- lid->data = d;
|
|
|
|
- lid->magic = KV5M_CCACHE;
|
|
|
|
- *id = lid;
|
|
|
|
- return KRB5_OK;
|
2013-10-02 18:46:20 +00:00
|
|
|
+cleanup:
|
|
|
|
+ free(anchor_name);
|
|
|
|
+ free(collection_name);
|
|
|
|
+ free(subsidiary_name);
|
|
|
|
+ return ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -653,47 +1093,37 @@ krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_cc_cursor * cursor)
|
|
|
|
{
|
2013-10-02 18:46:20 +00:00
|
|
|
krb5_krcc_cursor krcursor;
|
|
|
|
- krb5_error_code kret;
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_data *d;
|
|
|
|
- unsigned int size;
|
|
|
|
- int res;
|
|
|
|
+ void *keys;
|
|
|
|
+ long size;
|
|
|
|
|
|
|
|
DEBUG_PRINT(("krb5_krcc_start_seq_get: entered\n"));
|
|
|
|
|
|
|
|
d = id->data;
|
|
|
|
- kret = k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
- if (kret)
|
|
|
|
- return kret;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Determine how many keys currently exist and update numkeys.
|
|
|
|
- * We cannot depend on the current value of numkeys because
|
|
|
|
- * the ccache may have been updated elsewhere
|
|
|
|
- */
|
|
|
|
- d->numkeys = krb5_krcc_getkeycount(d->ring_id);
|
|
|
|
+ k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
|
|
|
|
- size = sizeof(*krcursor) + ((d->numkeys + 1) * sizeof(key_serial_t));
|
2013-10-02 18:46:20 +00:00
|
|
|
-
|
2013-09-06 18:12:24 +00:00
|
|
|
- krcursor = (krb5_krcc_cursor) malloc(size);
|
|
|
|
- if (krcursor == NULL) {
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (!d->cache_id) {
|
2013-09-06 18:12:24 +00:00
|
|
|
k5_cc_mutex_unlock(context, &d->lock);
|
|
|
|
- return KRB5_CC_NOMEM;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ return KRB5_FCC_NOFILE;
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- krcursor->keys = (key_serial_t *) ((char *) krcursor + sizeof(*krcursor));
|
|
|
|
- res = keyctl_read(d->ring_id, (char *) krcursor->keys,
|
|
|
|
- ((d->numkeys + 1) * sizeof(key_serial_t)));
|
|
|
|
- if (res < 0 || res > ((d->numkeys + 1) * sizeof(key_serial_t))) {
|
|
|
|
- DEBUG_PRINT(("Read %d bytes from keyring, numkeys %d: %s\n",
|
|
|
|
- res, d->numkeys, strerror(errno)));
|
|
|
|
- free(krcursor);
|
2013-10-02 18:46:20 +00:00
|
|
|
+ size = keyctl_read_alloc(d->cache_id, &keys);
|
|
|
|
+ if (size == -1) {
|
|
|
|
+ DEBUG_PRINT(("Error getting from keyring: %s\n", strerror(errno)));
|
2013-09-06 18:12:24 +00:00
|
|
|
k5_cc_mutex_unlock(context, &d->lock);
|
2013-10-02 18:46:20 +00:00
|
|
|
return KRB5_CC_IO;
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- krcursor->numkeys = d->numkeys;
|
|
|
|
- krcursor->currkey = 0;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krcursor = calloc(1, sizeof(*krcursor));
|
|
|
|
+ if (krcursor == NULL) {
|
|
|
|
+ free(keys);
|
|
|
|
+ k5_cc_mutex_unlock(context, &d->lock);
|
|
|
|
+ return KRB5_CC_NOMEM;
|
|
|
|
+ }
|
|
|
|
+
|
2013-09-06 18:12:24 +00:00
|
|
|
krcursor->princ_id = d->princ_id;
|
|
|
|
+ krcursor->numkeys = size / sizeof(key_serial_t);
|
|
|
|
+ krcursor->keys = keys;
|
|
|
|
|
|
|
|
k5_cc_mutex_unlock(context, &d->lock);
|
|
|
|
*cursor = (krb5_cc_cursor) krcursor;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -741,14 +1171,14 @@ krb5_krcc_next_cred(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
memset(creds, 0, sizeof(krb5_creds));
|
|
|
|
|
|
|
|
/* If we're pointing past the end of the keys array, there are no more */
|
|
|
|
- if (krcursor->currkey > krcursor->numkeys)
|
|
|
|
+ if (krcursor->currkey >= krcursor->numkeys)
|
|
|
|
return KRB5_CC_END;
|
|
|
|
|
|
|
|
/* If we're pointing at the entry with the principal, skip it */
|
|
|
|
if (krcursor->keys[krcursor->currkey] == krcursor->princ_id) {
|
|
|
|
krcursor->currkey++;
|
|
|
|
/* Check if we have now reached the end */
|
|
|
|
- if (krcursor->currkey > krcursor->numkeys)
|
|
|
|
+ if (krcursor->currkey >= krcursor->numkeys)
|
|
|
|
return KRB5_CC_END;
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -763,7 +1193,7 @@ krb5_krcc_next_cred(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
krcursor->currkey++;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_cred(context, id, creds, payload, psize);
|
|
|
|
+ kret = krb5_krcc_parse_cred(context, creds, payload, psize);
|
|
|
|
|
|
|
|
freepayload:
|
|
|
|
if (payload) free(payload);
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -787,19 +1217,24 @@ static krb5_error_code KRB5_CALLCONV
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_end_seq_get(krb5_context context, krb5_ccache id,
|
|
|
|
krb5_cc_cursor * cursor)
|
|
|
|
{
|
|
|
|
+ krb5_krcc_cursor krcursor = (krb5_krcc_cursor)*cursor;
|
|
|
|
DEBUG_PRINT(("krb5_krcc_end_seq_get: entered\n"));
|
|
|
|
|
|
|
|
- free(*cursor);
|
|
|
|
- *cursor = 0L;
|
2013-09-19 20:29:52 +00:00
|
|
|
+ if (krcursor != NULL) {
|
2013-09-06 18:12:24 +00:00
|
|
|
+ free(krcursor->keys);
|
|
|
|
+ free(krcursor);
|
|
|
|
+ }
|
|
|
|
+ *cursor = NULL;
|
|
|
|
return KRB5_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Utility routine: Creates the back-end data for a keyring cache.
|
|
|
|
|
|
|
|
Call with the global list lock held. */
|
2013-10-02 18:46:20 +00:00
|
|
|
-static krb5_error_code
|
|
|
|
-krb5_krcc_new_data(const char *name, key_serial_t ring,
|
|
|
|
- key_serial_t parent_ring, krb5_krcc_data ** datapp)
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_new_data(const char *anchor_name, const char *collection_name,
|
|
|
|
+ const char *subsidiary_name, key_serial_t cache_id,
|
|
|
|
+ key_serial_t collection_id, krb5_krcc_data **datapp)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_krcc_data *d;
|
|
|
|
@@ -814,17 +1249,18 @@ krb5_krcc_new_data(const char *name, key_serial_t ring,
|
|
|
|
return kret;
|
|
|
|
}
|
|
|
|
|
|
|
|
- d->name = strdup(name);
|
|
|
|
- if (d->name == NULL) {
|
|
|
|
+ kret = make_subsidiary_residual(anchor_name, collection_name,
|
|
|
|
+ subsidiary_name, &d->name);
|
|
|
|
+ if (kret) {
|
|
|
|
k5_cc_mutex_destroy(&d->lock);
|
|
|
|
free(d);
|
|
|
|
- return KRB5_CC_NOMEM;
|
|
|
|
+ return kret;
|
|
|
|
}
|
2013-09-06 18:12:24 +00:00
|
|
|
d->princ_id = 0;
|
2013-10-02 18:46:20 +00:00
|
|
|
- d->ring_id = ring;
|
|
|
|
- d->parent_id = parent_ring;
|
2013-09-06 18:12:24 +00:00
|
|
|
- d->numkeys = 0;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ d->cache_id = cache_id;
|
|
|
|
+ d->collection_id = collection_id;
|
2013-09-06 18:12:24 +00:00
|
|
|
d->changetime = 0;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ d->is_legacy_type = (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0);
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_update_change_time(d);
|
|
|
|
|
|
|
|
*datapp = d;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -846,82 +1282,73 @@ krb5_krcc_new_data(const char *name, key_serial_t ring,
|
2013-09-06 18:12:24 +00:00
|
|
|
static krb5_error_code KRB5_CALLCONV
|
|
|
|
krb5_krcc_generate_new(krb5_context context, krb5_ccache * id)
|
|
|
|
{
|
|
|
|
- krb5_ccache lid;
|
|
|
|
- char uniquename[8];
|
|
|
|
+ krb5_ccache lid = NULL;
|
|
|
|
krb5_error_code kret;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL;
|
|
|
|
+ char *new_subsidiary_name = NULL, *new_residual = NULL;
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_data *d;
|
|
|
|
- key_serial_t ring_id = KEY_SPEC_SESSION_KEYRING;
|
|
|
|
- key_serial_t key;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ key_serial_t collection_id;
|
|
|
|
+ key_serial_t cache_id = 0;
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
DEBUG_PRINT(("krb5_krcc_generate_new: entered\n"));
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* Determine the collection in which we will create the cache.*/
|
|
|
|
+ kret = get_default(context, &anchor_name, &collection_name,
|
|
|
|
+ &subsidiary_name);
|
2013-09-06 18:12:24 +00:00
|
|
|
+ if (kret)
|
|
|
|
+ return kret;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (anchor_name == NULL) {
|
|
|
|
+ kret = parse_residual(KRCC_DEFAULT_UNIQUE_COLLECTION, &anchor_name,
|
|
|
|
+ &collection_name, &subsidiary_name);
|
|
|
|
+ if (kret)
|
|
|
|
+ return kret;
|
|
|
|
+ }
|
|
|
|
+ if (subsidiary_name != NULL) {
|
2013-09-06 18:12:24 +00:00
|
|
|
+ krb5_set_error_message(context, KRB5_DCC_CANNOT_CREATE,
|
|
|
|
+ _("Can't create new subsidiary cache because "
|
|
|
|
+ "default cache is already a subsdiary"));
|
|
|
|
+ kret = KRB5_DCC_CANNOT_CREATE;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ goto cleanup;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
/* Allocate memory */
|
|
|
|
lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
|
|
|
|
- if (lid == NULL)
|
|
|
|
- return KRB5_CC_NOMEM;
|
|
|
|
+ if (lid == NULL) {
|
|
|
|
+ kret = ENOMEM;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ goto cleanup;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
|
|
|
|
|
|
|
lid->ops = &krb5_krcc_ops;
|
|
|
|
|
|
|
|
- kret = k5_cc_mutex_lock(context, &krb5int_krcc_mutex);
|
|
|
|
- if (kret) {
|
|
|
|
- free(lid);
|
|
|
|
- return kret;
|
|
|
|
- }
|
2013-10-02 18:46:20 +00:00
|
|
|
-
|
2013-09-06 18:12:24 +00:00
|
|
|
-/* XXX These values are platform-specific and should not be here! */
|
|
|
|
-/* XXX There is a bug in FC5 where these are not included in errno.h */
|
|
|
|
-#ifndef ENOKEY
|
|
|
|
-#define ENOKEY 126 /* Required key not available */
|
|
|
|
-#endif
|
|
|
|
-#ifndef EKEYEXPIRED
|
|
|
|
-#define EKEYEXPIRED 127 /* Key has expired */
|
|
|
|
-#endif
|
|
|
|
-#ifndef EKEYREVOKED
|
|
|
|
-#define EKEYREVOKED 128 /* Key has been revoked */
|
|
|
|
-#endif
|
|
|
|
-#ifndef EKEYREJECTED
|
|
|
|
-#define EKEYREJECTED 129 /* Key was rejected by service */
|
|
|
|
-#endif
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* Make a unique keyring within the chosen collection. */
|
|
|
|
+ kret = get_collection(anchor_name, collection_name, &collection_id);
|
|
|
|
+ if (kret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+ kret = unique_keyring(context, collection_id, &new_subsidiary_name,
|
|
|
|
+ &cache_id);
|
|
|
|
+ if (kret)
|
|
|
|
+ goto cleanup;
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
- /*
|
|
|
|
- * Loop until we successfully create a new ccache keyring with
|
|
|
|
- * a unique name, or we get an error.
|
|
|
|
- */
|
|
|
|
- while (1) {
|
|
|
|
- kret = krb5int_random_string(context, uniquename, sizeof(uniquename));
|
|
|
|
- if (kret) {
|
|
|
|
- k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
|
|
|
|
- free(lid);
|
|
|
|
- return kret;
|
|
|
|
- }
|
2013-10-02 18:46:20 +00:00
|
|
|
+ kret = krb5_krcc_new_data(anchor_name, collection_name,
|
|
|
|
+ new_subsidiary_name, cache_id, collection_id,
|
|
|
|
+ &d);
|
2013-09-06 18:12:24 +00:00
|
|
|
+ if (kret)
|
2013-10-02 18:46:20 +00:00
|
|
|
+ goto cleanup;
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_generate_new: searching for name '%s'\n",
|
|
|
|
- uniquename));
|
|
|
|
- key = keyctl_search(ring_id, KRCC_KEY_TYPE_KEYRING, uniquename, 0);
|
|
|
|
- /*XXX*/ DEBUG_PRINT(("krb5_krcc_generate_new: after searching for '%s', key = %d, errno = %d\n", uniquename, key, errno));
|
|
|
|
- if (key < 0 && errno == ENOKEY) {
|
|
|
|
- /* name does not already exist, create it to reserve the name */
|
|
|
|
- key = add_key(KRCC_KEY_TYPE_KEYRING, uniquename, NULL, 0, ring_id);
|
|
|
|
- if (key < 0) {
|
|
|
|
- kret = errno;
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_generate_new: '%s' trying to "
|
|
|
|
- "create '%s'\n", strerror(errno), uniquename));
|
|
|
|
- k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
|
|
|
|
- return kret;
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
+ lid->data = d;
|
|
|
|
+ krb5_change_cache();
|
|
|
|
|
|
|
|
- kret = krb5_krcc_new_data(uniquename, key, ring_id, &d);
|
|
|
|
- k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
|
2013-10-02 18:46:20 +00:00
|
|
|
+cleanup:
|
|
|
|
+ free(anchor_name);
|
|
|
|
+ free(collection_name);
|
|
|
|
+ free(subsidiary_name);
|
|
|
|
+ free(new_subsidiary_name);
|
|
|
|
+ free(new_residual);
|
2013-09-06 18:12:24 +00:00
|
|
|
if (kret) {
|
|
|
|
free(lid);
|
|
|
|
return kret;
|
|
|
|
}
|
|
|
|
- lid->data = d;
|
|
|
|
*id = lid;
|
|
|
|
- krb5_change_cache();
|
|
|
|
return KRB5_OK;
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1023,14 +1450,16 @@ krb5_krcc_store(krb5_context context, krb5_ccache id, krb5_creds * creds)
|
|
|
|
krb5_krcc_data *d = (krb5_krcc_data *) id->data;
|
|
|
|
char *payload = NULL;
|
2013-09-06 18:12:24 +00:00
|
|
|
unsigned int payloadlen;
|
2013-10-02 18:46:20 +00:00
|
|
|
- key_serial_t newkey;
|
2013-09-06 18:12:24 +00:00
|
|
|
char *keyname = NULL;
|
|
|
|
|
|
|
|
DEBUG_PRINT(("krb5_krcc_store: entered\n"));
|
|
|
|
|
|
|
|
- kret = k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
- if (kret)
|
|
|
|
- return kret;
|
|
|
|
+ k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (!d->cache_id) {
|
2013-09-06 18:12:24 +00:00
|
|
|
+ k5_cc_mutex_unlock(context, &d->lock);
|
|
|
|
+ return KRB5_FCC_NOFILE;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/* Get the service principal name and use it as the key name */
|
|
|
|
kret = krb5_unparse_name(context, creds->server, &keyname);
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1040,24 +1469,19 @@ krb5_krcc_store(krb5_context context, krb5_ccache id, krb5_creds * creds)
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Serialize credential into memory */
|
|
|
|
- kret = krb5_krcc_unparse_cred(context, id, creds, &payload, &payloadlen);
|
|
|
|
+ kret = krb5_krcc_unparse_cred_alloc(context, creds, &payload, &payloadlen);
|
|
|
|
if (kret != KRB5_OK)
|
|
|
|
goto errout;
|
|
|
|
|
|
|
|
/* Add new key (credentials) into keyring */
|
|
|
|
DEBUG_PRINT(("krb5_krcc_store: adding new key '%s' to keyring %d\n",
|
2013-10-02 18:46:20 +00:00
|
|
|
- keyname, d->ring_id));
|
2013-09-06 18:12:24 +00:00
|
|
|
- newkey = add_key(KRCC_KEY_TYPE_USER, keyname, payload,
|
|
|
|
- payloadlen, d->ring_id);
|
2013-10-02 18:46:20 +00:00
|
|
|
- if (newkey < 0) {
|
|
|
|
- kret = errno;
|
|
|
|
- DEBUG_PRINT(("Error adding user key '%s': %s\n",
|
|
|
|
- keyname, strerror(kret)));
|
2013-09-06 18:12:24 +00:00
|
|
|
- } else {
|
|
|
|
- d->numkeys++;
|
|
|
|
- kret = KRB5_OK;
|
|
|
|
- krb5_krcc_update_change_time(d);
|
2013-10-02 18:46:20 +00:00
|
|
|
- }
|
|
|
|
+ keyname, d->cache_id));
|
|
|
|
+ kret = add_cred_key(keyname, payload, payloadlen, d->cache_id,
|
|
|
|
+ d->is_legacy_type);
|
|
|
|
+ if (kret)
|
2013-09-06 18:12:24 +00:00
|
|
|
+ goto errout;
|
|
|
|
+
|
|
|
|
+ krb5_krcc_update_change_time(d);
|
2013-10-02 18:46:20 +00:00
|
|
|
|
2013-09-06 18:12:24 +00:00
|
|
|
errout:
|
|
|
|
if (keyname)
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1073,36 +1497,30 @@ static krb5_error_code KRB5_CALLCONV
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_last_change_time(krb5_context context, krb5_ccache id,
|
|
|
|
krb5_timestamp *change_time)
|
|
|
|
{
|
|
|
|
- krb5_error_code ret = 0;
|
|
|
|
krb5_krcc_data *data = (krb5_krcc_data *) id->data;
|
|
|
|
|
|
|
|
- *change_time = 0;
|
|
|
|
-
|
|
|
|
- ret = k5_cc_mutex_lock(context, &data->lock);
|
|
|
|
- if (!ret) {
|
|
|
|
- *change_time = data->changetime;
|
|
|
|
- k5_cc_mutex_unlock(context, &data->lock);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
+ k5_cc_mutex_lock(context, &data->lock);
|
|
|
|
+ *change_time = data->changetime;
|
|
|
|
+ k5_cc_mutex_unlock(context, &data->lock);
|
|
|
|
+ return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code KRB5_CALLCONV
|
|
|
|
krb5_krcc_lock(krb5_context context, krb5_ccache id)
|
|
|
|
{
|
|
|
|
- krb5_error_code ret = 0;
|
|
|
|
krb5_krcc_data *data = (krb5_krcc_data *) id->data;
|
|
|
|
- ret = k5_cc_mutex_lock(context, &data->lock);
|
|
|
|
- return ret;
|
|
|
|
+
|
|
|
|
+ k5_cc_mutex_lock(context, &data->lock);
|
|
|
|
+ return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code KRB5_CALLCONV
|
|
|
|
krb5_krcc_unlock(krb5_context context, krb5_ccache id)
|
|
|
|
{
|
|
|
|
- krb5_error_code ret = 0;
|
|
|
|
krb5_krcc_data *data = (krb5_krcc_data *) id->data;
|
|
|
|
- ret = k5_cc_mutex_unlock(context, &data->lock);
|
|
|
|
- return ret;
|
|
|
|
+
|
|
|
|
+ k5_cc_mutex_unlock(context, &data->lock);
|
|
|
|
+ return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1112,7 +1530,7 @@ krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
{
|
|
|
|
krb5_krcc_data *d;
|
|
|
|
krb5_error_code kret;
|
|
|
|
- char *payload;
|
|
|
|
+ char *payload = NULL;
|
|
|
|
key_serial_t newkey;
|
|
|
|
unsigned int payloadsize;
|
|
|
|
krb5_krcc_bc bc;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1121,14 +1539,19 @@ krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
d = (krb5_krcc_data *) id->data;
|
|
|
|
|
|
|
|
- payload = malloc(GUESS_CRED_SIZE);
|
|
|
|
+ /* Do a dry run first to calculate the size. */
|
|
|
|
+ bc.bpp = bc.endp = NULL;
|
|
|
|
+ bc.size = 0;
|
|
|
|
+ kret = krb5_krcc_unparse_principal(context, princ, &bc);
|
|
|
|
+ CHECK_N_GO(kret, errout);
|
|
|
|
+
|
|
|
|
+ /* Allocate a buffer and serialize for real. */
|
|
|
|
+ payload = malloc(bc.size);
|
|
|
|
if (payload == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
2013-10-02 18:46:20 +00:00
|
|
|
-
|
|
|
|
bc.bpp = payload;
|
|
|
|
- bc.endp = payload + GUESS_CRED_SIZE;
|
|
|
|
-
|
|
|
|
- kret = krb5_krcc_unparse_principal(context, id, princ, &bc);
|
|
|
|
+ bc.endp = payload + bc.size;
|
|
|
|
+ kret = krb5_krcc_unparse_principal(context, princ, &bc);
|
|
|
|
CHECK_N_GO(kret, errout);
|
|
|
|
|
|
|
|
/* Add new key into keyring */
|
|
|
|
@@ -1140,14 +1563,14 @@ krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
|
|
|
|
rc = krb5_unparse_name(context, princ, &princname);
|
|
|
|
DEBUG_PRINT(("krb5_krcc_save_principal: adding new key '%s' "
|
|
|
|
"to keyring %d for principal '%s'\n",
|
|
|
|
- KRCC_SPEC_PRINC_KEYNAME, d->ring_id,
|
|
|
|
+ KRCC_SPEC_PRINC_KEYNAME, d->cache_id,
|
|
|
|
rc ? "<unknown>" : princname));
|
|
|
|
if (rc == 0)
|
|
|
|
krb5_free_unparsed_name(context, princname);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
newkey = add_key(KRCC_KEY_TYPE_USER, KRCC_SPEC_PRINC_KEYNAME, payload,
|
|
|
|
- payloadsize, d->ring_id);
|
|
|
|
+ payloadsize, d->cache_id);
|
|
|
|
if (newkey < 0) {
|
|
|
|
kret = errno;
|
|
|
|
DEBUG_PRINT(("Error adding principal key: %s\n", strerror(kret)));
|
|
|
|
@@ -1172,11 +1595,9 @@ krb5_krcc_retrieve_principal(krb5_context context, krb5_ccache id,
|
|
|
|
int psize;
|
|
|
|
krb5_krcc_bc bc;
|
|
|
|
|
|
|
|
- kret = k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
- if (kret)
|
|
|
|
- return kret;
|
|
|
|
+ k5_cc_mutex_lock(context, &d->lock);
|
|
|
|
|
|
|
|
- if (!d->princ_id) {
|
|
|
|
+ if (!d->cache_id || !d->princ_id) {
|
|
|
|
princ = 0L;
|
|
|
|
kret = KRB5_FCC_NOFILE;
|
|
|
|
goto errout;
|
|
|
|
@@ -1191,7 +1612,7 @@ krb5_krcc_retrieve_principal(krb5_context context, krb5_ccache id,
|
|
|
|
}
|
|
|
|
bc.bpp = payload;
|
|
|
|
bc.endp = (char *)payload + psize;
|
|
|
|
- kret = krb5_krcc_parse_principal(context, id, princ, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_principal(context, princ, &bc);
|
|
|
|
|
|
|
|
errout:
|
|
|
|
if (payload)
|
|
|
|
@@ -1200,57 +1621,195 @@ errout:
|
|
|
|
return kret;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int
|
|
|
|
-krb5_krcc_get_ring_ids(krb5_krcc_ring_ids_t *p)
|
|
|
|
-{
|
|
|
|
- key_serial_t ids_key;
|
|
|
|
- char ids_buf[128];
|
|
|
|
- key_serial_t session, process, thread;
|
|
|
|
- long val;
|
2013-09-06 18:12:24 +00:00
|
|
|
+struct krcc_ptcursor_data {
|
2013-10-02 18:46:20 +00:00
|
|
|
+ key_serial_t collection_id;
|
|
|
|
+ char *anchor_name;
|
|
|
|
+ char *collection_name;
|
|
|
|
+ char *subsidiary_name;
|
|
|
|
+ char *primary_name;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ krb5_boolean first;
|
|
|
|
+ long num_keys;
|
|
|
|
+ long next_key;
|
|
|
|
+ key_serial_t *keys;
|
|
|
|
+};
|
2013-10-02 18:46:20 +00:00
|
|
|
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_get_ring_ids: entered\n"));
|
2013-09-06 18:12:24 +00:00
|
|
|
+static krb5_error_code KRB5_CALLCONV
|
|
|
|
+krb5_krcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor_out)
|
|
|
|
+{
|
|
|
|
+ struct krcc_ptcursor_data *data;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_cc_ptcursor cursor;
|
|
|
|
+ krb5_error_code ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ long size;
|
|
|
|
+
|
|
|
|
+ *cursor_out = NULL;
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ cursor = k5alloc(sizeof(struct krb5_cc_ptcursor_s), &ret);
|
|
|
|
+ if (cursor == NULL)
|
2013-09-06 18:12:24 +00:00
|
|
|
+ return ENOMEM;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ data = k5alloc(sizeof(struct krcc_ptcursor_data), &ret);
|
|
|
|
+ if (data == NULL)
|
|
|
|
+ goto error;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ cursor->ops = &krb5_krcc_ops;
|
|
|
|
+ cursor->data = data;
|
|
|
|
+ data->first = TRUE;
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ ret = get_default(context, &data->anchor_name, &data->collection_name,
|
|
|
|
+ &data->subsidiary_name);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto error;
|
2013-09-06 18:12:24 +00:00
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ /* If there is no default collection, return an empty cursor. */
|
|
|
|
+ if (data->anchor_name == NULL) {
|
2013-09-06 18:12:24 +00:00
|
|
|
+ *cursor_out = cursor;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ return 0;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
2013-10-02 18:46:20 +00:00
|
|
|
|
|
|
|
- if (!p)
|
|
|
|
- return EINVAL;
|
|
|
|
+ ret = get_collection(data->anchor_name, data->collection_name,
|
|
|
|
+ &data->collection_id);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto error;
|
|
|
|
+
|
|
|
|
+ if (data->subsidiary_name == NULL) {
|
|
|
|
+ ret = get_primary_name(context, data->anchor_name,
|
|
|
|
+ data->collection_name, data->collection_id,
|
|
|
|
+ &data->primary_name);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto error;
|
|
|
|
+
|
|
|
|
+ size = keyctl_read_alloc(data->collection_id, (void **)&data->keys);
|
|
|
|
+ if (size == -1) {
|
|
|
|
+ ret = errno;
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ data->num_keys = size / sizeof(key_serial_t);
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /* Use the defaults in case we find no ids key */
|
|
|
|
- p->session = KEY_SPEC_SESSION_KEYRING;
|
|
|
|
- p->process = KEY_SPEC_PROCESS_KEYRING;
|
|
|
|
- p->thread = KEY_SPEC_THREAD_KEYRING;
|
|
|
|
+ *cursor_out = cursor;
|
|
|
|
+ return 0;
|
|
|
|
|
|
|
|
- /*
|
|
|
|
- * Note that in the "normal" case, this will not be found.
|
|
|
|
- * The Linux gssd creates this key while creating a
|
|
|
|
- * context to communicate the user's key serial numbers.
|
|
|
|
- */
|
|
|
|
- ids_key = request_key(KRCC_KEY_TYPE_USER, KRCC_SPEC_IDS_KEYNAME, NULL, 0);
|
|
|
|
- if (ids_key < 0)
|
|
|
|
- goto out;
|
|
|
|
+error:
|
|
|
|
+ krb5_krcc_ptcursor_free(context, &cursor);
|
|
|
|
+ return ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+}
|
2013-10-02 18:46:20 +00:00
|
|
|
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_get_ring_ids: processing '%s' key %d\n",
|
|
|
|
- KRCC_SPEC_IDS_KEYNAME, ids_key));
|
|
|
|
- /*
|
|
|
|
- * Read and parse the ids file
|
|
|
|
- */
|
|
|
|
- memset(ids_buf, '\0', sizeof(ids_buf));
|
|
|
|
- val = keyctl_read(ids_key, ids_buf, sizeof(ids_buf));
|
|
|
|
- if (val > sizeof(ids_buf))
|
|
|
|
- goto out;
|
2013-09-06 18:12:24 +00:00
|
|
|
+static krb5_error_code KRB5_CALLCONV
|
|
|
|
+krb5_krcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor,
|
|
|
|
+ krb5_ccache *cache_out)
|
|
|
|
+{
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_error_code ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ struct krcc_ptcursor_data *data;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ key_serial_t key, cache_id = 0;
|
|
|
|
+ const char *first_name, *keytype, *sep, *subsidiary_name;
|
|
|
|
+ size_t keytypelen;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ char *description = NULL;
|
|
|
|
+
|
|
|
|
+ *cache_out = NULL;
|
|
|
|
+
|
|
|
|
+ data = cursor->data;
|
|
|
|
+
|
|
|
|
+ /* No keyring available */
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (data->collection_id == 0)
|
2013-09-06 18:12:24 +00:00
|
|
|
+ return 0;
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (data->first) {
|
|
|
|
+ /* Look for the primary cache for a collection cursor, or the
|
|
|
|
+ * subsidiary cache for a subsidiary cursor. */
|
2013-09-06 18:12:24 +00:00
|
|
|
+ data->first = FALSE;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ first_name = (data->primary_name != NULL) ? data->primary_name :
|
|
|
|
+ data->subsidiary_name;
|
|
|
|
+ cache_id = keyctl_search(data->collection_id, KRCC_KEY_TYPE_KEYRING,
|
|
|
|
+ first_name, 0);
|
|
|
|
+ if (cache_id != -1) {
|
|
|
|
+ return make_cache(data->collection_id, cache_id, data->anchor_name,
|
|
|
|
+ data->collection_name, first_name, cache_out);
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
|
|
|
+ }
|
2013-10-02 18:46:20 +00:00
|
|
|
|
|
|
|
- val = sscanf(ids_buf, "%d:%d:%d", &session, &process, &thread);
|
|
|
|
- if (val != 3)
|
|
|
|
- goto out;
|
|
|
|
+ /* A subsidiary cursor yields at most the first cache. */
|
|
|
|
+ if (data->subsidiary_name != NULL)
|
|
|
|
+ return 0;
|
2013-09-06 18:12:24 +00:00
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ keytype = KRCC_KEY_TYPE_KEYRING ";";
|
|
|
|
+ keytypelen = strlen(keytype);
|
2013-09-19 20:29:52 +00:00
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ for (; data->next_key < data->num_keys; data->next_key++) {
|
|
|
|
+ /* Free any previously retrieved key description. */
|
|
|
|
+ free(description);
|
|
|
|
+ description = NULL;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Get the key description, which should have the form:
|
|
|
|
+ * typename;UID;GID;permissions;description
|
|
|
|
+ */
|
|
|
|
+ key = data->keys[data->next_key];
|
|
|
|
+ if (keyctl_describe_alloc(key, &description) < 0)
|
|
|
|
+ continue;
|
|
|
|
+ sep = strrchr(description, ';');
|
|
|
|
+ if (sep == NULL)
|
|
|
|
+ continue;
|
|
|
|
+ subsidiary_name = sep + 1;
|
|
|
|
+
|
|
|
|
+ /* Skip this key if it isn't a keyring. */
|
|
|
|
+ if (strncmp(description, keytype, keytypelen) != 0)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ /* Don't repeat the primary cache. */
|
|
|
|
+ if (strcmp(subsidiary_name, data->primary_name) == 0)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ /* We found a valid key */
|
|
|
|
+ data->next_key++;
|
|
|
|
+ ret = make_cache(data->collection_id, key, data->anchor_name,
|
|
|
|
+ data->collection_name, subsidiary_name, cache_out);
|
|
|
|
+ free(description);
|
|
|
|
+ return ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ }
|
2013-10-02 18:46:20 +00:00
|
|
|
|
|
|
|
- p->session = session;
|
|
|
|
- p->process = process;
|
|
|
|
- p->thread = thread;
|
|
|
|
+ free(description);
|
|
|
|
+ return 0;
|
2013-09-06 18:12:24 +00:00
|
|
|
+}
|
2013-10-02 18:46:20 +00:00
|
|
|
|
|
|
|
-out:
|
|
|
|
- DEBUG_PRINT(("krb5_krcc_get_ring_ids: returning %d:%d:%d\n",
|
|
|
|
- p->session, p->process, p->thread));
|
2013-09-06 18:12:24 +00:00
|
|
|
+static krb5_error_code KRB5_CALLCONV
|
|
|
|
+krb5_krcc_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor)
|
|
|
|
+{
|
|
|
|
+ struct krcc_ptcursor_data *data = (*cursor)->data;
|
|
|
|
+
|
2013-10-02 18:46:20 +00:00
|
|
|
+ if (data != NULL) {
|
|
|
|
+ free(data->anchor_name);
|
|
|
|
+ free(data->collection_name);
|
|
|
|
+ free(data->subsidiary_name);
|
|
|
|
+ free(data->primary_name);
|
2013-09-06 18:12:24 +00:00
|
|
|
+ free(data->keys);
|
|
|
|
+ free(data);
|
|
|
|
+ }
|
|
|
|
+ free(*cursor);
|
|
|
|
+ *cursor = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static krb5_error_code KRB5_CALLCONV
|
|
|
|
+krb5_krcc_switch_to(krb5_context context, krb5_ccache cache)
|
|
|
|
+{
|
|
|
|
+ krb5_krcc_data *data = cache->data;
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_error_code ret;
|
|
|
|
+ char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL;
|
|
|
|
+ key_serial_t collection_id;
|
|
|
|
+
|
|
|
|
+ ret = parse_residual(data->name, &anchor_name, &collection_name,
|
|
|
|
+ &subsidiary_name);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+ ret = get_collection(anchor_name, collection_name, &collection_id);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto cleanup;
|
|
|
|
+ ret = set_primary_name(context, collection_id, subsidiary_name);
|
|
|
|
+cleanup:
|
|
|
|
+ free(anchor_name);
|
|
|
|
+ free(collection_name);
|
|
|
|
+ free(subsidiary_name);
|
|
|
|
+ return ret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* ===============================================================
|
|
|
|
* INTERNAL functions to parse a credential from a key payload
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1271,8 +1830,8 @@ out:
|
2013-09-06 18:12:24 +00:00
|
|
|
* KRB5_CC_END - there were not len bytes available
|
|
|
|
*/
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse(krb5_context context, krb5_ccache id, krb5_pointer buf,
|
|
|
|
- unsigned int len, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse(krb5_context context, krb5_pointer buf, unsigned int len,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
DEBUG_PRINT(("krb5_krcc_parse: entered\n"));
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1290,8 +1849,8 @@ krb5_krcc_parse(krb5_context context, krb5_ccache id, krb5_pointer buf,
|
2013-09-06 18:12:24 +00:00
|
|
|
* and parse it into a credential structure.
|
|
|
|
*/
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_cred(krb5_context context, krb5_ccache id, krb5_creds * creds,
|
|
|
|
- char *payload, int psize)
|
|
|
|
+krb5_krcc_parse_cred(krb5_context context, krb5_creds * creds, char *payload,
|
|
|
|
+ int psize)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_octet octet;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1301,36 +1860,36 @@ krb5_krcc_parse_cred(krb5_context context, krb5_ccache id, krb5_creds * creds,
|
2013-09-06 18:12:24 +00:00
|
|
|
/* Parse the pieces of the credential */
|
|
|
|
bc.bpp = payload;
|
|
|
|
bc.endp = bc.bpp + psize;
|
|
|
|
- kret = krb5_krcc_parse_principal(context, id, &creds->client, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_principal(context, &creds->client, &bc);
|
|
|
|
CHECK_N_GO(kret, out);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_principal(context, id, &creds->server, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_principal(context, &creds->server, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanclient);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_keyblock(context, id, &creds->keyblock, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_keyblock(context, &creds->keyblock, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanserver);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_times(context, id, &creds->times, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_times(context, &creds->times, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanserver);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_octet(context, id, &octet, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_octet(context, &octet, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanserver);
|
|
|
|
creds->is_skey = octet;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &int32, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &int32, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanserver);
|
|
|
|
creds->ticket_flags = int32;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_addrs(context, id, &creds->addresses, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_addrs(context, &creds->addresses, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanblock);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_authdata(context, id, &creds->authdata, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_authdata(context, &creds->authdata, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanaddrs);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_krb5data(context, id, &creds->ticket, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_krb5data(context, &creds->ticket, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanauthdata);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_krb5data(context, id, &creds->second_ticket, &bc);
|
|
|
|
+ kret = krb5_krcc_parse_krb5data(context, &creds->second_ticket, &bc);
|
|
|
|
CHECK_N_GO(kret, cleanticket);
|
|
|
|
|
|
|
|
kret = KRB5_OK;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1355,8 +1914,8 @@ out:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_principal(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_principal * princ, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_principal(krb5_context context, krb5_principal * princ,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
register krb5_principal tmpprinc;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1364,12 +1923,12 @@ krb5_krcc_parse_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Read principal type */
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &type, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &type, bc);
|
|
|
|
if (kret != KRB5_OK)
|
|
|
|
return kret;
|
|
|
|
|
|
|
|
/* Read the number of components */
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &length, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &length, bc);
|
|
|
|
if (kret != KRB5_OK)
|
|
|
|
return kret;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1380,12 +1939,7 @@ krb5_krcc_parse_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
if (tmpprinc == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
if (length) {
|
|
|
|
- size_t msize = length;
|
|
|
|
- if (msize != length) {
|
|
|
|
- free(tmpprinc);
|
|
|
|
- return KRB5_CC_NOMEM;
|
|
|
|
- }
|
|
|
|
- tmpprinc->data = ALLOC(msize, krb5_data);
|
|
|
|
+ tmpprinc->data = calloc(length, sizeof(krb5_data));
|
|
|
|
if (tmpprinc->data == 0) {
|
|
|
|
free(tmpprinc);
|
|
|
|
return KRB5_CC_NOMEM;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1396,15 +1950,12 @@ krb5_krcc_parse_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
tmpprinc->length = length;
|
|
|
|
tmpprinc->type = type;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_krb5data(context, id,
|
|
|
|
- krb5_princ_realm(context, tmpprinc), bc);
|
|
|
|
+ kret = krb5_krcc_parse_krb5data(context, &tmpprinc->realm, bc);
|
|
|
|
i = 0;
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
- kret = krb5_krcc_parse_krb5data(context, id,
|
|
|
|
- krb5_princ_component(context, tmpprinc,
|
|
|
|
- i), bc);
|
|
|
|
+ kret = krb5_krcc_parse_krb5data(context, &tmpprinc->data[i], bc);
|
|
|
|
CHECK(kret);
|
|
|
|
}
|
|
|
|
*princ = tmpprinc;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1412,16 +1963,16 @@ krb5_krcc_parse_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
|
|
|
|
errout:
|
|
|
|
while (--i >= 0)
|
|
|
|
- free(krb5_princ_component(context, tmpprinc, i)->data);
|
|
|
|
- free(krb5_princ_realm(context, tmpprinc)->data);
|
|
|
|
+ free(tmpprinc->data[i].data);
|
|
|
|
+ free(tmpprinc->realm.data);
|
|
|
|
free(tmpprinc->data);
|
|
|
|
free(tmpprinc);
|
|
|
|
return kret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_keyblock(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_keyblock * keyblock, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_keyblock(krb5_context context, krb5_keyblock * keyblock,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_ui_2 ui2;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1430,26 +1981,22 @@ krb5_krcc_parse_keyblock(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
keyblock->magic = KV5M_KEYBLOCK;
|
|
|
|
keyblock->contents = 0;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_ui_2(context, id, &ui2, bc);
|
|
|
|
+ kret = krb5_krcc_parse_ui_2(context, &ui2, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
keyblock->enctype = ui2;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &int32, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &int32, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
if (int32 < 0)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
keyblock->length = int32;
|
|
|
|
- /* Overflow check. */
|
|
|
|
- if (keyblock->length != int32)
|
|
|
|
- return KRB5_CC_NOMEM;
|
|
|
|
if (keyblock->length == 0)
|
|
|
|
return KRB5_OK;
|
|
|
|
- keyblock->contents = ALLOC(keyblock->length, krb5_octet);
|
|
|
|
+ keyblock->contents = malloc(keyblock->length);
|
|
|
|
if (keyblock->contents == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse(context, id, keyblock->contents,
|
|
|
|
- keyblock->length, bc);
|
|
|
|
+ kret = krb5_krcc_parse(context, keyblock->contents, keyblock->length, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
return KRB5_OK;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1460,25 +2007,25 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_times(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_ticket_times * t, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_times(krb5_context context, krb5_ticket_times * t,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_int32 i;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &i, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &i, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
t->authtime = i;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &i, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &i, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
t->starttime = i;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &i, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &i, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
t->endtime = i;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &i, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &i, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
t->renew_till = i;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1488,8 +2035,8 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_krb5data(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_data * data, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_krb5data(krb5_context context, krb5_data * data,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_int32 len;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1497,12 +2044,12 @@ krb5_krcc_parse_krb5data(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
data->magic = KV5M_DATA;
|
|
|
|
data->data = 0;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &len, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &len, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
if (len < 0)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
data->length = len;
|
|
|
|
- if (data->length != len || data->length + 1 == 0)
|
|
|
|
+ if (data->length + 1 == 0)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
|
|
|
if (data->length == 0) {
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1514,8 +2061,7 @@ krb5_krcc_parse_krb5data(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
if (data->data == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse(context, id, data->data, (unsigned) data->length,
|
|
|
|
- bc);
|
|
|
|
+ kret = krb5_krcc_parse(context, data->data, (unsigned) data->length, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
data->data[data->length] = 0; /* Null terminate, just in case.... */
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1527,13 +2073,12 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_int32(krb5_context context, krb5_ccache id, krb5_int32 * i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_int32(krb5_context context, krb5_int32 * i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
unsigned char buf[4];
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse(context, id, buf, 4, bc);
|
|
|
|
+ kret = krb5_krcc_parse(context, buf, 4, bc);
|
|
|
|
if (kret)
|
|
|
|
return kret;
|
|
|
|
*i = load_32_be(buf);
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1541,15 +2086,14 @@ krb5_krcc_parse_int32(krb5_context context, krb5_ccache id, krb5_int32 * i,
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_octet(krb5_context context, krb5_ccache id, krb5_octet * i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_octet(krb5_context context, krb5_octet * i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
- return krb5_krcc_parse(context, id, (krb5_pointer) i, 1, bc);
|
|
|
|
+ return krb5_krcc_parse(context, (krb5_pointer) i, 1, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_addrs(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_address *** addrs, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_addrs(krb5_context context, krb5_address *** addrs,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_int32 length;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1559,18 +2103,17 @@ krb5_krcc_parse_addrs(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
*addrs = 0;
|
|
|
|
|
|
|
|
/* Read the number of components */
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &length, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &length, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make *addrs able to hold length pointers to krb5_address structs
|
|
|
|
* Add one extra for a null-terminated list
|
|
|
|
*/
|
|
|
|
- msize = length;
|
|
|
|
- msize += 1;
|
|
|
|
- if (msize == 0 || msize - 1 != length || length < 0)
|
|
|
|
+ msize = (size_t)length + 1;
|
|
|
|
+ if (msize == 0 || length < 0)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
- *addrs = ALLOC(msize, krb5_address *);
|
|
|
|
+ *addrs = calloc(msize, sizeof(krb5_address *));
|
|
|
|
if (*addrs == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1580,7 +2123,7 @@ krb5_krcc_parse_addrs(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_free_addresses(context, *addrs);
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
}
|
|
|
|
- kret = krb5_krcc_parse_addr(context, id, (*addrs)[i], bc);
|
|
|
|
+ kret = krb5_krcc_parse_addr(context, (*addrs)[i], bc);
|
|
|
|
CHECK(kret);
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1592,7 +2135,7 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_addr(krb5_context context, krb5_ccache id, krb5_address * addr,
|
|
|
|
+krb5_krcc_parse_addr(krb5_context context, krb5_address * addr,
|
|
|
|
krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1602,22 +2145,15 @@ krb5_krcc_parse_addr(krb5_context context, krb5_ccache id, krb5_address * addr,
|
2013-09-06 18:12:24 +00:00
|
|
|
addr->magic = KV5M_ADDRESS;
|
|
|
|
addr->contents = 0;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_ui_2(context, id, &ui2, bc);
|
|
|
|
+ kret = krb5_krcc_parse_ui_2(context, &ui2, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
addr->addrtype = ui2;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &int32, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &int32, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
if ((int32 & VALID_INT_BITS) != int32) /* Overflow int??? */
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
addr->length = int32;
|
|
|
|
- /*
|
|
|
|
- * Length field is "unsigned int", which may be smaller
|
|
|
|
- * than 32 bits.
|
|
|
|
- */
|
|
|
|
- if (addr->length != int32)
|
|
|
|
- return KRB5_CC_NOMEM; /* XXX */
|
|
|
|
-
|
|
|
|
if (addr->length == 0)
|
|
|
|
return KRB5_OK;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1625,7 +2161,7 @@ krb5_krcc_parse_addr(krb5_context context, krb5_ccache id, krb5_address * addr,
|
2013-09-06 18:12:24 +00:00
|
|
|
if (addr->contents == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse(context, id, addr->contents, addr->length, bc);
|
|
|
|
+ kret = krb5_krcc_parse(context, addr->contents, addr->length, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
return KRB5_OK;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1636,8 +2172,8 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_authdata(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_authdata *** a, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_authdata(krb5_context context, krb5_authdata *** a,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_int32 length;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1647,7 +2183,7 @@ krb5_krcc_parse_authdata(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
*a = 0;
|
|
|
|
|
|
|
|
/* Read the number of components */
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &length, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &length, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
if (length == 0)
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1657,11 +2193,10 @@ krb5_krcc_parse_authdata(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
* Make *a able to hold length pointers to krb5_authdata structs
|
|
|
|
* Add one extra for a null-terminated list
|
|
|
|
*/
|
|
|
|
- msize = length;
|
|
|
|
- msize += 1;
|
|
|
|
- if (msize == 0 || msize - 1 != length || length < 0)
|
|
|
|
+ msize = (size_t)length + 1;
|
|
|
|
+ if (msize == 0 || length < 0)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
- *a = ALLOC(msize, krb5_authdata *);
|
|
|
|
+ *a = calloc(msize, sizeof(krb5_authdata *));
|
|
|
|
if (*a == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1672,7 +2207,7 @@ krb5_krcc_parse_authdata(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
*a = NULL;
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
}
|
|
|
|
- kret = krb5_krcc_parse_authdatum(context, id, (*a)[i], bc);
|
|
|
|
+ kret = krb5_krcc_parse_authdatum(context, (*a)[i], bc);
|
|
|
|
CHECK(kret);
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1686,8 +2221,8 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_authdatum(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_authdata * a, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_authdatum(krb5_context context, krb5_authdata * a,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_int32 int32;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1696,21 +2231,14 @@ krb5_krcc_parse_authdatum(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
a->magic = KV5M_AUTHDATA;
|
|
|
|
a->contents = NULL;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse_ui_2(context, id, &ui2, bc);
|
|
|
|
+ kret = krb5_krcc_parse_ui_2(context, &ui2, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
a->ad_type = (krb5_authdatatype) ui2;
|
|
|
|
- kret = krb5_krcc_parse_int32(context, id, &int32, bc);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, &int32, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
if ((int32 & VALID_INT_BITS) != int32) /* Overflow int??? */
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
a->length = int32;
|
|
|
|
- /*
|
|
|
|
- * Value could have gotten truncated if int is
|
|
|
|
- * smaller than 32 bits.
|
|
|
|
- */
|
|
|
|
- if (a->length != int32)
|
|
|
|
- return KRB5_CC_NOMEM; /* XXX */
|
|
|
|
-
|
|
|
|
if (a->length == 0)
|
|
|
|
return KRB5_OK;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1718,7 +2246,7 @@ krb5_krcc_parse_authdatum(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
if (a->contents == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse(context, id, a->contents, a->length, bc);
|
|
|
|
+ kret = krb5_krcc_parse(context, a->contents, a->length, bc);
|
|
|
|
CHECK(kret);
|
|
|
|
|
|
|
|
return KRB5_OK;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1730,13 +2258,12 @@ errout:
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_parse_ui_2(krb5_context context, krb5_ccache id, krb5_ui_2 * i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_parse_ui_2(krb5_context context, krb5_ui_2 * i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
unsigned char buf[2];
|
|
|
|
|
|
|
|
- kret = krb5_krcc_parse(context, id, buf, 2, bc);
|
|
|
|
+ kret = krb5_krcc_parse(context, buf, 2, bc);
|
|
|
|
if (kret)
|
|
|
|
return kret;
|
|
|
|
*i = load_16_be(buf);
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1756,9 +2283,15 @@ krb5_krcc_parse_ui_2(krb5_context context, krb5_ccache id, krb5_ui_2 * i,
|
2013-09-06 18:12:24 +00:00
|
|
|
* system errors
|
|
|
|
*/
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse(krb5_context context, krb5_ccache id, krb5_pointer buf,
|
|
|
|
- unsigned int len, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse(krb5_context context, krb5_pointer buf, unsigned int len,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
+ if (bc->bpp == NULL) {
|
|
|
|
+ /* This is a dry run; just increase size and return. */
|
|
|
|
+ bc->size += len;
|
|
|
|
+ return KRB5_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
if (bc->bpp + len > bc->endp)
|
|
|
|
return KRB5_CC_WRITE;
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1769,29 +2302,26 @@ krb5_krcc_unparse(krb5_context context, krb5_ccache id, krb5_pointer buf,
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_principal(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_principal princ, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_principal(krb5_context context, krb5_principal princ,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_int32 i, length, tmp, type;
|
|
|
|
|
|
|
|
- type = krb5_princ_type(context, princ);
|
|
|
|
- tmp = length = krb5_princ_size(context, princ);
|
|
|
|
+ type = princ->type;
|
|
|
|
+ tmp = length = princ->length;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, type, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, type, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, tmp, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, tmp, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_krb5data(context, id,
|
|
|
|
- krb5_princ_realm(context, princ), bc);
|
|
|
|
+ kret = krb5_krcc_unparse_krb5data(context, &princ->realm, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
- kret = krb5_krcc_unparse_krb5data(context, id,
|
|
|
|
- krb5_princ_component(context, princ,
|
|
|
|
- i), bc);
|
|
|
|
+ kret = krb5_krcc_unparse_krb5data(context, &princ->data[i], bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1799,67 +2329,65 @@ krb5_krcc_unparse_principal(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_keyblock(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_keyblock * keyblock, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_keyblock(krb5_context context, krb5_keyblock * keyblock,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_ui_2(context, id, keyblock->enctype, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_2(context, keyblock->enctype, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- kret = krb5_krcc_unparse_ui_4(context, id, keyblock->length, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_4(context, keyblock->length, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- return krb5_krcc_unparse(context, id, (char *) keyblock->contents,
|
|
|
|
+ return krb5_krcc_unparse(context, (char *) keyblock->contents,
|
|
|
|
keyblock->length, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_times(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_ticket_times * t, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_times(krb5_context context, krb5_ticket_times * t,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, t->authtime, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, t->authtime, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, t->starttime, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, t->starttime, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, t->endtime, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, t->endtime, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, t->renew_till, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, t->renew_till, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_krb5data(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_data * data, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_krb5data(krb5_context context, krb5_data * data,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_ui_4(context, id, data->length, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_4(context, data->length, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- return krb5_krcc_unparse(context, id, data->data, data->length, bc);
|
|
|
|
+ return krb5_krcc_unparse(context, data->data, data->length, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_int32(krb5_context context, krb5_ccache id, krb5_int32 i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_int32(krb5_context context, krb5_int32 i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
- return krb5_krcc_unparse_ui_4(context, id, (krb5_ui_4) i, bc);
|
|
|
|
+ return krb5_krcc_unparse_ui_4(context, (krb5_ui_4) i, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_octet(krb5_context context, krb5_ccache id, krb5_int32 i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_octet(krb5_context context, krb5_int32 i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_octet ibuf;
|
|
|
|
|
|
|
|
ibuf = (krb5_octet) i;
|
|
|
|
- return krb5_krcc_unparse(context, id, (char *) &ibuf, 1, bc);
|
|
|
|
+ return krb5_krcc_unparse(context, (char *) &ibuf, 1, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_addrs(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_address ** addrs, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_addrs(krb5_context context, krb5_address ** addrs,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
krb5_address **temp;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1872,10 +2400,10 @@ krb5_krcc_unparse_addrs(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
length += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, length, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, length, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
- kret = krb5_krcc_unparse_addr(context, id, addrs[i], bc);
|
|
|
|
+ kret = krb5_krcc_unparse_addr(context, addrs[i], bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1883,21 +2411,21 @@ krb5_krcc_unparse_addrs(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_addr(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_address * addr, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_addr(krb5_context context, krb5_address * addr,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_ui_2(context, id, addr->addrtype, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_2(context, addr->addrtype, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- kret = krb5_krcc_unparse_ui_4(context, id, addr->length, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_4(context, addr->length, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- return krb5_krcc_unparse(context, id, (char *) addr->contents,
|
|
|
|
+ return krb5_krcc_unparse(context, (char *) addr->contents,
|
|
|
|
addr->length, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_authdata(krb5_context context, krb5_ccache id,
|
|
|
|
+krb5_krcc_unparse_authdata(krb5_context context,
|
|
|
|
krb5_authdata ** a, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1909,47 +2437,45 @@ krb5_krcc_unparse_authdata(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
length++;
|
|
|
|
}
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, length, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, length, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
- kret = krb5_krcc_unparse_authdatum(context, id, a[i], bc);
|
|
|
|
+ kret = krb5_krcc_unparse_authdatum(context, a[i], bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
}
|
|
|
|
return KRB5_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_authdatum(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_authdata * a, krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_authdatum(krb5_context context, krb5_authdata * a,
|
|
|
|
+ krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_ui_2(context, id, a->ad_type, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_2(context, a->ad_type, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- kret = krb5_krcc_unparse_ui_4(context, id, a->length, bc);
|
|
|
|
+ kret = krb5_krcc_unparse_ui_4(context, a->length, bc);
|
|
|
|
CHECK_OUT(kret);
|
|
|
|
- return krb5_krcc_unparse(context, id, (krb5_pointer) a->contents,
|
|
|
|
+ return krb5_krcc_unparse(context, (krb5_pointer) a->contents,
|
|
|
|
a->length, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_ui_4(krb5_context context, krb5_ccache id, krb5_ui_4 i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_ui_4(krb5_context context, krb5_ui_4 i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
unsigned char buf[4];
|
|
|
|
|
|
|
|
store_32_be(i, buf);
|
|
|
|
- return krb5_krcc_unparse(context, id, buf, 4, bc);
|
|
|
|
+ return krb5_krcc_unparse(context, buf, 4, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_ui_2(krb5_context context, krb5_ccache id, krb5_int32 i,
|
|
|
|
- krb5_krcc_bc * bc)
|
|
|
|
+krb5_krcc_unparse_ui_2(krb5_context context, krb5_int32 i, krb5_krcc_bc * bc)
|
|
|
|
{
|
|
|
|
unsigned char buf[2];
|
|
|
|
|
|
|
|
store_16_be(i, buf);
|
|
|
|
- return krb5_krcc_unparse(context, id, buf, 2, bc);
|
|
|
|
+ return krb5_krcc_unparse(context, buf, 2, bc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1965,11 +2491,55 @@ krb5_krcc_unparse_ui_2(krb5_context context, krb5_ccache id, krb5_int32 i,
|
2013-09-06 18:12:24 +00:00
|
|
|
* Caller is responsible for freeing returned buffer.
|
|
|
|
*/
|
|
|
|
static krb5_error_code
|
|
|
|
-krb5_krcc_unparse_cred(krb5_context context, krb5_ccache id,
|
|
|
|
- krb5_creds * creds, char **datapp, unsigned int *lenptr)
|
|
|
|
+krb5_krcc_unparse_cred(krb5_context context, krb5_creds * creds,
|
|
|
|
+ krb5_krcc_bc *bc)
|
2013-10-02 18:46:20 +00:00
|
|
|
{
|
|
|
|
krb5_error_code kret;
|
|
|
|
- char *buf;
|
2013-09-06 18:12:24 +00:00
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_principal(context, creds->client, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_principal(context, creds->server, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_keyblock(context, &creds->keyblock, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_times(context, &creds->times, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_octet(context, (krb5_int32) creds->is_skey, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, creds->ticket_flags, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_addrs(context, creds->addresses, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_authdata(context, creds->authdata, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_krb5data(context, &creds->ticket, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+ CHECK(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_krb5data(context, &creds->second_ticket, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ /* Success! */
|
|
|
|
+ kret = KRB5_OK;
|
|
|
|
+
|
|
|
|
+errout:
|
|
|
|
+ return kret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_unparse_cred_alloc(krb5_context context, krb5_creds * creds,
|
|
|
|
+ char **datapp, unsigned int *lenptr)
|
2013-10-02 18:46:20 +00:00
|
|
|
+{
|
|
|
|
+ krb5_error_code kret;
|
2013-09-06 18:12:24 +00:00
|
|
|
+ char *buf = NULL;
|
|
|
|
krb5_krcc_bc bc;
|
|
|
|
|
|
|
|
if (!creds || !datapp || !lenptr)
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -1978,43 +2548,102 @@ krb5_krcc_unparse_cred(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
*datapp = NULL;
|
|
|
|
*lenptr = 0;
|
|
|
|
|
|
|
|
- buf = malloc(GUESS_CRED_SIZE);
|
|
|
|
+ /* Do a dry run first to calculate the size. */
|
|
|
|
+ bc.bpp = bc.endp = NULL;
|
|
|
|
+ bc.size = 0;
|
|
|
|
+ kret = krb5_krcc_unparse_cred(context, creds, &bc);
|
|
|
|
+ CHECK(kret);
|
|
|
|
+ if (bc.size > MAX_CRED_SIZE)
|
|
|
|
+ return KRB5_CC_WRITE;
|
|
|
|
+
|
|
|
|
+ /* Allocate a buffer and unparse for real. */
|
|
|
|
+ buf = malloc(bc.size);
|
|
|
|
if (buf == NULL)
|
|
|
|
return KRB5_CC_NOMEM;
|
|
|
|
-
|
|
|
|
bc.bpp = buf;
|
|
|
|
- bc.endp = buf + GUESS_CRED_SIZE;
|
|
|
|
+ bc.endp = buf + bc.size;
|
|
|
|
+ kret = krb5_krcc_unparse_cred(context, creds, &bc);
|
|
|
|
+ CHECK(kret);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_principal(context, id, creds->client, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ /* Success! */
|
|
|
|
+ *datapp = buf;
|
|
|
|
+ *lenptr = bc.bpp - buf;
|
|
|
|
+ buf = NULL;
|
|
|
|
+ kret = KRB5_OK;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_principal(context, id, creds->server, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+errout:
|
|
|
|
+ free(buf);
|
|
|
|
+ return kret;
|
|
|
|
+}
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_keyblock(context, id, &creds->keyblock, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_parse_index(krb5_context context, krb5_int32 *version,
|
|
|
|
+ char **primary, void *payload, int psize)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code kret;
|
|
|
|
+ krb5_krcc_bc bc;
|
|
|
|
+ krb5_data data;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_times(context, id, &creds->times, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ bc.bpp = payload;
|
|
|
|
+ bc.endp = bc.bpp + psize;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_octet(context, id, (krb5_int32) creds->is_skey,
|
|
|
|
- &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ kret = krb5_krcc_parse_int32(context, version, &bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_int32(context, id, creds->ticket_flags, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ kret = krb5_krcc_parse_krb5data(context, &data, &bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_addrs(context, id, creds->addresses, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ *primary = (char *)data.data;
|
|
|
|
+ return KRB5_OK;
|
|
|
|
+}
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_authdata(context, id, creds->authdata, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_unparse_index_internal(krb5_context context, krb5_int32 version,
|
|
|
|
+ const char *primary, krb5_krcc_bc *bc)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code kret;
|
|
|
|
+ krb5_data data;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_krb5data(context, id, &creds->ticket, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ data.length = strlen(primary) + 1;
|
|
|
|
+ data.data = (void *)primary;
|
|
|
|
|
|
|
|
- kret = krb5_krcc_unparse_krb5data(context, id, &creds->second_ticket, &bc);
|
|
|
|
- CHECK_N_GO(kret, errout);
|
|
|
|
+ kret = krb5_krcc_unparse_int32(context, version, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ kret = krb5_krcc_unparse_krb5data(context, &data, bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ return KRB5_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static krb5_error_code
|
|
|
|
+krb5_krcc_unparse_index(krb5_context context, krb5_int32 version,
|
|
|
|
+ const char *primary, void **datapp, int *lenptr)
|
|
|
|
+{
|
|
|
|
+ krb5_error_code kret;
|
|
|
|
+ krb5_krcc_bc bc;
|
|
|
|
+ char *buf;
|
|
|
|
+
|
|
|
|
+ if (!primary || !datapp || !lenptr)
|
|
|
|
+ return EINVAL;
|
|
|
|
+
|
|
|
|
+ *datapp = NULL;
|
|
|
|
+ *lenptr = 0;
|
|
|
|
+
|
|
|
|
+ /* Do a dry run first to calculate the size. */
|
|
|
|
+ bc.bpp = bc.endp = NULL;
|
|
|
|
+ bc.size = 0;
|
|
|
|
+ kret = krb5_krcc_unparse_index_internal(context, version, primary, &bc);
|
|
|
|
+ CHECK_OUT(kret);
|
|
|
|
+
|
|
|
|
+ buf = malloc(bc.size);
|
|
|
|
+ if (buf == NULL)
|
|
|
|
+ return ENOMEM;
|
|
|
|
+
|
|
|
|
+ bc.bpp = buf;
|
|
|
|
+ bc.endp = buf + bc.size;
|
|
|
|
+ kret = krb5_krcc_unparse_index_internal(context, version, primary, &bc);
|
|
|
|
+ CHECK(kret);
|
|
|
|
|
|
|
|
/* Success! */
|
|
|
|
*datapp = buf;
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -2022,6 +2651,8 @@ krb5_krcc_unparse_cred(krb5_context context, krb5_ccache id,
|
2013-09-06 18:12:24 +00:00
|
|
|
kret = KRB5_OK;
|
|
|
|
|
|
|
|
errout:
|
|
|
|
+ if (kret)
|
|
|
|
+ free(buf);
|
|
|
|
return kret;
|
|
|
|
}
|
|
|
|
|
2013-10-02 18:46:20 +00:00
|
|
|
@@ -2065,15 +2696,15 @@ const krb5_cc_ops krb5_krcc_ops = {
|
2013-09-06 18:12:24 +00:00
|
|
|
krb5_krcc_remove_cred,
|
|
|
|
krb5_krcc_set_flags,
|
|
|
|
krb5_krcc_get_flags, /* added after 1.4 release */
|
|
|
|
- NULL,
|
|
|
|
- NULL,
|
|
|
|
- NULL,
|
|
|
|
+ krb5_krcc_ptcursor_new,
|
|
|
|
+ krb5_krcc_ptcursor_next,
|
|
|
|
+ krb5_krcc_ptcursor_free,
|
|
|
|
NULL, /* move */
|
|
|
|
krb5_krcc_last_change_time, /* lastchange */
|
|
|
|
NULL, /* wasdefault */
|
|
|
|
krb5_krcc_lock,
|
|
|
|
krb5_krcc_unlock,
|
|
|
|
- NULL, /* switch_to */
|
2013-10-02 18:46:20 +00:00
|
|
|
+ krb5_krcc_switch_to,
|
2013-09-06 18:12:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#else /* !USE_KEYRING_CCACHE */
|
2013-10-02 18:46:20 +00:00
|
|
|
diff --git a/src/lib/krb5/ccache/t_cc.c b/src/lib/krb5/ccache/t_cc.c
|
|
|
|
index e14ae7f..6069cab 100644
|
|
|
|
--- a/src/lib/krb5/ccache/t_cc.c
|
|
|
|
+++ b/src/lib/krb5/ccache/t_cc.c
|
|
|
|
@@ -25,6 +25,7 @@
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "k5-int.h"
|
|
|
|
+#include "cc-int.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "autoconf.h"
|
|
|
|
@@ -331,14 +332,14 @@ check_registered(krb5_context context, const char *prefix)
|
|
|
|
if(kret != KRB5_OK) {
|
|
|
|
if(kret == KRB5_CC_UNKNOWN_TYPE)
|
|
|
|
return 0;
|
|
|
|
- com_err("Checking on credential type", kret,prefix);
|
|
|
|
+ com_err("Checking on credential type", kret, "%s", prefix);
|
|
|
|
fflush(stderr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
kret = krb5_cc_close(context, id);
|
|
|
|
if(kret != KRB5_OK) {
|
|
|
|
- com_err("Checking on credential type - closing", kret,prefix);
|
|
|
|
+ com_err("Checking on credential type - closing", kret, "%s", prefix);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -425,8 +426,8 @@ main(void)
|
|
|
|
test_misc(context);
|
|
|
|
do_test(context, "");
|
|
|
|
|
|
|
|
- if(check_registered(context, "KEYRING:"))
|
|
|
|
- do_test(context, "KEYRING:");
|
|
|
|
+ if (check_registered(context, "KEYRING:process:"))
|
|
|
|
+ do_test(context, "KEYRING:process:");
|
|
|
|
else
|
|
|
|
printf("Skiping KEYRING: test - unregistered type\n");
|
|
|
|
|
|
|
|
diff --git a/src/lib/krb5/ccache/t_cccol.c b/src/lib/krb5/ccache/t_cccol.c
|
|
|
|
new file mode 100644
|
|
|
|
index 0000000..444806e
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/lib/krb5/ccache/t_cccol.c
|
|
|
|
@@ -0,0 +1,363 @@
|
|
|
|
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
+/* lib/krb5/ccache/t_cccol.py - Test ccache collection via API */
|
|
|
|
+/*
|
|
|
|
+ * Copyright (C) 2013 by the Massachusetts Institute of Technology.
|
|
|
|
+ * All rights reserved.
|
|
|
|
+ *
|
|
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
|
|
+ * modification, are permitted provided that the following conditions
|
|
|
|
+ * are met:
|
|
|
|
+ *
|
|
|
|
+ * * Redistributions of source code must retain the above copyright
|
|
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
|
|
+ *
|
|
|
|
+ * * 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.
|
|
|
|
+ *
|
|
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
|
|
|
|
+ * COPYRIGHT HOLDER 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.h>
|
|
|
|
+#include <stdio.h>
|
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+#include <assert.h>
|
|
|
|
+
|
|
|
|
+static krb5_context ctx;
|
|
|
|
+
|
|
|
|
+/* Check that code is 0. Display an error message first if it is not. */
|
|
|
|
+static void
|
|
|
|
+check(krb5_error_code code)
|
|
|
|
+{
|
|
|
|
+ const char *errmsg;
|
|
|
|
+
|
|
|
|
+ if (code != 0) {
|
|
|
|
+ errmsg = krb5_get_error_message(ctx, code);
|
|
|
|
+ fprintf(stderr, "%s\n", errmsg);
|
|
|
|
+ krb5_free_error_message(ctx, errmsg);
|
|
|
|
+ }
|
|
|
|
+ assert(code == 0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Construct a list of the names of each credential cache in the collection. */
|
|
|
|
+static void
|
|
|
|
+get_collection_names(char ***list_out, size_t *count_out)
|
|
|
|
+{
|
|
|
|
+ krb5_cccol_cursor cursor;
|
|
|
|
+ krb5_ccache cache;
|
|
|
|
+ char **list = NULL;
|
|
|
|
+ size_t count = 0;
|
|
|
|
+ char *name;
|
|
|
|
+
|
|
|
|
+ check(krb5_cccol_cursor_new(ctx, &cursor));
|
|
|
|
+ while (1) {
|
|
|
|
+ check(krb5_cccol_cursor_next(ctx, cursor, &cache));
|
|
|
|
+ if (cache == NULL)
|
|
|
|
+ break;
|
|
|
|
+ check(krb5_cc_get_full_name(ctx, cache, &name));
|
|
|
|
+ krb5_cc_close(ctx, cache);
|
|
|
|
+ list = realloc(list, (count + 1) * sizeof(*list));
|
|
|
|
+ assert(list != NULL);
|
|
|
|
+ list[count++] = name;
|
|
|
|
+ }
|
|
|
|
+ krb5_cccol_cursor_free(ctx, &cursor);
|
|
|
|
+ *list_out = list;
|
|
|
|
+ *count_out = count;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Return true if list contains name. */
|
|
|
|
+static krb5_boolean
|
|
|
|
+in_list(char **list, size_t count, const char *name)
|
|
|
|
+{
|
|
|
|
+ size_t i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < count; i++) {
|
|
|
|
+ if (strcmp(list[i], name) == 0)
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+ return FALSE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Release the memory for a list of credential cache names. */
|
|
|
|
+static void
|
|
|
|
+free_list(char **list, size_t count)
|
|
|
|
+{
|
|
|
|
+ size_t i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < count; i++)
|
|
|
|
+ krb5_free_string(ctx, list[i]);
|
|
|
|
+ free(list);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Check that the cache names within the current collection begin with first
|
|
|
|
+ * (unless first is NULL), that the other elements match the remaining
|
|
|
|
+ * arguments in some order. others must be the number of additional cache
|
|
|
|
+ * names.
|
|
|
|
+ */
|
|
|
|
+static void
|
|
|
|
+check_collection(const char *first, size_t others, ...)
|
|
|
|
+{
|
|
|
|
+ va_list ap;
|
|
|
|
+ char **list;
|
|
|
|
+ size_t count, i;
|
|
|
|
+ const char *name;
|
|
|
|
+
|
|
|
|
+ get_collection_names(&list, &count);
|
|
|
|
+ if (first != NULL) {
|
|
|
|
+ assert(strcmp(first, list[0]) == 0);
|
|
|
|
+ assert(count == others + 1);
|
|
|
|
+ } else {
|
|
|
|
+ assert(count == others);
|
|
|
|
+ }
|
|
|
|
+ va_start(ap, others);
|
|
|
|
+ for (i = 0; i < others; i++) {
|
|
|
|
+ name = va_arg(ap, const char *);
|
|
|
|
+ assert(in_list(list, count, name));
|
|
|
|
+ }
|
|
|
|
+ va_end(ap);
|
|
|
|
+ free_list(list, count);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Check that the name of cache matches expected_name. */
|
|
|
|
+static void
|
|
|
|
+check_name(krb5_ccache cache, const char *expected_name)
|
|
|
|
+{
|
|
|
|
+ char *name;
|
|
|
|
+
|
|
|
|
+ check(krb5_cc_get_full_name(ctx, cache, &name));
|
|
|
|
+ assert(strcmp(name, expected_name) == 0);
|
|
|
|
+ krb5_free_string(ctx, name);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Check that when collection_name is resolved, the resulting cache's name
|
|
|
|
+ * matches expected_name. */
|
|
|
|
+static void
|
|
|
|
+check_primary_name(const char *collection_name, const char *expected_name)
|
|
|
|
+{
|
|
|
|
+ krb5_ccache cache;
|
|
|
|
+
|
|
|
|
+ check(krb5_cc_resolve(ctx, collection_name, &cache));
|
|
|
|
+ check_name(cache, expected_name);
|
|
|
|
+ krb5_cc_close(ctx, cache);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Check that when name is resolved, the resulting cache's principal matches
|
|
|
|
+ * expected_princ, or has no principal if expected_princ is NULL. */
|
|
|
|
+static void
|
|
|
|
+check_princ(const char *name, krb5_principal expected_princ)
|
|
|
|
+{
|
|
|
|
+ krb5_ccache cache;
|
|
|
|
+ krb5_principal princ;
|
|
|
|
+
|
|
|
|
+ check(krb5_cc_resolve(ctx, name, &cache));
|
|
|
|
+ if (expected_princ != NULL) {
|
|
|
|
+ check(krb5_cc_get_principal(ctx, cache, &princ));
|
|
|
|
+ assert(krb5_principal_compare(ctx, princ, expected_princ));
|
|
|
|
+ krb5_free_principal(ctx, princ);
|
|
|
|
+ } else {
|
|
|
|
+ assert(krb5_cc_get_principal(ctx, cache, &princ) != 0);
|
|
|
|
+ }
|
|
|
|
+ krb5_cc_close(ctx, cache);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Check that krb5_cc_cache_match on princ returns a cache whose name matches
|
|
|
|
+ * expected_name, or that the match fails if expected_name is NULL. */
|
|
|
|
+static void
|
|
|
|
+check_match(krb5_principal princ, const char *expected_name)
|
|
|
|
+{
|
|
|
|
+ krb5_ccache cache;
|
|
|
|
+
|
|
|
|
+ if (expected_name != NULL) {
|
|
|
|
+ check(krb5_cc_cache_match(ctx, princ, &cache));
|
|
|
|
+ check_name(cache, expected_name);
|
|
|
|
+ krb5_cc_close(ctx, cache);
|
|
|
|
+ } else {
|
|
|
|
+ assert(krb5_cc_cache_match(ctx, princ, &cache) != 0);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+main(int argc, char **argv)
|
|
|
|
+{
|
|
|
|
+ krb5_ccache ccinitial, ccu1, ccu2;
|
|
|
|
+ krb5_principal princ1, princ2, princ3;
|
|
|
|
+ const char *collection_name, *typename;
|
|
|
|
+ char *initial_primary_name, *unique1_name, *unique2_name;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Get the collection name from the command line. This is a ccache name
|
|
|
|
+ * with collection semantics, like DIR:/path/to/directory. This test
|
|
|
|
+ * program assumes that the collection is empty to start with.
|
|
|
|
+ */
|
|
|
|
+ assert(argc == 2);
|
|
|
|
+ collection_name = argv[1];
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Set the default ccache for the context to be the collection name, so the
|
|
|
|
+ * library can find the collection.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_init_context(&ctx));
|
|
|
|
+ check(krb5_cc_set_default_name(ctx, collection_name));
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Resolve the collection name. Since the collection is empty, this should
|
|
|
|
+ * generate a subsidiary name of an uninitialized cache. Getting the name
|
|
|
|
+ * of the resulting cache should give us the subsidiary name, not the
|
|
|
|
+ * collection name. This resulting subsidiary name should be consistent if
|
|
|
|
+ * we resolve the collection name again, and the collection should still be
|
|
|
|
+ * empty since we haven't initialized the cache.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_resolve(ctx, collection_name, &ccinitial));
|
|
|
|
+ check(krb5_cc_get_full_name(ctx, ccinitial, &initial_primary_name));
|
|
|
|
+ assert(strcmp(initial_primary_name, collection_name) != 0);
|
|
|
|
+ check_primary_name(collection_name, initial_primary_name);
|
|
|
|
+ check_collection(NULL, 0);
|
|
|
|
+ check_princ(collection_name, NULL);
|
|
|
|
+ check_princ(initial_primary_name, NULL);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Before initializing the primary ccache, generate and initialize two
|
|
|
|
+ * unique caches of the collection's type. Check that the cache names
|
|
|
|
+ * resolve to the generated caches and appear in the collection. (They
|
|
|
|
+ * might appear before being initialized; that's not currently considered
|
|
|
|
+ * important). The primary cache for the collection should remain as the
|
|
|
|
+ * unitialized cache from the previous step.
|
|
|
|
+ */
|
|
|
|
+ typename = krb5_cc_get_type(ctx, ccinitial);
|
|
|
|
+ check(krb5_cc_new_unique(ctx, typename, NULL, &ccu1));
|
|
|
|
+ check(krb5_cc_get_full_name(ctx, ccu1, &unique1_name));
|
|
|
|
+ check(krb5_parse_name(ctx, "princ1@X", &princ1));
|
|
|
|
+ check(krb5_cc_initialize(ctx, ccu1, princ1));
|
|
|
|
+ check_princ(unique1_name, princ1);
|
|
|
|
+ check_match(princ1, unique1_name);
|
|
|
|
+ check_collection(NULL, 1, unique1_name);
|
|
|
|
+ check(krb5_cc_new_unique(ctx, typename, NULL, &ccu2));
|
|
|
|
+ check(krb5_cc_get_full_name(ctx, ccu2, &unique2_name));
|
|
|
|
+ check(krb5_parse_name(ctx, "princ2@X", &princ2));
|
|
|
|
+ check(krb5_cc_initialize(ctx, ccu2, princ2));
|
|
|
|
+ check_princ(unique2_name, princ2);
|
|
|
|
+ check_match(princ1, unique1_name);
|
|
|
|
+ check_match(princ2, unique2_name);
|
|
|
|
+ check_collection(NULL, 2, unique1_name, unique2_name);
|
|
|
|
+ assert(strcmp(unique1_name, initial_primary_name) != 0);
|
|
|
|
+ assert(strcmp(unique1_name, collection_name) != 0);
|
|
|
|
+ assert(strcmp(unique2_name, initial_primary_name) != 0);
|
|
|
|
+ assert(strcmp(unique2_name, collection_name) != 0);
|
|
|
|
+ assert(strcmp(unique2_name, unique1_name) != 0);
|
|
|
|
+ check_primary_name(collection_name, initial_primary_name);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Initialize the initial primary cache. Make sure it didn't change names,
|
|
|
|
+ * that the previously retrieved name and the collection name both resolve
|
|
|
|
+ * to the initialized cache, and that it now appears first in the
|
|
|
|
+ * collection.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_parse_name(ctx, "princ3@X", &princ3));
|
|
|
|
+ check(krb5_cc_initialize(ctx, ccinitial, princ3));
|
|
|
|
+ check_name(ccinitial, initial_primary_name);
|
|
|
|
+ check_princ(initial_primary_name, princ3);
|
|
|
|
+ check_princ(collection_name, princ3);
|
|
|
|
+ check_match(princ3, initial_primary_name);
|
|
|
|
+ check_collection(initial_primary_name, 2, unique1_name, unique2_name);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Switch the primary cache to each cache we have open. One each switch,
|
|
|
|
+ * check the primary name, check that the collection resolves to the
|
|
|
|
+ * expected cache, and check that the new primary name appears first in the
|
|
|
|
+ * collection.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_switch(ctx, ccu1));
|
|
|
|
+ check_primary_name(collection_name, unique1_name);
|
|
|
|
+ check_princ(collection_name, princ1);
|
|
|
|
+ check_collection(unique1_name, 2, initial_primary_name, unique2_name);
|
|
|
|
+ check(krb5_cc_switch(ctx, ccu2));
|
|
|
|
+ check_primary_name(collection_name, unique2_name);
|
|
|
|
+ check_princ(collection_name, princ2);
|
|
|
|
+ check_collection(unique2_name, 2, initial_primary_name, unique1_name);
|
|
|
|
+ check(krb5_cc_switch(ctx, ccinitial));
|
|
|
|
+ check_primary_name(collection_name, initial_primary_name);
|
|
|
|
+ check_princ(collection_name, princ3);
|
|
|
|
+ check_collection(initial_primary_name, 2, unique1_name, unique2_name);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Temporarily set the context default ccache to a subsidiary name, and
|
|
|
|
+ * check that iterating over the collection yields that subsidiary cache
|
|
|
|
+ * and no others.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_set_default_name(ctx, unique1_name));
|
|
|
|
+ check_collection(unique1_name, 0);
|
|
|
|
+ check(krb5_cc_set_default_name(ctx, collection_name));
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Destroy the primary cache. Make sure this causes both the initial
|
|
|
|
+ * primary name and the collection name to resolve to an uninitialized
|
|
|
|
+ * cache. Make sure the primary name doesn't change and doesn't appear in
|
|
|
|
+ * the collection any more.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_destroy(ctx, ccinitial));
|
|
|
|
+ check_princ(initial_primary_name, NULL);
|
|
|
|
+ check_princ(collection_name, NULL);
|
|
|
|
+ check_primary_name(collection_name, initial_primary_name);
|
|
|
|
+ check_match(princ1, unique1_name);
|
|
|
|
+ check_match(princ2, unique2_name);
|
|
|
|
+ check_match(princ3, NULL);
|
|
|
|
+ check_collection(NULL, 2, unique1_name, unique2_name);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Switch to the first unique cache after destroying the primary cache.
|
|
|
|
+ * Check that the collection name resolves to this cache and that the new
|
|
|
|
+ * primary name appears first in the collection.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_switch(ctx, ccu1));
|
|
|
|
+ check_primary_name(collection_name, unique1_name);
|
|
|
|
+ check_princ(collection_name, princ1);
|
|
|
|
+ check_collection(unique1_name, 1, unique2_name);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Destroy the second unique cache (which is not the current primary),
|
|
|
|
+ * check that it is on longer initialized, and check that it no longer
|
|
|
|
+ * appears in the collection. Check that destroying the non-primary cache
|
|
|
|
+ * doesn't affect the primary name.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_destroy(ctx, ccu2));
|
|
|
|
+ check_princ(unique2_name, NULL);
|
|
|
|
+ check_match(princ2, NULL);
|
|
|
|
+ check_collection(unique1_name, 0);
|
|
|
|
+ check_primary_name(collection_name, unique1_name);
|
|
|
|
+ check_match(princ1, unique1_name);
|
|
|
|
+ check_princ(collection_name, princ1);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Destroy the first unique cache. Check that the collection is empty and
|
|
|
|
+ * still has the same primary name.
|
|
|
|
+ */
|
|
|
|
+ check(krb5_cc_destroy(ctx, ccu1));
|
|
|
|
+ check_princ(unique1_name, NULL);
|
|
|
|
+ check_princ(collection_name, NULL);
|
|
|
|
+ check_primary_name(collection_name, unique1_name);
|
|
|
|
+ check_match(princ1, NULL);
|
|
|
|
+ check_collection(NULL, 0);
|
|
|
|
+
|
|
|
|
+ krb5_free_string(ctx, initial_primary_name);
|
|
|
|
+ krb5_free_string(ctx, unique1_name);
|
|
|
|
+ krb5_free_string(ctx, unique2_name);
|
|
|
|
+ krb5_free_principal(ctx, princ1);
|
|
|
|
+ krb5_free_principal(ctx, princ2);
|
|
|
|
+ krb5_free_principal(ctx, princ3);
|
|
|
|
+ krb5_free_context(ctx);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
diff --git a/src/lib/krb5/ccache/t_cccol.py b/src/lib/krb5/ccache/t_cccol.py
|
|
|
|
index 8c459dd..e762625 100644
|
|
|
|
--- a/src/lib/krb5/ccache/t_cccol.py
|
|
|
|
+++ b/src/lib/krb5/ccache/t_cccol.py
|
|
|
|
@@ -1,6 +1,46 @@
|
|
|
|
#!/usr/bin/python
|
|
|
|
from k5test import *
|
|
|
|
|
|
|
|
+realm = K5Realm(create_kdb=False)
|
|
|
|
+
|
|
|
|
+keyctl = which('keyctl')
|
|
|
|
+out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1)
|
|
|
|
+test_keyring = (keyctl is not None and
|
|
|
|
+ 'Unknown credential cache type' not in out)
|
|
|
|
+
|
|
|
|
+# Run the collection test program against each collection-enabled type.
|
|
|
|
+realm.run(['./t_cccol', 'DIR:' + os.path.join(realm.testdir, 'cc')])
|
|
|
|
+if test_keyring:
|
|
|
|
+ # Use the test directory as the collection name to avoid colliding
|
|
|
|
+ # with other build trees.
|
|
|
|
+ cname = realm.testdir
|
|
|
|
+
|
|
|
|
+ # Remove any keys left behind by previous failed test runs.
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', '_krb_' + cname])
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', cname])
|
|
|
|
+ out = realm.run(['keyctl', 'list', '@u'])
|
|
|
|
+ if ('keyring: _krb_' + cname + '\n') in out:
|
|
|
|
+ id = realm.run(['keyctl', 'search', '@u', 'keyring', '_krb_' + cname])
|
|
|
|
+ realm.run(['keyctl', 'unlink', id.strip(), '@u'])
|
|
|
|
+
|
|
|
|
+ # Run test program over each subtype, cleaning up as we go. Don't
|
|
|
|
+ # test the persistent subtype, since it supports only one
|
|
|
|
+ # collection and might be in actual use.
|
|
|
|
+ realm.run(['./t_cccol', 'KEYRING:' + cname])
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', '_krb_' + cname])
|
|
|
|
+ realm.run(['./t_cccol', 'KEYRING:legacy:' + cname])
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', '_krb_' + cname])
|
|
|
|
+ realm.run(['./t_cccol', 'KEYRING:session:' + cname])
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', '_krb_' + cname])
|
|
|
|
+ realm.run(['./t_cccol', 'KEYRING:user:' + cname])
|
|
|
|
+ id = realm.run(['keyctl', 'search', '@u', 'keyring', '_krb_' + cname])
|
|
|
|
+ realm.run(['keyctl', 'unlink', id.strip(), '@u'])
|
|
|
|
+ realm.run(['./t_cccol', 'KEYRING:process:abcd'])
|
|
|
|
+ realm.run(['./t_cccol', 'KEYRING:thread:abcd'])
|
|
|
|
+
|
|
|
|
+realm.stop()
|
|
|
|
+
|
|
|
|
+# Test cursor semantics using real ccaches.
|
|
|
|
realm = K5Realm(create_host=False)
|
|
|
|
|
|
|
|
realm.addprinc('alice', password('alice'))
|
|
|
|
@@ -11,12 +51,25 @@ dccname = 'DIR:%s' % ccdir
|
|
|
|
duser = 'DIR::%s/tkt1' % ccdir
|
|
|
|
dalice = 'DIR::%s/tkt2' % ccdir
|
|
|
|
dbob = 'DIR::%s/tkt3' % ccdir
|
|
|
|
+dnoent = 'DIR::%s/noent' % ccdir
|
|
|
|
realm.kinit('user', password('user'), flags=['-c', duser])
|
|
|
|
realm.kinit('alice', password('alice'), flags=['-c', dalice])
|
|
|
|
realm.kinit('bob', password('bob'), flags=['-c', dbob])
|
|
|
|
|
|
|
|
+if test_keyring:
|
|
|
|
+ cname = realm.testdir
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', '_krb_' + cname])
|
|
|
|
+ krccname = 'KEYRING:session:' + cname
|
|
|
|
+ kruser = '%s:tkt1' % krccname
|
|
|
|
+ kralice = '%s:tkt2' % krccname
|
|
|
|
+ krbob = '%s:tkt3' % krccname
|
|
|
|
+ krnoent = '%s:noent' % krccname
|
|
|
|
+ realm.kinit('user', password('user'), flags=['-c', kruser])
|
|
|
|
+ realm.kinit('alice', password('alice'), flags=['-c', kralice])
|
|
|
|
+ realm.kinit('bob', password('bob'), flags=['-c', krbob])
|
|
|
|
+
|
|
|
|
def cursor_test(testname, args, expected):
|
|
|
|
- outlines = realm.run_as_client(['./t_cccursor'] + args).splitlines()
|
|
|
|
+ outlines = realm.run(['./t_cccursor'] + args).splitlines()
|
|
|
|
outlines.sort()
|
|
|
|
expected.sort()
|
|
|
|
if outlines != expected:
|
|
|
|
@@ -30,21 +83,33 @@ cursor_test('file-default2', [realm.ccache], [fccname])
|
|
|
|
cursor_test('file-default3', [fccname], [fccname])
|
|
|
|
|
|
|
|
cursor_test('dir', [dccname], [duser, dalice, dbob])
|
|
|
|
+cursor_test('dir-subsidiary', [duser], [duser])
|
|
|
|
+cursor_test('dir-nofile', [dnoent], [])
|
|
|
|
+
|
|
|
|
+if test_keyring:
|
|
|
|
+ cursor_test('keyring', [krccname], [kruser, kralice, krbob])
|
|
|
|
+ cursor_test('keyring-subsidiary', [kruser], [kruser])
|
|
|
|
+ cursor_test('keyring-noent', [krnoent], [])
|
|
|
|
|
|
|
|
mfoo = 'MEMORY:foo'
|
|
|
|
mbar = 'MEMORY:bar'
|
|
|
|
cursor_test('filemem', [fccname, mfoo, mbar], [fccname, mfoo, mbar])
|
|
|
|
cursor_test('dirmem', [dccname, mfoo], [duser, dalice, dbob, mfoo])
|
|
|
|
+if test_keyring:
|
|
|
|
+ cursor_test('keyringmem', [krccname, mfoo], [kruser, kralice, krbob, mfoo])
|
|
|
|
|
|
|
|
# Test krb5_cccol_have_content.
|
|
|
|
-realm.run_as_client(['./t_cccursor', dccname, 'CONTENT'])
|
|
|
|
-realm.run_as_client(['./t_cccursor', fccname, 'CONTENT'])
|
|
|
|
-realm.run_as_client(['./t_cccursor', realm.ccache, 'CONTENT'])
|
|
|
|
-realm.run_as_client(['./t_cccursor', mfoo, 'CONTENT'], expected_code=1)
|
|
|
|
+realm.run(['./t_cccursor', dccname, 'CONTENT'])
|
|
|
|
+realm.run(['./t_cccursor', fccname, 'CONTENT'])
|
|
|
|
+realm.run(['./t_cccursor', realm.ccache, 'CONTENT'])
|
|
|
|
+realm.run(['./t_cccursor', mfoo, 'CONTENT'], expected_code=1)
|
|
|
|
+if test_keyring:
|
|
|
|
+ realm.run(['./t_cccursor', krccname, 'CONTENT'])
|
|
|
|
+ realm.run(['keyctl', 'purge', 'keyring', '_krb_' + cname])
|
|
|
|
|
|
|
|
# Make sure FILE doesn't yield a nonexistent default cache.
|
|
|
|
-realm.run_as_client([kdestroy])
|
|
|
|
+realm.run([kdestroy])
|
|
|
|
cursor_test('noexist', [], [])
|
|
|
|
-realm.run_as_client(['./t_cccursor', fccname, 'CONTENT'], expected_code=1)
|
|
|
|
+realm.run(['./t_cccursor', fccname, 'CONTENT'], expected_code=1)
|
|
|
|
|
|
|
|
success('Renewing credentials')
|
|
|
|
diff --git a/src/util/k5test.py b/src/util/k5test.py
|
|
|
|
index 3400154..aead832 100644
|
|
|
|
--- a/src/util/k5test.py
|
|
|
|
+++ b/src/util/k5test.py
|
|
|
|
@@ -142,6 +133,9 @@ Scripts may use the following functions and variables:
|
|
|
|
added newline) in testlog, and write it to stdout if running
|
|
|
|
verbosely.
|
|
|
|
|
|
|
|
+* which(progname): Return the location of progname in the executable
|
|
|
|
+ path, or None if it is not found.
|
|
|
|
+
|
|
|
|
* password(name): Return a weakly random password based on name. The
|
|
|
|
password will be consistent across calls with the same name.
|
|
|
|
|
|
|
|
@@ -388,6 +374,16 @@ def output(msg, force_verbose=False):
|
|
|
|
sys.stdout.write(msg)
|
|
|
|
|
|
|
|
|
|
|
|
+# Return the location of progname in the executable path, or None if
|
|
|
|
+# it is not found.
|
|
|
|
+def which(progname):
|
|
|
|
+ for dir in os.environ["PATH"].split(os.pathsep):
|
|
|
|
+ path = os.path.join(dir, progname)
|
|
|
|
+ if os.access(path, os.X_OK):
|
|
|
|
+ return path
|
|
|
|
+ return None
|
|
|
|
+
|
|
|
|
+
|
|
|
|
def password(name):
|
|
|
|
"""Choose a weakly random password from name, consistent across calls."""
|
|
|
|
return name + str(os.getpid())
|
|
|
|
@@ -880,6 +880,11 @@ class K5Realm(object):
|
|
|
|
env['KPROP_PORT'] = str(self.portbase + 3)
|
|
|
|
return env
|
|
|
|
|
|
|
|
+ def run(self, args, env=None, **keywords):
|
|
|
|
+ if env is None:
|
|
|
|
+ env = self.env_client
|
|
|
|
+ return _run_cmd(args, env, **keywords)
|
|
|
|
+
|
|
|
|
def run_as_client(self, args, **keywords):
|
|
|
|
return _run_cmd(args, self.env_client, **keywords)
|
|
|
|
|
|
|
|
diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in
|
|
|
|
index f64226b..ad53e65 100644
|
|
|
|
--- a/src/lib/krb5/ccache/Makefile.in
|
|
|
|
+++ b/src/lib/krb5/ccache/Makefile.in
|
|
|
|
@@ -71,6 +66,7 @@ SRCS= $(srcdir)/ccbase.c \
|
|
|
|
|
|
|
|
EXTRADEPSRCS= \
|
|
|
|
$(srcdir)/t_cc.c \
|
|
|
|
+ $(srcdir)/t_cccol.c \
|
|
|
|
$(srcdir)/t_cccursor.c
|
|
|
|
|
|
|
|
##DOS##OBJS=$(OBJS) $(OUTPRE)ccfns.$(OBJEXT)
|
|
|
|
@@ -108,6 +104,10 @@ T_CC_OBJS=t_cc.o
|
|
|
|
t_cc: $(T_CC_OBJS) $(KRB5_BASE_DEPLIBS)
|
|
|
|
$(CC_LINK) -o t_cc $(T_CC_OBJS) $(KRB5_BASE_LIBS)
|
|
|
|
|
|
|
|
+T_CCCOL_OBJS = t_cccol.o
|
|
|
|
+t_cccol: $(T_CCCOL_OBJS) $(KRB5_BASE_DEPLIBS)
|
|
|
|
+ $(CC_LINK) -o $@ $(T_CCCOL_OBJS) $(KRB5_BASE_LIBS)
|
|
|
|
+
|
|
|
|
T_CCCURSOR_OBJS = t_cccursor.o
|
|
|
|
t_cccursor: $(T_CCCURSOR_OBJS) $(KRB5_BASE_DEPLIBS)
|
|
|
|
$(CC_LINK) -o $@ $(T_CCCURSOR_OBJS) $(KRB5_BASE_LIBS)
|
|
|
|
@@ -116,11 +116,11 @@ check-unix:: t_cc
|
|
|
|
KRB5_CONFIG=$(srcdir)/t_krb5.conf ; export KRB5_CONFIG ;\
|
|
|
|
$(RUN_SETUP) $(VALGRIND) ./t_cc
|
|
|
|
|
|
|
|
-check-pytests:: t_cccursor
|
|
|
|
+check-pytests:: t_cccursor t_cccol
|
|
|
|
$(RUNPYTEST) $(srcdir)/t_cccol.py $(PYTESTFLAGS)
|
|
|
|
|
|
|
|
clean-unix::
|
|
|
|
- $(RM) t_cc t_cc.o t_cccursor t_cccursor.o
|
|
|
|
+ $(RM) t_cc t_cc.o t_cccursor t_cccursor.o t_cccol t_cccol.o
|
|
|
|
|
|
|
|
##WIN32## $(OUTPRE)cc_mslsa.$(OBJEXT): cc_mslsa.c $(top_srcdir)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS)
|
|
|
|
|