krb5_error_code securid_make_sam_challenge_2_and_cksum(krb5_context context, krb5_sam_challenge_2 *sc2, krb5_sam_challenge_2_body *sc2b, krb5_keyblock *cksum_key) { krb5_error_code retval; krb5_checksum **cksum_array = NULL; krb5_checksum *cksum = NULL; krb5_cksumtype cksumtype; krb5_data *encoded_challenge_body = NULL; if (!cksum_key) return KRB5_PREAUTH_NO_KEY; if (!sc2 || !sc2b) return KRB5KDC_ERR_PREAUTH_FAILED; retval = encode_krb5_sam_challenge_2_body(sc2b, &encoded_challenge_body); if (retval || !encoded_challenge_body) { encoded_challenge_body = NULL; goto cksum_cleanup; } cksum_array = calloc(2, sizeof(krb5_checksum *)); if (!cksum_array) { retval = ENOMEM; goto cksum_cleanup; } cksum = (krb5_checksum *)k5alloc(sizeof(krb5_checksum), &retval); if (retval) goto cksum_cleanup; cksum_array[0] = cksum; cksum_array[1] = NULL; retval = krb5int_c_mandatory_cksumtype(context, cksum_key->enctype, &cksumtype); if (retval) goto cksum_cleanup; retval = krb5_c_make_checksum(context, cksumtype, cksum_key, KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM, encoded_challenge_body, cksum); if (retval) goto cksum_cleanup; sc2->sam_cksum = cksum_array; sc2->sam_challenge_2_body = *encoded_challenge_body; return 0; cksum_cleanup: krb5_free_data(context, encoded_challenge_body); free(cksum_array); free(cksum); return retval; }
static krb5_error_code make_ad_signedpath_checksum(krb5_context context, krb5_const_principal for_user_princ, const krb5_db_entry *krbtgt, krb5_keyblock *krbtgt_key, krb5_enc_tkt_part *enc_tkt_part, krb5_principal *deleg_path, krb5_pa_data **method_data, krb5_checksum *cksum) { krb5_error_code code; krb5_data *data; krb5_cksumtype cksumtype; krb5_const_principal client; if (for_user_princ != NULL) client = for_user_princ; else client = enc_tkt_part->client; code = make_ad_signedpath_data(context, client, enc_tkt_part->times.authtime, deleg_path, method_data, enc_tkt_part->authorization_data, &data); if (code != 0) return code; code = krb5int_c_mandatory_cksumtype(context, krbtgt_key->enctype, &cksumtype); if (code != 0) { krb5_free_data(context, data); return code; } if (!krb5_c_is_keyed_cksum(cksumtype)) { krb5_free_data(context, data); return KRB5KRB_AP_ERR_INAPP_CKSUM; } code = krb5_c_make_checksum(context, cksumtype, krbtgt_key, KRB5_KEYUSAGE_AD_SIGNEDPATH, data, cksum); krb5_free_data(context, data); return code; }
krb5_error_code KRB5_CALLCONV krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum) { const struct krb5_cksumtypes *ctp; krb5_crypto_iov iov; krb5_data cksum_data; krb5_octet *trunc; krb5_error_code ret; if (cksumtype == 0) { ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, &cksumtype); if (ret != 0) return ret; } ctp = find_cksumtype(cksumtype); if (ctp == NULL) return KRB5_BAD_ENCTYPE; ret = verify_key(ctp, key); if (ret != 0) return ret; ret = alloc_data(&cksum_data, ctp->compute_size); if (ret != 0) return ret; iov.flags = KRB5_CRYPTO_TYPE_DATA; iov.data = *input; ret = ctp->checksum(ctp, key, usage, &iov, 1, &cksum_data); if (ret != 0) goto cleanup; cksum->magic = KV5M_CHECKSUM; cksum->checksum_type = cksumtype; cksum->length = ctp->output_size; cksum->contents = (krb5_octet *) cksum_data.data; cksum_data.data = NULL; if (ctp->output_size < ctp->compute_size) { trunc = realloc(cksum->contents, ctp->output_size); if (trunc != NULL) cksum->contents = trunc; } cleanup: zapfree(cksum_data.data, ctp->compute_size); return ret; }
static krb5_error_code k5_insert_checksum(krb5_context context, krb5_pac pac, krb5_ui_4 type, const krb5_keyblock *key, krb5_cksumtype *cksumtype) { krb5_error_code ret; size_t len; krb5_data cksumdata; ret = krb5int_c_mandatory_cksumtype(context, key->enctype, cksumtype); if (ret != 0) return ret; ret = krb5_c_checksum_length(context, *cksumtype, &len); if (ret != 0) return ret; ret = k5_pac_locate_buffer(context, pac, type, &cksumdata); if (ret == 0) { /* * If we're resigning PAC, make sure we can fit checksum * into existing buffer */ if (cksumdata.length != PAC_SIGNATURE_DATA_LENGTH + len) return ERANGE; memset(cksumdata.data, 0, cksumdata.length); } else { /* Add a zero filled buffer */ cksumdata.length = PAC_SIGNATURE_DATA_LENGTH + len; cksumdata.data = NULL; ret = k5_pac_add_buffer(context, pac, type, &cksumdata, TRUE, &cksumdata); if (ret != 0) return ret; } /* Encode checksum type into buffer */ store_32_le((krb5_ui_4)*cksumtype, cksumdata.data); return 0; }
/* Construct an AP-REQ message for a TGS request. */ static krb5_error_code tgs_construct_ap_req(krb5_context context, krb5_data *checksum_data, krb5_creds *tgt, krb5_keyblock *subkey, krb5_data **ap_req_asn1_out) { krb5_cksumtype cksumtype; krb5_error_code ret; krb5_checksum checksum; krb5_authenticator authent; krb5_ap_req ap_req; krb5_data *authent_asn1 = NULL; krb5_ticket *ticket = NULL; krb5_enc_data authent_enc; *ap_req_asn1_out = NULL; memset(&checksum, 0, sizeof(checksum)); memset(&ap_req, 0, sizeof(ap_req)); memset(&authent_enc, 0, sizeof(authent_enc)); /* Determine the authenticator checksum type. */ switch (tgt->keyblock.enctype) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_MD5: case ENCTYPE_ARCFOUR_HMAC: case ENCTYPE_ARCFOUR_HMAC_EXP: cksumtype = context->kdc_req_sumtype; break; default: ret = krb5int_c_mandatory_cksumtype(context, tgt->keyblock.enctype, &cksumtype); if (ret) goto cleanup; } /* Generate checksum. */ ret = krb5_c_make_checksum(context, cksumtype, &tgt->keyblock, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, checksum_data, &checksum); if (ret) goto cleanup; /* Construct, encode, and encrypt an authenticator. */ authent.subkey = subkey; authent.seq_number = 0; authent.checksum = &checksum; authent.client = tgt->client; authent.authorization_data = tgt->authdata; ret = krb5_us_timeofday(context, &authent.ctime, &authent.cusec); if (ret) goto cleanup; ret = encode_krb5_authenticator(&authent, &authent_asn1); if (ret) goto cleanup; ret = krb5_encrypt_helper(context, &tgt->keyblock, KRB5_KEYUSAGE_TGS_REQ_AUTH, authent_asn1, &authent_enc); if (ret) goto cleanup; ret = decode_krb5_ticket(&tgt->ticket, &ticket); if (ret) goto cleanup; /* Encode the AP-REQ. */ ap_req.authenticator = authent_enc; ap_req.ticket = ticket; ret = encode_krb5_ap_req(&ap_req, ap_req_asn1_out); cleanup: free(checksum.contents); krb5_free_ticket(context, ticket); krb5_free_data_contents(context, &authent_enc.ciphertext); if (authent_asn1 != NULL) zapfree(authent_asn1->data, authent_asn1->length); free(authent_asn1); return ret; }
krb5_error_code KRB5_CALLCONV krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata) { krb5_error_code retval; krb5_key key; krb5_replay_data replaydata; /* Clear replaydata block */ memset(&replaydata, 0, sizeof(krb5_replay_data)); /* Get key */ if ((key = auth_context->send_subkey) == NULL) key = auth_context->key; /* Get replay info */ if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) /* Need a better error */ return KRB5_RC_REQUIRED; if (!auth_context->local_addr) return KRB5_LOCAL_ADDR_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) { if ((retval = krb5_us_timeofday(context, &replaydata.timestamp, &replaydata.usec))) return retval; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; } } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { replaydata.seq = auth_context->local_seq_number++; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) outdata->seq = replaydata.seq; } { krb5_address * premote_fulladdr = NULL; krb5_address * plocal_fulladdr; krb5_address remote_fulladdr; krb5_address local_fulladdr; krb5_cksumtype sumtype; CLEANUP_INIT(2); if (auth_context->local_port) { if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, auth_context->local_port, &local_fulladdr))){ CLEANUP_PUSH(local_fulladdr.contents, free); plocal_fulladdr = &local_fulladdr; } else { goto error; } } else { plocal_fulladdr = auth_context->local_addr; } if (auth_context->remote_addr) { if (auth_context->remote_port) { if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, auth_context->remote_port, &remote_fulladdr))){ CLEANUP_PUSH(remote_fulladdr.contents, free); premote_fulladdr = &remote_fulladdr; } else { CLEANUP_DONE(); goto error; } } else { premote_fulladdr = auth_context->remote_addr; } } { krb5_enctype enctype = krb5_k_key_enctype(context, key); unsigned int nsumtypes; unsigned int i; krb5_cksumtype *sumtypes; retval = krb5_c_keyed_checksum_types (context, enctype, &nsumtypes, &sumtypes); if (retval) { CLEANUP_DONE (); goto error; } if (nsumtypes == 0) { retval = KRB5_BAD_ENCTYPE; krb5_free_cksumtypes (context, sumtypes); CLEANUP_DONE (); goto error; } for (i = 0; i < nsumtypes; i++) if (auth_context->safe_cksumtype == sumtypes[i]) break; krb5_free_cksumtypes (context, sumtypes); if (i < nsumtypes) sumtype = auth_context->safe_cksumtype; else { switch (enctype) { case ENCTYPE_DES_CBC_MD4: sumtype = CKSUMTYPE_RSA_MD4_DES; break; case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES_CBC_CRC: sumtype = CKSUMTYPE_RSA_MD5_DES; break; default: retval = krb5int_c_mandatory_cksumtype(context, enctype, &sumtype); if (retval) { CLEANUP_DONE(); goto error; } break; } } } if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata, plocal_fulladdr, premote_fulladdr, sumtype, outbuf))) { CLEANUP_DONE(); goto error; } CLEANUP_DONE(); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5_gen_replay_name(context, auth_context->local_addr, "_safe", &replay.client))) { free(outbuf); goto error; } replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { /* should we really error out here? XXX */ free(outbuf); goto error; } free(replay.client); } return 0; error: if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) auth_context->local_seq_number--; return retval; }
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; }
/* Get the RFC3961 mandator cksumtype for key. */ static inline krb5_error_code get_cksumtype(krb5_key key, krb5_cksumtype *out) { return krb5int_c_mandatory_cksumtype(NULL, key->keyblock.enctype, out); }
krb5_error_code KRB5_CALLCONV krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_data *outbuf) { krb5_error_code retval; krb5_checksum checksum; krb5_checksum *checksump = 0; krb5_auth_context new_auth_context; krb5_enctype *desired_etypes = NULL; krb5_ap_req request; krb5_data *scratch = 0; krb5_data *toutbuf; request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK; request.authenticator.ciphertext.data = NULL; request.ticket = 0; if (!in_creds->ticket.length) return(KRB5_NO_TKT_SUPPLIED); if ((ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) && !(ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) return(EINVAL); /* we need a native ticket */ if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket))) return(retval); /* verify that the ticket is not expired */ if ((retval = krb5_validate_times(context, &in_creds->times)) != 0) goto cleanup; /* generate auth_context if needed */ if (*auth_context == NULL) { if ((retval = krb5_auth_con_init(context, &new_auth_context))) goto cleanup; *auth_context = new_auth_context; } if ((*auth_context)->keyblock != NULL) { krb5_free_keyblock(context, (*auth_context)->keyblock); (*auth_context)->keyblock = NULL; } /* set auth context keyblock */ if ((retval = krb5_copy_keyblock(context, &in_creds->keyblock, &((*auth_context)->keyblock)))) goto cleanup; /* generate seq number if needed */ if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && ((*auth_context)->local_seq_number == 0)) if ((retval = krb5_generate_seq_number(context, &in_creds->keyblock, &(*auth_context)->local_seq_number))) goto cleanup; /* generate subkey if needed */ if (!in_data &&(*auth_context)->checksum_func) { retval = (*auth_context)->checksum_func( context, *auth_context, (*auth_context)->checksum_func_data, &in_data); if (retval) goto cleanup; } if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->send_subkey)) { retval = krb5int_generate_and_save_subkey (context, *auth_context, &in_creds->keyblock, in_creds->keyblock.enctype); if (retval) goto cleanup; } if (in_data) { if ((*auth_context)->req_cksumtype == 0x8003) { /* XXX Special hack for GSSAPI */ checksum.checksum_type = 0x8003; checksum.length = in_data->length; checksum.contents = (krb5_octet *) in_data->data; } else { krb5_cksumtype cksumtype; retval = krb5int_c_mandatory_cksumtype(context, (*auth_context)->keyblock->enctype, &cksumtype); if (retval) goto cleanup_cksum; if ((*auth_context)->req_cksumtype) cksumtype = (*auth_context)->req_cksumtype; if ((retval = krb5_c_make_checksum(context, cksumtype, (*auth_context)->keyblock, KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, in_data, &checksum))) goto cleanup_cksum; } checksump = &checksum; } /* Generate authenticator */ if (((*auth_context)->authentp = (krb5_authenticator *)malloc(sizeof( krb5_authenticator))) == NULL) { retval = ENOMEM; goto cleanup_cksum; } if (ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) { if ((*auth_context)->permitted_etypes == NULL) { retval = krb5_get_tgs_ktypes(context, in_creds->server, &desired_etypes); if (retval) goto cleanup_cksum; } else desired_etypes = (*auth_context)->permitted_etypes; } if ((retval = krb5_generate_authenticator(context, (*auth_context)->authentp, in_creds->client, checksump, (*auth_context)->send_subkey, (*auth_context)->local_seq_number, in_creds->authdata, (*auth_context)->ad_context, desired_etypes, in_creds->keyblock.enctype))) goto cleanup_cksum; /* encode the authenticator */ if ((retval = encode_krb5_authenticator((*auth_context)->authentp, &scratch))) goto cleanup_cksum; /* call the encryption routine */ if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock, KRB5_KEYUSAGE_AP_REQ_AUTH, scratch, &request.authenticator))) goto cleanup_cksum; if ((retval = encode_krb5_ap_req(&request, &toutbuf))) goto cleanup_cksum; *outbuf = *toutbuf; free(toutbuf); cleanup_cksum: /* Null out these fields, to prevent pointer sharing problems; * they were supplied by the caller */ if ((*auth_context)->authentp != NULL) { (*auth_context)->authentp->client = NULL; (*auth_context)->authentp->checksum = NULL; } if (checksump && checksump->checksum_type != 0x8003) free(checksump->contents); cleanup: if (desired_etypes && desired_etypes != (*auth_context)->permitted_etypes) free(desired_etypes); if (request.ticket) krb5_free_ticket(context, request.ticket); if (request.authenticator.ciphertext.data) { (void) memset(request.authenticator.ciphertext.data, 0, request.authenticator.ciphertext.length); free(request.authenticator.ciphertext.data); } if (scratch) { memset(scratch->data, 0, scratch->length); free(scratch->data); free(scratch); } return retval; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context = NULL; size_t i; struct test *test; krb5_keyblock kb, *kbp; krb5_checksum cksum; krb5_cksumtype mtype; krb5_boolean valid, verbose = FALSE; int status = 0; if (argc >= 2 && strcmp(argv[1], "-v") == 0) verbose = TRUE; for (i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) { test = &test_cases[i]; if (test->enctype != 0) { kb.magic = KV5M_KEYBLOCK; kb.enctype = test->enctype; kb.length = test->keybits.length; kb.contents = (unsigned char *)test->keybits.data; kbp = &kb; } else kbp = NULL; ret = krb5_c_make_checksum(context, test->sumtype, kbp, test->usage, &test->plaintext, &cksum); assert(!ret); if (verbose) { char buf[64]; krb5_cksumtype_to_string(test->sumtype, buf, sizeof(buf)); printf("\nTest %d:\n", (int)i); printf("Plaintext: %.*s\n", (int)test->plaintext.length, test->plaintext.data); printf("Checksum type: %s\n", buf); if (test->enctype != 0) { krb5_enctype_to_name(test->enctype, FALSE, buf, sizeof(buf)); printf("Enctype: %s\n", buf); printhex("Key: ", test->keybits.data, test->keybits.length); printf("Key usage: %d\n", (int)test->usage); } printhex("Checksum: ", cksum.contents, cksum.length); } if (test->cksum.length != cksum.length || memcmp(test->cksum.data, cksum.contents, cksum.length) != 0) { printf("derive test %d failed\n", (int)i); status = 1; if (!verbose) break; } /* Test that the checksum verifies successfully. */ ret = krb5_c_verify_checksum(context, kbp, test->usage, &test->plaintext, &cksum, &valid); assert(!ret); if (!valid) { printf("test %d verify failed\n", (int)i); status = 1; if (!verbose) break; } if (kbp != NULL) { ret = krb5int_c_mandatory_cksumtype(context, kbp->enctype, &mtype); assert(!ret); if (test->sumtype == mtype) { /* Test that a checksum type of 0 uses the mandatory checksum * type for the key. */ cksum.checksum_type = 0; ret = krb5_c_verify_checksum(context, kbp, test->usage, &test->plaintext, &cksum, &valid); assert(!ret && valid); } } krb5_free_checksum_contents(context, &cksum); } return status; }
krb5_error_code krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *state, krb5_kdc_req *request, const krb5_data *to_be_checksummed, kdc_req_encoder_proc encoder, krb5_data **encoded_request) { krb5_error_code retval = 0; krb5_pa_data *pa_array[2]; krb5_pa_data pa[2]; krb5_fast_req fast_req; krb5_fast_armored_req *armored_req = NULL; krb5_data *encoded_fast_req = NULL; krb5_data *encoded_armored_req = NULL; krb5_data *local_encoded_result = NULL; krb5_cksumtype cksumtype; krb5_data random_data; char random_buf[4]; assert(state != NULL); assert(state->fast_outer_request.padata == NULL); memset(pa_array, 0, sizeof pa_array); if (state->armor_key == NULL) { return encoder(request, encoded_request); } /* Fill in a fresh random nonce for each inner request*/ random_data.length = 4; random_data.data = (char *)random_buf; retval = krb5_c_random_make_octets(context, &random_data); if (retval == 0) { request->nonce = 0x7fffffff & load_32_n(random_buf); state->nonce = request->nonce; } fast_req.req_body = request; if (fast_req.req_body->padata == NULL) { fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *)); if (fast_req.req_body->padata == NULL) retval = ENOMEM; } fast_req.fast_options = state->fast_options; if (retval == 0) retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req); if (retval == 0) { armored_req = calloc(1, sizeof(krb5_fast_armored_req)); if (armored_req == NULL) retval = ENOMEM; } if (retval == 0) armored_req->armor = state->armor; if (retval == 0) retval = krb5int_c_mandatory_cksumtype(context, state->armor_key->enctype, &cksumtype); if (retval ==0) retval = krb5_c_make_checksum(context, cksumtype, state->armor_key, KRB5_KEYUSAGE_FAST_REQ_CHKSUM, to_be_checksummed, &armored_req->req_checksum); if (retval == 0) retval = krb5_encrypt_helper(context, state->armor_key, KRB5_KEYUSAGE_FAST_ENC, encoded_fast_req, &armored_req->enc_part); if (retval == 0) retval = encode_krb5_pa_fx_fast_request(armored_req, &encoded_armored_req); if (retval==0) { pa[0].pa_type = KRB5_PADATA_FX_FAST; pa[0].contents = (unsigned char *) encoded_armored_req->data; pa[0].length = encoded_armored_req->length; pa_array[0] = &pa[0]; } state->fast_outer_request.padata = pa_array; if(retval == 0) retval = encoder(&state->fast_outer_request, &local_encoded_result); if (retval == 0) { *encoded_request = local_encoded_result; local_encoded_result = NULL; } if (encoded_armored_req) krb5_free_data(context, encoded_armored_req); if (armored_req) { armored_req->armor = NULL; /*owned by state*/ krb5_free_fast_armored_req(context, armored_req); } if (encoded_fast_req) krb5_free_data(context, encoded_fast_req); if (local_encoded_result) krb5_free_data(context, local_encoded_result); state->fast_outer_request.padata = NULL; return retval; }