svn rev #25214: trunk/src/ include/ lib/kdb/ lib/krb5/error_tables/

ghudson@MIT.EDU ghudson at MIT.EDU
Wed Sep 21 12:28:54 EDT 2011


http://src.mit.edu/fisheye/changelog/krb5/?cs=25214
Commit By: ghudson
Log Message:
Add KRB5_TL_STRING_ATTRS and libkdb5 accessors.


Changed Files:
U   trunk/src/include/kdb.h
U   trunk/src/lib/kdb/Makefile.in
U   trunk/src/lib/kdb/kdb5.c
U   trunk/src/lib/kdb/libkdb5.exports
A   trunk/src/lib/kdb/t_stringattr.c
U   trunk/src/lib/krb5/error_tables/kdb5_err.et
Modified: trunk/src/include/kdb.h
===================================================================
--- trunk/src/include/kdb.h	2011-09-21 04:40:49 UTC (rev 25213)
+++ trunk/src/include/kdb.h	2011-09-21 16:28:54 UTC (rev 25214)
@@ -145,6 +145,13 @@
     krb5_octet          * tl_data_contents;
 } krb5_tl_data;
 
+/* String attributes (currently stored inside tl-data) map C string keys to
+ * values.  They can be set via kadmin and consumed by KDC plugins. */
+typedef struct krb5_string_attr_st {
+    char *key;
+    char *value;
+} krb5_string_attr;
+
 /*
  * If this ever changes up the version number and make the arrays be as
  * big as necessary.
@@ -235,6 +242,10 @@
 #define KRB5_TL_ACTKVNO                 0x0009
 #define KRB5_TL_MKEY_AUX                0x000a
 
+/* String attributes may not always be represented in tl-data.  kadmin clients
+ * must use the modify_strings and get_strings RPCs. */
+#define KRB5_TL_STRING_ATTRS            0x000b
+
 #define KRB5_TL_PAC_LOGON_INFO          0x0100 /* NDR encoded validation info */
 #define KRB5_TL_SERVER_REFERRAL         0x0200 /* ASN.1 encoded ServerReferralInfo */
 #define KRB5_TL_SVR_REFERRAL_DATA       0x0300 /* ASN.1 encoded PA-SVR-REFERRAL-DATA */
@@ -538,7 +549,24 @@
                                    krb5_db_entry       * entry,
                                    krb5_timestamp      * stamp);
 
+/* Retrieve the set of string attributes in entry, in no particular order.
+ * Free *strings_out with krb5_dbe_free_strings when done. */
 krb5_error_code
+krb5_dbe_get_strings(krb5_context context, krb5_db_entry *entry,
+                     krb5_string_attr **strings_out, int *count_out);
+
+/* Retrieve a single string attribute from entry, or NULL if there is no
+ * attribute for key.  Free *value_out with krb5_dbe_free_string when done. */
+krb5_error_code
+krb5_dbe_get_string(krb5_context context, krb5_db_entry *entry,
+                    const char *key, char **value_out);
+
+/* Change or add a string attribute in entry, or delete it if value is NULL. */
+krb5_error_code
+krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry,
+                    const char *key, const char *value);
+
+krb5_error_code
 krb5_dbe_delete_tl_data( krb5_context    context,
                          krb5_db_entry * entry,
                          krb5_int16      tl_data_type);
@@ -741,6 +769,12 @@
 void
 krb5_dbe_free_tl_data(krb5_context, krb5_tl_data *);
 
+void
+krb5_dbe_free_strings(krb5_context, krb5_string_attr *, int count);
+
+void
+krb5_dbe_free_string(krb5_context, char *);
+
 #define KRB5_KDB_DEF_FLAGS      0
 
 #define KDB_MAX_DB_NAME                 128

Modified: trunk/src/lib/kdb/Makefile.in
===================================================================
--- trunk/src/lib/kdb/Makefile.in	2011-09-21 04:40:49 UTC (rev 25213)
+++ trunk/src/lib/kdb/Makefile.in	2011-09-21 16:28:54 UTC (rev 25214)
@@ -1,5 +1,6 @@
 mydir=lib$(S)kdb
 BUILDTOP=$(REL)..$(S)..
+RUN_SETUP = @KRB5_RUN_ENV@
 KRB5_RUN_ENV = @KRB5_RUN_ENV@
 KRB5_CONFIG_SETUP = KRB5_CONFIG=$(top_srcdir)/config-files/krb5.conf ; export KRB5_CONFIG ;
 PROG_LIBPATH=-L$(TOPLIBD)
@@ -56,12 +57,19 @@
 all-unix:: all-liblinks
 install-unix:: install-libs
 clean-unix:: clean-liblinks clean-libs clean-libobjs
-	$(RM) adb_err.c adb_err.h
+	$(RM) adb_err.c adb_err.h t_stringattr.o t_stringattr
+check-unix:: t_stringattr
+	KRB5_CONFIG=$(top_srcdir)/config-files/krb5.conf; export KRB5_CONFIG; \
+	$(RUN_SETUP) $(VALGRIND) ./t_stringattr
 
 generate-files-mac: darwin.exports
 
 depend:: adb_err.h
 
+t_stringattr: t_stringattr.o $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+	$(CC_LINK) -o $@ t_stringattr.o $(KDB5_LIBS) $(KADM_COMM_LIBS) \
+		$(KRB5_BASE_LIBS)
+
 @lib_frag@
 @libobj_frag@
 

Modified: trunk/src/lib/kdb/kdb5.c
===================================================================
--- trunk/src/lib/kdb/kdb5.c	2011-09-21 04:40:49 UTC (rev 25213)
+++ trunk/src/lib/kdb/kdb5.c	2011-09-21 16:28:54 UTC (rev 25214)
@@ -162,6 +162,27 @@
     }
 }
 
+void
+krb5_dbe_free_strings(krb5_context context, krb5_string_attr *strings,
+                      int count)
+{
+    int i;
+
+    if (strings == NULL)
+        return;
+    for (i = 0; i < count; i++) {
+        free(strings[i].key);
+        free(strings[i].value);
+    }
+    free(strings);
+}
+
+void
+krb5_dbe_free_string(krb5_context context, char *string)
+{
+    free(string);
+}
+
 /* Set *section to the appropriate section to use for a database module's
  * profile queries.  The caller must free the result. */
 static krb5_error_code
@@ -1960,7 +1981,164 @@
     return (krb5_dbe_update_tl_data(context, entry, &tl_data));
 }
 
+/*
+ * Prepare to iterate over the string attributes of entry.  The returned
+ * pointers are aliases into entry's tl_data (or into an empty string literal)
+ * and remain valid until the entry's tl_data is changed.
+ */
+static krb5_error_code
+begin_attrs(krb5_context context, krb5_db_entry *entry, const char **pos_out,
+            const char **end_out)
+{
+    krb5_error_code code;
+    krb5_tl_data tl_data;
+
+    *pos_out = *end_out = NULL;
+    tl_data.tl_data_type = KRB5_TL_STRING_ATTRS;
+    code = krb5_dbe_lookup_tl_data(context, entry, &tl_data);
+    if (code)
+        return code;
+
+    /* Copy the current mapping to buf, updating key with value if found. */
+    *pos_out = (const char *)tl_data.tl_data_contents;
+    *end_out = *pos_out + tl_data.tl_data_length;
+    return 0;
+}
+
+/* Find the next key and value pair in *pos and update *pos. */
+static krb5_boolean
+next_attr(const char **pos, const char *end, const char **key_out,
+          const char **val_out)
+{
+    const char *key, *key_end, *val, *val_end;
+
+    *key_out = *val_out = NULL;
+    if (*pos == end)
+        return FALSE;
+    key = *pos;
+    key_end = memchr(key, '\0', end - key);
+    if (key_end == NULL)        /* Malformed representation; give up. */
+        return FALSE;
+    val = key_end + 1;
+    val_end = memchr(val, '\0', end - val);
+    if (val_end == NULL)        /* Malformed representation; give up. */
+        return FALSE;
+
+    *key_out = key;
+    *val_out = val;
+    *pos = val_end + 1;
+    return TRUE;
+}
+
 krb5_error_code
+krb5_dbe_get_strings(krb5_context context, krb5_db_entry *entry,
+                     krb5_string_attr **strings_out, int *count_out)
+{
+    krb5_error_code code;
+    const char *pos, *end, *mapkey, *mapval;
+    char *key = NULL, *val = NULL;
+    krb5_string_attr *strings = NULL, *newstrings;
+    int count = 0;
+
+    *strings_out = NULL;
+    *count_out = 0;
+    code = begin_attrs(context, entry, &pos, &end);
+    if (code)
+        return code;
+
+    while (next_attr(&pos, end, &mapkey, &mapval)) {
+        /* Add a copy of mapkey and mapvalue to strings. */
+        key = strdup(mapkey);
+        val = strdup(mapval);
+        newstrings = realloc(strings, (count + 1) * sizeof(*strings));
+        if (key == NULL || val == NULL || newstrings == NULL) {
+            free(key);
+            free(val);
+            krb5_dbe_free_strings(context, strings, count);
+            return ENOMEM;
+        }
+        strings = newstrings;
+        strings[count].key = key;
+        strings[count].value = val;
+        count++;
+    }
+
+    *strings_out = strings;
+    *count_out = count;
+    return 0;
+}
+
+krb5_error_code
+krb5_dbe_get_string(krb5_context context, krb5_db_entry *entry,
+                    const char *key, char **value_out)
+{
+    krb5_error_code code;
+    const char *pos, *end, *mapkey, *mapval;
+
+    *value_out = NULL;
+    code = begin_attrs(context, entry, &pos, &end);
+    if (code)
+        return code;
+    while (next_attr(&pos, end, &mapkey, &mapval)) {
+        if (strcmp(mapkey, key) == 0) {
+            *value_out = strdup(mapval);
+            return (*value_out == NULL) ? ENOMEM : 0;
+        }
+    }
+
+    return 0;
+}
+
+krb5_error_code
+krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry,
+                    const char *key, const char *value)
+{
+    krb5_error_code code;
+    const char *pos, *end, *mapkey, *mapval;
+    struct k5buf buf;
+    krb5_boolean found = FALSE;
+    krb5_tl_data tl_data;
+    ssize_t len;
+
+    /* Copy the current mapping to buf, updating key with value if found. */
+    code = begin_attrs(context, entry, &pos, &end);
+    if (code)
+        return code;
+    krb5int_buf_init_dynamic(&buf);
+    while (next_attr(&pos, end, &mapkey, &mapval)) {
+        if (strcmp(mapkey, key) == 0) {
+            if (value != NULL) {
+                krb5int_buf_add_len(&buf, mapkey, strlen(mapkey) + 1);
+                krb5int_buf_add_len(&buf, value, strlen(value) + 1);
+            }
+            found = TRUE;
+        } else {
+            krb5int_buf_add_len(&buf, mapkey, strlen(mapkey) + 1);
+            krb5int_buf_add_len(&buf, mapval, strlen(mapval) + 1);
+        }
+    }
+
+    /* If key wasn't found in the map, add a new entry for it. */
+    if (!found && value != NULL) {
+        krb5int_buf_add_len(&buf, key, strlen(key) + 1);
+        krb5int_buf_add_len(&buf, value, strlen(value) + 1);
+    }
+
+    len = krb5int_buf_len(&buf);
+    if (len == -1)
+        return ENOMEM;
+    if (len > 65535)
+        return KRB5_KDB_STRINGS_TOOLONG;
+    tl_data.tl_data_type = KRB5_TL_STRING_ATTRS;
+    tl_data.tl_data_contents = (krb5_octet *)krb5int_buf_data(&buf);
+    tl_data.tl_data_length = len;
+
+    code = krb5_dbe_update_tl_data(context, entry, &tl_data);
+    krb5int_free_buf(&buf);
+    return code;
+}
+
+krb5_error_code
 krb5_dbe_delete_tl_data(krb5_context context, krb5_db_entry *entry,
                         krb5_int16 tl_data_type)
 {

Modified: trunk/src/lib/kdb/libkdb5.exports
===================================================================
--- trunk/src/lib/kdb/libkdb5.exports	2011-09-21 04:40:49 UTC (rev 25213)
+++ trunk/src/lib/kdb/libkdb5.exports	2011-09-21 16:28:54 UTC (rev 25214)
@@ -43,7 +43,11 @@
 krb5_dbe_free_key_data_contents
 krb5_dbe_free_mkey_aux_list
 krb5_dbe_free_key_list
+krb5_dbe_free_string
+krb5_dbe_free_strings
 krb5_dbe_get_mkvno
+krb5_dbe_get_string
+krb5_dbe_get_strings
 krb5_dbe_lookup_last_admin_unlock
 krb5_dbe_lookup_last_pwd_change
 krb5_dbe_lookup_actkvno
@@ -52,6 +56,7 @@
 krb5_dbe_lookup_mod_princ_data
 krb5_dbe_lookup_tl_data
 krb5_dbe_search_enctype
+krb5_dbe_set_string
 krb5_dbe_update_actkvno
 krb5_dbe_update_last_admin_unlock
 krb5_dbe_update_last_pwd_change

Added: trunk/src/lib/kdb/t_stringattr.c
===================================================================
--- trunk/src/lib/kdb/t_stringattr.c	                        (rev 0)
+++ trunk/src/lib/kdb/t_stringattr.c	2011-09-21 16:28:54 UTC (rev 25214)
@@ -0,0 +1,94 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/kdb/t_strings.c - Test program for KDB string attribute functions */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include <kdb.h>
+
+/*
+ * This program exercises the KDB entry APIs for string attributes.  It relies
+ * on some implementation knowledge:
+ *
+ * - The APIs will work on a DB entry initialized to all zeros (because it has
+ *   an empty tl_data list).
+ * 
+ * - Attribute order in krb5_dbe_get_strings matches attribute insertion order.
+ */
+
+int
+main()
+{
+    krb5_db_entry *ent;
+    krb5_context context;
+    krb5_string_attr *strings;
+    char *val;
+    int count;
+
+    assert(krb5_init_context(&context) == 0);
+
+    /* Start with an empty entry. */
+    ent = krb5_db_alloc(context, NULL, sizeof(*ent));
+    if (ent == NULL)
+        return ENOMEM;
+    memset(ent, 0, sizeof(*ent));
+
+    /* Check that the entry has no strings to start. */
+    assert(krb5_dbe_get_strings(context, ent, &strings, &count) == 0);
+    assert(strings == NULL && count == 0);
+    krb5_dbe_free_strings(context, strings, count);
+
+    /* Check that we get a null value querying a specific attribute. */
+    assert(krb5_dbe_get_string(context, ent, "foo", &val) == 0);
+    assert(val == NULL);
+
+    /* Set some attributes one at a time, including a deletion. */
+    assert(krb5_dbe_set_string(context, ent, "eggs", "dozen") == 0);
+    assert(krb5_dbe_set_string(context, ent, "price", "right") == 0);
+    assert(krb5_dbe_set_string(context, ent, "eggs", NULL) == 0);
+    assert(krb5_dbe_set_string(context, ent, "time", "flies") == 0);
+
+    /* Query each attribute. */
+    assert(krb5_dbe_get_string(context, ent, "price", &val) == 0);
+    assert(strcmp(val, "right") == 0);
+    krb5_dbe_free_string(context, val);
+    assert(krb5_dbe_get_string(context, ent, "time", &val) == 0);
+    assert(strcmp(val, "flies") == 0);
+    krb5_dbe_free_string(context, val);
+    assert(krb5_dbe_get_string(context, ent, "eggs", &val) == 0);
+    assert(val == NULL);
+
+    /* Query the list of attributes and verify it. */
+    assert(krb5_dbe_get_strings(context, ent, &strings, &count) == 0);
+    assert(count == 2);
+    assert(strcmp(strings[0].key, "price") == 0);
+    assert(strcmp(strings[0].value, "right") == 0);
+    assert(strcmp(strings[1].key, "time") == 0);
+    assert(strcmp(strings[1].value, "flies") == 0);
+    krb5_dbe_free_strings(context, strings, count);
+
+    krb5_db_free_principal(context, ent);
+    krb5_free_context(context);
+    return 0;
+}

Modified: trunk/src/lib/krb5/error_tables/kdb5_err.et
===================================================================
--- trunk/src/lib/krb5/error_tables/kdb5_err.et	2011-09-21 04:40:49 UTC (rev 25213)
+++ trunk/src/lib/krb5/error_tables/kdb5_err.et	2011-09-21 16:28:54 UTC (rev 25214)
@@ -84,5 +84,6 @@
 ec KRB5_LOG_ERROR,		"Generic update log error"
 ec KRB5_KDB_DBTYPE_MISMATCH,    "Database module does not match KDC version"
 ec KRB5_KDB_POLICY_REF,		"Policy is in use"
+ec KRB5_KDB_STRINGS_TOOLONG,    "Too much string mapping data"
 
 end




More information about the cvs-krb5 mailing list