예제 #1
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_remove_lookaside_multiple(void **state)
{
    struct entry *e1;
    krb5_context context = *state;
    krb5_data req1 = string2data("I'm a test request");
    krb5_data rep1 = string2data("I'm a test response");
    krb5_data req2 = string2data("I'm a different test request");

    e1 = insert_entry(context, &req1, &rep1, 0);
    insert_entry(context, &req2, NULL, 0);

    kdc_remove_lookaside(context, &req2);

    assert_null(k5_hashtab_get(hash_table, req2.data, req2.length));
    assert_ptr_equal(k5_hashtab_get(hash_table, req1.data, req1.length), e1);
    assert_int_equal(num_entries, 1);
    assert_int_equal(total_size, entry_size(&req1, &rep1));

    kdc_remove_lookaside(context, &req1);

    assert_null(k5_hashtab_get(hash_table, req1.data, req1.length));
    assert_int_equal(num_entries, 0);
    assert_int_equal(total_size, 0);
}
예제 #2
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_check_lookaside_hit_multiple(void **state)
{
    struct entry *e1, *e2;
    krb5_boolean result;
    krb5_data *result_data;
    krb5_context context = *state;
    krb5_data req1 = string2data("I'm a test request");
    krb5_data rep1 = string2data("I'm a test response");
    krb5_data req2 = string2data("I'm a different test request");

    e1 = insert_entry(context, &req1, &rep1, 0);
    e2 = insert_entry(context, &req2, NULL, 0);

    result = kdc_check_lookaside(context, &req1, &result_data);

    assert_true(result);
    assert_true(data_eq(rep1, *result_data));
    assert_int_equal(hits, 1);
    assert_int_equal(e1->num_hits, 1);
    assert_int_equal(e2->num_hits, 0);

    krb5_free_data(context, result_data);

    /* Set result_data so we can verify that it is reset to NULL. */
    result_data = &req1;
    result = kdc_check_lookaside(context, &req2, &result_data);

    assert_true(result);
    assert_null(result_data);
    assert_int_equal(hits, 2);
    assert_int_equal(e1->num_hits, 1);
    assert_int_equal(e2->num_hits, 1);
}
예제 #3
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_insert_entry_multiple(void **state)
{
    struct entry *e1, *e2;
    krb5_context context = *state;
    krb5_data req1 = string2data("I'm a test request");
    krb5_data rep1 = string2data("I'm a test response");
    krb5_data req2 = string2data("I'm a different test request");

    e1 = insert_entry(context, &req1, &rep1, 20);

    assert_ptr_equal(k5_hashtab_get(hash_table, req1.data, req1.length), e1);
    assert_ptr_equal(K5_TAILQ_FIRST(&expiration_queue), e1);
    assert_true(data_eq(e1->req_packet, req1));
    assert_true(data_eq(e1->reply_packet, rep1));
    assert_int_equal(e1->timein, 20);

    e2 = insert_entry(context, &req2, NULL, 30);

    assert_ptr_equal(k5_hashtab_get(hash_table, req2.data, req2.length), e2);
    assert_ptr_equal(K5_TAILQ_LAST(&expiration_queue,entry_queue), e2);
    assert_true(data_eq(e2->req_packet, req2));
    assert_int_equal(e2->reply_packet.length, 0);
    assert_int_equal(e2->timein, 30);
}
예제 #4
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_entry_size_w_response(void **state)
{
    size_t result;
    const krb5_data req = string2data("I'm a test request");
    const krb5_data rep = string2data("I'm a test response");

    result = entry_size(&req, &rep);
    assert_int_equal(result, sizeof(struct entry) + 18 + 19);
}
예제 #5
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_remove_lookaside(void **state)
{
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");
    krb5_data rep = string2data("I'm a test response");

    insert_entry(context, &req, &rep, 0);
    kdc_remove_lookaside(context, &req);

    assert_null(k5_hashtab_get(hash_table, req.data, req.length));
    assert_int_equal(num_entries, 0);
    assert_int_equal(total_size, 0);
}
예제 #6
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_discard_entry(void **state)
{
    struct entry *e;
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");
    krb5_data rep = string2data("I'm a test response");

    e = insert_entry(context, &req, &rep, 0);
    discard_entry(context, e);

    assert_null(k5_hashtab_get(hash_table, req.data, req.length));
    assert_int_equal(num_entries, 0);
    assert_int_equal(total_size, 0);
}
예제 #7
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_insert_entry(void **state)
{
    struct entry *e;
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");
    krb5_data rep = string2data("I'm a test response");

    e = insert_entry(context, &req, &rep, 15);

    assert_ptr_equal(k5_hashtab_get(hash_table, req.data, req.length), e);
    assert_ptr_equal(K5_TAILQ_FIRST(&expiration_queue), e);
    assert_true(data_eq(e->req_packet, req));
    assert_true(data_eq(e->reply_packet, rep));
    assert_int_equal(e->timein, 15);
}
예제 #8
0
/*
 * Set up cred to be an S4U2Proxy credential by copying in the impersonator's
 * creds, setting a cache config variable with the impersonator principal name,
 * and saving the impersonator principal name in the cred structure.
 */
static krb5_error_code
make_proxy_cred(krb5_context context, krb5_gss_cred_id_t cred,
                krb5_gss_cred_id_t impersonator_cred)
{
    krb5_error_code code;
    krb5_data data;
    char *str;

    code = krb5_cc_copy_creds(context, impersonator_cred->ccache,
                              cred->ccache);
    if (code)
        return code;

    code = krb5_unparse_name(context, impersonator_cred->name->princ, &str);
    if (code)
        return code;

    data = string2data(str);
    code = krb5_cc_set_config(context, cred->ccache, NULL,
                              KRB5_CONF_PROXY_IMPERSONATOR, &data);
    krb5_free_unparsed_name(context, str);
    if (code)
        return code;

    return krb5_copy_principal(context, impersonator_cred->name->princ,
                               &cred->impersonator);
}
예제 #9
0
static krb5_error_code
prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
                  int error, krb5_pa_data **e_data, krb5_boolean typed_e_data,
                  krb5_principal canon_client, krb5_data **response,
                  const char *status)
{
    krb5_error errpkt;
    krb5_error_code retval;
    krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
    kdc_realm_t *kdc_active_realm = rstate->realm_data;

    errpkt.ctime = request->nonce;
    errpkt.cusec = 0;

    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
    if (retval)
        return retval;
    errpkt.error = error;
    errpkt.server = request->server;
    errpkt.client = (error == KRB5KDC_ERR_WRONG_REALM) ? canon_client :
        request->client;
    errpkt.text = string2data((char *)status);

    if (e_data != NULL) {
        if (typed_e_data)
            retval = encode_krb5_typed_data(e_data, &e_data_asn1);
        else
            retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
        if (retval)
            goto cleanup;
        errpkt.e_data = *e_data_asn1;
    } else
        errpkt.e_data = empty_data();

    retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
                                   &errpkt, &fast_edata);
    if (retval)
        goto cleanup;
    if (fast_edata != NULL)
        errpkt.e_data = *fast_edata;

    scratch = k5alloc(sizeof(*scratch), &retval);
    if (scratch == NULL)
        goto cleanup;
    if (kdc_fast_hide_client(rstate) && errpkt.client != NULL)
        errpkt.client = (krb5_principal)krb5_anonymous_principal();
    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
    if (retval)
        goto cleanup;

    *response = scratch;
    scratch = NULL;

cleanup:
    krb5_free_data(kdc_context, fast_edata);
    krb5_free_data(kdc_context, e_data_asn1);
    free(scratch);
    return retval;
}
예제 #10
0
파일: parse.c 프로젝트: irush-cs/krb5
krb5_error_code KRB5_CALLCONV
krb5_parse_name_flags(krb5_context context, const char *name,
                      int flags, krb5_principal *principal_out)
{
    krb5_error_code ret;
    krb5_principal princ = NULL;
    char *default_realm;
    krb5_boolean has_realm;
    krb5_boolean enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE);
    krb5_boolean require_realm = (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM);
    krb5_boolean no_realm = (flags & KRB5_PRINCIPAL_PARSE_NO_REALM);
    krb5_boolean ignore_realm = (flags & KRB5_PRINCIPAL_PARSE_IGNORE_REALM);

    *principal_out = NULL;

    ret = allocate_princ(context, name, enterprise, &princ, &has_realm);
    if (ret)
        goto cleanup;
    parse_name_into_princ(name, enterprise, princ);

    /*
     * If a realm was not found, then use the default realm, unless
     * KRB5_PRINCIPAL_PARSE_NO_REALM was specified in which case the
     * realm will be empty.
     */
    if (!has_realm) {
        if (require_realm) {
            ret = KRB5_PARSE_MALFORMED;
            krb5_set_error_message(context, ret,
                                   _("Principal %s is missing required realm"),
                                   name);
            goto cleanup;
        }
        if (!no_realm && !ignore_realm) {
            ret = krb5_get_default_realm(context, &default_realm);
            if (ret)
                goto cleanup;
            princ->realm = string2data(default_realm);
        }
    } else if (no_realm) {
        ret = KRB5_PARSE_MALFORMED;
        krb5_set_error_message(context, ret,
                               _("Principal %s has realm present"), name);
        goto cleanup;
    } else if (ignore_realm) {
        krb5_free_data_contents(context, &princ->realm);
        princ->realm = empty_data();
    }

    princ->type = (enterprise) ? KRB5_NT_ENTERPRISE_PRINCIPAL :
        KRB5_NT_PRINCIPAL;
    princ->magic = KV5M_PRINCIPAL;
    *principal_out = princ;
    princ = NULL;

cleanup:
    krb5_free_principal(context, princ);
    return ret;
}
예제 #11
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_insert_lookaside_cache_expire(void **state)
{
    struct entry *e;
    krb5_context context = *state;
    krb5_data req1 = string2data("I'm a test request");
    krb5_data rep1 = string2data("I'm a test response");
    size_t e1_size = entry_size(&req1, &rep1);
    krb5_data req2 = string2data("I'm a different test request");
    size_t e2_size = entry_size(&req2, NULL);
    struct entry *hash1_ent, *hash2_ent, *exp_ent;

    time_return(0, 0);
    kdc_insert_lookaside(context, &req1, &rep1);

    hash1_ent = k5_hashtab_get(hash_table, req1.data, req1.length);
    assert_non_null(hash1_ent);
    assert_true(data_eq(hash1_ent->req_packet, req1));
    assert_true(data_eq(hash1_ent->reply_packet, rep1));
    exp_ent = K5_TAILQ_FIRST(&expiration_queue);
    assert_true(data_eq(exp_ent->req_packet, req1));
    assert_true(data_eq(exp_ent->reply_packet, rep1));
    assert_int_equal(num_entries, 1);
    assert_int_equal(total_size, e1_size);

    /* Increase hits on entry */
    e = k5_hashtab_get(hash_table, req1.data, req1.length);
    assert_non_null(e);
    e->num_hits = 5;

    time_return(STALE_TIME + 1, 0);
    kdc_insert_lookaside(context, &req2, NULL);

    assert_null(k5_hashtab_get(hash_table, req1.data, req1.length));
    assert_int_equal(max_hits_per_entry, 5);

    hash2_ent = k5_hashtab_get(hash_table, req2.data, req2.length);
    assert_non_null(hash2_ent);
    assert_true(data_eq(hash2_ent->req_packet, req2));
    assert_int_equal(hash2_ent-> reply_packet.length, 0);
    exp_ent = K5_TAILQ_FIRST(&expiration_queue);
    assert_true(data_eq(exp_ent->req_packet, req2));
    assert_int_equal(exp_ent->reply_packet.length, 0);
    assert_int_equal(num_entries, 1);
    assert_int_equal(total_size, e2_size);
}
예제 #12
0
파일: s2k_pbkdf2.c 프로젝트: INNOAUS/krb5
krb5_error_code
krb5int_aes2_string_to_key(const struct krb5_keytypes *ktp,
                           const krb5_data *string, const krb5_data *salt,
                           const krb5_data *params, krb5_keyblock *key)
{
    krb5_data pepper = string2data(ktp->name);

    return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key,
                                DERIVE_SP800_108_HMAC, 32768);
}
예제 #13
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_remove_lookaside_empty_cache(void **state)
{
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");

    assert_int_equal(num_entries, 0);
    kdc_remove_lookaside(context, &req);

    assert_int_equal(num_entries, 0);
    assert_int_equal(total_size, 0);
}
예제 #14
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_check_lookaside_hit(void **state)
{
    struct entry *e;
    krb5_boolean result;
    krb5_data *result_data;
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");
    krb5_data rep = string2data("I'm a test response");

    e = insert_entry(context, &req, &rep, 0);

    result = kdc_check_lookaside(context, &req, &result_data);

    assert_true(result);
    assert_true(data_eq(rep, *result_data));
    assert_int_equal(hits, 1);
    assert_int_equal(e->num_hits, 1);

    krb5_free_data(context, result_data);
}
예제 #15
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_insert_lookaside_single(void **state)
{
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");
    krb5_data rep = string2data("I'm a test response");
    struct entry *hash_ent, *exp_ent;

    time_return(0, 0);
    kdc_insert_lookaside(context, &req, &rep);

    hash_ent = k5_hashtab_get(hash_table, req.data, req.length);
    assert_non_null(hash_ent);
    assert_true(data_eq(hash_ent->req_packet, req));
    assert_true(data_eq(hash_ent->reply_packet, rep));
    exp_ent = K5_TAILQ_FIRST(&expiration_queue);
    assert_true(data_eq(exp_ent->req_packet, req));
    assert_true(data_eq(exp_ent->reply_packet, rep));
    assert_int_equal(num_entries, 1);
    assert_int_equal(total_size, entry_size(&req, &rep));
}
예제 #16
0
파일: preauth_otp.c 프로젝트: Akasurde/krb5
/* Converts a property of a json object into a krb5_data struct. */
static krb5_error_code
codec_value_to_data(k5_json_object obj, const char *key, krb5_data *data)
{
    krb5_error_code retval;
    char *tmp;

    retval = codec_value_to_string(obj, key, &tmp);
    if (retval != 0)
        return retval;

    *data = string2data(tmp);
    return 0;
}
예제 #17
0
파일: t_cc_config.c 프로젝트: WeiY/krb5
int
main(int argc, char **argv)
{
    krb5_context context;
    krb5_principal server;
    krb5_ccache ccache;
    krb5_data data;
    krb5_error_code ret;
    char *perr;
    int c;
    unsigned int i;

    bail_on_err(NULL, "Error initializing Kerberos library",
                krb5_init_context(&context));
    bail_on_err(context, "Error getting location of default ccache",
                krb5_cc_default(context, &ccache));
    server = NULL;
    while ((c = getopt(argc, argv, "p:")) != -1) {
        switch (c) {
        case 'p':
            if (asprintf(&perr, "Error parsing principal name \"%s\"",
                         optarg) < 0)
                perr = "Error parsing principal name";
            bail_on_err(context, perr,
                        krb5_parse_name(context, optarg, &server));
            break;
        }
    }
    if (argc - optind < 1 || argc - optind > 2) {
        fprintf(stderr, "Usage: %s [-p principal] key [value]\n", argv[0]);
        return 1;
    }
    memset(&data, 0, sizeof(data));
    if (argc - optind == 2) {
        unset_config(context, ccache, server, argv[optind]);
        data = string2data(argv[optind + 1]);
        bail_on_err(context, "Error adding configuration data to ccache",
                    krb5_cc_set_config(context, ccache, server, argv[optind],
                                       &data));
    } else {
        ret = krb5_cc_get_config(context, ccache, server, argv[optind], &data);
        if (ret == 0) {
            for (i = 0; i < data.length; i++)
                putc((unsigned int)data.data[i], stdout);
        }
    }
    krb5_free_principal(context, server);
    krb5_cc_close(context, ccache);
    krb5_free_context(context);
    return 0;
}
예제 #18
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_check_lookaside_no_hit(void **state)
{
    krb5_boolean result;
    krb5_data *result_data;
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");

    result = kdc_check_lookaside(context, &req, &result_data);

    assert_false(result);
    assert_null(result_data);
    assert_int_equal(hits, 0);
}
예제 #19
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_insert_lookaside_multiple(void **state)
{
    krb5_context context = *state;
    krb5_data req1 = string2data("I'm a test request");
    krb5_data rep1 = string2data("I'm a test response");
    size_t e1_size = entry_size(&req1, &rep1);
    krb5_data req2 = string2data("I'm a different test request");
    size_t e2_size = entry_size(&req2, NULL);
    struct entry *hash1_ent, *hash2_ent, *exp_first, *exp_last;

    time_return(0, 0);
    kdc_insert_lookaside(context, &req1, &rep1);

    hash1_ent = k5_hashtab_get(hash_table, req1.data, req1.length);
    assert_non_null(hash1_ent);
    assert_true(data_eq(hash1_ent->req_packet, req1));
    assert_true(data_eq(hash1_ent->reply_packet, rep1));
    exp_first = K5_TAILQ_FIRST(&expiration_queue);
    assert_true(data_eq(exp_first->req_packet, req1));
    assert_true(data_eq(exp_first->reply_packet, rep1));
    assert_int_equal(num_entries, 1);
    assert_int_equal(total_size, e1_size);

    time_return(0, 0);
    kdc_insert_lookaside(context, &req2, NULL);

    hash2_ent = k5_hashtab_get(hash_table, req2.data, req2.length);
    assert_non_null(hash2_ent);
    assert_true(data_eq(hash2_ent->req_packet, req2));
    assert_int_equal(hash2_ent->reply_packet.length, 0);
    exp_last = K5_TAILQ_LAST(&expiration_queue, entry_queue);
    assert_true(data_eq(exp_last->req_packet, req2));
    assert_int_equal(exp_last->reply_packet.length, 0);
    assert_int_equal(num_entries, 2);
    assert_int_equal(total_size, e1_size + e2_size);
}
예제 #20
0
파일: t_attr.c 프로젝트: Akasurde/krb5
int
main()
{
    unsigned char outbuf[MAX_ATTRSETSIZE];
    const char *decoded = "accept";
    const char *secret = "foo";
    krb5_error_code retval;
    krb5_context ctx;
    const char *tmp;
    krb5_data in;
    size_t len;

    noerror(krb5_init_context(&ctx));

    /* Make sure User-Name is 1. */
    insist(krad_attr_name2num("User-Name") == 1);

    /* Make sure 2 is User-Password. */
    tmp = krad_attr_num2name(2);
    insist(tmp != NULL);
    insist(strcmp(tmp, "User-Password") == 0);

    /* Test decoding. */
    in = make_data((void *)encoded, sizeof(encoded));
    noerror(kr_attr_decode(ctx, secret, auth,
                           krad_attr_name2num("User-Password"),
                           &in, outbuf, &len));
    insist(len == strlen(decoded));
    insist(memcmp(outbuf, decoded, len) == 0);

    /* Test encoding. */
    in = string2data((char *)decoded);
    retval = kr_attr_encode(ctx, secret, auth,
                            krad_attr_name2num("User-Password"),
                            &in, outbuf, &len);
    insist(retval == 0);
    insist(len == sizeof(encoded));
    insist(memcmp(outbuf, encoded, len) == 0);

    /* Test constraint. */
    in.length = 100;
    insist(kr_attr_valid(krad_attr_name2num("User-Password"), &in) == 0);
    in.length = 200;
    insist(kr_attr_valid(krad_attr_name2num("User-Password"), &in) != 0);

    krb5_free_context(ctx);
    return 0;
}
예제 #21
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_check_lookaside_empty(void **state)
{
    krb5_boolean result;
    krb5_data *result_data;
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");

    /* Set result_data so we can verify that it is reset to NULL. */
    result_data = &req;
    result = kdc_check_lookaside(context, &req, &result_data);

    assert_false(result);
    assert_null(result_data);
    assert_int_equal(hits, 0);
}
예제 #22
0
파일: fast_util.c 프로젝트: Akasurde/krb5
/*
 * Construct the secure cookie encryption key for the given local-realm TGT
 * entry, kvno, and client principal.  The cookie key is derived from the first
 * TGT key for the given kvno, using the concatenation of "COOKIE" and the
 * unparsed client principal name as input.  If kvno is 0, the highest current
 * kvno of the TGT is used.  If kvno_out is not null, *kvno_out is set to the
 * kvno used.
 */
static krb5_error_code
get_cookie_key(krb5_context context, krb5_db_entry *tgt, krb5_kvno kvno,
               krb5_const_principal client_princ, krb5_keyblock **key_out,
               krb5_kvno *kvno_out)
{
    krb5_error_code ret;
    krb5_key_data *kd;
    krb5_keyblock kb;
    krb5_data d;
    krb5_int32 start = 0;
    char *princstr = NULL, *derive_input = NULL;

    *key_out = NULL;
    memset(&kb, 0, sizeof(kb));

    /* Find the first krbtgt key with the specified kvno. */
    ret = krb5_dbe_search_enctype(context, tgt, &start, -1, -1, kvno, &kd);
    if (ret)
        goto cleanup;

    /* Decrypt the key. */
    ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL);
    if (ret)
        goto cleanup;

    /* Construct the input string and derive the cookie key. */
    ret = krb5_unparse_name(context, client_princ, &princstr);
    if (ret)
        goto cleanup;
    if (asprintf(&derive_input, "COOKIE%s", princstr) < 0) {
        ret = ENOMEM;
        goto cleanup;
    }
    d = string2data(derive_input);
    ret = krb5_c_derive_prfplus(context, &kb, &d, ENCTYPE_NULL, key_out);

    if (kvno_out != NULL)
        *kvno_out = kd->key_data_kvno;

cleanup:
    krb5_free_keyblock_contents(context, &kb);
    krb5_free_unparsed_name(context, princstr);
    free(derive_input);
    return ret;
}
예제 #23
0
파일: get_creds.c 프로젝트: davidben/krb5
/* Possibly try a non-referral request after a referral request failure.
 * Expects ctx->reply_code to be set to the error from a referral request. */
static krb5_error_code
try_fallback(krb5_context context, krb5_tkt_creds_context ctx)
{
    krb5_error_code code;
    char **hrealms;

    /* Only fall back if our error was from the first referral request. */
    if (ctx->referral_count > 1)
        return ctx->reply_code;

    /* If the request used a specified realm, make a non-referral request to
     * that realm (in case it's a KDC which rejects KDC_OPT_CANONICALIZE). */
    if (!krb5_is_referral_realm(&ctx->req_server->realm))
        return begin_non_referral(context, ctx);

    if (ctx->server->length < 2) {
        /* We need a type/host format principal to find a fallback realm. */
        return KRB5_ERR_HOST_REALM_UNKNOWN;
    }

    /* We expect this to give exactly one answer (XXX clean up interface). */
    code = krb5_get_fallback_host_realm(context, &ctx->server->data[1],
                                        &hrealms);
    if (code != 0)
        return code;

    /* If the fallback realm isn't any different, use the existing TGT. */
    if (data_eq_string(ctx->server->realm, hrealms[0])) {
        krb5_free_host_realm(context, hrealms);
        return begin_non_referral(context, ctx);
    }

    /* Rewrite server->realm to be the fallback realm. */
    krb5_free_data_contents(context, &ctx->server->realm);
    ctx->server->realm = string2data(hrealms[0]);
    free(hrealms);
    TRACE_TKT_CREDS_FALLBACK(context, &ctx->server->realm);

    /* Obtain a TGT for the new service realm. */
    ctx->getting_tgt_for = STATE_NON_REFERRAL;
    return begin_get_tgt(context, ctx);
}
예제 #24
0
파일: t_replay.c 프로젝트: PADL/krb5
static void
test_kdc_check_lookaside_no_response(void **state)
{
    struct entry *e;
    krb5_boolean result;
    krb5_data *result_data;
    krb5_context context = *state;
    krb5_data req = string2data("I'm a test request");

    e = insert_entry(context, &req, NULL, 0);

    /* Set result_data so we can verify that it is reset to NULL. */
    result_data = &req;
    result = kdc_check_lookaside(context, &req, &result_data);

    assert_true(result);
    assert_null(result_data);
    assert_int_equal(hits, 1);
    assert_int_equal(e->num_hits, 1);
}
예제 #25
0
파일: hooks.c 프로젝트: INNOAUS/krb5
/* Create a fake error reply. */
static krb5_error_code
test_send_error(krb5_context context, void *data, const krb5_data *realm,
                const krb5_data *message, krb5_data **new_message_out,
                krb5_data **reply_out)
{
    krb5_error_code ret;
    krb5_error err;
    krb5_principal client, server;
    char *realm_str, *princ_str;
    int r;

    realm_str = k5memdup0(realm->data, realm->length, &ret);
    check(ret);

    r = asprintf(&princ_str, "invalid@%s", realm_str);
    assert(r > 0);
    check(krb5_parse_name(ctx, princ_str, &client));
    free(princ_str);

    r = asprintf(&princ_str, "krbtgt@%s", realm_str);
    assert(r > 0);
    check(krb5_parse_name(ctx, princ_str, &server));
    free(princ_str);
    free(realm_str);

    err.magic = KV5M_ERROR;
    err.ctime = 1971196337;
    err.cusec = 0;
    err.susec = 97008;
    err.stime = 1458219390;
    err.error = 6;
    err.client = client;
    err.server = server;
    err.text = string2data("CLIENT_NOT_FOUND");
    err.e_data = empty_data();
    check(encode_krb5_error(&err, reply_out));

    krb5_free_principal(ctx, client);
    krb5_free_principal(ctx, server);
    return 0;
}
int ril_request_get_sim_status(void *data, size_t size, RIL_Token token)
{
	void *card_status_data;
	size_t card_status_size;
#if RIL_VERSION >= 6
	RIL_CardStatus_v6 *card_status;
#else
	RIL_CardStatus *card_status;
#endif
	struct ril_request *request;
	int rc;

	rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_GET_SIM_STATUS, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	card_status_size = ril_request_data_size_get(RIL_REQUEST_GET_SIM_STATUS);
	card_status_data = ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS);

#if RIL_VERSION >= 6
	if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus_v6)) {
		card_status = (RIL_CardStatus_v6 *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS);
#else
	if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus)) {
		card_status = (RIL_CardStatus *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS);
#endif
		ril_request_complete(token, RIL_E_SUCCESS, card_status_data, card_status_size);

		free(card_status_data);

		return RIL_REQUEST_COMPLETED;
	} else {
		rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_GET, NULL, 0);
		if (rc < 0) {
			ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
			return RIL_REQUEST_COMPLETED;
		}

		return RIL_REQUEST_HANDLED;
	}
}

int ipc_sec_phone_lock(struct ipc_message *message)
{
	struct ipc_sec_phone_lock_response_data *data;
	int active;

	if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_phone_lock_response_data))
		return -1;

	if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
		return 0;

	data = (struct ipc_sec_phone_lock_response_data *) message->data;

	active = !!data->active;

	ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &active, sizeof(active));

	return 0;
}

int ril_request_query_facility_lock(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_phone_lock_request_get_data request_data;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 4 * sizeof(char *))
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	request_data.facility_type = ril2ipc_sec_facility_type(values[0]);
	if (request_data.facility_type == 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc =  RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ipc_sec_callback(struct ipc_message *message)
{
	struct ipc_sec_lock_infomation_request_data request_data;
	struct ipc_gen_phone_res_data *data;
	struct ril_request *request = NULL;
	void *request_complete_data;
	size_t request_complete_size;
	unsigned char facility_type;
	char **values;
	int retry_count;
	int rc;

	if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
		return -1;

	data = (struct ipc_gen_phone_res_data *) message->data;

	request = ril_request_find_token(ipc_fmt_request_token(message->aseq));
	if (request == NULL)
		goto error;

	if (request->request == RIL_REQUEST_ENTER_SIM_PIN || request->request == RIL_REQUEST_CHANGE_SIM_PIN) {
		// Grab the count of remaining tries before completing the request

		ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data));

		rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1);
		if (rc < 0) {
			ril_request_data_free(request->request);
			goto error;
		}

		rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
		if (rc < 0) {
			ril_request_data_free(request->request);
			goto error;
		}
	} else if (request->request == RIL_REQUEST_ENTER_SIM_PIN2 || request->request == RIL_REQUEST_CHANGE_SIM_PIN2) {
		// Grab the count of remaining tries before completing the request

		ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data));

		rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2);
		if (rc < 0) {
			ril_request_data_free(request->request);
			goto error;
		}

		rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
		if (rc < 0) {
			ril_request_data_free(request->request);
			goto error;
		}
	} else if (request->request == RIL_REQUEST_SET_FACILITY_LOCK) {
		values = (char **) request->data;

		request_complete_size = ril_request_data_size_get(RIL_REQUEST_SET_FACILITY_LOCK);
		request_complete_data = ril_request_data_get(RIL_REQUEST_SET_FACILITY_LOCK);

		rc = ipc_gen_phone_res_check(data);

		if (request_complete_data != NULL && request_complete_size > 0 && rc >= 0) {
			rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_SEC_PHONE_LOCK, ipc_sec_callback);
			if (rc < 0) {
				strings_array_free(values, request->size);
				goto error;
			}

			rc = ipc_fmt_send(message->aseq, IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, request_complete_data, request_complete_size);
			if (rc < 0) {
				strings_array_free(values, request->size);
				goto error;
			}
		} else {
			// When FD facility PIN2 unlock failed, ask the count of remaining tries directly

			facility_type = ril2ipc_sec_facility_type(values[0]);

			strings_array_free(values, request->size);

			// Grab the count of remaining tries before completing the request

			ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, (void *) data, sizeof(struct ipc_gen_phone_res_data));

			if (facility_type == IPC_SEC_FACILITY_TYPE_FD) {
				rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2);
				if (rc < 0) {
					ril_request_data_free(request->request);
					goto error;
				}
			} else {
				rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1);
				if (rc < 0) {
					ril_request_data_free(request->request);
					goto error;
				}
			}

			rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
			if (rc < 0) {
				ril_request_data_free(request->request);
				goto error;
			}
		}
	} else if (request->request == RIL_REQUEST_SIM_IO) {
		request_complete_size = ril_request_data_size_get(RIL_REQUEST_SIM_IO);
		request_complete_data = ril_request_data_get(RIL_REQUEST_SIM_IO);

		rc = ipc_gen_phone_res_check(data);
		if (rc < 0) {
			ril_request_complete(request->token, RIL_E_SIM_PIN2, NULL, 0);
			goto complete;
		}

		if (request_complete_data != NULL && request_complete_size > 0) {
			rc = ipc_fmt_send(message->aseq, IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_complete_data, request_complete_size);
			if (rc < 0)
				goto error;
		} else {
			goto error;
		}
	} else {
		retry_count = -1;

		rc = ipc_gen_phone_res_check(data);
		if (rc < 0) {
			if ((data->code & 0xff) == 0x10) {
				RIL_LOGE("%s: Wrong password", __func__);
				ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
			} else if ((data->code & 0xff) == 0x0c) {
				RIL_LOGE("%s: Wrong password and no attempts left", __func__);
				retry_count = 0;
				ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
			} else {
				ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count));
			}
		} else {
			ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count));
		}
	}

	if (request->request == RIL_REQUEST_ENTER_SIM_PUK || request->request == RIL_REQUEST_ENTER_SIM_PUK2)
		ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);

	goto complete;

error:
	if (request != NULL)
		ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0);

complete:
	return 0;
}

int ril_request_set_facility_lock(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_phone_lock_request_set_data request_data;
	struct ipc_sec_pin_status_request_data pin_request_data;
	struct ril_request *request;
	unsigned char facility_type;
	unsigned char active;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 4 * sizeof(char *))
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_SET_FACILITY_LOCK, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	facility_type = ril2ipc_sec_facility_type(values[0]);
	if (facility_type == 0)
		goto error;

	active = values[1][0] == '1';

	rc = ipc_sec_phone_lock_request_set_setup(&request_data, facility_type, active, values[2]);
	if (rc < 0)
		goto error;

	if (facility_type == IPC_SEC_FACILITY_TYPE_FD) {
		// FD facility requires PIN2 unlock first

		rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, values[2], NULL);
		if (rc < 0)
			goto error;

		ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, &request_data, sizeof(request_data));

		rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
		if (rc < 0) {
			ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK);
			goto error;
		}

		rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data));
		if (rc < 0) {
			ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK);
			goto error;
		}

		rc = RIL_REQUEST_HANDLED;
		goto complete;
	}

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ril_request_enter_sim_pin(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_pin_status_request_data request_data;
	struct ril_request *request;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 2 * sizeof(char *) || ril_data == NULL)
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;
	if (values[0] == NULL)
		goto error;

	if (ril_data->sim_pin != NULL)
		free(ril_data->sim_pin);

	ril_data->sim_pin = strdup(values[0]);

	rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[0], NULL);
	if (rc < 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ril_request_enter_sim_puk(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_pin_status_request_data request_data;
	struct ril_request *request;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 2 * sizeof(char *))
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[1], values[0]);
	if (rc < 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ril_request_enter_sim_pin2(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_pin_status_request_data request_data;
	struct ril_request *request;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 2 * sizeof(char *))
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[0], NULL);
	if (rc < 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ril_request_enter_sim_puk2(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_pin_status_request_data request_data;
	struct ril_request *request;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 2 * sizeof(char *))
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK2, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[1], values[0]);
	if (rc < 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ril_request_change_sim_pin(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_change_locking_pw_data request_data;
	struct ril_request *request;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 3 * sizeof(char *))
		goto error;

	request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_SC, values[0], values[1]);
	if (rc < 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ril_request_change_sim_pin2(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_change_locking_pw_data request_data;
	struct ril_request *request;
	char **values = NULL;
	int rc;

	if (data == NULL || size < 3 * sizeof(char *))
		goto error;

	request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

	rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	values = (char **) data;

	rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_FD, values[0], values[1]);
	if (rc < 0)
		goto error;

	strings_array_free(values, size);
	values = NULL;

	rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback);
	if (rc < 0)
		goto error;

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (values != NULL)
		strings_array_free(values, size);

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	return rc;
}

int ipc_sec_rsim_access(struct ipc_message *message)
{
	struct ipc_sec_rsim_access_response_header *header;
	struct ipc_sec_rsim_access_usim_response_header *usim_header;
	struct sim_file_response sim_file_response;
	struct ril_request *request;
	struct ril_client *client;
	struct ipc_fmt_data *ipc_fmt_data;
	RIL_SIM_IO_Response response;
#if RIL_VERSION >= 6
	RIL_SIM_IO_v6 *sim_io;
#else
	RIL_SIM_IO *sim_io;
#endif
	unsigned char *p;
	unsigned int offset;
	unsigned int i;
	void *data;
	size_t size;

	if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_rsim_access_response_header))
		return -1;

	client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
	if (client == NULL || client->data == NULL)
		return 0;

	if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
		return 0;

	ipc_fmt_data = (struct ipc_fmt_data *) client->data;

	header = (struct ipc_sec_rsim_access_response_header *) message->data;

	size = ipc_sec_rsim_access_size_extract(message->data, message->size);
	data = ipc_sec_rsim_access_extract(message->data, message->size);

	request = ril_request_find_token(ipc_fmt_request_token(message->aseq));
#if RIL_VERSION >= 6
	if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO_v6))
#else
	if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO))
#endif
		return 0;

#if RIL_VERSION >= 6
	sim_io = (RIL_SIM_IO_v6 *) request->data;
#else
	sim_io = (RIL_SIM_IO *) request->data;
#endif

	memset(&response, 0, sizeof(response));
	response.sw1 = header->sw1;
	response.sw2 = header->sw2;

	switch (sim_io->command) {
		case SIM_COMMAND_READ_BINARY:
		case SIM_COMMAND_READ_RECORD:
			if (header->length == 0)
				break;

			response.simResponse = data2string(data, header->length);
			break;
		case SIM_COMMAND_GET_RESPONSE:
			if (header->length == 0)
				break;

			if (ipc_fmt_data->sim_icc_type_data.type == 0x01) {
				response.simResponse = data2string(data, header->length);
				break;
			}

			if (header->length < sizeof(struct ipc_sec_rsim_access_usim_response_header))
				break;

			usim_header = (struct ipc_sec_rsim_access_usim_response_header *) data;

			memset(&sim_file_response, 0, sizeof(sim_file_response));

			offset = sizeof(struct ipc_sec_rsim_access_usim_response_header) + usim_header->offset;
			if (offset > header->length)
				break;

			offset = usim_header->offset - 2;
			p = (unsigned char *) usim_header + offset;

			sim_file_response.file_id[0] = p[0];
			sim_file_response.file_id[1] = p[1];

			offset = header->length - 2;
			p = (unsigned char *) usim_header;

			while (offset > 2) {
				if (p[offset] == 0x88) {
					offset -= 2;
					break;
				}

				offset--;
			}

			if (offset <= 2)
				break;

			p = (unsigned char *) usim_header + offset;

			sim_file_response.file_size[0] = p[0];
			sim_file_response.file_size[1] = p[1];

			// Fallback to EF
			sim_file_response.file_type = SIM_FILE_TYPE_EF;
			for (i = 0; i < sim_file_ids_count; i++) {
				if (sim_io->fileid == sim_file_ids[i].file_id) {
					sim_file_response.file_type = sim_file_ids[i].type;
					break;
				}
			}

			sim_file_response.access_condition[0] = 0x00;
			sim_file_response.access_condition[1] = 0xff;
			sim_file_response.access_condition[2] = 0xff;

			sim_file_response.file_status = 0x01;
			sim_file_response.file_length = 0x02;

			switch (usim_header->file_structure) {
				case IPC_SEC_RSIM_FILE_STRUCTURE_TRANSPARENT:
					sim_file_response.file_structure = SIM_FILE_STRUCTURE_TRANSPARENT;
					break;
				case IPC_SEC_RSIM_FILE_STRUCTURE_LINEAR_FIXED:
				default:
					sim_file_response.file_structure = SIM_FILE_STRUCTURE_LINEAR_FIXED;
					break;
			}

			sim_file_response.record_length = usim_header->length;

			response.simResponse = data2string((void *) &sim_file_response, sizeof(sim_file_response));
			break;
		case SIM_COMMAND_UPDATE_BINARY:
		case SIM_COMMAND_UPDATE_RECORD:
		case SIM_COMMAND_SEEK:
		default:
			response.simResponse = NULL;
			break;
	}

	ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &response, sizeof(response));

	if (response.simResponse != NULL)
		free(response.simResponse);

	return 0;
}

int ril_request_sim_io(void *data, size_t size, RIL_Token token)
{
	struct ipc_sec_rsim_access_request_header request_header;
	struct ipc_sec_pin_status_request_data pin_request_data;
	struct ril_request *request;
#if RIL_VERSION >= 6
	RIL_SIM_IO_v6 *sim_io = NULL;
#else
	RIL_SIM_IO *sim_io = NULL;
#endif
	void *sim_io_data = NULL;
	size_t sim_io_size = 0;
	void *request_data = NULL;
	size_t request_size = 0;
	int pin_request = 0;
	int rc;

#if RIL_VERSION >= 6
	if (data == NULL || size < sizeof(RIL_SIM_IO_v6))
#else
	if (data == NULL || size < sizeof(RIL_SIM_IO))
#endif
		goto error;

	rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
	if (rc < 0)
		return RIL_REQUEST_UNHANDLED;

	request = ril_request_find_request_status(RIL_REQUEST_SIM_IO, RIL_REQUEST_HANDLED);
	if (request != NULL)
		return RIL_REQUEST_UNHANDLED;

#if RIL_VERSION >= 6
	sim_io = (RIL_SIM_IO_v6 *) data;
#else
	sim_io = (RIL_SIM_IO *) data;
#endif

	if (sim_io->data != NULL) {
		sim_io_size = string2data_size(sim_io->data);
		if (sim_io_size == 0)
			goto error;

		sim_io_data = string2data(sim_io->data);
		if (sim_io_data == NULL)
			goto error;
	}

	if (sim_io->pin2 != NULL) {
		// PIN2 unlock first

		pin_request = 1;

		rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, sim_io->pin2, NULL);
		if (rc < 0)
			goto error;
	}

	if (sim_io->path != NULL)
		free(sim_io->path);

	if (sim_io->data != NULL)
		free(sim_io->data);

	if (sim_io->pin2 != NULL)
		free(sim_io->pin2);

#if RIL_VERSION >= 6
	if (sim_io->aidPtr != NULL)
		free(sim_io->aidPtr);
#endif

	memset(&request_header, 0, sizeof(request_header));
	request_header.command = sim_io->command;
	request_header.file_id = sim_io->fileid;
	request_header.p1 = sim_io->p1;
	request_header.p2 = sim_io->p2;
	request_header.p3 = sim_io->p3;

	sim_io = NULL;

	request_size = ipc_sec_rsim_access_size_setup(&request_header, sim_io_data, sim_io_size);
	if (request_size == 0)
		goto error;

	request_data = ipc_sec_rsim_access_setup(&request_header, sim_io_data, sim_io_size);
	if (request_data == NULL)
		goto error;

	if (pin_request) {
		// PIN2 unlock first

		ril_request_data_set_uniq(RIL_REQUEST_SIM_IO, request_data, request_size);

		rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
		if (rc < 0) {
			ril_request_data_free(RIL_REQUEST_SIM_IO);
			goto error;
		}

		rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data));
		if (rc < 0) {
			ril_request_data_free(RIL_REQUEST_SIM_IO);
			goto error;
		}

		rc = RIL_REQUEST_HANDLED;
		goto complete;
	}

	rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_data, request_size);
	if (rc < 0)
		goto error;

	rc = RIL_REQUEST_HANDLED;
	goto complete;

error:
	if (sim_io != NULL) {
		if (sim_io->path != NULL)
			free(sim_io->path);

		if (sim_io->data != NULL)
			free(sim_io->data);

		if (sim_io->pin2 != NULL)
			free(sim_io->pin2);

#if RIL_VERSION >= 6
		if (sim_io->aidPtr != NULL)
			free(sim_io->aidPtr);
#endif
	}

	ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);

	rc = RIL_REQUEST_COMPLETED;

complete:
	if (sim_io_data != NULL && sim_io_size > 0)
		free(sim_io_data);

	if (request_data != NULL && request_size > 0)
		free(request_data);

	return rc;
}

int ipc_sec_sim_icc_type(struct ipc_message *message)
{
	struct ipc_sec_sim_icc_type_data *data;
	struct ril_client *client;
	struct ipc_fmt_data *ipc_fmt_data;

	if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_sim_icc_type_data))
		return -1;

	client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
	if (client == NULL || client->data == NULL)
		return 0;

	ipc_fmt_data = (struct ipc_fmt_data *) client->data;

	data = (struct ipc_sec_sim_icc_type_data *) message->data;

	if (ipc_fmt_data->sim_icc_type_data.type != data->type)
		ipc_fmt_data->sim_icc_type_data.type = data->type;

	return 0;
}

int ipc_sec_lock_infomation(struct ipc_message *message)
{
	struct ipc_sec_lock_infomation_response_data *data;
	struct ipc_gen_phone_res_data *gen_phone_res;
	int requests[] = { RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_CHANGE_SIM_PIN2, RIL_REQUEST_SET_FACILITY_LOCK };
	void *gen_phone_res_data = NULL;
	size_t gen_phone_res_size = 0;
	int retry_count;
	unsigned int count;
	unsigned int i;
	int rc;

	if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_lock_infomation_response_data))
		return -1;

	rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
	if (rc < 0)
		return 0;

	if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
		return 0;

	data = (struct ipc_sec_lock_infomation_response_data *) message->data;
	if (data->type != IPC_SEC_PIN_TYPE_PIN1 && data->type != IPC_SEC_PIN_TYPE_PIN2)
		return 0;

	count = sizeof(requests) / sizeof(int);

	for (i = 0; i < count; i++) {
		gen_phone_res_size = ril_request_data_size_get(requests[i]);
		if (gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data))
			continue;

		gen_phone_res_data = ril_request_data_get(requests[i]);
		if (gen_phone_res_data == NULL)
			continue;

		break;
	}

	if (gen_phone_res_data == NULL || gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data))
		return 0;

	gen_phone_res = (struct ipc_gen_phone_res_data *) gen_phone_res_data;

	retry_count = data->retry_count;

	rc = ipc_gen_phone_res_check(gen_phone_res);
	if (rc < 0) {
		if ((gen_phone_res->code & 0xff) == 0x10) {
			RIL_LOGE("%s: Wrong password and %d attempts left", __func__, retry_count);
			ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
		} else if ((gen_phone_res->code & 0xff) == 0x0c) {
			RIL_LOGE("%s: Wrong password and no attempts left", __func__);
			retry_count = 0;
			ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
		} else {
			ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count));
		}
	} else {
		ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count));
	}

	free(gen_phone_res_data);

	return 0;
}
예제 #27
0
파일: chpw.c 프로젝트: Akasurde/krb5
krb5_error_code
krb5int_mk_setpw_req(krb5_context context,
                     krb5_auth_context auth_context,
                     krb5_data *ap_req,
                     krb5_principal targprinc,
                     const char *passwd,
                     krb5_data *packet)
{
    krb5_error_code ret;
    krb5_data   cipherpw;
    krb5_data   *encoded_setpw;
    struct krb5_setpw_req req;

    char *ptr;

    cipherpw.data = NULL;
    cipherpw.length = 0;

    if ((ret = krb5_auth_con_setflags(context, auth_context,
                                      KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
        return(ret);

    req.target = targprinc;
    req.password = string2data((char *)passwd);
    ret = encode_krb5_setpw_req(&req, &encoded_setpw);
    if (ret) {
        return ret;
    }

    if ((ret = krb5_mk_priv(context, auth_context, encoded_setpw, &cipherpw, NULL)) != 0) {
        krb5_free_data(context, encoded_setpw);
        return(ret);
    }
    krb5_free_data(context, encoded_setpw);


    packet->length = 6 + ap_req->length + cipherpw.length;
    packet->data = (char *) malloc(packet->length);
    if (packet->data  == NULL) {
        ret = ENOMEM;
        goto cleanup;
    }
    ptr = packet->data;
    /*
    ** build the packet -
    */
    /* put in the length */
    store_16_be(packet->length, ptr);
    ptr += 2;
    /* put in the version */
    *ptr++ = (char)0xff;
    *ptr++ = (char)0x80;
    /* the ap_req length is big endian */
    store_16_be(ap_req->length, ptr);
    ptr += 2;
    /* put in the request data */
    memcpy(ptr, ap_req->data, ap_req->length);
    ptr += ap_req->length;
    /*
    ** put in the "private" password data -
    */
    memcpy(ptr, cipherpw.data, cipherpw.length);
    ret = 0;
cleanup:
    if (cipherpw.data)
        krb5_free_data_contents(context, &cipherpw);
    if ((ret != 0) && packet->data) {
        free(packet->data);
        packet->data = NULL;
    }
    return ret;
}
예제 #28
0
파일: do_as_req.c 프로젝트: mrogers950/krb5
static krb5_error_code
prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request,
                 krb5_db_entry *local_tgt, int error, krb5_pa_data **e_data_in,
                 krb5_boolean typed_e_data, krb5_principal canon_client,
                 krb5_data **response, const char *status)
{
    krb5_error errpkt;
    krb5_error_code retval;
    krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
    krb5_pa_data **e_data = NULL, *cookie = NULL;
    kdc_realm_t *kdc_active_realm = rstate->realm_data;
    size_t count;

    if (e_data_in != NULL) {
        /* Add a PA-FX-COOKIE to e_data_in.  e_data is a shallow copy
         * containing aliases. */
        for (count = 0; e_data_in[count] != NULL; count++);
        e_data = calloc(count + 2, sizeof(*e_data));
        if (e_data == NULL)
            return ENOMEM;
        memcpy(e_data, e_data_in, count * sizeof(*e_data));
        retval = kdc_fast_make_cookie(kdc_context, rstate, local_tgt,
                                      request->client, &cookie);
        e_data[count] = cookie;
    }

    errpkt.ctime = request->nonce;
    errpkt.cusec = 0;

    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
    if (retval)
        goto cleanup;
    errpkt.error = error;
    errpkt.server = request->server;
    errpkt.client = (error == KDC_ERR_WRONG_REALM) ? canon_client :
                    request->client;
    errpkt.text = string2data((char *)status);

    if (e_data != NULL) {
        if (typed_e_data)
            retval = encode_krb5_typed_data(e_data, &e_data_asn1);
        else
            retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
        if (retval)
            goto cleanup;
        errpkt.e_data = *e_data_asn1;
    } else
        errpkt.e_data = empty_data();

    retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
                                   &errpkt, &fast_edata);
    if (retval)
        goto cleanup;
    if (fast_edata != NULL)
        errpkt.e_data = *fast_edata;

    scratch = k5alloc(sizeof(*scratch), &retval);
    if (scratch == NULL)
        goto cleanup;
    if (kdc_fast_hide_client(rstate) && errpkt.client != NULL)
        errpkt.client = (krb5_principal)krb5_anonymous_principal();
    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
    if (retval)
        goto cleanup;

    *response = scratch;
    scratch = NULL;

cleanup:
    krb5_free_data(kdc_context, fast_edata);
    krb5_free_data(kdc_context, e_data_asn1);
    free(scratch);
    free(e_data);
    if (cookie != NULL)
        free(cookie->contents);
    free(cookie);
    return retval;
}
예제 #29
0
파일: chpw.c 프로젝트: Akasurde/krb5
krb5_error_code
krb5int_mk_chpw_req(krb5_context context,
                    krb5_auth_context auth_context,
                    krb5_data *ap_req,
                    const char *passwd,
                    krb5_data *packet)
{
    krb5_error_code ret = 0;
    krb5_data clearpw;
    krb5_data cipherpw;
    krb5_replay_data replay;
    char *ptr;

    cipherpw.data = NULL;

    if ((ret = krb5_auth_con_setflags(context, auth_context,
                                      KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
        goto cleanup;

    clearpw = string2data((char *)passwd);

    if ((ret = krb5_mk_priv(context, auth_context,
                            &clearpw, &cipherpw, &replay)))
        goto cleanup;

    packet->length = 6 + ap_req->length + cipherpw.length;
    packet->data = (char *) malloc(packet->length);
    if (packet->data == NULL) {
        ret = ENOMEM;
        goto cleanup;
    }
    ptr = packet->data;

    /* length */

    store_16_be(packet->length, ptr);
    ptr += 2;

    /* version == 0x0001 big-endian */

    *ptr++ = 0;
    *ptr++ = 1;

    /* ap_req length, big-endian */

    store_16_be(ap_req->length, ptr);
    ptr += 2;

    /* ap-req data */

    memcpy(ptr, ap_req->data, ap_req->length);
    ptr += ap_req->length;

    /* krb-priv of password */

    memcpy(ptr, cipherpw.data, cipherpw.length);

cleanup:
    if (cipherpw.data != NULL)  /* allocated by krb5_mk_priv */
        free(cipherpw.data);

    return(ret);
}