Esempio n. 1
0
/* 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;
}
Esempio n. 2
0
/* Convert a JSON value to a null-terminated authdata list or to NULL. */
static int
json_to_authdata(krb5_context context, k5_json_value v,
                 krb5_authdata ***authdata_out)
{
    k5_json_array array;
    krb5_authdata **authdata = NULL;
    size_t len, i;

    *authdata_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);
    authdata = calloc(len + 1, sizeof(*authdata));
    for (i = 0; i < len; i++) {
        if (json_to_authdata_element(k5_json_array_get(array, i),
                                     &authdata[i]))
            goto invalid;
    }
    authdata[i] = NULL;
    *authdata_out = authdata;
    return 0;

invalid:
    krb5_free_authdata(context, authdata);
    return -1;
}
Esempio n. 3
0
/* Convert a JSON value to a null-terminated list of krb5 addresses or to
 * NULL. */
static int
json_to_addresses(krb5_context context, k5_json_value v,
                  krb5_address ***addresses_out)
{
    k5_json_array array;
    krb5_address **addrs = NULL;
    size_t len, i;

    *addresses_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);
    addrs = calloc(len + 1, sizeof(*addrs));
    for (i = 0; i < len; i++) {
        if (json_to_address(k5_json_array_get(array, i), &addrs[i]))
            goto invalid;
    }
    addrs[i] = NULL;
    *addresses_out = addrs;
    return 0;

invalid:
    krb5_free_addresses(context, addrs);
    return -1;
}
Esempio n. 4
0
/* Converts a JSON object into a krb5_responder_otp_challenge. */
static krb5_responder_otp_challenge *
codec_decode_challenge(krb5_context ctx, const char *json)
{
    krb5_responder_otp_challenge *chl = NULL;
    k5_json_value obj = NULL, arr = NULL, tmp = NULL;
    krb5_error_code retval;
    size_t i;

    retval = k5_json_decode(json, &obj);
    if (retval != 0)
        goto error;

    if (k5_json_get_tid(obj) != K5_JSON_TID_OBJECT)
        goto error;

    arr = k5_json_object_get(obj, "tokenInfo");
    if (arr == NULL)
        goto error;

    if (k5_json_get_tid(arr) != K5_JSON_TID_ARRAY)
        goto error;

    chl = calloc(1, sizeof(krb5_responder_otp_challenge));
    if (chl == NULL)
        goto error;

    chl->tokeninfo = calloc(k5_json_array_length(arr) + 1,
                            sizeof(krb5_responder_otp_tokeninfo*));
    if (chl->tokeninfo == NULL)
        goto error;

    retval = codec_value_to_string(obj, "service", &chl->service);
    if (retval != 0 && retval != ENOENT)
        goto error;

    for (i = 0; i < k5_json_array_length(arr); i++) {
        tmp = k5_json_array_get(arr, i);
        if (k5_json_get_tid(tmp) != K5_JSON_TID_OBJECT)
            goto error;

        chl->tokeninfo[i] = codec_decode_tokeninfo(tmp);
        if (chl->tokeninfo[i] == NULL)
            goto error;
    }

    k5_json_release(obj);
    return chl;

error:
    if (chl != NULL) {
        for (i = 0; chl->tokeninfo != NULL && chl->tokeninfo[i] != NULL; i++)
            free_tokeninfo(chl->tokeninfo[i]);
        free(chl->tokeninfo);
        free(chl);
    }
    k5_json_release(obj);
    return NULL;
}
Esempio n. 5
0
/* 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;
}
Esempio n. 6
0
/* 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;
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
/* 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;
}
Esempio n. 10
0
/* Return the idx element of array if it is of type tid; otherwise return
 * NULL.  The caller is responsible for checking the array length. */
static k5_json_value
check_element(k5_json_array array, size_t idx, k5_json_tid tid)
{
    k5_json_value v;

    v = k5_json_array_get(array, idx);
    return (k5_json_get_tid(v) == tid) ? v : NULL;
}
Esempio n. 11
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
/* Convert a JSON value to a krb5 GSS name or to NULL. */
static int
json_to_kgname(krb5_context context, k5_json_value v,
               krb5_gss_name_t *name_out)
{
    k5_json_array array;
    krb5_gss_name_t name = NULL;

    *name_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;
    if (k5_json_array_length(array) != 3)
        return -1;
    name = calloc(1, sizeof(*name));
    if (name == NULL)
        return -1;
    if (k5_mutex_init(&name->lock)) {
        free(name);
        return -1;
    }

    if (json_to_principal(context, k5_json_array_get(array, 0), &name->princ))
        goto invalid;
    if (json_to_optional_string(k5_json_array_get(array, 1), &name->service))
        goto invalid;
    if (json_to_optional_string(k5_json_array_get(array, 2), &name->host))
        goto invalid;

    *name_out = name;
    return 0;

invalid:
    kg_release_name(context, &name);
    return -1;
}
Esempio n. 14
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;
}
Esempio n. 15
0
/* Decode the responder answer into a tokeninfo, a value and a pin. */
static krb5_error_code
codec_decode_answer(krb5_context context, const char *answer,
                    krb5_otp_tokeninfo **tis, krb5_otp_tokeninfo **ti,
                    krb5_data *value, krb5_data *pin)
{
    krb5_error_code retval;
    k5_json_value val = NULL;
    krb5_int32 indx, i;
    krb5_data tmp;

    if (answer == NULL)
        return EBADMSG;

    retval = k5_json_decode(answer, &val);
    if (retval != 0)
        goto cleanup;

    if (k5_json_get_tid(val) != K5_JSON_TID_OBJECT)
        goto cleanup;

    retval = codec_value_to_int32(val, "tokeninfo", &indx);
    if (retval != 0)
        goto cleanup;

    for (i = 0; tis[i] != NULL; i++) {
        if (i == indx) {
            retval = codec_value_to_data(val, "value", &tmp);
            if (retval != 0 && retval != ENOENT)
                goto cleanup;

            retval = codec_value_to_data(val, "pin", pin);
            if (retval != 0 && retval != ENOENT) {
                krb5_free_data_contents(context, &tmp);
                goto cleanup;
            }

            *value = tmp;
            *ti = tis[i];
            retval = 0;
            goto cleanup;
        }
    }
    retval = EINVAL;

cleanup:
    k5_json_release(val);
    return retval;
}
Esempio n. 16
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;
}
Esempio n. 17
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;
}
Esempio n. 18
0
/* 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;
}