Fixes for cross-realm, including (but not limited to):

* allow client to be non-existant (should probably check for "local realm")

* if server isn't found and it is a request for a krbtgt, try to find
  a realm on the way to the requested realm

* update the transited encoding iff client-realm != server-realm != tgt-realm


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@3463 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Johan Danielsson
1997-09-10 19:26:09 +00:00
parent 0c311e02c1
commit ec242eb9f5

View File

@@ -530,7 +530,7 @@ as_rep(KDC_REQ *req,
&ekey->key,
&rep.enc_part);
hdb_free_key(ekey);
set_salt_padata (&rep.padata, ckey->salt);
set_salt_padata ((METHOD_DATA**)&rep.padata, ckey->salt);
ret = encode_AS_REP(buf + sizeof(buf) - 1, sizeof(buf), &rep, &len);
free_AS_REP(&rep);
@@ -675,9 +675,65 @@ check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
return 0;
}
static krb5_error_code
fix_transited_encoding(TransitedEncoding *tr,
const char *client_realm,
const char *server_realm,
const char *tgt_realm)
{
krb5_error_code ret = 0;
if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)){
char **realms = NULL, **tmp;
int num_realms = 0;
int i;
if(tr->tr_type){
if(tr->tr_type != DOMAIN_X500_COMPRESS){
kdc_log(0, "Unknown transited type: %u",
tr->tr_type);
return KRB5KDC_ERR_TRTYPE_NOSUPP;
}
ret = krb5_domain_x500_decode(&tr->contents,
&realms,
&num_realms,
client_realm,
server_realm);
if(ret){
krb5_warn(context, ret, "Decoding transited encoding");
return ret;
}
}
tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
if(tmp == NULL){
ret = ENOMEM;
goto free_realms;
}
realms = tmp;
realms[num_realms] = strdup(tgt_realm);
if(realms[num_realms] == NULL){
ret = ENOMEM;
goto free_realms;
}
num_realms++;
free_TransitedEncoding(tr);
tr->tr_type = DOMAIN_X500_COMPRESS;
ret = krb5_domain_x500_encode(realms, num_realms, &tr->contents);
if(ret)
krb5_warn(context, ret, "Encoding transited encoding");
free_realms:
for(i = 0; i < num_realms; i++)
free(realms[i]);
free(realms);
}
return ret;
}
static krb5_error_code
tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt,
hdb_entry *server, hdb_entry *client, krb5_data *reply)
hdb_entry *server, hdb_entry *client,
krb5_principal client_principal,
hdb_entry *krbtgt,
krb5_data *reply)
{
KDC_REP rep;
EncKDCRepPart ek;
@@ -719,6 +775,17 @@ tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt,
if(ret)
return ret;
copy_TransitedEncoding(&tgt->transited, &et.transited);
ret = fix_transited_encoding(&et.transited,
*krb5_princ_realm(context, client_principal),
*krb5_princ_realm(context, server->principal),
*krb5_princ_realm(context, krbtgt->principal));
if(ret){
free_TransitedEncoding(&et.transited);
return ret;
}
copy_Realm(krb5_princ_realm(context, server->principal),
&rep.ticket.realm);
krb5_principal2principalname(&rep.ticket.sname, server->principal);
@@ -733,7 +800,7 @@ tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt,
{
time_t life;
life = et.endtime - *et.starttime;
if(client->max_life)
if(client && client->max_life)
life = min(life, *client->max_life);
if(server->max_life)
life = min(life, *server->max_life);
@@ -748,7 +815,7 @@ tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt,
if(et.renew_till){
time_t renew;
renew = *et.renew_till - et.authtime;
if(client->max_renew)
if(client && client->max_renew)
renew = min(renew, *client->max_renew);
if(server->max_renew)
renew = min(renew, *server->max_renew);
@@ -800,6 +867,7 @@ tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt,
ek.srealm = rep.ticket.realm;
ek.sname = rep.ticket.sname;
{
unsigned char buf[8192]; /* XXX The data could be indefinite */
size_t len;
@@ -854,6 +922,7 @@ tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt,
krb5_data_copy(reply, buf + sizeof(buf) - len, len);
out:
free_TGS_REP(&rep);
free_TransitedEncoding(&et.transited);
if(et.starttime)
free(et.starttime);
if(et.renew_till)
@@ -911,11 +980,29 @@ out:
return ret;
}
static Realm
is_krbtgt(PrincipalName *p)
{
if(p->name_string.len == 2 && strcmp(p->name_string.val[0], "krbtgt") == 0)
return p->name_string.val[1];
else
return NULL;
}
static Realm
find_rpath(Realm r)
{
const char *new_realm = krb5_config_get_string(context->cf,
"libdefaults",
"capath",
r,
NULL);
return (Realm)new_realm;
}
static krb5_error_code
tgs_rep2(KDC_REQ_BODY *b,
krb5_principal sp,
PA_DATA *pa_data,
krb5_data *reply,
const char *from)
@@ -933,6 +1020,7 @@ tgs_rep2(KDC_REQ_BODY *b,
EncTicketPart *tgt;
Key *ekey;
krb5_principal cp = NULL;
krb5_principal sp = NULL;
memset(&ap_req, 0, sizeof(ap_req));
ret = krb5_decode_ap_req(context, &pa_data->padata_value, &ap_req);
@@ -942,8 +1030,7 @@ tgs_rep2(KDC_REQ_BODY *b,
goto out2;
}
if(ap_req.ticket.sname.name_string.len != 2 ||
strcmp(ap_req.ticket.sname.name_string.val[0], "krbtgt")){
if(!is_krbtgt(&ap_req.ticket.sname)){
kdc_log(0, "PA-DATA is not a ticket-granting ticket");
ret = KRB5KDC_ERR_POLICY; /* ? */
goto out2;
@@ -998,9 +1085,12 @@ tgs_rep2(KDC_REQ_BODY *b,
Realm r;
char *spn = NULL, *cpn = NULL;
hdb_entry *server = NULL, *client = NULL;
TransitedEncoding tr;
int loop = 0;
s = b->sname;
r = b->realm;
if(s == NULL)
if(b->kdc_options.enc_tkt_in_skey &&
b->additional_tickets &&
@@ -1022,30 +1112,47 @@ tgs_rep2(KDC_REQ_BODY *b,
goto out;
}
#if 0
principalname2krb5_principal(&sp, *s, r);
#endif
krb5_unparse_name(context, sp, &spn);
server = db_fetch(sp);
principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
krb5_unparse_name(context, cp, &cpn);
client = db_fetch(cp);
kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn);
server_lookup:
server = db_fetch(sp);
if(server == NULL){
Realm req_rlm, new_rlm;
if(loop++ < 2 && (req_rlm = is_krbtgt(&sp->name))){
new_rlm = find_rpath(req_rlm);
if(new_rlm){
kdc_log(5, "krbtgt for realm %s not found, trying %s",
req_rlm, new_rlm);
krb5_free_principal(context, sp);
free(spn);
krb5_make_principal(context, &sp, r,
"krbtgt", new_rlm, NULL);
krb5_unparse_name(context, sp, &spn);
goto server_lookup;
}
}
kdc_log(0, "Server not found in database: %s", spn);
/* do foreign realm stuff */
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
}
client = db_fetch(cp);
if(client == NULL)
kdc_log(1, "Client not found in database: %s", cpn);
#if 0
/* XXX check client only if same realm as krbtgt-instance */
if(client == NULL){
kdc_log(0, "Client not found in database: %s", cpn);
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
}
#endif
if((b->kdc_options.validate || b->kdc_options.renew) &&
!krb5_principal_compare(context,
@@ -1056,7 +1163,7 @@ tgs_rep2(KDC_REQ_BODY *b,
goto out;
}
ret = tgs_make_reply(b, tgt, server, client, reply);
ret = tgs_make_reply(b, tgt, server, client, cp, krbtgt, reply);
out:
free(spn);
@@ -1083,6 +1190,7 @@ out2:
0,
reply);
krb5_free_principal(context, cp);
krb5_free_principal(context, sp);
if (ticket) {
krb5_free_ticket(context, ticket);
free(ticket);
@@ -1096,27 +1204,6 @@ out2:
return ret;
}
static krb5_error_code
request_server(KDC_REQ *req, krb5_principal *server)
{
PrincipalName *s = NULL;
Realm r;
s = req->req_body.sname;
r = req->req_body.realm;
if(s == NULL &&
req->req_body.additional_tickets &&
req->req_body.additional_tickets->len){
s = &req->req_body.additional_tickets->val[0].sname;
r = req->req_body.additional_tickets->val[0].realm;
}
if(s)
principalname2krb5_principal(server, *s, r);
else
krb5_build_principal(context, server, strlen(r), r, "anonymous", NULL);
return 0;
}
krb5_error_code
tgs_rep(KDC_REQ *req,
krb5_data *data,
@@ -1125,9 +1212,6 @@ tgs_rep(KDC_REQ *req,
krb5_error_code ret;
int i;
PA_DATA *pa_data = NULL;
krb5_principal server;
request_server(req, &server);
if(req->padata == NULL){
ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
@@ -1146,7 +1230,7 @@ tgs_rep(KDC_REQ *req,
kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from);
goto out;
}
ret = tgs_rep2(&req->req_body, server, pa_data, data, from);
ret = tgs_rep2(&req->req_body, pa_data, data, from);
out:
if(ret && data->data == NULL)
krb5_mk_error(context,
@@ -1154,9 +1238,8 @@ out:
NULL,
NULL,
NULL,
server,
NULL,
0,
data);
krb5_free_principal(context, server);
return ret;
}