KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_rd_req_out_get_keyblock(krb5_context context, krb5_rd_req_out_ctx out, krb5_keyblock **keyblock) { return krb5_copy_keyblock(context, out->keyblock, keyblock); }
mit_krb5_error_code KRB5_CALLCONV krb5_kt_read_service_key(mit_krb5_context context, mit_krb5_pointer keyprocarg, mit_krb5_principal principal, mit_krb5_kvno vno, mit_krb5_enctype enctype, mit_krb5_keyblock **key) { mit_krb5_keytab keytab; mit_krb5_keytab_entry entry; mit_krb5_error_code ret; LOG_ENTRY(); if (keyprocarg) ret = krb5_kt_resolve (context, keyprocarg, &keytab); else ret = krb5_kt_default (context, &keytab); if (ret) return ret; ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry); krb5_kt_close (context, keytab); if (ret) return ret; ret = krb5_copy_keyblock (context, &entry.key, key); krb5_kt_free_entry(context, &entry); return ret; }
krb5_error_code KRB5_LIB_FUNCTION krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key) { krb5_keytab keytab; krb5_keytab_entry entry; krb5_error_code ret; if (keyprocarg) ret = krb5_kt_resolve (context, keyprocarg, &keytab); else ret = krb5_kt_default (context, &keytab); if (ret) return ret; ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry); krb5_kt_close (context, keytab); if (ret) return ret; ret = krb5_copy_keyblock (context, &entry.keyblock, key); krb5_kt_free_entry(context, &entry); return ret; }
static krb5_error_code HMAC_MD5_any_checksum(krb5_context context, const krb5_keyblock *key, const void *data, size_t len, unsigned usage, Checksum *result) { struct key_data local_key; krb5_error_code ret; memset(&local_key, 0, sizeof(local_key)); ret = krb5_copy_keyblock(context, key, &local_key.key); if (ret) return ret; ret = krb5_data_alloc (&result->checksum, 16); if (ret) { krb5_free_keyblock(context, local_key.key); return ret; } result->cksumtype = CKSUMTYPE_HMAC_MD5; ret = _krb5_HMAC_MD5_checksum(context, &local_key, data, len, usage, result); if (ret) krb5_data_free(&result->checksum); krb5_free_keyblock(context, local_key.key); return ret; }
KRB5_DEPRECATED KRB5_LIB_FUNCTION krb5_error_code KRB5_CALLCONV krb5_keytab_key_proc (krb5_context context, krb5_enctype enctype, krb5_salt salt, krb5_const_pointer keyseed, krb5_keyblock **key) { krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed); krb5_keytab keytab = args->keytab; krb5_principal principal = args->principal; krb5_error_code ret; krb5_keytab real_keytab; krb5_keytab_entry entry; if(keytab == NULL) krb5_kt_default(context, &real_keytab); else real_keytab = keytab; ret = krb5_kt_get_entry (context, real_keytab, principal, 0, enctype, &entry); if (keytab == NULL) krb5_kt_close (context, real_keytab); if (ret) return ret; ret = krb5_copy_keyblock (context, &entry.keyblock, key); krb5_kt_free_entry(context, &entry); return ret; }
static krb5_error_code keyblock_key_proc(krb5_context context, krb5_enctype enctype, krb5_const_pointer keyseed, krb5_salt salt, krb5_data *s2kparms, krb5_keyblock **key) { return krb5_copy_keyblock (context, keyseed, key); }
static krb5_error_code KRB5_CALLCONV krb5_skey_key_proc (krb5_context context, krb5_enctype type, krb5_salt salt, krb5_const_pointer keyseed, krb5_keyblock **key) { return krb5_copy_keyblock (context, keyseed, key); }
krb5_error_code KRB5_LIB_FUNCTION krb5_keyblock_key_proc (krb5_context context, krb5_keytype type, krb5_data *salt, krb5_const_pointer keyseed, krb5_keyblock **key) { return krb5_copy_keyblock (context, keyseed, key); }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_auth_con_setuserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock) { if(auth_context->keyblock) krb5_free_keyblock(context, auth_context->keyblock); return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock); }
static krb5_error_code copy_key(krb5_context context, krb5_keyblock *in, krb5_keyblock **out) { if(in) return krb5_copy_keyblock(context, in, out); *out = NULL; /* is this right? */ return 0; }
static krb5_error_code krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent, krb5_principal client, krb5_checksum *cksum, krb5_keyblock *key, krb5_ui_4 seq_number, krb5_authdata **authorization, krb5_authdata_context ad_context, krb5_enctype *desired_etypes, krb5_enctype tkt_enctype) { krb5_error_code retval; krb5_authdata **ext_authdata = NULL; authent->client = client; authent->checksum = cksum; if (key) { retval = krb5_copy_keyblock(context, key, &authent->subkey); if (retval) return retval; } else authent->subkey = 0; authent->seq_number = seq_number; authent->authorization_data = NULL; if (ad_context != NULL) { retval = krb5_authdata_export_authdata(context, ad_context, AD_USAGE_AP_REQ, &ext_authdata); if (retval) return retval; } if (authorization != NULL || ext_authdata != NULL) { retval = krb5_merge_authdata(context, authorization, ext_authdata, &authent->authorization_data); if (retval) { krb5_free_authdata(context, ext_authdata); return retval; } krb5_free_authdata(context, ext_authdata); } /* Only send EtypeList if we prefer another enctype to tkt_enctype */ if (desired_etypes != NULL && desired_etypes[0] != tkt_enctype) { retval = make_etype_list(context, desired_etypes, tkt_enctype, &authent->authorization_data); if (retval) return retval; } return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec)); }
krb5_error_code KRB5_CALLCONV krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, krb5_authenticator **authto) { krb5_error_code retval; krb5_authenticator *tempto; if (!(tempto = (krb5_authenticator *)MALLOC(sizeof(*tempto)))) return ENOMEM; #ifdef HAVE_C_STRUCTURE_ASSIGNMENT *tempto = *authfrom; #else (void) memcpy(tempto, authfrom, sizeof(krb5_authenticator)); #endif retval = krb5_copy_principal(context, authfrom->client, &tempto->client); if (retval) { krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } if (authfrom->checksum && (retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) { krb5_free_principal(context, tempto->client); krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } if (authfrom->subkey) { retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey); if (retval) { krb5_xfree_wrap(tempto->subkey, sizeof(krb5_keyblock)); krb5_free_checksum(context, tempto->checksum); krb5_free_principal(context, tempto->client); krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } } if (authfrom->authorization_data) { retval = krb5_copy_authdata(context, authfrom->authorization_data, &tempto->authorization_data); if (retval) { krb5_xfree_wrap(tempto->subkey, sizeof(krb5_keyblock)); krb5_free_checksum(context, tempto->checksum); krb5_free_principal(context, tempto->client); krb5_free_authdata(context, tempto->authorization_data); krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } } *authto = tempto; return 0; }
// Get session key from ccache or service ticket. void DecryptionManager::PacketHandler::readServiceSessionKey( krb5_ticket* ticket) { Krb5CCache *ccache = decryptionManager_->getCCache(); if (ccache) { Krb5Credentials creds = ccache->retrieveCred(ticket->server); krb5_copy_keyblock(ctx_->get(), &creds.get().keyblock, &sessionKey_); } else { krb5_error_code code = krb5_server_decrypt_ticket_keytab( ctx_->get(), decryptionManager_->getServerKeytab()->get(), ticket); if (code) { onError("Cannot decrypt service ticket using the given server keytab"); return; } krb5_copy_keyblock(ctx_->get(), ticket->enc_part2->session, &sessionKey_); } }
static krb5_error_code get_as_key_keytab(krb5_context context, krb5_principal client, krb5_enctype etype, krb5_prompter_fct prompter, void *prompter_data, krb5_data *salt, krb5_data *params, krb5_keyblock *as_key, void *gak_data, k5_response_items *ritems) { krb5_keytab keytab = (krb5_keytab) gak_data; krb5_error_code ret; krb5_keytab_entry kt_ent; krb5_keyblock *kt_key; /* We don't need the password from the responder to create the AS key. */ if (as_key == NULL) return 0; /* if there's already a key of the correct etype, we're done. if the etype is wrong, free the existing key, and make a new one. */ if (as_key->length) { if (as_key->enctype == etype) return(0); krb5_free_keyblock_contents(context, as_key); as_key->length = 0; } if (!krb5_c_valid_enctype(etype)) return(KRB5_PROG_ETYPE_NOSUPP); if ((ret = krb5_kt_get_entry(context, keytab, client, 0, /* don't have vno available */ etype, &kt_ent))) return(ret); ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key); /* again, krb5's memory management is lame... */ *as_key = *kt_key; free(kt_key); (void) krb5_kt_free_entry(context, &kt_ent); return(ret); }
void encryption_init (krb5_creds * creds) { krb5_keyblock *newkey = 0; krb5_auth_con_getlocalsubkey (telnet_context, auth_context, &newkey); if (session_key) { krb5_free_keyblock (telnet_context, session_key); session_key = 0; } if (newkey) { switch (newkey->enctype) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD5: krb5_copy_keyblock (telnet_context, newkey, &session_key); break; default: switch (creds->keyblock.enctype) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD5: krb5_copy_keyblock (telnet_context, &creds->keyblock, &session_key); break; default: DEBUG (("can't determine which keyblock to use")); /*FIXME: abort? */ } } krb5_free_keyblock (telnet_context, newkey); } }
krb5_error_code KRB5_CALLCONV krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, krb5_authenticator **authto) { krb5_error_code retval; krb5_authenticator *tempto; if (!(tempto = (krb5_authenticator *)malloc(sizeof(*tempto)))) return ENOMEM; *tempto = *authfrom; retval = krb5_copy_principal(context, authfrom->client, &tempto->client); if (retval) { free(tempto); return retval; } if (authfrom->checksum && (retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) { krb5_free_principal(context, tempto->client); free(tempto); return retval; } if (authfrom->subkey) { retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey); if (retval) { free(tempto->subkey); krb5_free_checksum(context, tempto->checksum); krb5_free_principal(context, tempto->client); free(tempto); return retval; } } if (authfrom->authorization_data) { retval = krb5_copy_authdata(context, authfrom->authorization_data, &tempto->authorization_data); if (retval) { free(tempto->subkey); krb5_free_checksum(context, tempto->checksum); krb5_free_principal(context, tempto->client); krb5_free_authdata(context, tempto->authorization_data); free(tempto); return retval; } } *authto = tempto; return 0; }
void ZSetSession(krb5_keyblock *keyblock) { krb5_error_code result; if (__Zephyr_keyblock) { krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock); result = krb5_copy_keyblock_contents(Z_krb5_ctx, keyblock, __Zephyr_keyblock); } else { result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &__Zephyr_keyblock); } if (result) /*XXX we're out of memory? */ return; }
krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, krb5_keyblock *existing_key, krb5_keyblock **out_key) { krb5_error_code retval = 0; kdc_realm_t *kdc_active_realm = state->realm_data; if (state->armor_key) retval = krb5_c_fx_cf2_simple(kdc_context, state->strengthen_key, "strengthenkey", existing_key, "replykey", out_key); else retval = krb5_copy_keyblock(kdc_context, existing_key, out_key); return retval; }
static krb5_error_code get_key_from_keytab(krb5_context context, krb5_auth_context *auth_context, krb5_ap_req *ap_req, krb5_const_principal server, krb5_keytab keytab, krb5_keyblock **out_key) { krb5_keytab_entry entry; krb5_error_code ret; int kvno; krb5_keytab real_keytab; if(keytab == NULL) krb5_kt_default(context, &real_keytab); else real_keytab = keytab; if (ap_req->ticket.enc_part.kvno) kvno = *ap_req->ticket.enc_part.kvno; else kvno = 0; ret = krb5_kt_get_entry (context, real_keytab, server, kvno, ap_req->ticket.enc_part.etype, &entry); if(ret) goto out; ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); krb5_kt_free_entry (context, &entry); out: if(keytab == NULL) krb5_kt_close(context, real_keytab); return ret; }
krb5_error_code krb5int_generate_and_save_subkey (krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock, krb5_enctype enctype) { /* Provide some more fodder for random number code. This isn't strong cryptographically; the point here is not to guarantee randomness, but to make it less likely that multiple sessions could pick the same subkey. */ struct { krb5_int32 sec, usec; } rnd_data; krb5_data d; krb5_error_code retval; krb5_crypto_us_timeofday (&rnd_data.sec, &rnd_data.usec); d.length = sizeof (rnd_data); d.data = (char *) &rnd_data; (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_TIMING, &d); if (auth_context->send_subkey) krb5_free_keyblock(context, auth_context->send_subkey); if ((retval = krb5_generate_subkey_extended(context, keyblock, enctype, &auth_context->send_subkey))) return retval; if (auth_context->recv_subkey) krb5_free_keyblock(context, auth_context->recv_subkey); retval = krb5_copy_keyblock(context, auth_context->send_subkey, &auth_context->recv_subkey); if (retval) { krb5_free_keyblock(context, auth_context->send_subkey); auth_context->send_subkey = NULL; return retval; } return 0; }
static krb5_error_code HMAC_MD5_any_checksum(krb5_context context, const krb5_keyblock *key, const void *data, size_t len, unsigned usage, Checksum *result) { struct _krb5_key_data local_key; struct krb5_crypto_iov iov; krb5_error_code ret; memset(&local_key, 0, sizeof(local_key)); ret = krb5_copy_keyblock(context, key, &local_key.key); if (ret) return ret; ret = krb5_data_alloc (&result->checksum, 16); if (ret) { krb5_free_keyblock(context, local_key.key); return ret; } result->cksumtype = CKSUMTYPE_HMAC_MD5; iov.data.data = (void *)data; iov.data.length = len; iov.flags = KRB5_CRYPTO_TYPE_DATA; ret = _krb5_HMAC_MD5_checksum(context, NULL, &local_key, usage, &iov, 1, result); if (ret) krb5_data_free(&result->checksum); krb5_free_keyblock(context, local_key.key); return ret; }
/* * effects: If keyprocarg is not NULL, it is taken to be the name of a * keytab. Otherwise, the default keytab will be used. This * routine opens the keytab and finds the principal associated with * principal, vno, and enctype and returns the resulting key in *key * or returning an error code if it is not found. * returns: Either KSUCCESS or error code. * errors: error code if not found or keyprocarg is invalid. */ krb5_error_code KRB5_CALLCONV krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key) { krb5_error_code kerror = KSUCCESS; char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */ krb5_keytab id; krb5_keytab_entry entry; /* * Get the name of the file that we should use. */ if (!keyprocarg) { if ((kerror = krb5_kt_default_name(context, (char *)keytabname, sizeof(keytabname) - 1))!= KSUCCESS) return (kerror); } else { memset(keytabname, 0, sizeof(keytabname)); (void) strncpy(keytabname, (char *)keyprocarg, sizeof(keytabname) - 1); } if ((kerror = krb5_kt_resolve(context, (char *)keytabname, &id))) return (kerror); kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry); krb5_kt_close(context, id); if (kerror) return(kerror); krb5_copy_keyblock(context, &entry.key, key); krb5_kt_free_entry(context, &entry); return (KSUCCESS); }
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 }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_rd_req_ctx(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_rd_req_in_ctx inctx, krb5_rd_req_out_ctx *outctx) { krb5_error_code ret; krb5_ap_req ap_req; krb5_rd_req_out_ctx o = NULL; krb5_keytab id = NULL, keytab = NULL; krb5_principal service = NULL; *outctx = NULL; o = calloc(1, sizeof(*o)); if (o == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); if (ret) goto out; } ret = krb5_decode_ap_req(context, inbuf, &ap_req); if(ret) goto out; /* Save that principal that was in the request */ ret = _krb5_principalname2krb5_principal(context, &o->server, ap_req.ticket.sname, ap_req.ticket.realm); if (ret) goto out; if (ap_req.ap_options.use_session_key && (*auth_context)->keyblock == NULL) { ret = KRB5KRB_AP_ERR_NOKEY; krb5_set_error_message(context, ret, N_("krb5_rd_req: user to user auth " "without session key given", "")); goto out; } if (inctx && inctx->keytab) id = inctx->keytab; if((*auth_context)->keyblock){ ret = krb5_copy_keyblock(context, (*auth_context)->keyblock, &o->keyblock); if (ret) goto out; } else if(inctx && inctx->keyblock){ ret = krb5_copy_keyblock(context, inctx->keyblock, &o->keyblock); if (ret) goto out; } else { if(id == NULL) { krb5_kt_default(context, &keytab); id = keytab; } if (id == NULL) goto out; if (server == NULL) { ret = _krb5_principalname2krb5_principal(context, &service, ap_req.ticket.sname, ap_req.ticket.realm); if (ret) goto out; server = service; } ret = get_key_from_keytab(context, &ap_req, server, id, &o->keyblock); if (ret) { /* If caller specified a server, fail. */ if (service == NULL && (context->flags & KRB5_CTX_F_RD_REQ_IGNORE) == 0) goto out; /* Otherwise, fall back to iterating over the keytab. This * have serious performace issues for larger keytab. */ o->keyblock = NULL; } } if (o->keyblock) { /* * We got an exact keymatch, use that. */ ret = krb5_verify_ap_req2(context, auth_context, &ap_req, server, o->keyblock, 0, &o->ap_req_options, &o->ticket, KRB5_KU_AP_REQ_AUTH); if (ret) goto out; } else { /* * Interate over keytab to find a key that can decrypt the request. */ krb5_keytab_entry entry; krb5_kt_cursor cursor; int done = 0, kvno = 0; memset(&cursor, 0, sizeof(cursor)); if (ap_req.ticket.enc_part.kvno) kvno = *ap_req.ticket.enc_part.kvno; ret = krb5_kt_start_seq_get(context, id, &cursor); if (ret) goto out; done = 0; while (!done) { krb5_principal p; ret = krb5_kt_next_entry(context, id, &entry, &cursor); if (ret) { _krb5_kt_principal_not_found(context, ret, id, o->server, ap_req.ticket.enc_part.etype, kvno); krb5_kt_end_seq_get(context, id, &cursor); goto out; } if (entry.keyblock.keytype != ap_req.ticket.enc_part.etype) { krb5_kt_free_entry (context, &entry); continue; } ret = krb5_verify_ap_req2(context, auth_context, &ap_req, server, &entry.keyblock, 0, &o->ap_req_options, &o->ticket, KRB5_KU_AP_REQ_AUTH); if (ret) { krb5_kt_free_entry(context, &entry); continue; } /* * Found a match, save the keyblock for PAC processing, * and update the service principal in the ticket to match * whatever is in the keytab. */ ret = krb5_copy_keyblock(context, &entry.keyblock, &o->keyblock); if (ret) { krb5_kt_free_entry(context, &entry); krb5_kt_end_seq_get(context, id, &cursor); goto out; } ret = krb5_copy_principal(context, entry.principal, &p); if (ret) { krb5_kt_free_entry(context, &entry); krb5_kt_end_seq_get(context, id, &cursor); goto out; } krb5_free_principal(context, o->ticket->server); o->ticket->server = p; krb5_kt_free_entry(context, &entry); done = 1; } krb5_kt_end_seq_get(context, id, &cursor); } /* If there is a PAC, verify its server signature */ if (inctx == NULL || inctx->check_pac) { krb5_pac pac; krb5_data data; ret = krb5_ticket_get_authorization_data_type(context, o->ticket, KRB5_AUTHDATA_WIN2K_PAC, &data); if (ret == 0) { ret = krb5_pac_parse(context, data.data, data.length, &pac); krb5_data_free(&data); if (ret) goto out; ret = krb5_pac_verify(context, pac, o->ticket->ticket.authtime, o->ticket->client, o->keyblock, NULL); krb5_pac_free(context, pac); if (ret == 0) o->flags |= KRB5_RD_REQ_OUT_PAC_VALID; ret = 0; } else ret = 0; } out: if (ret || outctx == NULL) { krb5_rd_req_out_ctx_free(context, o); } else *outctx = o; free_AP_REQ(&ap_req); if (service) krb5_free_principal(context, service); if (keytab) krb5_kt_close(context, keytab); return ret; }
krb5_error_code KRB5_CALLCONV krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_ap_rep_enc_part **repl) { krb5_error_code retval; krb5_ap_rep * reply; krb5_data scratch; if (!krb5_is_ap_rep(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; /* decode it */ if ((retval = decode_krb5_ap_rep(inbuf, &reply))) return retval; /* put together an eblock for this encryption */ scratch.length = reply->enc_part.ciphertext.length; if (!(scratch.data = malloc(scratch.length))) { krb5_free_ap_rep(context, reply); return(ENOMEM); } if ((retval = krb5_c_decrypt(context, auth_context->keyblock, KRB5_KEYUSAGE_AP_REP_ENCPART, 0, &reply->enc_part, &scratch))) goto clean_scratch; /* now decode the decrypted stuff */ retval = decode_krb5_ap_rep_enc_part(&scratch, repl); if (retval) goto clean_scratch; /* Check reply fields */ if (((*repl)->ctime != auth_context->authentp->ctime) || ((*repl)->cusec != auth_context->authentp->cusec)) { retval = KRB5_MUTUAL_FAILED; goto clean_scratch; } /* Set auth subkey */ if ((*repl)->subkey) { if (auth_context->recv_subkey) { krb5_free_keyblock(context, auth_context->recv_subkey); auth_context->recv_subkey = NULL; } retval = krb5_copy_keyblock(context, (*repl)->subkey, &auth_context->recv_subkey); if (retval) goto clean_scratch; if (auth_context->send_subkey) { krb5_free_keyblock(context, auth_context->send_subkey); auth_context->send_subkey = NULL; } retval = krb5_copy_keyblock(context, (*repl)->subkey, &auth_context->send_subkey); if (retval) { krb5_free_keyblock(context, auth_context->send_subkey); auth_context->send_subkey = NULL; } /* not used for anything yet */ auth_context->negotiated_etype = (*repl)->subkey->enctype; } /* Get remote sequence number */ auth_context->remote_seq_number = (*repl)->seq_number; clean_scratch: memset(scratch.data, 0, scratch.length); krb5_free_ap_rep(context, reply); free(scratch.data); return retval; }
krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_ctx(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_rd_req_in_ctx inctx, krb5_rd_req_out_ctx *outctx) { krb5_error_code ret; krb5_ap_req ap_req; krb5_principal service = NULL; krb5_rd_req_out_ctx o = NULL; ret = _krb5_rd_req_out_ctx_alloc(context, &o); if (ret) goto out; if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); if (ret) goto out; } ret = krb5_decode_ap_req(context, inbuf, &ap_req); if(ret) goto out; if(server == NULL){ ret = _krb5_principalname2krb5_principal(context, &service, ap_req.ticket.sname, ap_req.ticket.realm); if (ret) goto out; server = service; } if (ap_req.ap_options.use_session_key && (*auth_context)->keyblock == NULL) { krb5_set_error_string(context, "krb5_rd_req: user to user auth " "without session key given"); ret = KRB5KRB_AP_ERR_NOKEY; goto out; } if((*auth_context)->keyblock){ ret = krb5_copy_keyblock(context, (*auth_context)->keyblock, &o->keyblock); if (ret) goto out; } else if(inctx->keyblock){ ret = krb5_copy_keyblock(context, inctx->keyblock, &o->keyblock); if (ret) goto out; } else { krb5_keytab keytab = NULL; if (inctx && inctx->keytab) keytab = inctx->keytab; ret = get_key_from_keytab(context, auth_context, &ap_req, server, keytab, &o->keyblock); if(ret) goto out; } ret = krb5_verify_ap_req2(context, auth_context, &ap_req, server, o->keyblock, 0, &o->ap_req_options, &o->ticket, KRB5_KU_AP_REQ_AUTH); if (ret) goto out; /* If there is a PAC, verify its server signature */ if (inctx->check_pac) { krb5_pac pac; krb5_data data; ret = krb5_ticket_get_authorization_data_type(context, o->ticket, KRB5_AUTHDATA_WIN2K_PAC, &data); if (ret == 0) { ret = krb5_pac_parse(context, data.data, data.length, &pac); krb5_data_free(&data); if (ret) goto out; ret = krb5_pac_verify(context, pac, o->ticket->ticket.authtime, o->ticket->client, o->keyblock, NULL); krb5_pac_free(context, pac); if (ret) goto out; } ret = 0; } out: if (ret || outctx == NULL) { krb5_rd_req_out_ctx_free(context, o); } else *outctx = o; free_AP_REQ(&ap_req); if(service) krb5_free_principal(context, service); return ret; }
static krb5_error_code make_seal_token_v1_iov(krb5_context context, krb5_gss_ctx_id_rec *ctx, int conf_req_flag, int *conf_state, gss_iov_buffer_desc *iov, int iov_count, int toktype) { krb5_error_code code = 0; gss_iov_buffer_t header; gss_iov_buffer_t padding; gss_iov_buffer_t trailer; krb5_checksum md5cksum; krb5_checksum cksum; size_t k5_headerlen = 0, k5_trailerlen = 0; size_t data_length = 0, assoc_data_length = 0; size_t tmsglen = 0, tlen; unsigned char *ptr; krb5_keyusage sign_usage = KG_USAGE_SIGN; assert(toktype == KG_TOK_WRAP_MSG); md5cksum.length = cksum.length = 0; md5cksum.contents = cksum.contents = NULL; header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); if (header == NULL) return EINVAL; padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); if (padding == NULL && (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) return EINVAL; trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); if (trailer != NULL) trailer->buffer.length = 0; /* Determine confounder length */ if (toktype == KG_TOK_WRAP_MSG || conf_req_flag) k5_headerlen = kg_confounder_size(context, ctx->enc); /* Check padding length */ if (toktype == KG_TOK_WRAP_MSG) { size_t k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8; size_t gss_padlen; size_t conf_data_length; kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); conf_data_length = k5_headerlen + data_length - assoc_data_length; if (k5_padlen == 1) gss_padlen = 1; /* one byte to indicate one byte of padding */ else gss_padlen = k5_padlen - (conf_data_length % k5_padlen); if (ctx->gss_flags & GSS_C_DCE_STYLE) { /* DCE will pad the actual data itself; padding buffer optional and will be zeroed */ gss_padlen = 0; if (conf_data_length % k5_padlen) code = KRB5_BAD_MSIZE; } else if (padding->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { code = kg_allocate_iov(padding, gss_padlen); } else if (padding->buffer.length < gss_padlen) { code = KRB5_BAD_MSIZE; } if (code != 0) goto cleanup; /* Initialize padding buffer to pad itself */ if (padding != NULL) { padding->buffer.length = gss_padlen; memset(padding->buffer.value, (int)gss_padlen, gss_padlen); } if (ctx->gss_flags & GSS_C_DCE_STYLE) tmsglen = k5_headerlen; /* confounder length */ else tmsglen = conf_data_length + padding->buffer.length + assoc_data_length; } /* Determine token size */ tlen = g_token_size(ctx->mech_used, 14 + ctx->cksum_size + tmsglen); k5_headerlen += tlen - tmsglen; if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) code = kg_allocate_iov(header, k5_headerlen); else if (header->buffer.length < k5_headerlen) code = KRB5_BAD_MSIZE; if (code != 0) goto cleanup; header->buffer.length = k5_headerlen; ptr = (unsigned char *)header->buffer.value; g_make_token_header(ctx->mech_used, 14 + ctx->cksum_size + tmsglen, &ptr, toktype); /* 0..1 SIGN_ALG */ store_16_le(ctx->signalg, &ptr[0]); /* 2..3 SEAL_ALG or Filler */ if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { store_16_le(ctx->sealalg, &ptr[2]); } else { /* No seal */ ptr[2] = 0xFF; ptr[3] = 0xFF; } /* 4..5 Filler */ ptr[4] = 0xFF; ptr[5] = 0xFF; /* pad the plaintext, encrypt if needed, and stick it in the token */ /* initialize the checksum */ switch (ctx->signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_MD2_5: md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; break; case SGN_ALG_HMAC_SHA1_DES3_KD: md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; break; case SGN_ALG_HMAC_MD5: md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; if (toktype != KG_TOK_WRAP_MSG) sign_usage = 15; break; default: case SGN_ALG_DES_MAC: abort (); } code = krb5_c_checksum_length(context, md5cksum.checksum_type, &k5_trailerlen); if (code != 0) goto cleanup; md5cksum.length = k5_trailerlen; if (k5_headerlen != 0) { code = kg_make_confounder(context, ctx->enc, ptr + 14 + ctx->cksum_size); if (code != 0) goto cleanup; } /* compute the checksum */ code = kg_make_checksum_iov_v1(context, md5cksum.checksum_type, ctx->cksum_size, ctx->seq, ctx->enc, sign_usage, iov, iov_count, toktype, &md5cksum); if (code != 0) goto cleanup; switch (ctx->signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_3: code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? ctx->seq->contents : NULL), md5cksum.contents, md5cksum.contents, 16); if (code != 0) goto cleanup; cksum.length = ctx->cksum_size; cksum.contents = md5cksum.contents + 16 - cksum.length; memcpy(ptr + 14, cksum.contents, cksum.length); break; case SGN_ALG_HMAC_SHA1_DES3_KD: assert(md5cksum.length == ctx->cksum_size); memcpy(ptr + 14, md5cksum.contents, md5cksum.length); break; case SGN_ALG_HMAC_MD5: memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size); break; } /* create the seq_num */ code = kg_make_seq_num(context, ctx->seq, ctx->initiate ? 0 : 0xFF, (OM_uint32)ctx->seq_send, ptr + 14, ptr + 6); if (code != 0) goto cleanup; if (conf_req_flag) { if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { unsigned char bigend_seqnum[4]; krb5_keyblock *enc_key; size_t i; store_32_be(ctx->seq_send, bigend_seqnum); code = krb5_copy_keyblock(context, ctx->enc, &enc_key); if (code != 0) goto cleanup; assert(enc_key->length == 16); for (i = 0; i < enc_key->length; i++) ((char *)enc_key->contents)[i] ^= 0xF0; code = kg_arcfour_docrypt_iov(context, enc_key, 0, bigend_seqnum, 4, iov, iov_count); krb5_free_keyblock(context, enc_key); } else { code = kg_encrypt_iov(context, ctx->proto, ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), 0 /*EC*/, 0 /*RRC*/, ctx->enc, KG_USAGE_SEAL, NULL, iov, iov_count); } if (code != 0) goto cleanup; } ctx->seq_send++; ctx->seq_send &= 0xFFFFFFFFL; code = 0; if (conf_state != NULL) *conf_state = conf_req_flag; cleanup: if (code != 0) kg_release_iov(iov, iov_count); krb5_free_checksum_contents(context, &md5cksum); return code; }
static krb5_error_code krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context, const krb5_ap_req *req, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket, int check_valid_flag) { krb5_error_code retval = 0; krb5_timestamp currenttime; krb5_principal_data princ_data; req->ticket->enc_part2 == NULL; if (server && krb5_is_referral_realm(&server->realm)) { char *realm; princ_data = *server; server = &princ_data; retval = krb5_get_default_realm(context, &realm); if (retval) return retval; princ_data.realm.data = realm; princ_data.realm.length = strlen(realm); } if (server && !krb5_principal_compare(context, server, req->ticket->server)) { char *found_name = 0, *wanted_name = 0; if (krb5_unparse_name(context, server, &wanted_name) == 0 && krb5_unparse_name(context, req->ticket->server, &found_name) == 0) krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request (found %s, wanted %s)", found_name, wanted_name); krb5_free_unparsed_name(context, wanted_name); krb5_free_unparsed_name(context, found_name); retval = KRB5KRB_AP_WRONG_PRINC; goto cleanup; } /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY) do we need special processing here ? */ /* decrypt the ticket */ if ((*auth_context)->keyblock) { /* User to User authentication */ if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock, req->ticket))) goto cleanup; krb5_free_keyblock(context, (*auth_context)->keyblock); (*auth_context)->keyblock = NULL; } else { if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab))) goto cleanup; } /* XXX this is an evil hack. check_valid_flag is set iff the call is not from inside the kdc. we can use this to determine which key usage to use */ if ((retval = decrypt_authenticator(context, req, &((*auth_context)->authentp), check_valid_flag))) goto cleanup; if (!krb5_principal_compare(context, (*auth_context)->authentp->client, req->ticket->enc_part2->client)) { retval = KRB5KRB_AP_ERR_BADMATCH; goto cleanup; } if ((*auth_context)->remote_addr && !krb5_address_search(context, (*auth_context)->remote_addr, req->ticket->enc_part2->caddrs)) { retval = KRB5KRB_AP_ERR_BADADDR; goto cleanup; } /* okay, now check cross-realm policy */ #if defined(_SINGLE_HOP_ONLY) /* Single hop cross-realm tickets only */ { krb5_transited *trans = &(req->ticket->enc_part2->transited); /* If the transited list is empty, then we have at most one hop */ if (trans->tr_contents.data && trans->tr_contents.data[0]) retval = KRB5KRB_AP_ERR_ILL_CR_TKT; } #elif defined(_NO_CROSS_REALM) /* No cross-realm tickets */ { char * lrealm; krb5_data * realm; krb5_transited * trans; realm = krb5_princ_realm(context, req->ticket->enc_part2->client); trans = &(req->ticket->enc_part2->transited); /* * If the transited list is empty, then we have at most one hop * So we also have to check that the client's realm is the local one */ krb5_get_default_realm(context, &lrealm); if ((trans->tr_contents.data && trans->tr_contents.data[0]) || strlen(lrealm) != realm->length || memcmp(lrealm, realm->data, strlen(lrealm))) { retval = KRB5KRB_AP_ERR_ILL_CR_TKT; } free(lrealm); } #else /* Hierarchical Cross-Realm */ { krb5_data * realm; krb5_transited * trans; realm = krb5_princ_realm(context, req->ticket->enc_part2->client); trans = &(req->ticket->enc_part2->transited); /* * If the transited list is not empty, then check that all realms * transited are within the hierarchy between the client's realm * and the local realm. */ if (trans->tr_contents.data && trans->tr_contents.data[0]) { retval = krb5_check_transited_list(context, &(trans->tr_contents), realm, krb5_princ_realm (context, server)); } } #endif if (retval) goto cleanup; /* only check rcache if sender has provided one---some services may not be able to use replay caches (such as datagram servers) */ if ((*auth_context)->rcache) { krb5_donot_replay rep; krb5_tkt_authent tktauthent; tktauthent.ticket = req->ticket; tktauthent.authenticator = (*auth_context)->authentp; if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) { retval = krb5_rc_store(context, (*auth_context)->rcache, &rep); krb5_xfree(rep.server); krb5_xfree(rep.client); } if (retval) goto cleanup; } retval = krb5_validate_times(context, &req->ticket->enc_part2->times); if (retval != 0) goto cleanup; if ((retval = krb5_timeofday(context, ¤ttime))) goto cleanup; if (!in_clock_skew((*auth_context)->authentp->ctime)) { retval = KRB5KRB_AP_ERR_SKEW; goto cleanup; } if (check_valid_flag) { if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) { retval = KRB5KRB_AP_ERR_TKT_INVALID; goto cleanup; } } /* check if the various etypes are permitted */ if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) { /* no etype check needed */; } else if ((*auth_context)->permitted_etypes == NULL) { int etype; /* check against the default set */ if ((!krb5_is_permitted_enctype(context, etype = req->ticket->enc_part.enctype)) || (!krb5_is_permitted_enctype(context, etype = req->ticket->enc_part2->session->enctype)) || (((*auth_context)->authentp->subkey) && !krb5_is_permitted_enctype(context, etype = (*auth_context)->authentp->subkey->enctype))) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } } else { /* check against the set in the auth_context */ int i; for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == req->ticket->enc_part.enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(req->ticket->enc_part.enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == req->ticket->enc_part2->session->enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } if ((*auth_context)->authentp->subkey) { for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == (*auth_context)->authentp->subkey->enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } } } (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number; if ((*auth_context)->authentp->subkey) { if ((retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->recv_subkey)))) goto cleanup; retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->send_subkey)); if (retval) { krb5_free_keyblock(context, (*auth_context)->recv_subkey); (*auth_context)->recv_subkey = NULL; goto cleanup; } } else { (*auth_context)->recv_subkey = 0; (*auth_context)->send_subkey = 0; } if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session, &((*auth_context)->keyblock)))) goto cleanup; /* * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used * then the default sequence number is the one's complement of the * sequence number sent ot us. */ if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && (*auth_context)->remote_seq_number) { (*auth_context)->local_seq_number ^= (*auth_context)->remote_seq_number; } if (ticket) if ((retval = krb5_copy_ticket(context, req->ticket, ticket))) goto cleanup; if (ap_req_options) *ap_req_options = req->ap_options; retval = 0; cleanup: if (server == &princ_data) krb5_free_default_realm(context, princ_data.realm.data); if (retval) { /* only free if we're erroring out...otherwise some applications will need the output. */ if (req->ticket->enc_part2) krb5_free_enc_tkt_part(context, req->ticket->enc_part2); req->ticket->enc_part2 = NULL; } return retval; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf) { krb5_error_code ret; AP_REP ap; EncAPRepPart body; u_char *buf = NULL; size_t buf_size; size_t len = 0; krb5_crypto crypto; ap.pvno = 5; ap.msg_type = krb_ap_rep; memset (&body, 0, sizeof(body)); body.ctime = auth_context->authenticator->ctime; body.cusec = auth_context->authenticator->cusec; if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) { if (auth_context->local_subkey == NULL) { ret = krb5_auth_con_generatelocalsubkey(context, auth_context, auth_context->keyblock); if(ret) { free_EncAPRepPart(&body); return ret; } } ret = krb5_copy_keyblock(context, auth_context->local_subkey, &body.subkey); if (ret) { free_EncAPRepPart(&body); return krb5_enomem(context); } } else body.subkey = NULL; if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { if(auth_context->local_seqnumber == 0) krb5_generate_seq_number (context, auth_context->keyblock, &auth_context->local_seqnumber); ALLOC(body.seq_number, 1); if (body.seq_number == NULL) { free_EncAPRepPart(&body); return krb5_enomem(context); } *(body.seq_number) = auth_context->local_seqnumber; } else body.seq_number = NULL; ap.enc_part.etype = auth_context->keyblock->keytype; ap.enc_part.kvno = NULL; ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret); free_EncAPRepPart (&body); if(ret) return ret; if (buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_crypto_init(context, auth_context->keyblock, 0 /* ap.enc_part.etype */, &crypto); if (ret) { free (buf); return ret; } ret = krb5_encrypt (context, crypto, KRB5_KU_AP_REQ_ENC_PART, buf + buf_size - len, len, &ap.enc_part.cipher); krb5_crypto_destroy(context, crypto); free(buf); if (ret) return ret; ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret); if (ret == 0 && outbuf->length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); free_AP_REP (&ap); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_verify_ap_req2(krb5_context context, krb5_auth_context *auth_context, krb5_ap_req *ap_req, krb5_const_principal server, krb5_keyblock *keyblock, krb5_flags flags, krb5_flags *ap_req_options, krb5_ticket **ticket, krb5_key_usage usage) { krb5_ticket *t; krb5_auth_context ac; krb5_error_code ret; EtypeList etypes; memset(&etypes, 0, sizeof(etypes)); if(ticket) *ticket = NULL; if (auth_context && *auth_context) { ac = *auth_context; } else { ret = krb5_auth_con_init(context, &ac); if (ret) return ret; } t = calloc(1, sizeof(*t)); if (t == NULL) { ret = ENOMEM; krb5_clear_error_message(context); goto out; } if (ap_req->ap_options.use_session_key && ac->keyblock){ ret = krb5_decrypt_ticket(context, &ap_req->ticket, ac->keyblock, &t->ticket, flags); krb5_free_keyblock(context, ac->keyblock); ac->keyblock = NULL; }else ret = krb5_decrypt_ticket(context, &ap_req->ticket, keyblock, &t->ticket, flags); if(ret) goto out; ret = _krb5_principalname2krb5_principal(context, &t->server, ap_req->ticket.sname, ap_req->ticket.realm); if (ret) goto out; ret = _krb5_principalname2krb5_principal(context, &t->client, t->ticket.cname, t->ticket.crealm); if (ret) goto out; ret = decrypt_authenticator(context, &t->ticket.key, &ap_req->authenticator, ac->authenticator, usage); if (ret) goto out; { krb5_principal p1, p2; krb5_boolean res; _krb5_principalname2krb5_principal(context, &p1, ac->authenticator->cname, ac->authenticator->crealm); _krb5_principalname2krb5_principal(context, &p2, t->ticket.cname, t->ticket.crealm); res = krb5_principal_compare(context, p1, p2); krb5_free_principal(context, p1); krb5_free_principal(context, p2); if (!res) { ret = KRB5KRB_AP_ERR_BADMATCH; krb5_clear_error_message(context); goto out; } } /* check addresses */ if (t->ticket.caddr && ac->remote_address && !krb5_address_search(context, ac->remote_address, t->ticket.caddr)) { ret = KRB5KRB_AP_ERR_BADADDR; krb5_clear_error_message(context); goto out; } /* check timestamp in authenticator */ { krb5_timestamp now; krb5_timeofday(context, &now); if (krb5_time_abs(ac->authenticator->ctime, now) > context->max_skew) { ret = KRB5KRB_AP_ERR_SKEW; krb5_clear_error_message(context); goto out; } } if (ac->authenticator->seq_number) krb5_auth_con_setremoteseqnumber(context, ac, *ac->authenticator->seq_number); /* XXX - Xor sequence numbers */ if (ac->authenticator->subkey) { ret = krb5_auth_con_setremotesubkey(context, ac, ac->authenticator->subkey); if (ret) goto out; } ret = find_etypelist(context, ac, &etypes); if (ret) goto out; ac->keytype = (krb5_keytype)ETYPE_NULL; if (etypes.val) { size_t i; for (i = 0; i < etypes.len; i++) { if (krb5_enctype_valid(context, etypes.val[i]) == 0) { ac->keytype = etypes.val[i]; break; } } } /* save key */ ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); if (ret) goto out; if (ap_req_options) { *ap_req_options = 0; if (ac->keytype != ETYPE_NULL) *ap_req_options |= AP_OPTS_USE_SUBKEY; if (ap_req->ap_options.use_session_key) *ap_req_options |= AP_OPTS_USE_SESSION_KEY; if (ap_req->ap_options.mutual_required) *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; } if(ticket) *ticket = t; else krb5_free_ticket(context, t); if (auth_context) { if (*auth_context == NULL) *auth_context = ac; } else krb5_auth_con_free(context, ac); free_EtypeList(&etypes); return 0; out: free_EtypeList(&etypes); if (t) krb5_free_ticket(context, t); if (auth_context == NULL || *auth_context == NULL) krb5_auth_con_free(context, ac); return ret; }