make AS work with FAST

This commit is contained in:
Love Hornquist Astrand
2011-05-09 20:46:31 -07:00
committed by Love Hörnquist Åstrand
parent 6c31f5a95f
commit 17d5f8d19e
5 changed files with 500 additions and 289 deletions

View File

@@ -147,6 +147,12 @@ _kdc_fast_mk_error(krb5_context context,
e_text = NULL; e_text = NULL;
} }
ret = krb5_padata_add(context, error_method,
KRB5_PADATA_FX_COOKIE,
NULL, 0);
if (ret)
return ret;
ret = _kdc_fast_mk_response(context, armor_crypto, ret = _kdc_fast_mk_response(context, armor_crypto,
error_method, NULL, NULL, error_method, NULL, NULL,
req_body->nonce, &e_data); req_body->nonce, &e_data);
@@ -157,17 +163,9 @@ _kdc_fast_mk_error(krb5_context context,
ret = krb5_padata_add(context, error_method, ret = krb5_padata_add(context, error_method,
KRB5_PADATA_FX_FAST, KRB5_PADATA_FX_FAST,
e_data.data, e_data.length); e_data.data, e_data.length);
krb5_data_zero(&e_data);
if (ret) if (ret)
return ret; return ret;
/*
* Set cookie to let client know we want conversation to
* continue.
*/
ret = krb5_padata_add(context, error_method,
KRB5_PADATA_FX_COOKIE,
NULL, 0);
if (ret) if (ret)
return ret; return ret;
} }

View File

@@ -271,6 +271,30 @@ _kdc_log_timestamp(krb5_context context,
type, authtime_str, starttime_str, endtime_str, renewtime_str); type, authtime_str, starttime_str, endtime_str, renewtime_str);
} }
struct kdc_patypes {
int type;
char *name;
unsigned int flags;
#define PA_ANNOUNCE 1
#ifdef PKINIT
#define PA_ANNOUNCE_PKINIT PA_ANNOUNCE
#else
#define PA_ANNOUNCE_PKINIT 0
#endif
};
static const struct kdc_patypes pat[] = {
{ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE_PKINIT },
{ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE_PKINIT },
{ KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0 },
{ KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS", PA_ANNOUNCE },
{ KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL", PA_ANNOUNCE },
{ KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0 },
{ KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE },
{ KRB5_PADATA_FX_ERROR, "FX-ERROR", 0 },
{ KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0 }
};
static void static void
log_patypes(krb5_context context, log_patypes(krb5_context context,
krb5_kdc_configuration *config, krb5_kdc_configuration *config,
@@ -278,27 +302,18 @@ log_patypes(krb5_context context,
{ {
struct rk_strpool *p = NULL; struct rk_strpool *p = NULL;
char *str; char *str;
size_t i; size_t n, m;
for (i = 0; i < padata->len; i++) { for (n = 0; n < padata->len; n++) {
switch(padata->val[i].padata_type) { for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
case KRB5_PADATA_PK_AS_REQ: if (padata->val[n].padata_type == pat[m].type) {
p = rk_strpoolprintf(p, "PK-INIT(ietf)"); p = rk_strpoolprintf(p, "%s", pat[m].name);
break; break;
case KRB5_PADATA_PK_AS_REQ_WIN: }
p = rk_strpoolprintf(p, "PK-INIT(win2k)");
break;
case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
p = rk_strpoolprintf(p, "OCSP");
break;
case KRB5_PADATA_ENC_TIMESTAMP:
p = rk_strpoolprintf(p, "encrypted-timestamp");
break;
default:
p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
break;
} }
if (p && i + 1 < padata->len) if (m == sizeof(pat) / sizeof(pat[0]))
p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
if (p && n + 1 < padata->len)
p = rk_strpoolprintf(p, ", "); p = rk_strpoolprintf(p, ", ");
if (p == NULL) { if (p == NULL) {
kdc_log(context, config, 0, "out of memory"); kdc_log(context, config, 0, "out of memory");
@@ -321,8 +336,9 @@ log_patypes(krb5_context context,
krb5_error_code krb5_error_code
_kdc_encode_reply(krb5_context context, _kdc_encode_reply(krb5_context context,
krb5_kdc_configuration *config, krb5_kdc_configuration *config,
const krb5_data *req_buffer,
krb5_crypto armor_crypto, uint32_t nonce, krb5_crypto armor_crypto, uint32_t nonce,
KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
krb5_enctype etype, krb5_enctype etype,
int skvno, const EncryptionKey *skey, int skvno, const EncryptionKey *skey,
int ckvno, const EncryptionKey *reply_key, int ckvno, const EncryptionKey *reply_key,
@@ -336,25 +352,62 @@ _kdc_encode_reply(krb5_context context,
krb5_error_code ret; krb5_error_code ret;
krb5_crypto crypto; krb5_crypto crypto;
if (rep->msg_type == krb_as_rep && req_buffer) {
Checksum checksum;
krb5_data cdata;
et->flags.enc_pa_rep = 1;
ek->flags.enc_pa_rep = 1;
ret = krb5_crypto_init(context, reply_key, 0, &crypto);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
free(buf);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(context, msg);
return ret;
}
ret = krb5_create_checksum(context, crypto,
KRB5_KU_AS_REQ, 0,
req_buffer->data, req_buffer->length,
&checksum);
krb5_crypto_destroy(context, crypto);
if (ret) {
return ret;
}
ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
&checksum, &len, ret);
free_Checksum(&checksum);
if (ret) {
return ret;
}
ek->encrypted_pa_data = calloc(1, sizeof(*ek->encrypted_pa_data));
ret = krb5_padata_add(context, ek->encrypted_pa_data,
KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
if (ret) {
return ret;
}
ret = krb5_padata_add(context, ek->encrypted_pa_data,
KRB5_PADATA_FX_FAST, NULL, 0);
if (ret)
return ret;
}
ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret); ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
if(ret) { if(ret) {
const char *msg = krb5_get_error_message(context, ret); const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0, "Failed to encode ticket: %s", msg); kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
krb5_free_error_message(context, msg); krb5_free_error_message(context, msg);
krb5_crypto_destroy(context, crypto);
return ret; return ret;
} }
if(buf_size != len) { if(buf_size != len)
free(buf); krb5_abortx(context, "Internal error in ASN.1 encoder");
kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
*e_text = "KDC internal error";
return KRB5KRB_ERR_GENERIC;
}
ret = krb5_crypto_init(context, skey, etype, &crypto); ret = krb5_crypto_init(context, skey, etype, &crypto);
if (ret) { if (ret) {
const char *msg; const char *msg = krb5_get_error_message(context, ret);
free(buf);
msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg); kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(context, msg); krb5_free_error_message(context, msg);
return ret; return ret;
@@ -381,6 +434,8 @@ _kdc_encode_reply(krb5_context context,
krb5_keyblock *strengthen_key = NULL; krb5_keyblock *strengthen_key = NULL;
KrbFastFinished finished; KrbFastFinished finished;
kdc_log(context, config, 0, "FAST armor protection");
memset(&finished, 0, sizeof(finished)); memset(&finished, 0, sizeof(finished));
krb5_data_zero(&data); krb5_data_zero(&data);
@@ -1048,6 +1103,234 @@ make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
return ret; return ret;
} }
static krb5_error_code
unwrap_fast(krb5_context context,
krb5_kdc_configuration *config,
KDC_REQ *req,
krb5_crypto *armor_crypto)
{
krb5_crypto crypto_subkey = NULL, crypto_session = NULL;
krb5_principal armor_server = NULL;
hdb_entry_ex *armor_user = NULL;
krb5_data pepper1, pepper2;
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;
KrbFastReq fastreq;
size_t len, size;
krb5_data data;
const PA_DATA *pa;
int i = 0;
pa = _kdc_find_padata(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(context, config, 0,
"AS-REQ FAST contain unknown type");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
/* pull out armor key */
if (fxreq.u.armored_data.armor == NULL) {
kdc_log(context, config, 0,
"AS-REQ armor missing");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
if (fxreq.u.armored_data.armor->armor_type != 1) {
kdc_log(context, config, 0,
"AS-REQ armor type not ap-req");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
ret = krb5_decode_ap_req(context,
&fxreq.u.armored_data.armor->armor_value,
&ap_req);
if(ret) {
kdc_log(context, config, 0, "AP-REQ decode failed");
goto out;
}
/* Save that principal that was in the request */
ret = _krb5_principalname2krb5_principal(context,
&armor_server,
ap_req.ticket.sname,
ap_req.ticket.realm);
if (ret) {
free_AP_REQ(&ap_req);
goto out;
}
ret = _kdc_db_fetch(context, config, armor_server,
HDB_F_GET_SERVER, NULL, NULL, &armor_user);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5,
"armor key does not have secrets at this KDC, "
"need to proxy");
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
} if(ret){
free_AP_REQ(&ap_req);
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
}
ret = hdb_enctype2key(context, &armor_user->entry,
ap_req.ticket.enc_part.etype,
&armor_key);
if (ret) {
free_AP_REQ(&ap_req);
goto out;
}
ret = krb5_verify_ap_req2(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(context, ac);
kdc_log(context, config, 0,
"FAST AP-REQ remote subkey missing");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
ret = krb5_crypto_init(context, ac->remote_subkey,
0, &crypto_subkey);
if (ret) {
krb5_auth_con_free(context, ac);
krb5_free_ticket(context, ticket);
goto out;
}
ret = krb5_crypto_init(context, &ticket->ticket.key,
0, &crypto_session);
krb5_free_ticket(context, ticket);
if (ret) {
krb5_auth_con_free(context, ac);
krb5_crypto_destroy(context, crypto_subkey);
goto out;
}
pepper1.data = "subkeyarmor";
pepper1.length = strlen(pepper1.data);
pepper2.data = "ticketarmor";
pepper2.length = strlen(pepper2.data);
ret = krb5_crypto_fx_cf2(context, crypto_subkey, crypto_session,
&pepper1, &pepper2,
ac->remote_subkey->keytype,
&armorkey);
krb5_crypto_destroy(context, crypto_subkey);
krb5_crypto_destroy(context, crypto_session);
krb5_auth_con_free(context, ac);
if (ret)
goto out;
ret = krb5_crypto_init(context, &armorkey, 0, armor_crypto);
if (ret)
goto out;
krb5_free_keyblock_contents(context, &armorkey);
/* verify req-checksum of the outer body */
ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, len, &req->req_body, &size, ret);
if (ret)
goto out;
if (size != len) {
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
ret = krb5_verify_checksum(context, *armor_crypto,
KRB5_KU_FAST_REQ_CHKSUM,
buf, len,
&fxreq.u.armored_data.req_checksum);
free(buf);
if (ret)
goto out;
ret = krb5_decrypt_EncryptedData(context, *armor_crypto,
KRB5_KU_FAST_ENC,
&fxreq.u.armored_data.enc_fast_req,
&data);
if (ret)
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(&req->req_body);
ret = copy_KDC_REQ_BODY(&fastreq.req_body, &req->req_body);
if (ret)
goto out;
/* check for unsupported mandatory options */
if (FastOptions2int(fastreq.fast_options) & 0xfffc) {
kdc_log(context, 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 */
free_METHOD_DATA(req->padata);
ret = copy_METHOD_DATA(&fastreq.padata, req->padata);
if (ret)
goto out;
free_KrbFastReq(&fastreq);
free_PA_FX_FAST_REQUEST(&fxreq);
out:
if (armor_server)
krb5_free_principal(context, armor_server);
if(armor_user)
_kdc_free_ent(context, armor_user);
return ret;
}
/* /*
* *
@@ -1066,7 +1349,7 @@ _kdc_as_rep(krb5_context context,
KDC_REQ_BODY *b = NULL; KDC_REQ_BODY *b = NULL;
AS_REP rep; AS_REP rep;
KDCOptions f; KDCOptions f;
hdb_entry_ex *client = NULL, *server = NULL, *armor_user = NULL; hdb_entry_ex *client = NULL, *server = NULL;
HDB *clientdb; HDB *clientdb;
krb5_enctype setype, sessionetype; krb5_enctype setype, sessionetype;
EncTicketPart et; EncTicketPart et;
@@ -1099,217 +1382,9 @@ _kdc_as_rep(krb5_context context,
/* /*
* Look for FAST armor and unwrap * Look for FAST armor and unwrap
*/ */
{ ret = unwrap_fast(context, config, req, &armor_crypto);
const PA_DATA *pa; if (ret)
int i = 0; goto out;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST);
if (pa != NULL) {
krb5_crypto crypto_subkey = NULL, crypto_session = NULL;
krb5_data pepper1, pepper2;
PA_FX_FAST_REQUEST fxreq;
krb5_principal armor_server;
krb5_auth_context ac = NULL;
krb5_ticket *ticket = NULL;
krb5_flags ap_req_options;
Key *armor_key = NULL;
krb5_keyblock armorkey;
krb5_ap_req ap_req;
unsigned char *buf;
KrbFastReq fastreq;
size_t len, size;
krb5_data data;
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(context, config, 0,
"AS-REQ FAST contain unknown type");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
/* pull out armor key */
if (fxreq.u.armored_data.armor == NULL) {
kdc_log(context, config, 0,
"AS-REQ armor missing");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
if (fxreq.u.armored_data.armor->armor_type != 1) {
kdc_log(context, config, 0,
"AS-REQ armor type not ap-req");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
ret = krb5_decode_ap_req(context,
&fxreq.u.armored_data.armor->armor_value,
&ap_req);
if(ret) {
kdc_log(context, config, 0, "AP-REQ decode failed");
goto out;
}
/* Save that principal that was in the request */
ret = _krb5_principalname2krb5_principal(context,
&armor_server,
ap_req.ticket.sname,
ap_req.ticket.realm);
if (ret) {
free_AP_REQ(&ap_req);
goto out;
}
ret = _kdc_db_fetch(context, config, armor_server,
HDB_F_GET_SERVER, NULL, NULL, &armor_user);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5,
"armor key does not have secrets at this KDC, "
"need to proxy");
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
} if(ret){
free_AP_REQ(&ap_req);
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
}
ret = hdb_enctype2key(context, &armor_user->entry,
ap_req.ticket.enc_part.etype,
&armor_key);
if (ret) {
free_AP_REQ(&ap_req);
goto out;
}
ret = krb5_verify_ap_req2(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(context, ac);
kdc_log(context, config, 0,
"FAST AP-REQ remote subkey missing");
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
ret = krb5_crypto_init(context, ac->remote_subkey,
0, &crypto_subkey);
if (ret) {
krb5_auth_con_free(context, ac);
krb5_free_ticket(context, ticket);
goto out;
}
ret = krb5_crypto_init(context, &ticket->ticket.key,
0, &crypto_session);
krb5_free_ticket(context, ticket);
if (ret) {
krb5_auth_con_free(context, ac);
krb5_crypto_destroy(context, crypto_subkey);
goto out;
}
pepper1.data = "subkeyarmor";
pepper1.length = strlen(pepper1.data);
pepper2.data = "ticketarmor";
pepper2.length = strlen(pepper2.data);
ret = krb5_crypto_fx_cf2(context, crypto_subkey, crypto_session,
&pepper1, &pepper2,
ac->remote_subkey->keytype,
&armorkey);
krb5_crypto_destroy(context, crypto_subkey);
krb5_crypto_destroy(context, crypto_session);
krb5_auth_con_free(context, ac);
if (ret)
goto out;
ret = krb5_crypto_init(context, &armorkey, 0, &armor_crypto);
if (ret)
goto out;
krb5_free_keyblock_contents(context, &armorkey);
/* verify req-checksum of the outer body */
ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, len, &req->req_body, &size, ret);
if (ret)
goto out;
if (size != len) {
ret = KRB5KDC_ERR_PREAUTH_FAILED;
goto out;
}
ret = krb5_verify_checksum(context, armor_crypto,
KRB5_KU_FAST_REQ_CHKSUM,
buf, len,
&fxreq.u.armored_data.req_checksum);
free(buf);
if (ret)
goto out;
ret = krb5_decrypt_EncryptedData(context, armor_crypto,
KRB5_KU_FAST_ENC,
&fxreq.u.armored_data.enc_fast_req,
&data);
if (ret)
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(&req->req_body);
ret = copy_KDC_REQ_BODY(&fastreq.req_body, &req->req_body);
if (ret)
goto out;
/* check for unsupported mandatory options */
if (FastOptions2int(fastreq.fast_options) & 0xfffc) {
kdc_log(context, 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 */
free_METHOD_DATA(req->padata);
ret = copy_METHOD_DATA(&fastreq.padata, req->padata);
if (ret)
goto out;
free_KrbFastReq(&fastreq);
free_PA_FX_FAST_REQUEST(&fxreq);
}
}
b = &req->req_body; b = &req->req_body;
f = b->kdc_options; f = b->kdc_options;
@@ -1796,42 +1871,16 @@ _kdc_as_rep(krb5_context context,
|| b->kdc_options.request_anonymous /* hack to force anon */ || b->kdc_options.request_anonymous /* hack to force anon */
|| client->entry.flags.require_preauth || client->entry.flags.require_preauth
|| server->entry.flags.require_preauth) { || server->entry.flags.require_preauth) {
PA_DATA *pa; size_t n;
use_pa: use_pa:
for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
ret = realloc_method_data(&error_method); if ((pat[n].flags & PA_ANNOUNCE) == 0)
if (ret) continue;
goto out; ret = krb5_padata_add(context, &error_method,
pa = &error_method.val[error_method.len-1]; pat[n].type, NULL, 0);
pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; if (ret)
pa->padata_value.length = 0; goto out;
pa->padata_value.data = NULL; }
#ifdef PKINIT
ret = realloc_method_data(&error_method);
if (ret)
goto out;
pa = &error_method.val[error_method.len-1];
pa->padata_type = KRB5_PADATA_PK_AS_REQ;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
ret = realloc_method_data(&error_method);
if (ret)
goto out;
pa = &error_method.val[error_method.len-1];
pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
#endif
/*
* Announce FX-FAST
*/
ret = krb5_padata_add(context, &error_method,
KRB5_PADATA_FX_FAST, NULL, 0);
if (ret)
goto out;
/* /*
* If there is a client key, send ETYPE_INFO{,2} * If there is a client key, send ETYPE_INFO{,2}
@@ -2239,7 +2288,17 @@ _kdc_as_rep(krb5_context context,
log_as_req(context, config, reply_key->keytype, setype, b); log_as_req(context, config, reply_key->keytype, setype, b);
ret = _kdc_encode_reply(context, config, armor_crypto, req->req_body.nonce, {
PA_DATA *pa;
int i = 0;
pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
if (pa == NULL)
req_buffer = NULL;
}
ret = _kdc_encode_reply(context, config, req_buffer,
armor_crypto, req->req_body.nonce,
&rep, &et, &ek, setype, server->entry.kvno, &rep, &et, &ek, setype, server->entry.kvno,
&skey->key, client->entry.kvno, &skey->key, client->entry.kvno,
reply_key, 0, &e_text, reply); reply_key, 0, &e_text, reply);
@@ -2292,8 +2351,6 @@ out2:
_kdc_free_ent(context, client); _kdc_free_ent(context, client);
if(server) if(server)
_kdc_free_ent(context, server); _kdc_free_ent(context, server);
if(armor_user)
_kdc_free_ent(context, armor_user);
if (armor_crypto) if (armor_crypto)
krb5_crypto_destroy(context, armor_crypto); krb5_crypto_destroy(context, armor_crypto);
return ret; return ret;

View File

@@ -987,7 +987,7 @@ tgs_make_reply(krb5_context context,
CAST session key. Should the DES3 etype be added to the CAST session key. Should the DES3 etype be added to the
etype list, even if we don't want a session key with etype list, even if we don't want a session key with
DES3? */ DES3? */
ret = _kdc_encode_reply(context, config, NULL, 0, ret = _kdc_encode_reply(context, config, NULL, NULL, 0,
&rep, &et, &ek, et.key.keytype, &rep, &et, &ek, et.key.keytype,
kvno, kvno,
serverkey, 0, replykey, rk_is_subkey, serverkey, 0, replykey, rk_is_subkey,

View File

@@ -14,6 +14,7 @@ SCRIPT_TESTS = \
check-delegation \ check-delegation \
check-des \ check-des \
check-digest \ check-digest \
check-fast \
check-kadmin \ check-kadmin \
check-kdc \ check-kdc \
check-kdc-weak \ check-kdc-weak \
@@ -63,6 +64,11 @@ check-des: check-des.in Makefile krb5.conf
chmod +x check-des.tmp chmod +x check-des.tmp
mv check-des.tmp check-des mv check-des.tmp check-des
check-fast: check-fast.in Makefile
$(do_subst) < $(srcdir)/check-fast.in > check-fast.tmp
chmod +x check-fast.tmp
mv check-fast.tmp check-fast
check-kdc: check-kdc.in Makefile check-kdc: check-kdc.in Makefile
$(do_subst) < $(srcdir)/check-kdc.in > check-kdc.tmp $(do_subst) < $(srcdir)/check-kdc.in > check-kdc.tmp
chmod +x check-kdc.tmp chmod +x check-kdc.tmp

150
tests/kdc/check-fast.in Normal file
View File

@@ -0,0 +1,150 @@
#!/bin/sh
#
# Copyright (c) 2006 - 2011 Kungliga Tekniska Högskolan
# (Royal Institute of Technology, Stockholm, Sweden).
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
top_builddir="@top_builddir@"
env_setup="@env_setup@"
objdir="@objdir@"
. ${env_setup}
KRB5_CONFIG="${1-${objdir}/krb5.conf}"
export KRB5_CONFIG
testfailed="echo test failed; cat messages.log; exit 1"
# If there is no useful db support compile in, disable test
${have_db} || exit 77
R=TEST.H5L.SE
port=@port@
kadmin="${kadmin} -l -r $R"
kdc="${kdc} --addresses=localhost -P $port"
server=host/datan.test.h5l.se
cache="FILE:${objdir}/cache.krb5"
acache="FILE:${objdir}/acache.krb5"
kinit="${kinit} -c $cache ${afs_no_afslog}"
klist="${klist} -c $cache"
aklist="${klist} -c $acache"
kgetcred="${kgetcred} -c $cache"
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
rm -f ${keytabfile}
rm -f current-db*
rm -f out-*
rm -f mkey.file*
> messages.log
echo Creating database
${kadmin} \
init \
--realm-max-ticket-life=1day \
--realm-max-renewable-life=1month \
${R} || exit 1
${kadmin} add -p foo --use-defaults foo@${R} || exit 1
${kadmin} add -p foo --use-defaults ${server}@${R} || exit 1
echo "Doing database check"
${kadmin} check ${R} || exit 1
echo foo > ${objdir}/foopassword
echo Starting kdc
env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
${kdc} &
kdcpid=$!
sh ${wait_kdc}
if [ "$?" != 0 ] ; then
kill -9 ${kdcpid}
exit 1
fi
trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
ec=0
echo "Getting client initial tickets"; > messages.log
${kinit} --password-file=${objdir}/foopassword foo@$R || \
{ ec=1 ; eval "${testfailed}"; }
echo "Getting tickets"; > messages.log
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
echo "Listing tickets"; > messages.log
${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
${kdestroy}
echo foo > ${objdir}/foopassword
kinitpty=${objdir}/foopassword.rkpty
cat > ${kinitpty} <<EOF
expect Password
password foo\n
EOF
mit=/usr/local/mitkerberos/bin
if [ -f ${mit}/kinit ] ; then
echo "Running MIT FAST tests"
echo "Acquire host ticket"
${rkpty} ${kinitpty} ${mit}/kinit -c ${acache} ${server}@${R} >/dev/null|| { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Checking for FAST avail"
${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
echo "Using plain to get a initial ticket"
${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} foo@${R} >/dev/null|| { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Using FAST to get a initial ticket"
${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} -T ${acache} foo@${R} >/dev/null || { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Checking for FAST avail"
${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
fi
echo "killing kdc (${kdcpid})"
sh ${leaks_kill} kdc $kdcpid || exit 1
trap "" EXIT
exit $ec