static krb5_error_code
kdc_return_preauth(krb5_context context, krb5_pa_data *padata,
                   struct _krb5_db_entry_new *client, krb5_data *req_pkt,
                   krb5_kdc_req *request, krb5_kdc_rep *reply,
                   struct _krb5_key_data *client_keys,
                   krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
                   preauth_get_entry_data_proc get_entry_proc,
                   void *pa_module_context, void **pa_request_context)
{
    krb5_error_code retval = 0;
    krb5_keyblock *challenge_key = *pa_request_context;
    krb5_pa_enc_ts ts;
    krb5_data *plain = NULL;
    krb5_enc_data enc;
    krb5_data *encoded = NULL;
    krb5_pa_data *pa = NULL;
    krb5int_access kaccess;

    if (krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION) != 0)
        return 0;
    if (challenge_key == NULL)
        return 0;
    * pa_request_context = NULL; /*this function will free the
                                  * challenge key*/
    enc.ciphertext.data = NULL; /* In case of error pass through */

    retval = krb5_us_timeofday(context, &ts.patimestamp, &ts.pausec);
    if (retval == 0)
        retval = kaccess.encode_enc_ts(&ts, &plain);
    if (retval == 0)
        retval = kaccess.encrypt_helper(context, challenge_key,
                                        KRB5_KEYUSAGE_ENC_CHALLENGE_KDC,
                                        plain, &enc);
    if (retval == 0)
        retval = kaccess.encode_enc_data(&enc, &encoded);
    if (retval == 0) {
        pa = calloc(1, sizeof(krb5_pa_data));
        if (pa == NULL)
            retval = ENOMEM;
    }
    if (retval == 0) {
        pa->pa_type = KRB5_PADATA_ENCRYPTED_CHALLENGE;
        pa->contents = (unsigned char *) encoded->data;
        pa->length = encoded->length;
        encoded->data = NULL;
        *send_pa = pa;
        pa = NULL;
    }
    if (challenge_key)
        krb5_free_keyblock(context, challenge_key);
    if (encoded)
        krb5_free_data(context, encoded);
    if (plain)
        krb5_free_data(context, plain);
    if (enc.ciphertext.data)
        krb5_free_data_contents(context, &enc.ciphertext);
    return retval;
}
Exemple #2
0
krb5_error_code
kg_arcfour_docrypt(const krb5_keyblock *keyblock, int usage,
                   const unsigned char *kd_data, size_t kd_data_len,
                   const unsigned char *input_buf, size_t input_len,
                   unsigned char *output_buf)
{
    krb5_error_code code;
    krb5_data kd = make_data((char *) kd_data, kd_data_len);
    krb5_crypto_iov kiov;
    krb5int_access kaccess;

    code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION);
    if (code)
        return code;
    memcpy(output_buf, input_buf, input_len);
    kiov.flags = KRB5_CRYPTO_TYPE_DATA;
    kiov.data = make_data(output_buf, input_len);
    return (*kaccess.arcfour_gsscrypt)(keyblock, usage, &kd, &kiov, 1);
}
/*
 * Grab internal function pointers from the krb5int_accessor
 * structure and make them available
 */
krb5_error_code
pkinit_accessor_init(void)
{
    krb5_error_code retval;
    krb5int_access k5int;

    retval = krb5int_accessor(&k5int, KRB5INT_ACCESS_VERSION);
    if (retval)
	return retval;
#define SET_PTRS(type) \
k5int_encode_##type = k5int.encode_##type; \
k5int_decode_##type = k5int.decode_##type;

    SET_PTRS(krb5_auth_pack);
    SET_PTRS(krb5_auth_pack_draft9);
    SET_PTRS(krb5_kdc_dh_key_info);
    SET_PTRS(krb5_pa_pk_as_rep);
    SET_PTRS(krb5_pa_pk_as_rep_draft9);
    SET_PTRS(krb5_pa_pk_as_req);
    SET_PTRS(krb5_pa_pk_as_req_draft9);
    SET_PTRS(krb5_reply_key_pack);
    SET_PTRS(krb5_reply_key_pack_draft9);
    SET_PTRS(krb5_td_dh_parameters);
    SET_PTRS(krb5_td_trusted_certifiers);
    SET_PTRS(krb5_typed_data);

    /* special cases... */
    k5int_decode_krb5_principal_name = k5int.decode_krb5_principal_name;
    k5int_decode_krb5_as_req = k5int.decode_krb5_as_req;
    k5int_encode_krb5_kdc_req_body = k5int.encode_krb5_kdc_req_body;
    k5int_krb5_free_kdc_req = k5int.krb5_free_kdc_req;
    k5int_set_prompt_types = k5int.krb5int_set_prompt_types;
    k5int_encode_krb5_authdata_elt = k5int.encode_krb5_authdata_elt;
    k5int_make_srv_query_realm = k5int.make_srv_query_realm;
    k5int_free_srv_dns_data = k5int.free_srv_dns_data;
    return 0;
}
Exemple #4
0
krb5_error_code
kg_arcfour_docrypt_iov(krb5_context context, const krb5_keyblock *keyblock,
                       int usage, const unsigned char *kd_data,
                       size_t kd_data_len, gss_iov_buffer_desc *iov,
                       int iov_count)
{
    krb5_error_code code;
    krb5_data kd = make_data((char *) kd_data, kd_data_len);
    krb5int_access kaccess;
    krb5_crypto_iov *kiov = NULL;
    size_t kiov_count = 0;

    code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
    if (code)
        return code;
    code = kg_translate_iov(context, 0 /* proto */, 0 /* dce_style */,
                            0 /* ec */, 0 /* rrc */, keyblock->enctype,
                            iov, iov_count, &kiov, &kiov_count);
    if (code)
        return code;
    code = (*kaccess.arcfour_gsscrypt)(keyblock, usage, &kd, kiov, kiov_count);
    free(kiov);
    return code;
}
static krb5_error_code
process_preauth(krb5_context context, void *plugin_context,
                void *request_context, krb5_get_init_creds_opt *opt,
                preauth_get_client_data_proc get_data_proc,
                struct _krb5_preauth_client_rock *rock, krb5_kdc_req *request,
                krb5_data *encoded_request_body,
                krb5_data *encoded_previous_request, krb5_pa_data *padata,
                krb5_prompter_fct prompter, void *prompter_data,
                preauth_get_as_key_proc gak_fct, void *gak_data,
                krb5_data *salt, krb5_data *s2kparams, krb5_keyblock *as_key,
                krb5_pa_data ***out_padata)
{
    krb5_error_code retval = 0;
    krb5_enctype enctype = 0;
    krb5_keyblock *challenge_key = NULL, *armor_key = NULL;
    krb5_data *etype_data = NULL;
    krb5int_access kaccess;

    if (krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION) != 0)
        return 0;
    retval = fast_get_armor_key(context, get_data_proc, rock, &armor_key);
    if (retval || armor_key == NULL)
        return 0;
    retval = get_data_proc(context, rock, krb5plugin_preauth_client_get_etype, &etype_data);
    if (retval == 0) {
        enctype = *((krb5_enctype *)etype_data->data);
        if (as_key->length == 0 ||as_key->enctype != enctype)
            retval = gak_fct(context, request->client,
                             enctype, prompter, prompter_data,
                             salt, s2kparams,
                             as_key, gak_data);
    }
    if (retval == 0 && padata->length) {
        krb5_enc_data *enc = NULL;
        krb5_data scratch;
        scratch.length = padata->length;
        scratch.data = (char *) padata->contents;
        retval = krb5_c_fx_cf2_simple(context,armor_key, "kdcchallengearmor",
                                      as_key, "challengelongterm",
                                      &challenge_key);
        if (retval == 0)
            retval =kaccess.decode_enc_data(&scratch, &enc);
        scratch.data = NULL;
        if (retval == 0) {
            scratch.data = malloc(enc->ciphertext.length);
            scratch.length = enc->ciphertext.length;
            if (scratch.data == NULL)
                retval = ENOMEM;
        }
        if (retval == 0)
            retval = krb5_c_decrypt(context, challenge_key,
                                    KRB5_KEYUSAGE_ENC_CHALLENGE_KDC, NULL,
                                    enc, &scratch);
        /*
         * Per draft 11 of the preauth framework, the client MAY but is not
         * required to actually check the timestamp from the KDC other than to
         * confirm it decrypts. This code does not perform that check.
         */
        if (scratch.data)
            krb5_free_data_contents(context, &scratch);
        if (retval == 0)
            fast_set_kdc_verified(context, get_data_proc, rock);
        if (enc)
            kaccess.free_enc_data(context, enc);
    } else if (retval == 0) { /*No padata; we send*/
        krb5_enc_data enc;
        krb5_pa_data *pa = NULL;
        krb5_pa_data **pa_array = NULL;
        krb5_data *encoded_ts = NULL;
        krb5_pa_enc_ts ts;
        enc.ciphertext.data = NULL;
        retval = krb5_us_timeofday(context, &ts.patimestamp, &ts.pausec);
        if (retval == 0)
            retval = kaccess.encode_enc_ts(&ts, &encoded_ts);
        if (retval == 0)
            retval = krb5_c_fx_cf2_simple(context,
                                          armor_key, "clientchallengearmor",
                                          as_key, "challengelongterm",
                                          &challenge_key);
        if (retval == 0)
            retval = kaccess.encrypt_helper(context, challenge_key,
                                            KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT,
                                            encoded_ts, &enc);
        if (encoded_ts)
            krb5_free_data(context, encoded_ts);
        encoded_ts = NULL;
        if (retval == 0) {
            retval = kaccess.encode_enc_data(&enc, &encoded_ts);
            krb5_free_data_contents(context, &enc.ciphertext);
        }
        if (retval == 0) {
            pa = calloc(1, sizeof(krb5_pa_data));
            if (pa == NULL)
                retval = ENOMEM;
        }
        if (retval == 0) {
            pa_array = calloc(2, sizeof(krb5_pa_data *));
            if (pa_array == NULL)
                retval = ENOMEM;
        }
        if (retval == 0) {
            pa->length = encoded_ts->length;
            pa->contents = (unsigned char *) encoded_ts->data;
            pa->pa_type = KRB5_PADATA_ENCRYPTED_CHALLENGE;
            free(encoded_ts);
            encoded_ts = NULL;
            pa_array[0] = pa;
            pa = NULL;
            *out_padata = pa_array;
            pa_array = NULL;
        }
        if (pa)
            free(pa);
        if (encoded_ts)
            krb5_free_data(context, encoded_ts);
        if (pa_array)
            free(pa_array);
    }
    if (challenge_key)
        krb5_free_keyblock(context, challenge_key);
    if (armor_key)
        krb5_free_keyblock(context, armor_key);
    if (etype_data != NULL)
        get_data_proc(context, rock, krb5plugin_preauth_client_free_etype,
                      &etype_data);
    return retval;
}
static krb5_error_code
kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client,
                   krb5_data *req_pkt, krb5_kdc_req *request,
                   krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data,
                   preauth_get_entry_data_proc get_entry_proc,
                   void *pa_module_context, void **pa_request_context,
                   krb5_data **e_data, krb5_authdata ***authz_data)
{
    krb5_error_code retval = 0;
    krb5_timestamp now;
    krb5_enc_data *enc = NULL;
    krb5_data scratch, plain;
    krb5_keyblock *armor_key = NULL;
    krb5_pa_enc_ts *ts = NULL;
    krb5int_access kaccess;
    krb5_keyblock *client_keys = NULL;
    krb5_data *client_data = NULL;
    krb5_keyblock *challenge_key = NULL;
    int i = 0;

    plain.data = NULL;
    if (krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION) != 0)
        return 0;

    retval = fast_kdc_get_armor_key(context, get_entry_proc, request, client, &armor_key);
    if (retval == 0 &&armor_key == NULL) {
        retval = ENOENT;
        krb5_set_error_message(context, ENOENT, "Encrypted Challenge used outside of FAST tunnel");
    }
    scratch.data = (char *) data->contents;
    scratch.length = data->length;
    if (retval == 0)
        retval = kaccess.decode_enc_data(&scratch, &enc);
    if (retval == 0) {
        plain.data =  malloc(enc->ciphertext.length);
        plain.length = enc->ciphertext.length;
        if (plain.data == NULL)
            retval = ENOMEM;
    }
    if (retval == 0)
        retval = get_entry_proc(context, request, client,
                                krb5plugin_preauth_keys, &client_data);
    if (retval == 0) {
        client_keys = (krb5_keyblock *) client_data->data;
        for (i = 0; client_keys[i].enctype&& (retval == 0); i++ ) {
            retval = krb5_c_fx_cf2_simple(context,
                                          armor_key, "clientchallengearmor",
                                          &client_keys[i], "challengelongterm",
                                          &challenge_key);
            if (retval == 0)
                retval  = krb5_c_decrypt(context, challenge_key,
                                         KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT,
                                         NULL, enc, &plain);
            if (challenge_key)
                krb5_free_keyblock(context, challenge_key);
            challenge_key = NULL;
            if (retval == 0)
                break;
            /*We failed to decrypt. Try next key*/
            retval = 0;
            krb5_free_keyblock_contents(context, &client_keys[i]);
        }
        if (client_keys[i].enctype == 0) {
            retval = KRB5KDC_ERR_PREAUTH_FAILED;
            krb5_set_error_message(context, retval, "Incorrect password  in encrypted challenge");
        } else { /*not run out of keys*/
            int j;
            assert (retval == 0);
            for (j = i+1; client_keys[j].enctype; j++)
                krb5_free_keyblock_contents(context, &client_keys[j]);
        }

    }
    if (retval == 0)
        retval = kaccess.decode_enc_ts(&plain, &ts);
    if (retval == 0)
        retval = krb5_timeofday(context, &now);
    if (retval == 0) {
        if (labs(now-ts->patimestamp) < context->clockskew) {
            enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
            /*
             * If this fails, we won't generate a reply to the client.  That
             * may cause the client to fail, but at this point the KDC has
             * considered this a success, so the return value is ignored.
             */
            fast_kdc_replace_reply_key(context, get_entry_proc, request);
            krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor",
                                 &client_keys[i], "challengelongterm",
                                 (krb5_keyblock **) pa_request_context);
        } else { /*skew*/
            retval = KRB5KRB_AP_ERR_SKEW;
        }
    }
    if (client_keys) {
        if (client_keys[i].enctype)
            krb5_free_keyblock_contents(context, &client_keys[i]);
        krb5_free_data(context, client_data);
    }
    if (armor_key)
        krb5_free_keyblock(context, armor_key);
    if (plain.data)
        free(plain.data);
    if (enc)
        kaccess.free_enc_data(context, enc);
    if (ts)
        kaccess.free_enc_ts(context, ts);
    return retval;
}
Exemple #7
0
int
krb4int_send_to_kdc_addr(
    KTEXT pkt, KTEXT rpkt, char *realm,
    struct sockaddr *addr, socklen_t *addrlen)
{
    struct addrlist	al = ADDRLIST_INIT;
    char		lrealm[REALM_SZ];
    krb5int_access	internals;
    krb5_error_code	retval;
    struct servent	*sp;
    int			krb_udp_port = 0;
    int			krbsec_udp_port = 0;
    char		krbhst[MAXHOSTNAMELEN];
    char		*scol;
    int			i;
    int			err;
    krb5_data		message, reply;

    /*
     * If "realm" is non-null, use that, otherwise get the
     * local realm.
     */
    if (realm)
	strncpy(lrealm, realm, sizeof(lrealm) - 1);
    else {
	if (krb_get_lrealm(lrealm, 1)) {
	    DEB (("%s: can't get local realm\n", prog));
	    return SKDC_CANT;
	}
    }
    lrealm[sizeof(lrealm) - 1] = '\0';
    DEB (("lrealm is %s\n", lrealm));

    retval = krb5int_accessor(&internals, KRB5INT_ACCESS_VERSION);
    if (retval)
	return KFAILURE;

    /* The first time, decide what port to use for the KDC.  */
    if (cached_krb_udp_port == 0) {
	sp = getservbyname("kerberos","udp");
        if (sp)
	    cached_krb_udp_port = sp->s_port;
	else
	    cached_krb_udp_port = htons(KERBEROS_PORT); /* kerberos/udp */
        DEB (("cached_krb_udp_port is %d\n", cached_krb_udp_port));
    }
    /* If kerberos/udp isn't 750, try using kerberos-sec/udp (or 750) 
       as a fallback. */
    if (cached_krbsec_udp_port == 0 && 
	cached_krb_udp_port != htons(KERBEROS_PORT)) {
	sp = getservbyname("kerberos-sec","udp");
        if (sp)
	    cached_krbsec_udp_port = sp->s_port;
	else
	    cached_krbsec_udp_port = htons(KERBEROS_PORT); /* kerberos/udp */
        DEB (("cached_krbsec_udp_port is %d\n", cached_krbsec_udp_port));
    }

    for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
#ifdef DEBUG
        if (krb_debug) {
            DEB (("Getting host entry for %s...",krbhst));
            (void) fflush(stdout);
        }
#endif
	if (0 != (scol = strchr(krbhst,':'))) {
	    krb_udp_port = htons(atoi(scol+1));
	    *scol = 0;
	    if (krb_udp_port == 0) {
#ifdef DEBUG
		if (krb_debug) {
		    DEB (("bad port number %s\n",scol+1));
		    (void) fflush(stdout);
		}
#endif
		continue;
	    }
	    krbsec_udp_port = 0;
	} else {
	    krb_udp_port = cached_krb_udp_port;
	    krbsec_udp_port = cached_krbsec_udp_port;
	}
        err = internals.add_host_to_list(&al, krbhst,
					 krb_udp_port, krbsec_udp_port,
					 SOCK_DGRAM, PF_INET);
	if (err) {
	    retval = SKDC_CANT;
	    goto free_al;
	}
    }
    if (al.naddrs == 0) {
	DEB (("%s: can't find any Kerberos host.\n", prog));
        retval = SKDC_CANT;
    }

    message.length = pkt->length;
    message.data = (char *)pkt->dat; /* XXX yuck */
    retval = internals.sendto_udp(NULL, &message, &al, NULL, &reply, addr,
				  addrlen, NULL, 0, NULL);
    DEB(("sendto_udp returns %d\n", retval));
free_al:
    internals.free_addrlist(&al);
    if (retval)
	return SKDC_CANT;
    DEB(("reply.length=%d\n", reply.length));
    if (reply.length > sizeof(rpkt->dat))
	retval = SKDC_CANT;
    rpkt->length = 0;
    if (!retval) {
	memcpy(rpkt->dat, reply.data, reply.length);
	rpkt->length = reply.length;
    }
    krb5_free_data_contents(NULL, &reply);
    return retval;
}
Exemple #8
0
krb5_error_code
kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey,
              krb5_cksumtype *cksumtype)
{
    krb5_error_code code;
    krb5int_access kaccess;

    assert(ctx != NULL);
    assert(subkey != NULL);

    *cksumtype = 0;
    ctx->proto = 0;

    if (ctx->enc == NULL) {
        ctx->signalg = -1;
        ctx->sealalg = -1;
    }

    code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION);
    if (code != 0)
        return code;

    code = (*kaccess.mandatory_cksumtype)(context, subkey->keyblock.enctype,
                                          cksumtype);
    if (code != 0)
        return code;

    switch (subkey->keyblock.enctype) {
    case ENCTYPE_DES_CBC_MD5:
    case ENCTYPE_DES_CBC_MD4:
    case ENCTYPE_DES_CBC_CRC:
        krb5_k_free_key(context, ctx->seq);
        code = krb5_k_create_key(context, &subkey->keyblock, &ctx->seq);
        if (code != 0)
            return code;

        krb5_k_free_key(context, ctx->enc);
        code = kg_derive_des_enc_key(context, subkey, &ctx->enc);
        if (code != 0)
            return code;

        ctx->enc->keyblock.enctype = ENCTYPE_DES_CBC_RAW;
        ctx->seq->keyblock.enctype = ENCTYPE_DES_CBC_RAW;
        ctx->signalg = SGN_ALG_DES_MAC_MD5;
        ctx->cksum_size = 8;
        ctx->sealalg = SEAL_ALG_DES;

        break;
    case ENCTYPE_DES3_CBC_SHA1:
        code = kg_copy_keys(context, ctx, subkey);
        if (code != 0)
            return code;

        ctx->enc->keyblock.enctype = ENCTYPE_DES3_CBC_RAW;
        ctx->seq->keyblock.enctype = ENCTYPE_DES3_CBC_RAW;
        ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
        ctx->cksum_size = 20;
        ctx->sealalg = SEAL_ALG_DES3KD;
        break;
    case ENCTYPE_ARCFOUR_HMAC:
    case ENCTYPE_ARCFOUR_HMAC_EXP:
        code = kg_copy_keys(context, ctx, subkey);
        if (code != 0)
            return code;

        ctx->signalg = SGN_ALG_HMAC_MD5;
        ctx->cksum_size = 8;
        ctx->sealalg = SEAL_ALG_MICROSOFT_RC4;
        break;
    default:
        ctx->proto = 1;
        break;
    }

    return 0;
}