/* Convert a JSON value to a zero-terminated enctypes list or to NULL. */ static int json_to_etypes(k5_json_value v, krb5_enctype **etypes_out) { krb5_enctype *etypes = NULL; k5_json_array array; k5_json_number n; size_t len, i; *etypes_out = NULL; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; len = k5_json_array_length(array); etypes = calloc(len + 1, sizeof(*etypes)); for (i = 0; i < len; i++) { n = check_element(array, i, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; etypes[i] = k5_json_number_value(n); } *etypes_out = etypes; return 0; invalid: free(etypes); return -1; }
/* Convert a JSON value to a keyblock, filling in keyblock. */ static int json_to_keyblock(k5_json_value v, krb5_keyblock *keyblock) { k5_json_array array; k5_json_number n; k5_json_string s; size_t len; memset(keyblock, 0, sizeof(*keyblock)); if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; if (k5_json_array_length(array) != 2) return -1; n = check_element(array, 0, K5_JSON_TID_NUMBER); if (n == NULL) return -1; keyblock->enctype = k5_json_number_value(n); s = check_element(array, 1, K5_JSON_TID_STRING); if (s == NULL) return -1; if (k5_json_string_unbase64(s, &keyblock->contents, &len)) return -1; keyblock->length = len; keyblock->magic = KV5M_KEYBLOCK; return 0; }
/* Converts a property of a json object into a krb5_int32. */ static krb5_error_code codec_value_to_int32(k5_json_object obj, const char *key, krb5_int32 *int32) { k5_json_value val; val = k5_json_object_get(obj, key); if (val == NULL) return ENOENT; if (k5_json_get_tid(val) != K5_JSON_TID_NUMBER) return EINVAL; *int32 = k5_json_number_value(val); return 0; }
/* Convert a JSON value to an authdata element. */ static int json_to_authdata_element(k5_json_value v, krb5_authdata **ad_out) { k5_json_array array; krb5_authdata *ad = NULL; k5_json_number n; k5_json_string s; size_t len; *ad_out = NULL; if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; if (k5_json_array_length(array) != 2) return -1; n = check_element(array, 0, K5_JSON_TID_NUMBER); if (n == NULL) return -1; s = check_element(array, 1, K5_JSON_TID_STRING); if (s == NULL) return -1; ad = malloc(sizeof(*ad)); if (ad == NULL) return -1; ad->ad_type = k5_json_number_value(n); if (k5_json_string_unbase64(s, &ad->contents, &len)) { free(ad); return -1; } ad->length = len; ad->magic = KV5M_AUTHDATA; *ad_out = ad; return 0; }
/* Convert a JSON array value to a krb5 GSS credential. */ static int json_to_kgcred(krb5_context context, k5_json_array array, krb5_gss_cred_id_t *cred_out) { krb5_gss_cred_id_t cred; k5_json_number n; k5_json_bool b; krb5_boolean is_new; OM_uint32 tmp; *cred_out = NULL; if (k5_json_array_length(array) != 14) return -1; cred = calloc(1, sizeof(*cred)); if (cred == NULL) return -1; if (k5_mutex_init(&cred->lock)) { free(cred); return -1; } n = check_element(array, 0, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; cred->usage = k5_json_number_value(n); if (json_to_kgname(context, k5_json_array_get(array, 1), &cred->name)) goto invalid; if (json_to_principal(context, k5_json_array_get(array, 2), &cred->impersonator)) goto invalid; b = check_element(array, 3, K5_JSON_TID_BOOL); if (b == NULL) goto invalid; cred->default_identity = k5_json_bool_value(b); b = check_element(array, 4, K5_JSON_TID_BOOL); if (b == NULL) goto invalid; cred->iakerb_mech = k5_json_bool_value(b); if (json_to_keytab(context, k5_json_array_get(array, 5), &cred->keytab)) goto invalid; if (json_to_rcache(context, k5_json_array_get(array, 6), &cred->rcache)) goto invalid; if (json_to_ccache(context, k5_json_array_get(array, 7), &cred->ccache, &is_new)) goto invalid; cred->destroy_ccache = is_new; if (json_to_keytab(context, k5_json_array_get(array, 8), &cred->client_keytab)) goto invalid; b = check_element(array, 9, K5_JSON_TID_BOOL); if (b == NULL) goto invalid; cred->have_tgt = k5_json_bool_value(b); n = check_element(array, 10, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; cred->expire = k5_json_number_value(n); n = check_element(array, 11, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; cred->refresh_time = k5_json_number_value(n); if (json_to_etypes(k5_json_array_get(array, 12), &cred->req_enctypes)) goto invalid; if (json_to_optional_string(k5_json_array_get(array, 13), &cred->password)) goto invalid; *cred_out = cred; return 0; invalid: (void)krb5_gss_release_cred(&tmp, (gss_cred_id_t *)&cred); return -1; }
/* Convert a JSON value to a krb5 credential structure, filling in creds. */ static int json_to_creds(krb5_context context, k5_json_value v, krb5_creds *creds) { k5_json_array array; k5_json_number n; k5_json_bool b; k5_json_string s; unsigned char *data; size_t len; memset(creds, 0, sizeof(*creds)); if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; if (k5_json_array_length(array) != 13) return -1; if (json_to_principal(context, k5_json_array_get(array, 0), &creds->client)) goto invalid; if (json_to_principal(context, k5_json_array_get(array, 1), &creds->server)) goto invalid; if (json_to_keyblock(k5_json_array_get(array, 2), &creds->keyblock)) goto invalid; n = check_element(array, 3, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; creds->times.authtime = k5_json_number_value(n); n = check_element(array, 4, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; creds->times.starttime = k5_json_number_value(n); n = check_element(array, 5, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; creds->times.endtime = k5_json_number_value(n); n = check_element(array, 6, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; creds->times.renew_till = k5_json_number_value(n); b = check_element(array, 7, K5_JSON_TID_BOOL); if (b == NULL) goto invalid; creds->is_skey = k5_json_bool_value(b); n = check_element(array, 8, K5_JSON_TID_NUMBER); if (n == NULL) goto invalid; creds->ticket_flags = k5_json_number_value(n); if (json_to_addresses(context, k5_json_array_get(array, 9), &creds->addresses)) goto invalid; s = check_element(array, 10, K5_JSON_TID_STRING); if (s == NULL) goto invalid; if (k5_json_string_unbase64(s, &data, &len)) goto invalid; creds->ticket.data = (char *)data; creds->ticket.length = len; s = check_element(array, 11, K5_JSON_TID_STRING); if (s == NULL) goto invalid; if (k5_json_string_unbase64(s, &data, &len)) goto invalid; creds->second_ticket.data = (char *)data; creds->second_ticket.length = len; if (json_to_authdata(context, k5_json_array_get(array, 12), &creds->authdata)) goto invalid; creds->magic = KV5M_CREDS; return 0; invalid: krb5_free_cred_contents(context, creds); memset(creds, 0, sizeof(*creds)); return -1; }