Esempio n. 1
0
krb5_error_code
Z_krb5_init_keyblock(krb5_context context,
	krb5_enctype type,
	size_t size,
	krb5_keyblock **key)
{
#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
	return krb5_init_keyblock(context, type, size, key);
#else
	krb5_error_code ret;
	krb5_keyblock *tmp, tmp_ss;
	tmp = &tmp_ss;

	*key = NULL;
	Z_enctype(tmp) = type;
	Z_keylen(tmp) = size;
	Z_keydata(tmp) = malloc(size);
	if (!Z_keydata(tmp))
		return ENOMEM;
	ret =  krb5_copy_keyblock(context, tmp, key);
	free(Z_keydata(tmp));
	return ret;
#endif
}
Esempio n. 2
0
krb5_error_code
kdc_fast_response_handle_padata(struct kdc_request_state *state,
                                krb5_kdc_req *request,
                                krb5_kdc_rep *rep, krb5_enctype enctype)
{
    krb5_error_code retval = 0;
    krb5_fast_finished finish;
    krb5_fast_response fast_response;
    krb5_data *encoded_ticket = NULL;
    krb5_data *encrypted_reply = NULL;
    krb5_pa_data *pa = NULL, **pa_array = NULL;
    krb5_cksumtype cksumtype = CKSUMTYPE_RSA_MD5;
    krb5_pa_data *empty_padata[] = {NULL};
    krb5_keyblock *strengthen_key = NULL;
    kdc_realm_t *kdc_active_realm = state->realm_data;

    if (!state->armor_key)
        return 0;
    memset(&finish, 0, sizeof(finish));
    retval = krb5_init_keyblock(kdc_context, enctype, 0, &strengthen_key);
    if (retval == 0)
        retval = krb5_c_make_random_key(kdc_context, enctype, strengthen_key);
    if (retval == 0) {
        state->strengthen_key = strengthen_key;
        strengthen_key = NULL;
    }

    fast_response.padata = rep->padata;
    if (fast_response.padata == NULL)
        fast_response.padata = &empty_padata[0];
    fast_response.strengthen_key = state->strengthen_key;
    fast_response.nonce = request->nonce;
    fast_response.finished = &finish;
    finish.client = rep->client;
    pa_array = calloc(3, sizeof(*pa_array));
    if (pa_array == NULL)
        retval = ENOMEM;
    pa = calloc(1, sizeof(krb5_pa_data));
    if (retval == 0 && pa == NULL)
        retval = ENOMEM;
    if (retval == 0)
        retval = krb5_us_timeofday(kdc_context, &finish.timestamp, &finish.usec);
    if (retval == 0)
        retval = encode_krb5_ticket(rep->ticket, &encoded_ticket);
    if (retval == 0)
        retval = krb5int_c_mandatory_cksumtype(kdc_context,
                                               state->armor_key->enctype,
                                               &cksumtype);
    if (retval == 0)
        retval = krb5_c_make_checksum(kdc_context, cksumtype,
                                      state->armor_key,
                                      KRB5_KEYUSAGE_FAST_FINISHED,
                                      encoded_ticket, &finish.ticket_checksum);
    if (retval == 0)
        retval = encrypt_fast_reply(state, &fast_response, &encrypted_reply);
    if (retval == 0) {
        pa[0].pa_type = KRB5_PADATA_FX_FAST;
        pa[0].length = encrypted_reply->length;
        pa[0].contents = (unsigned char *)  encrypted_reply->data;
        pa_array[0] = &pa[0];
        krb5_free_pa_data(kdc_context, rep->padata);
        rep->padata = pa_array;
        pa_array = NULL;
        free(encrypted_reply);
        encrypted_reply = NULL;
        pa = NULL;
    }
    if (pa)
        free(pa);
    if (pa_array)
        free(pa_array);
    if (encrypted_reply)
        krb5_free_data(kdc_context, encrypted_reply);
    if (encoded_ticket)
        krb5_free_data(kdc_context, encoded_ticket);
    if (strengthen_key != NULL)
        krb5_free_keyblock(kdc_context, strengthen_key);
    if (finish.ticket_checksum.contents)
        krb5_free_checksum_contents(kdc_context, &finish.ticket_checksum);
    return retval;
}
Esempio n. 3
0
static krb5_error_code
client_process(krb5_context kcontext,
	       void *plugin_context,
	       void *request_context,
	       krb5_get_init_creds_opt *opt,
	       preauth_get_client_data_proc client_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 *pa_data,
	       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_pa_data)
{
    krb5_pa_data *send_pa;
    krb5_int32 nnonce, enctype;
    krb5_keyblock *kb;
    krb5_error_code status;
    int *pctx;

#ifdef DEBUG
    fprintf(stderr, "%d bytes of preauthentication data (type %d)\n",
	    pa_data->length, pa_data->pa_type);
#endif

    pctx = plugin_context;
    if (pctx) {
	(*pctx)++;
    }

    if (pa_data->length == 0) {
	/* Create preauth data. */
	send_pa = malloc(sizeof(krb5_pa_data));
	if (send_pa == NULL)
	    return ENOMEM;
	send_pa->pa_type = KRB5_PADATA_WPSE_REQ;
	send_pa->length = 4;
	send_pa->contents = malloc(4);
	if (send_pa->contents == NULL) {
	    free(send_pa);
	    return ENOMEM;
	}
	/* Store the preauth data. */
	nnonce = htonl(request->nonce);
	memcpy(send_pa->contents, &nnonce, 4);
	*out_pa_data = send_pa;
    } else {
	/* A reply from the KDC.  Conventionally this would be
	 * indicated by a different preauthentication type, but this
	 * mechanism/implementation doesn't do that. */
	if (pa_data->length > 4) {
	    memcpy(&enctype, pa_data->contents, 4);
	    kb = NULL;
	    status = krb5_init_keyblock(kcontext, ntohl(enctype),
					pa_data->length - 4, &kb);
	    if (status != 0)
		return status;
	    memcpy(kb->contents, pa_data->contents + 4, pa_data->length - 4);
#ifdef DEBUG
	    fprintf(stderr, "Recovered key type=%d, length=%d.\n",
		    kb->enctype, kb->length);
#endif
	    status = krb5_copy_keyblock_contents(kcontext, kb, as_key);
	    krb5_free_keyblock(kcontext, kb);
	    return status;
	}
	return KRB5KRB_ERR_GENERIC;
    }
    return 0;
}
Esempio n. 4
0
/* Create the response for a client. */
static krb5_error_code
server_return(krb5_context kcontext,
	      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_key,
	      krb5_keyblock *encrypting_key,
	      krb5_pa_data **send_pa,
	      preauth_get_entry_data_proc server_get_entry_data,
	      void *pa_module_context,
	      void **pa_request_context)
{
    /* This module does a couple of dumb things.  It tags its reply with
     * the same type as the initial challenge (expecting the client to sort
     * out whether there's anything useful in there).  Oh, and it replaces
     * the AS reply key with one which is sent in the clear. */
    krb5_keyblock *kb;
    krb5_int32 enctype;
    int i;

    *send_pa = NULL;

    /* We'll want a key with the first supported enctype. */
    for (i = 0; i < request->nktypes; i++) {
	kb = NULL;
	if (krb5_init_keyblock(kcontext, request->ktype[i], 0, &kb) == 0) {
	    break;
	}
    }
    if (i >= request->nktypes) {
	/* No matching cipher type found. */
	return 0;
    }

    /* Randomize a key and save it for the client. */
    if (krb5_c_make_random_key(kcontext, request->ktype[i], kb) != 0) {
	krb5_free_keyblock(kcontext, kb);
	return 0;
    }
#ifdef DEBUG
    fprintf(stderr, "Generated random key, type=%d, length=%d.\n",
	    kb->enctype, kb->length);
#endif

    *send_pa = malloc(sizeof(krb5_pa_data));
    if (*send_pa == NULL) {
	krb5_free_keyblock(kcontext, kb);
	return ENOMEM;
    }
    (*send_pa)->pa_type = KRB5_PADATA_WPSE_REQ;
    (*send_pa)->length = 4 + kb->length;
    (*send_pa)->contents = malloc(4 + kb->length);
    if ((*send_pa)->contents == NULL) {
	free(*send_pa);
	*send_pa = NULL;
	krb5_free_keyblock(kcontext, kb);
	return ENOMEM;
    }

    /* Store the preauth data. */
    enctype = htonl(kb->enctype);
    memcpy((*send_pa)->contents, &enctype, 4);
    memcpy((*send_pa)->contents + 4, kb->contents, kb->length);
    krb5_free_keyblock_contents(kcontext, encrypting_key);
    krb5_copy_keyblock_contents(kcontext, kb, encrypting_key);

    /* Clean up. */
    krb5_free_keyblock(kcontext, kb);

    return 0;
}
Esempio n. 5
0
int
main ()
{
    krb5_context context = 0;
    krb5_data  in, in2, out, out2, check, check2, state, signdata;
    krb5_crypto_iov iov[5];
    int i, j, pos;
    unsigned int dummy;
    size_t len;
    krb5_enc_data enc_out, enc_out2;
    krb5_keyblock *keyblock;
    krb5_key key;

    memset(iov, 0, sizeof(iov));

    in.data = "This is a test.\n";
    in.length = strlen (in.data);
    in2.data = "This is another test.\n";
    in2.length = strlen (in2.data);

    test ("Seeding random number generator",
          krb5_c_random_seed (context, &in));

    /* Set up output buffers. */
    out.data = malloc(2048);
    out2.data = malloc(2048);
    check.data = malloc(2048);
    check2.data = malloc(2048);
    if (out.data == NULL || out2.data == NULL
        || check.data == NULL || check2.data == NULL)
        abort();
    out.magic = KV5M_DATA;
    out.length = 2048;
    out2.magic = KV5M_DATA;
    out2.length = 2048;
    check.length = 2048;
    check2.length = 2048;

    for (i = 0; interesting_enctypes[i]; i++) {
        krb5_enctype enctype = interesting_enctypes [i];

        printf ("Testing enctype %d\n", enctype);
        test ("Initializing a keyblock",
              krb5_init_keyblock (context, enctype, 0, &keyblock));
        test ("Generating random keyblock",
              krb5_c_make_random_key (context, enctype, keyblock));
        test ("Creating opaque key from keyblock",
              krb5_k_create_key (context, keyblock, &key));

        enc_out.ciphertext = out;
        enc_out2.ciphertext = out2;
        /* We use an intermediate `len' because size_t may be different size
           than `int' */
        krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len);
        enc_out.ciphertext.length = len;

        /* Encrypt, decrypt, and see if we got the plaintext back again. */
        test ("Encrypting (c)",
              krb5_c_encrypt (context, keyblock, 7, 0, &in, &enc_out));
        display ("Enc output", &enc_out.ciphertext);
        test ("Decrypting",
              krb5_c_decrypt (context, keyblock, 7, 0, &enc_out, &check));
        test ("Comparing", compare_results (&in, &check));

        /* Try again with the opaque-key-using variants. */
        memset(out.data, 0, out.length);
        test ("Encrypting (k)",
              krb5_k_encrypt (context, key, 7, 0, &in, &enc_out));
        display ("Enc output", &enc_out.ciphertext);
        test ("Decrypting",
              krb5_k_decrypt (context, key, 7, 0, &enc_out, &check));
        test ("Comparing", compare_results (&in, &check));

        /* Check if this enctype supports IOV encryption. */
        if ( krb5_c_crypto_length(context, keyblock->enctype,
                                  KRB5_CRYPTO_TYPE_HEADER, &dummy) == 0 ){
            /* Set up iovecs for stream decryption. */
            memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length);
            iov[0].flags= KRB5_CRYPTO_TYPE_STREAM;
            iov[0].data.data = out2.data;
            iov[0].data.length = enc_out.ciphertext.length;
            iov[1].flags = KRB5_CRYPTO_TYPE_DATA;

            /* Decrypt the encrypted data from above and check it. */
            test("IOV stream decrypting (c)",
                 krb5_c_decrypt_iov( context, keyblock, 7, 0, iov, 2));
            test("Comparing results",
                 compare_results(&in, &iov[1].data));

            /* Try again with the opaque-key-using variant. */
            memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length);
            test("IOV stream decrypting (k)",
                 krb5_k_decrypt_iov( context, key, 7, 0, iov, 2));
            test("Comparing results",
                 compare_results(&in, &iov[1].data));

            /* Set up iovecs for AEAD encryption. */
            signdata.magic = KV5M_DATA;
            signdata.data = (char *) "This should be signed";
            signdata.length = strlen(signdata.data);
            iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
            iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
            iov[1].data = in; /*We'll need to copy memory before encrypt*/
            iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
            iov[2].data = signdata;
            iov[3].flags = KRB5_CRYPTO_TYPE_PADDING;
            iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER;

            /* "Allocate" data for the iovec buffers from the "out" buffer. */
            test("Setting up iov lengths",
                 krb5_c_crypto_length_iov(context, keyblock->enctype, iov, 5));
            for (j=0,pos=0; j <= 4; j++ ){
                if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
                    continue;
                iov[j].data.data = &out.data[pos];
                pos += iov[j].data.length;
            }
            assert (iov[1].data.length == in.length);
            memcpy(iov[1].data.data, in.data, in.length);

            /* Encrypt and decrypt in place, and check the result. */
            test("iov encrypting (c)",
                 krb5_c_encrypt_iov(context, keyblock, 7, 0, iov, 5));
            assert(iov[1].data.length == in.length);
            display("Header", &iov[0].data);
            display("Data", &iov[1].data);
            display("Padding", &iov[3].data);
            display("Trailer", &iov[4].data);
            test("iov decrypting",
                 krb5_c_decrypt_iov(context, keyblock, 7, 0, iov, 5));
            test("Comparing results",
                 compare_results(&in, &iov[1].data));

            /* Try again with opaque-key-using variants. */
            test("iov encrypting (k)",
                 krb5_k_encrypt_iov(context, key, 7, 0, iov, 5));
            assert(iov[1].data.length == in.length);
            display("Header", &iov[0].data);
            display("Data", &iov[1].data);
            display("Padding", &iov[3].data);
            display("Trailer", &iov[4].data);
            test("iov decrypting",
                 krb5_k_decrypt_iov(context, key, 7, 0, iov, 5));
            test("Comparing results",
                 compare_results(&in, &iov[1].data));
        }

        enc_out.ciphertext.length = out.length;
        check.length = 2048;

        test ("init_state",
              krb5_c_init_state (context, keyblock, 7, &state));
        test ("Encrypting with state",
              krb5_c_encrypt (context, keyblock, 7, &state, &in, &enc_out));
        display ("Enc output", &enc_out.ciphertext);
        test ("Encrypting again with state",
              krb5_c_encrypt (context, keyblock, 7, &state, &in2, &enc_out2));
        display ("Enc output", &enc_out2.ciphertext);
        test ("free_state",
              krb5_c_free_state (context, keyblock, &state));
        test ("init_state",
              krb5_c_init_state (context, keyblock, 7, &state));
        test ("Decrypting with state",
              krb5_c_decrypt (context, keyblock, 7, &state, &enc_out, &check));
        test ("Decrypting again with state",
              krb5_c_decrypt (context, keyblock, 7, &state, &enc_out2, &check2));
        test ("free_state",
              krb5_c_free_state (context, keyblock, &state));
        test ("Comparing",
              compare_results (&in, &check));
        test ("Comparing",
              compare_results (&in2, &check2));

        krb5_free_keyblock (context, keyblock);
        krb5_k_free_key (context, key);
    }

    /* Test the RC4 decrypt fallback from key usage 9 to 8. */
    test ("Initializing an RC4 keyblock",
          krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock));
    test ("Generating random RC4 key",
          krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock));
    enc_out.ciphertext = out;
    krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len);
    enc_out.ciphertext.length = len;
    check.length = 2048;
    test ("Encrypting with RC4 key usage 8",
          krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out));
    display ("Enc output", &enc_out.ciphertext);
    test ("Decrypting with RC4 key usage 9",
          krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check));
    test ("Comparing", compare_results (&in, &check));

    krb5_free_keyblock (context, keyblock);
    free(out.data);
    free(out2.data);
    free(check.data);
    free(check2.data);
    return 0;
}
Esempio n. 6
0
Code_t
ZLoadSession(char *buffer, int len)
{
#ifdef HAVE_KRB5
    struct _Z_SessionKey *key;
    uint32_t num_keys, keylength;
    krb5_enctype enctype;
    int i;
#endif
    Code_t ret;
    uint16_t version, port;

    if (len < 2) return (EINVAL);
    version = ntohs(*((uint16_t *) buffer)); buffer += 2; len -= 2;
    if (version != SESSION_VERSION)
	return (EINVAL);

    if (len < 2) return (EINVAL);
    port = ntohs(*((uint16_t *) buffer)); buffer += 2; len -= 2;
    if ((ret = ZOpenPort(&port)) != ZERR_NONE)
	return ret;

#ifdef HAVE_KRB5
    if (len < 4) return (EINVAL);
    num_keys = ntohl(*((uint32_t *) buffer)); buffer += 4; len -= 4;

    for (i = 0; i < num_keys; i++) {
	key = (struct _Z_SessionKey *)malloc(sizeof(struct _Z_SessionKey));
	if (!key)
	    return (ENOMEM);
	if (len < 4) {
	    free(key);
	    return (EINVAL);
	}
	enctype = ntohl(*((uint32_t *) buffer)); buffer += 4; len -= 4;
	if (len < 4) {
	    free(key);
	    return (EINVAL);
	}
	keylength = ntohl(*((uint32_t *) buffer)); buffer += 4; len -= 4;
	if (len < keylength) {
	    free(key);
	    return (EINVAL);
	}
	ret = krb5_init_keyblock(Z_krb5_ctx, enctype, keylength, &key->keyblock);
	if (ret) {
	    free(key);
	    return ret;
	}
	memcpy((char *)key->keyblock->contents, buffer, keylength);
	buffer += keylength; len -= keylength;
	/* Just set recent times. It means we might not be able to
	   retire the keys, but that's fine. */
	key->send_time = time(NULL);
	key->first_use = time(NULL);
	/* Prepend to the key list. */
	key->prev = NULL;
	key->next = Z_keys_head;
	if (Z_keys_head)
	    Z_keys_head->prev = key;
	Z_keys_head = key;
	if (!Z_keys_tail)
	    Z_keys_tail = key;
    }
#endif

    if (len)
	return (EINVAL);
    return (ZERR_NONE);
}