krb5: Add name attributes to krb5_principal

We now have what we need in krb5_principal to implement much of RFC6680.
Now we populate those fields so that they can be accessed by GSS-API
RFC6680 name attributes functions.

The next commit should add much of the GSS-API RFC6680 name attributes
functions and functionality.
This commit is contained in:
Nicolas Williams
2021-12-20 16:22:52 -06:00
committed by Nico Williams
parent f3484d5e2e
commit 87f8c0d2b5
6 changed files with 163 additions and 19 deletions

View File

@@ -70,3 +70,93 @@ _krb5_principalname2krb5_principal (krb5_context context,
*principal = p;
return 0;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_ticket2krb5_principal(krb5_context context,
krb5_principal *principal,
const EncTicketPart *ticket,
const AuthorizationData *authenticator_ad)
{
krb5_error_code ret;
krb5_principal p;
*principal = NULL;
ret = _krb5_principalname2krb5_principal(context,
&p,
ticket->cname,
ticket->crealm);
if (ret == 0 &&
(p->nameattrs = calloc(1, sizeof(p->nameattrs[0]))) == NULL)
ret = krb5_enomem(context);
if (ret == 0)
p->nameattrs->authenticated = 1;
if (ret == 0 &&
(p->nameattrs->source =
calloc(1, sizeof(p->nameattrs->source[0]))) == NULL)
ret = krb5_enomem(context);
if (ret == 0) {
p->nameattrs->source->element =
choice_PrincipalNameAttrSrc_enc_ticket_part;
ret = copy_EncTicketPart(ticket,
&p->nameattrs->source->u.enc_ticket_part);
/* NOTE: we don't want to keep a copy of the session key here! */
if (ret == 0)
der_free_octet_string(&p->nameattrs->source->u.enc_ticket_part.key.keyvalue);
}
if (ret == 0 && authenticator_ad) {
p->nameattrs->authenticator_ad =
calloc(1, sizeof(p->nameattrs->authenticator_ad[0]));
if (p->nameattrs->authenticator_ad == NULL)
ret = krb5_enomem(context);
if (ret == 0)
ret = copy_AuthorizationData(authenticator_ad,
p->nameattrs->authenticator_ad);
}
if (ret == 0)
*principal = p;
else
krb5_free_principal(context, p);
return ret;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_kdcrep2krb5_principal(krb5_context context,
krb5_principal *principal,
const EncKDCRepPart *kdcrep)
{
krb5_error_code ret;
krb5_principal p;
*principal = NULL;
ret = _krb5_principalname2krb5_principal(context,
&p,
kdcrep->sname,
kdcrep->srealm);
if (ret == 0 &&
(p->nameattrs = calloc(1, sizeof(p->nameattrs[0]))) == NULL)
ret = krb5_enomem(context);
if (ret == 0)
p->nameattrs->authenticated = 1;
if (ret == 0 &&
(p->nameattrs->source =
calloc(1, sizeof(p->nameattrs->source[0]))) == NULL)
ret = krb5_enomem(context);
if (ret == 0) {
p->nameattrs->source->element =
choice_PrincipalNameAttrSrc_enc_kdc_rep_part;
ret = copy_EncKDCRepPart(kdcrep,
&p->nameattrs->source->u.enc_kdc_rep_part);
/* NOTE: we don't want to keep a copy of the session key here! */
if (ret == 0)
der_free_octet_string(&p->nameattrs->source->u.enc_kdc_rep_part.key.keyvalue);
}
if (ret == 0)
*principal = p;
else
krb5_free_principal(context, p);
return ret;
}

View File

@@ -837,6 +837,8 @@ EXPORTS
_krb5_enctype_requires_random_salt
_krb5_principal2principalname
_krb5_principalname2krb5_principal
_krb5_kdcrep2krb5_principal
_krb5_ticket2krb5_principal
_krb5_put_int
_krb5_s4u2self_to_checksumdata
_krb5_HMAC_MD5_checksum

View File

@@ -351,11 +351,6 @@ krb5_verify_ap_req2(krb5_context context,
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,
@@ -387,6 +382,27 @@ krb5_verify_ap_req2(krb5_context context,
}
}
/*
* The ticket authenticates the client, and conveys naming attributes that
* we want to expose in GSS using RFC6680 APIs.
*
* So we same the ticket enc-part in the client's krb5_principal object
* (note though that the session key will be absent in that copy of the
* ticket enc-part).
*/
ret = _krb5_ticket2krb5_principal(context, &t->client, &t->ticket,
ac->authenticator->authorization_data);
if (ret) goto out;
t->client->nameattrs->peer_realm =
calloc(1, sizeof(t->client->nameattrs->peer_realm[0]));
if (t->client->nameattrs->peer_realm == NULL) {
ret = krb5_enomem(context);
goto out;
}
ret = copy_Realm(&ap_req->ticket.realm, t->client->nameattrs->peer_realm);
if (ret) goto out;
/* check addresses */
if (t->ticket.caddr
@@ -1042,6 +1058,8 @@ krb5_rd_req_ctx(krb5_context context,
o->ticket->client,
o->keyblock,
NULL);
if (ret == 0)
o->ticket->client->nameattrs->pac_verified = 1;
if (ret == 0 && (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME)) {
krb5_error_code ret2;
krb5_principal canon_name;

View File

@@ -752,9 +752,9 @@ _krb5_extract_ticket(krb5_context context,
/* compare client and save */
ret = _krb5_principalname2krb5_principal(context,
&tmp_principal,
rep->kdc_rep.cname,
rep->kdc_rep.crealm);
&tmp_principal,
rep->kdc_rep.cname,
rep->kdc_rep.crealm);
if (ret)
goto out;
@@ -785,12 +785,19 @@ _krb5_extract_ticket(krb5_context context,
creds->client = tmp_principal;
/* check server referral and save principal */
ret = _krb5_principalname2krb5_principal (context,
&tmp_principal,
rep->enc_part.sname,
rep->enc_part.srealm);
ret = _krb5_kdcrep2krb5_principal(context, &tmp_principal, &rep->enc_part);
if (ret)
goto out;
tmp_principal->nameattrs->peer_realm =
calloc(1, sizeof(tmp_principal->nameattrs->peer_realm[0]));
if (tmp_principal->nameattrs->peer_realm == NULL) {
ret = krb5_enomem(context);
goto out;
}
ret = copy_Realm(&creds->client->realm, tmp_principal->nameattrs->peer_realm);
if (ret) goto out;
if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
ret = check_server_referral(context,
rep,

View File

@@ -828,6 +828,8 @@ HEIMDAL_KRB5_2.0 {
_krb5_plugin_run_f;
_krb5_principal2principalname;
_krb5_principalname2krb5_principal;
_krb5_kdcrep2krb5_principal;
_krb5_ticket2krb5_principal;
_krb5_put_int;
_krb5_s4u2self_to_checksumdata;
_krb5_HMAC_MD5_checksum;