summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2013-02-11 21:07:54 -0500
committerGreg Hudson <ghudson@mit.edu>2013-02-13 15:53:29 -0500
commit80f53c8b2c745e75dc9d22acba63812d8533c133 (patch)
tree258cbc960e82ffacea2e634ebcef4d6a9685ff99 /src/lib
parent61116eb28a7520dda1e5febba95ac6ba1e70e6ac (diff)
downloadkrb5-80f53c8b2c745e75dc9d22acba63812d8533c133.tar.gz
krb5-80f53c8b2c745e75dc9d22acba63812d8533c133.tar.xz
krb5-80f53c8b2c745e75dc9d22acba63812d8533c133.zip
Add k5_json_array_fmt and use it in export_cred.c
Add a template-based array constructor for convenient marshalling of structured values as JSON array values. Use it to simplify export_cred.c.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/gssapi/krb5/export_cred.c534
1 files changed, 273 insertions, 261 deletions
diff --git a/src/lib/gssapi/krb5/export_cred.c b/src/lib/gssapi/krb5/export_cred.c
index e5ffaf54aa..652b2604bd 100644
--- a/src/lib/gssapi/krb5/export_cred.c
+++ b/src/lib/gssapi/krb5/export_cred.c
@@ -34,387 +34,400 @@
#include "k5-json.h"
#include "gssapiP_krb5.h"
-/* Add v to array and then release it. Return -1 if v is NULL. */
-static int
-add(k5_json_array array, k5_json_value v)
-{
- if (v == NULL || k5_json_array_add(array, v))
- return -1;
- k5_json_release(v);
- return 0;
-}
-
-static inline k5_json_number
-number(long long nval)
-{
- k5_json_number num;
-
- return k5_json_number_create(nval, &num) ? NULL : num;
-}
-
-static inline k5_json_string
-string(const char *cstring)
-{
- k5_json_string str;
-
- return k5_json_string_create(cstring, &str) ? NULL : str;
-}
-
-static inline k5_json_string
-base64string(const void *data, size_t len)
-{
- k5_json_string str;
-
- return k5_json_string_create_base64(data, len, &str) ? NULL : str;
-}
-
-static inline k5_json_null
-null(void)
-{
- k5_json_null n;
-
- return k5_json_null_create(&n) ? NULL : n;
-}
-
-static inline k5_json_bool
-bool(int truth)
-{
- k5_json_bool b;
-
- return k5_json_bool_create(truth, &b) ? NULL : b;
-}
-
-/* Return a JSON null or string value representing str. */
-static k5_json_value
-json_optional_string(const char *str)
-{
- return (str == NULL) ? (k5_json_value)null() : string(str);
-}
-
/* Return a JSON null or array value representing princ. */
-static k5_json_value
-json_principal(krb5_context context, krb5_principal princ)
+static krb5_error_code
+json_principal(krb5_context context, krb5_principal princ,
+ k5_json_value *val_out)
{
+ krb5_error_code ret;
+ k5_json_string str = NULL;
char *princname;
- k5_json_string str;
+ *val_out = NULL;
if (princ == NULL)
- return null();
- if (krb5_unparse_name(context, princ, &princname))
- return NULL;
- str = string(princname);
+ return k5_json_null_create_val(val_out);
+ ret = krb5_unparse_name(context, princ, &princname);
+ if (ret)
+ return ret;
+ ret = k5_json_string_create(princname, &str);
krb5_free_unparsed_name(context, princname);
- return str;
+ *val_out = str;
+ return ret;
}
/* Return a json null or array value representing etypes. */
-static k5_json_value
-json_etypes(krb5_enctype *etypes)
+static krb5_error_code
+json_etypes(krb5_enctype *etypes, k5_json_value *val_out)
{
+ krb5_error_code ret;
+ k5_json_number num;
k5_json_array array;
+ *val_out = NULL;
if (etypes == NULL)
- return null();
- if (k5_json_array_create(&array))
- return NULL;
+ return k5_json_null_create_val(val_out);
+ ret = k5_json_array_create(&array);
+ if (ret)
+ return ret;
for (; *etypes != 0; etypes++) {
- if (add(array, number(*etypes)))
- goto oom;
+ ret = k5_json_number_create(*etypes, &num);
+ if (ret)
+ goto err;
+ ret = k5_json_array_add(array, num);
+ k5_json_release(num);
+ if (ret)
+ goto err;
}
- return array;
-oom:
+ *val_out = array;
+ return 0;
+err:
k5_json_release(array);
- return NULL;
+ return ret;
}
/* Return a JSON null or array value representing name. */
-static k5_json_value
-json_kgname(krb5_context context, krb5_gss_name_t name)
+static krb5_error_code
+json_kgname(krb5_context context, krb5_gss_name_t name, k5_json_value *val_out)
{
- k5_json_array array;
+ krb5_error_code ret;
+ k5_json_array array = NULL;
+ k5_json_value princ;
+ *val_out = NULL;
if (name == NULL)
- return null();
- if (k5_json_array_create(&array))
- return NULL;
- if (add(array, json_principal(context, name->princ)))
- goto oom;
- if (add(array, json_optional_string(name->service)))
- goto oom;
- if (add(array, json_optional_string(name->host)))
- goto oom;
- return array;
-oom:
- k5_json_release(array);
- return NULL;
+ return k5_json_null_create_val(val_out);
+ ret = json_principal(context, name->princ, &princ);
+ if (ret)
+ return ret;
+ ret = k5_json_array_fmt(&array, "vss", princ, name->service, name->host);
+ k5_json_release(princ);
+ *val_out = array;
+ return ret;
}
/* Return a JSON null or string value representing keytab. */
-static k5_json_value
-json_keytab(krb5_context context, krb5_keytab keytab)
+static krb5_error_code
+json_keytab(krb5_context context, krb5_keytab keytab, k5_json_value *val_out)
{
+ krb5_error_code ret;
+ k5_json_string str;
char name[1024];
+ *val_out = NULL;
if (keytab == NULL)
- return null();
- if (krb5_kt_get_name(context, keytab, name, sizeof(name)))
- return NULL;
- return string(name);
+ return k5_json_null_create_val(val_out);
+ ret = krb5_kt_get_name(context, keytab, name, sizeof(name));
+ if (ret)
+ return ret;
+ ret = k5_json_string_create(name, &str);
+ *val_out = str;
+ return ret;
}
/* Return a JSON null or string value representing rcache. */
-static k5_json_value
-json_rcache(krb5_context context, krb5_rcache rcache)
+static krb5_error_code
+json_rcache(krb5_context context, krb5_rcache rcache, k5_json_value *val_out)
{
+ krb5_error_code ret;
+ k5_json_string str = NULL;
char *name;
- k5_json_string str;
if (rcache == NULL)
- return null();
+ return k5_json_null_create_val(val_out);
if (asprintf(&name, "%s:%s", krb5_rc_get_type(context, rcache),
krb5_rc_get_name(context, rcache)) < 0)
- return NULL;
- str = string(name);
+ return ENOMEM;
+ ret = k5_json_string_create(name, &str);
free(name);
- return str;
+ *val_out = str;
+ return ret;
}
/* Return a JSON array value representing keyblock. */
-static k5_json_value
-json_keyblock(krb5_keyblock *keyblock)
+static krb5_error_code
+json_keyblock(krb5_keyblock *kb, k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
- if (k5_json_array_create(&array))
- return NULL;
- if (add(array, number(keyblock->enctype)))
- goto oom;
- if (add(array, base64string(keyblock->contents, keyblock->length)))
- goto oom;
- return array;
-oom:
- k5_json_release(array);
- return NULL;
+ *val_out = NULL;
+ ret = k5_json_array_fmt(&array, "iB", kb->enctype, (void *)kb->contents,
+ (size_t)kb->length);
+ if (ret)
+ return ret;
+ *val_out = array;
+ return 0;
}
/* Return a JSON array value representing addr. */
-static k5_json_value
-json_address(krb5_address *addr)
+static krb5_error_code
+json_address(krb5_address *addr, k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
- if (k5_json_array_create(&array))
- return NULL;
- if (add(array, number(addr->addrtype)))
- goto oom;
- if (add(array, base64string(addr->contents, addr->length)))
- goto oom;
- return array;
-oom:
- k5_json_release(array);
- return NULL;
+ *val_out = NULL;
+ ret = k5_json_array_fmt(&array, "iB", addr->addrtype,
+ (void *)addr->contents, (size_t)addr->length);
+ if (ret)
+ return ret;
+ *val_out = array;
+ return 0;
}
/* Return a JSON null or array value representing addrs. */
-static k5_json_value
-json_addresses(krb5_address **addrs)
+static krb5_error_code
+json_addresses(krb5_address **addrs, k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
+ k5_json_value val;
+ *val_out = NULL;
if (addrs == NULL)
- return null();
- if (k5_json_array_create(&array))
- return NULL;
+ return k5_json_null_create_val(val_out);
+ ret = k5_json_array_create(&array);
+ if (ret)
+ return ret;
for (; *addrs != NULL; addrs++) {
- if (add(array, json_address(*addrs))) {
- k5_json_release(array);
- return NULL;
- }
+ ret = json_address(*addrs, &val);
+ if (ret)
+ goto err;
+ ret = k5_json_array_add(array, val);
+ k5_json_release(val);
+ if (ret)
+ goto err;
}
- return array;
+ *val_out = array;
+ return 0;
+err:
+ k5_json_release(array);
+ return ret;
}
/* Return a JSON array value representing ad. */
-static k5_json_value
-json_authdata_element(krb5_authdata *ad)
+static krb5_error_code
+json_authdata_element(krb5_authdata *ad, k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
- if (k5_json_array_create(&array))
- return NULL;
- if (add(array, number(ad->ad_type)))
- goto oom;
- if (add(array, base64string(ad->contents, ad->length)))
- goto oom;
- return array;
-oom:
- k5_json_release(array);
- return NULL;
+ *val_out = NULL;
+ ret = k5_json_array_fmt(&array, "iB", ad->ad_type, (void *)ad->contents,
+ (size_t)ad->length);
+ if (ret)
+ return ret;
+ *val_out = array;
+ return 0;
}
/* Return a JSON null or array value representing authdata. */
-static k5_json_value
-json_authdata(krb5_authdata **authdata)
+static krb5_error_code
+json_authdata(krb5_authdata **authdata, k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
+ k5_json_value val;
+ *val_out = NULL;
if (authdata == NULL)
- return null();
- if (k5_json_array_create(&array))
- return NULL;
+ return k5_json_null_create_val(val_out);
+ ret = k5_json_array_create(&array);
+ if (ret)
+ return ret;
for (; *authdata != NULL; authdata++) {
- if (add(array, json_authdata_element(*authdata))) {
- k5_json_release(array);
- return NULL;
- }
+ ret = json_authdata_element(*authdata, &val);
+ if (ret)
+ goto err;
+ ret = k5_json_array_add(array, val);
+ k5_json_release(val);
+ if (ret)
+ goto err;
}
- return array;
+ *val_out = array;
+ return 0;
+err:
+ k5_json_release(array);
+ return ret;
}
/* Return a JSON array value representing creds. */
-static k5_json_value
-json_creds(krb5_context context, krb5_creds *creds)
+static krb5_error_code
+json_creds(krb5_context context, krb5_creds *creds, k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
+ k5_json_value client = NULL, server = NULL, keyblock = NULL, addrs = NULL;
+ k5_json_value authdata = NULL;
+
+ *val_out = NULL;
+ ret = json_principal(context, creds->client, &client);
+ if (ret)
+ goto cleanup;
+ ret = json_principal(context, creds->server, &server);
+ if (ret)
+ goto cleanup;
+ ret = json_keyblock(&creds->keyblock, &keyblock);
+ if (ret)
+ goto cleanup;
+ ret = json_addresses(creds->addresses, &addrs);
+ if (ret)
+ goto cleanup;
+ ret = json_authdata(creds->authdata, &authdata);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_json_array_fmt(&array, "vvviiiibivBBv", client, server, keyblock,
+ creds->times.authtime, creds->times.starttime,
+ creds->times.endtime, creds->times.renew_till,
+ creds->is_skey, creds->ticket_flags, addrs,
+ (void *)creds->ticket.data,
+ (size_t)creds->ticket.length,
+ (void *)creds->second_ticket.data,
+ (size_t)creds->second_ticket.length, authdata);
+ if (ret)
+ goto cleanup;
+ *val_out = array;
- if (k5_json_array_create(&array))
- return NULL;
- if (add(array, json_principal(context, creds->client)))
- goto eom;
- if (add(array, json_principal(context, creds->server)))
- goto eom;
- if (add(array, json_keyblock(&creds->keyblock)))
- goto eom;
- if (add(array, number(creds->times.authtime)))
- goto eom;
- if (add(array, number(creds->times.starttime)))
- goto eom;
- if (add(array, number(creds->times.endtime)))
- goto eom;
- if (add(array, number(creds->times.renew_till)))
- goto eom;
- if (add(array, bool(creds->is_skey)))
- goto eom;
- if (add(array, number(creds->ticket_flags)))
- goto eom;
- if (add(array, json_addresses(creds->addresses)))
- goto eom;
- if (add(array, base64string(creds->ticket.data, creds->ticket.length)))
- goto eom;
- if (add(array, base64string(creds->second_ticket.data,
- creds->second_ticket.length)))
- goto eom;
- if (add(array, json_authdata(creds->authdata)))
- goto eom;
- return array;
-eom:
- k5_json_release(array);
- return NULL;
+cleanup:
+ k5_json_release(client);
+ k5_json_release(server);
+ k5_json_release(keyblock);
+ k5_json_release(addrs);
+ k5_json_release(authdata);
+ return ret;
}
/* Return a JSON array value representing the contents of ccache. */
-static k5_json_value
-json_ccache_contents(krb5_context context, krb5_ccache ccache)
+static krb5_error_code
+json_ccache_contents(krb5_context context, krb5_ccache ccache,
+ k5_json_value *val_out)
{
krb5_error_code ret;
krb5_principal princ;
krb5_cc_cursor cursor;
krb5_creds creds;
k5_json_array array;
- int st;
+ k5_json_value val;
- if (k5_json_array_create(&array))
- return NULL;
+ *val_out = NULL;
+ ret = k5_json_array_create(&array);
+ if (ret)
+ return ret;
/* Put the principal in the first array entry. */
- if (krb5_cc_get_principal(context, ccache, &princ))
+ ret = krb5_cc_get_principal(context, ccache, &princ);
+ if (ret)
goto err;
- st = add(array, json_principal(context, princ));
+ ret = json_principal(context, princ, &val);
krb5_free_principal(context, princ);
- if (st)
+ if (ret)
+ goto err;
+ ret = k5_json_array_add(array, val);
+ k5_json_release(val);
+ if (ret)
goto err;
/* Put credentials in the remaining array entries. */
- if (krb5_cc_start_seq_get(context, ccache, &cursor))
+ ret = krb5_cc_start_seq_get(context, ccache, &cursor);
+ if (ret)
goto err;
while ((ret = krb5_cc_next_cred(context, ccache, &cursor, &creds)) == 0) {
- if (add(array, json_creds(context, &creds))) {
- krb5_free_cred_contents(context, &creds);
- break;
- }
+ ret = json_creds(context, &creds, &val);
krb5_free_cred_contents(context, &creds);
+ if (ret)
+ break;
+ ret = k5_json_array_add(array, val);
+ k5_json_release(val);
+ if (ret)
+ break;
}
krb5_cc_end_seq_get(context, ccache, &cursor);
if (ret != KRB5_CC_END)
goto err;
- return array;
+ *val_out = array;
+ return 0;
err:
k5_json_release(array);
- return NULL;
+ return ret;
}
/* Return a JSON null, string, or array value representing ccache. */
-static k5_json_value
-json_ccache(krb5_context context, krb5_ccache ccache)
+static krb5_error_code
+json_ccache(krb5_context context, krb5_ccache ccache, k5_json_value *val_out)
{
- char *name;
+ krb5_error_code ret;
k5_json_string str;
+ char *name;
+ *val_out = NULL;
if (ccache == NULL)
- return null();
+ return k5_json_null_create_val(val_out);
if (strcmp(krb5_cc_get_type(context, ccache), "MEMORY") == 0) {
- return json_ccache_contents(context, ccache);
+ return json_ccache_contents(context, ccache, val_out);
} else {
- if (krb5_cc_get_full_name(context, ccache, &name))
- return NULL;
- str = string(name);
+ ret = krb5_cc_get_full_name(context, ccache, &name);
+ if (ret)
+ return ret;
+ ret = k5_json_string_create(name, &str);
free(name);
- return str;
+ *val_out = str;
+ return ret;
}
}
/* Return a JSON array value representing cred. */
-static k5_json_value
-json_kgcred(krb5_context context, krb5_gss_cred_id_t cred)
+static krb5_error_code
+json_kgcred(krb5_context context, krb5_gss_cred_id_t cred,
+ k5_json_value *val_out)
{
+ krb5_error_code ret;
k5_json_array array;
+ k5_json_value name = NULL, imp = NULL, keytab = NULL, rcache = NULL;
+ k5_json_value ccache = NULL, ckeytab = NULL, etypes = NULL;
+
+ *val_out = NULL;
+ ret = json_kgname(context, cred->name, &name);
+ if (ret)
+ goto cleanup;
+ ret = json_principal(context, cred->impersonator, &imp);
+ if (ret)
+ goto cleanup;
+ ret = json_keytab(context, cred->keytab, &keytab);
+ if (ret)
+ goto cleanup;
+ ret = json_rcache(context, cred->rcache, &rcache);
+ if (ret)
+ goto cleanup;
+ ret = json_ccache(context, cred->ccache, &ccache);
+ if (ret)
+ goto cleanup;
+ ret = json_keytab(context, cred->client_keytab, &ckeytab);
+ if (ret)
+ goto cleanup;
+ ret = json_etypes(cred->req_enctypes, &etypes);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_json_array_fmt(&array, "ivvbbvvvvbiivs", cred->usage, name, imp,
+ cred->default_identity, cred->iakerb_mech, keytab,
+ rcache, ccache, ckeytab, cred->have_tgt,
+ cred->expire, cred->refresh_time, etypes,
+ cred->password);
+ if (ret)
+ goto cleanup;
+ *val_out = array;
- if (k5_json_array_create(&array))
- return NULL;
- if (add(array, number(cred->usage)))
- goto oom;
- if (add(array, json_kgname(context, cred->name)))
- goto oom;
- if (add(array, json_principal(context, cred->impersonator)))
- goto oom;
- if (add(array, bool(cred->default_identity)))
- goto oom;
- if (add(array, bool(cred->iakerb_mech)))
- goto oom;
- /* Don't marshal cred->destroy_ccache. */
- if (add(array, json_keytab(context, cred->keytab)))
- goto oom;
- if (add(array, json_rcache(context, cred->rcache)))
- goto oom;
- if (add(array, json_ccache(context, cred->ccache)))
- goto oom;
- if (add(array, json_keytab(context, cred->client_keytab)))
- goto oom;
- if (add(array, bool(cred->have_tgt)))
- goto oom;
- if (add(array, number(cred->expire)))
- goto oom;
- if (add(array, number(cred->refresh_time)))
- goto oom;
- if (add(array, json_etypes(cred->req_enctypes)))
- goto oom;
- if (add(array, json_optional_string(cred->password)))
- goto oom;
- return array;
-oom:
- k5_json_release(array);
- return NULL;
+cleanup:
+ k5_json_release(name);
+ k5_json_release(imp);
+ k5_json_release(keytab);
+ k5_json_release(rcache);
+ k5_json_release(ccache);
+ k5_json_release(ckeytab);
+ k5_json_release(etypes);
+ return ret;
}
OM_uint32 KRB5_CALLCONV
@@ -426,6 +439,7 @@ krb5_gss_export_cred(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
krb5_error_code ret;
krb5_gss_cred_id_t cred;
k5_json_array array = NULL;
+ k5_json_value jcred = NULL;
char *str = NULL;
krb5_data d;
@@ -441,13 +455,10 @@ krb5_gss_export_cred(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
return status;
cred = (krb5_gss_cred_id_t)cred_handle;
- if (k5_json_array_create(&array))
- goto oom;
- if (add(array, string(CRED_EXPORT_MAGIC)))
+ if (json_kgcred(context, cred, &jcred))
goto oom;
- if (add(array, json_kgcred(context, cred)))
+ if (k5_json_array_fmt(&array, "sv", CRED_EXPORT_MAGIC, jcred))
goto oom;
-
if (k5_json_encode(array, &str))
goto oom;
d = string2data(str);
@@ -459,6 +470,7 @@ cleanup:
free(str);
k5_mutex_unlock(&cred->lock);
k5_json_release(array);
+ k5_json_release(jcred);
krb5_free_context(context);
return status;