diff options
author | Greg Hudson <ghudson@mit.edu> | 2011-09-21 16:28:54 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2011-09-21 16:28:54 +0000 |
commit | 237e57c297708c8009cf2af4833b78abc4e05bbc (patch) | |
tree | 14a0837807841de1b1211b1ecb7a69131c24d476 /src/lib/kdb/kdb5.c | |
parent | e3e006d3aedccb88d5238d0175c81a6bf535c18f (diff) | |
download | krb5-237e57c297708c8009cf2af4833b78abc4e05bbc.tar.gz krb5-237e57c297708c8009cf2af4833b78abc4e05bbc.tar.xz krb5-237e57c297708c8009cf2af4833b78abc4e05bbc.zip |
Add KRB5_TL_STRING_ATTRS and libkdb5 accessors
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25214 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/kdb/kdb5.c')
-rw-r--r-- | src/lib/kdb/kdb5.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index b82bbcb406..4dfe66151a 100644 --- a/src/lib/kdb/kdb5.c +++ b/src/lib/kdb/kdb5.c @@ -162,6 +162,27 @@ krb5_dbe_free_tl_data(krb5_context context, krb5_tl_data *tl_data) } } +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,6 +1981,163 @@ krb5_dbe_update_last_admin_unlock(krb5_context context, krb5_db_entry *entry, 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) |