/* Convert a JSON value to a ccache handle or to NULL. Set *new_out to true if * the ccache handle is a newly created memory ccache, false otherwise. */ static int json_to_ccache(krb5_context context, k5_json_value v, krb5_ccache *ccache_out, krb5_boolean *new_out) { krb5_error_code ret; krb5_ccache ccache = NULL; krb5_principal princ; krb5_creds creds; k5_json_array array; size_t i, len; *ccache_out = NULL; *new_out = FALSE; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) == K5_JSON_TID_STRING) { /* We got a reference to an external ccache; just resolve it. */ return krb5_cc_resolve(context, k5_json_string_utf8(v), ccache_out) ? -1 : 0; } /* We got the contents of a memory ccache. */ if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) return -1; array = v; len = k5_json_array_length(array); if (len < 1) return -1; /* Initialize a new memory ccache using the principal in the first array * entry.*/ if (krb5_cc_new_unique(context, "MEMORY", NULL, &ccache)) return -1; if (json_to_principal(context, k5_json_array_get(array, 0), &princ)) goto invalid; ret = krb5_cc_initialize(context, ccache, princ); krb5_free_principal(context, princ); if (ret) goto invalid; /* Add remaining array entries to the ccache as credentials. */ for (i = 1; i < len; i++) { if (json_to_creds(context, k5_json_array_get(array, 1), &creds)) goto invalid; ret = krb5_cc_store_cred(context, ccache, &creds); krb5_free_cred_contents(context, &creds); if (ret) goto invalid; } *ccache_out = ccache; *new_out = TRUE; return 0; invalid: (void)krb5_cc_destroy(context, ccache); return -1; }
OM_uint32 KRB5_CALLCONV krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token, gss_cred_id_t *cred_handle) { OM_uint32 status = GSS_S_COMPLETE; krb5_context context; krb5_error_code ret; krb5_gss_cred_id_t cred; k5_json_value v = NULL; k5_json_array array; k5_json_string str; char *copy = NULL; ret = krb5_gss_init_context(&context); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } /* Decode token. */ copy = k5memdup0(token->value, token->length, &ret); if (copy == NULL) { status = GSS_S_FAILURE; *minor_status = ret; goto cleanup; } if (k5_json_decode(copy, &v)) goto invalid; /* Decode the CRED_EXPORT_MAGIC array wrapper. */ if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) goto invalid; array = v; if (k5_json_array_length(array) != 2) goto invalid; str = check_element(array, 0, K5_JSON_TID_STRING); if (str == NULL || strcmp(k5_json_string_utf8(str), CRED_EXPORT_MAGIC) != 0) goto invalid; if (json_to_kgcred(context, k5_json_array_get(array, 1), &cred)) goto invalid; *cred_handle = (gss_cred_id_t)cred; cleanup: free(copy); k5_json_release(v); krb5_free_context(context); return status; invalid: status = GSS_S_DEFECTIVE_TOKEN; goto cleanup; }
/* Convert a JSON value to a C string or to NULL. */ static int json_to_optional_string(k5_json_value v, char **string_out) { *string_out = NULL; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) != K5_JSON_TID_STRING) return -1; *string_out = strdup(k5_json_string_utf8(v)); return (*string_out == NULL) ? -1 : 0; }
/* Convert a JSON value to a keytab handle or to NULL. */ static int json_to_keytab(krb5_context context, k5_json_value v, krb5_keytab *keytab_out) { *keytab_out = NULL; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) != K5_JSON_TID_STRING) return -1; if (krb5_kt_resolve(context, k5_json_string_utf8(v), keytab_out)) return -1; return 0; }
/* Convert a JSON value to a principal or to NULL. */ static int json_to_principal(krb5_context context, k5_json_value v, krb5_principal *princ_out) { *princ_out = NULL; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) != K5_JSON_TID_STRING) return -1; if (krb5_parse_name(context, k5_json_string_utf8(v), princ_out)) return -1; return 0; }
/* Convert a JSON value to an rcache handle or to NULL. */ static int json_to_rcache(krb5_context context, k5_json_value v, krb5_rcache *rcache_out) { krb5_rcache rcache; *rcache_out = NULL; if (k5_json_get_tid(v) == K5_JSON_TID_NULL) return 0; if (k5_json_get_tid(v) != K5_JSON_TID_STRING) return -1; if (krb5_rc_resolve_full(context, &rcache, (char *)k5_json_string_utf8(v))) return -1; if (krb5_rc_recover_or_initialize(context, rcache, context->clockskew)) { krb5_rc_close(context, rcache); return -1; } *rcache_out = rcache; return 0; }
/* Converts a property of a json object into a char*. */ static krb5_error_code codec_value_to_string(k5_json_object obj, const char *key, char **string) { k5_json_value val; char *str; val = k5_json_object_get(obj, key); if (val == NULL) return ENOENT; if (k5_json_get_tid(val) != K5_JSON_TID_STRING) return EINVAL; str = strdup(k5_json_string_utf8(val)); if (str == NULL) return ENOMEM; *string = str; return 0; }