krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_with_keyblock(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keyblock *keyblock, krb5_flags *ap_req_options, krb5_ticket **ticket) { krb5_error_code ret; krb5_ap_req ap_req; if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); if (ret) return ret; } ret = krb5_decode_ap_req(context, inbuf, &ap_req); if(ret) return ret; ret = krb5_verify_ap_req(context, auth_context, &ap_req, server, keyblock, 0, ap_req_options, ticket); free_AP_REQ(&ap_req); return ret; }
krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, const krb5_data *inbuf, krb5_kvno *kvno, krb5_enctype *enctype) { #ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */ { krb5_error_code ret; krb5_ap_req ap_req; ret = krb5_decode_ap_req(context, inbuf, &ap_req); if (ret) return ret; *kvno = get_kvno_from_ap_req(&ap_req); *enctype = get_enctype_from_ap_req(&ap_req); free_AP_REQ(&ap_req); return 0; } #endif /* Possibly not an appropriate error code. */ return KRB5KDC_ERR_BADOPTION; }
static OM_uint32 send_error_token(OM_uint32 *minor_status, krb5_context context, krb5_error_code kret, krb5_principal server, krb5_data *indata, gss_buffer_t output_token) { krb5_principal ap_req_server = NULL; krb5_error_code ret; krb5_data outbuf; /* this e_data value encodes KERB_AP_ERR_TYPE_SKEW_RECOVERY which tells windows to try again with the corrected timestamp. See [MS-KILE] 2.2.1 KERB-ERROR-DATA */ krb5_data e_data = { 7, rk_UNCONST("\x30\x05\xa1\x03\x02\x01\x02") }; /* build server from request if the acceptor had not selected one */ if (server == NULL) { AP_REQ ap_req; ret = krb5_decode_ap_req(context, indata, &ap_req); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = _krb5_principalname2krb5_principal(context, &ap_req_server, ap_req.ticket.sname, ap_req.ticket.realm); free_AP_REQ(&ap_req); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } server = ap_req_server; } ret = krb5_mk_error(context, kret, NULL, &e_data, NULL, server, NULL, NULL, &outbuf); if (ap_req_server) krb5_free_principal(context, ap_req_server); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = _gsskrb5_encapsulate(minor_status, &outbuf, output_token, "\x03\x00", GSS_KRB5_MECHANISM); krb5_data_free (&outbuf); if (ret) return ret; *minor_status = 0; return GSS_S_CONTINUE_NEEDED; }
krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, const krb5_data *inbuf, krb5_kvno *kvno, krb5_enctype *enctype) { krb5_error_code ret; #ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */ { krb5_ap_req ap_req; ret = krb5_decode_ap_req(context, inbuf, &ap_req); if (ret) return ret; *kvno = get_kvno_from_ap_req(&ap_req); *enctype = get_enctype_from_ap_req(&ap_req); smb_krb5_free_ap_req(context, &ap_req); } #elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */ { krb5_ap_req *ap_req = NULL; ret = decode_krb5_ap_req(inbuf, &ap_req); if (ret) return ret; *kvno = get_kvno_from_ap_req(ap_req); *enctype = get_enctype_from_ap_req(ap_req); smb_krb5_free_ap_req(context, ap_req); } #else #error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION #endif return ret; }
static krb5_error_code tgs_parse_request(krb5_context context, krb5_kdc_configuration *config, KDC_REQ_BODY *b, const PA_DATA *tgs_req, hdb_entry_ex **krbtgt, krb5_enctype *krbtgt_etype, krb5_ticket **ticket, const char **e_text, const char *from, const struct sockaddr *from_addr, time_t **csec, int **cusec, AuthorizationData **auth_data) { krb5_ap_req ap_req; krb5_error_code ret; krb5_principal princ; krb5_auth_context ac = NULL; krb5_flags ap_req_options; krb5_flags verify_ap_req_flags; krb5_crypto crypto; Key *tkey; *auth_data = NULL; *csec = NULL; *cusec = NULL; memset(&ap_req, 0, sizeof(ap_req)); ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); if(ret){ kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", krb5_get_err_text(context, ret)); goto out; } if(!get_krbtgt_realm(&ap_req.ticket.sname)){ /* XXX check for ticket.sname == req.sname */ kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket"); ret = KRB5KDC_ERR_POLICY; /* ? */ goto out; } _krb5_principalname2krb5_principal(context, &princ, ap_req.ticket.sname, ap_req.ticket.realm); ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt); if(ret) { char *p; ret = krb5_unparse_name(context, princ, &p); if (ret != 0) p = "<unparse_name failed>"; krb5_free_principal(context, princ); kdc_log(context, config, 0, "Ticket-granting ticket not found in database: %s: %s", p, krb5_get_err_text(context, ret)); if (ret == 0) free(p); ret = KRB5KRB_AP_ERR_NOT_US; goto out; } if(ap_req.ticket.enc_part.kvno && *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){ char *p; ret = krb5_unparse_name (context, princ, &p); krb5_free_principal(context, princ); if (ret != 0) p = "<unparse_name failed>"; kdc_log(context, config, 0, "Ticket kvno = %d, DB kvno = %d (%s)", *ap_req.ticket.enc_part.kvno, (*krbtgt)->entry.kvno, p); if (ret == 0) free (p); ret = KRB5KRB_AP_ERR_BADKEYVER; goto out; } *krbtgt_etype = ap_req.ticket.enc_part.etype; ret = hdb_enctype2key(context, &(*krbtgt)->entry, ap_req.ticket.enc_part.etype, &tkey); if(ret){ char *str, *p; krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str); krb5_unparse_name(context, princ, &p); kdc_log(context, config, 0, "No server key with enctype %s found for %s", str, p); free(str); free(p); ret = KRB5KRB_AP_ERR_BADKEYVER; goto out; } if (b->kdc_options.validate) verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID; else verify_ap_req_flags = 0; ret = krb5_verify_ap_req2(context, &ac, &ap_req, princ, &tkey->key, verify_ap_req_flags, &ap_req_options, ticket, KRB5_KU_TGS_REQ_AUTH); krb5_free_principal(context, princ); if(ret) { kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", krb5_get_err_text(context, ret)); goto out; } { krb5_authenticator auth; ret = krb5_auth_con_getauthenticator(context, ac, &auth); if (ret == 0) { *csec = malloc(sizeof(**csec)); if (*csec == NULL) { krb5_free_authenticator(context, &auth); kdc_log(context, config, 0, "malloc failed"); goto out; } **csec = auth->ctime; *cusec = malloc(sizeof(**cusec)); if (*cusec == NULL) { krb5_free_authenticator(context, &auth); kdc_log(context, config, 0, "malloc failed"); goto out; } **cusec = auth->cusec; krb5_free_authenticator(context, &auth); } } ret = tgs_check_authenticator(context, config, ac, b, e_text, &(*ticket)->ticket.key); if (ret) { krb5_auth_con_free(context, ac); goto out; } if (b->enc_authorization_data) { krb5_keyblock *subkey; krb5_data ad; ret = krb5_auth_con_getremotesubkey(context, ac, &subkey); if(ret){ krb5_auth_con_free(context, ac); kdc_log(context, config, 0, "Failed to get remote subkey: %s", krb5_get_err_text(context, ret)); goto out; } if(subkey == NULL){ ret = krb5_auth_con_getkey(context, ac, &subkey); if(ret) { krb5_auth_con_free(context, ac); kdc_log(context, config, 0, "Failed to get session key: %s", krb5_get_err_text(context, ret)); goto out; } } if(subkey == NULL){ krb5_auth_con_free(context, ac); kdc_log(context, config, 0, "Failed to get key for enc-authorization-data"); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out; } ret = krb5_crypto_init(context, subkey, 0, &crypto); if (ret) { krb5_auth_con_free(context, ac); kdc_log(context, config, 0, "krb5_crypto_init failed: %s", krb5_get_err_text(context, ret)); goto out; } ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, b->enc_authorization_data, &ad); krb5_crypto_destroy(context, crypto); if(ret){ krb5_auth_con_free(context, ac); kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data"); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out; } krb5_free_keyblock(context, subkey); ALLOC(*auth_data); if (*auth_data == NULL) { krb5_auth_con_free(context, ac); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out; } ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL); if(ret){ krb5_auth_con_free(context, ac); free(*auth_data); *auth_data = NULL; kdc_log(context, config, 0, "Failed to decode authorization data"); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ goto out; } } krb5_auth_con_free(context, ac); out: free_AP_REQ(&ap_req); return ret; }
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_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; }
krb5_error_code _kdc_fast_unwrap_request(kdc_request_t r) { krb5_principal armor_server = NULL; hdb_entry_ex *armor_user = NULL; PA_FX_FAST_REQUEST fxreq; krb5_auth_context ac = NULL; krb5_ticket *ticket = NULL; krb5_flags ap_req_options; Key *armor_key = NULL; krb5_keyblock armorkey; krb5_error_code ret; krb5_ap_req ap_req; unsigned char *buf = NULL; KrbFastReq fastreq; size_t len, size; krb5_data data; const PA_DATA *pa; int i = 0; /* * First look for FX_COOKIE and and process it */ pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_COOKIE); if (pa) { ret = fast_parse_cookie(r, pa); if (ret) goto out; } i = 0; pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_FAST); if (pa == NULL) return 0; ret = decode_PA_FX_FAST_REQUEST(pa->padata_value.data, pa->padata_value.length, &fxreq, &len); if (ret) goto out; if (len != pa->padata_value.length) { ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } if (fxreq.element != choice_PA_FX_FAST_REQUEST_armored_data) { kdc_log(r->context, r->config, 0, "AS-REQ FAST contain unknown type: %d", (int)fxreq.element); ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } /* pull out armor key */ if (fxreq.u.armored_data.armor == NULL) { kdc_log(r->context, r->config, 0, "AS-REQ armor missing"); ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } if (fxreq.u.armored_data.armor->armor_type != 1) { kdc_log(r->context, r->config, 0, "AS-REQ armor type not ap-req"); ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } ret = krb5_decode_ap_req(r->context, &fxreq.u.armored_data.armor->armor_value, &ap_req); if(ret) { kdc_log(r->context, r->config, 0, "AP-REQ decode failed"); goto out; } /* Save that principal that was in the request */ ret = _krb5_principalname2krb5_principal(r->context, &armor_server, ap_req.ticket.sname, ap_req.ticket.realm); if (ret) { free_AP_REQ(&ap_req); goto out; } ret = _kdc_db_fetch(r->context, r->config, armor_server, HDB_F_GET_SERVER, NULL, NULL, &armor_user); if(ret == HDB_ERR_NOT_FOUND_HERE) { kdc_log(r->context, r->config, 5, "armor key does not have secrets at this KDC, " "need to proxy"); goto out; } else if (ret) { free_AP_REQ(&ap_req); ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto out; } ret = hdb_enctype2key(r->context, &armor_user->entry, NULL, ap_req.ticket.enc_part.etype, &armor_key); if (ret) { free_AP_REQ(&ap_req); goto out; } ret = krb5_verify_ap_req2(r->context, &ac, &ap_req, armor_server, &armor_key->key, 0, &ap_req_options, &ticket, KRB5_KU_AP_REQ_AUTH); free_AP_REQ(&ap_req); if (ret) goto out; if (ac->remote_subkey == NULL) { krb5_auth_con_free(r->context, ac); kdc_log(r->context, r->config, 0, "FAST AP-REQ remote subkey missing"); ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } ret = _krb5_fast_armor_key(r->context, ac->remote_subkey, &ticket->ticket.key, &armorkey, &r->armor_crypto); krb5_auth_con_free(r->context, ac); krb5_free_ticket(r->context, ticket); if (ret) goto out; krb5_free_keyblock_contents(r->context, &armorkey); /* verify req-checksum of the outer body */ ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, len, &r->req.req_body, &size, ret); if (ret) goto out; if (size != len) { ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } ret = krb5_verify_checksum(r->context, r->armor_crypto, KRB5_KU_FAST_REQ_CHKSUM, buf, len, &fxreq.u.armored_data.req_checksum); if (ret) { kdc_log(r->context, r->config, 0, "FAST request have a bad checksum"); goto out; } ret = krb5_decrypt_EncryptedData(r->context, r->armor_crypto, KRB5_KU_FAST_ENC, &fxreq.u.armored_data.enc_fast_req, &data); if (ret) { kdc_log(r->context, r->config, 0, "Failed to decrypt FAST request"); goto out; } ret = decode_KrbFastReq(data.data, data.length, &fastreq, &size); if (ret) { krb5_data_free(&data); goto out; } if (data.length != size) { krb5_data_free(&data); ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } krb5_data_free(&data); free_KDC_REQ_BODY(&r->req.req_body); ret = copy_KDC_REQ_BODY(&fastreq.req_body, &r->req.req_body); if (ret) goto out; /* check for unsupported mandatory options */ if (FastOptions2int(fastreq.fast_options) & 0xfffc) { kdc_log(r->context, r->config, 0, "FAST unsupported mandatory option set"); ret = KRB5KDC_ERR_PREAUTH_FAILED; goto out; } /* KDC MUST ignore outer pa data preauth-14 - 6.5.5 */ if (r->req.padata) free_METHOD_DATA(r->req.padata); else ALLOC(r->req.padata); ret = copy_METHOD_DATA(&fastreq.padata, r->req.padata); if (ret) goto out; free_KrbFastReq(&fastreq); free_PA_FX_FAST_REQUEST(&fxreq); out: if (armor_server) krb5_free_principal(r->context, armor_server); if(armor_user) _kdc_free_ent(r->context, armor_user); return ret; }
krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket) { krb5_error_code ret; krb5_ap_req ap_req; krb5_keyblock *keyblock = NULL; krb5_principal service = NULL; if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); if (ret) return ret; } ret = krb5_decode_ap_req(context, inbuf, &ap_req); if(ret) return ret; if(server == NULL){ _krb5_principalname2krb5_principal(&service, ap_req.ticket.sname, ap_req.ticket.realm); 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 == NULL){ ret = get_key_from_keytab(context, auth_context, &ap_req, server, keytab, &keyblock); if(ret) goto out; } else { ret = krb5_copy_keyblock(context, (*auth_context)->keyblock, &keyblock); if (ret) goto out; } ret = krb5_verify_ap_req(context, auth_context, &ap_req, server, keyblock, 0, ap_req_options, ticket); krb5_free_keyblock(context, keyblock); out: free_AP_REQ(&ap_req); if(service) krb5_free_principal(context, service); return ret; }