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:

committed by
Nico Williams

parent
f3484d5e2e
commit
87f8c0d2b5
@@ -18,6 +18,7 @@ EXPORTS
|
|||||||
CKSUMTYPE,
|
CKSUMTYPE,
|
||||||
ChangePasswdDataMS,
|
ChangePasswdDataMS,
|
||||||
Checksum,
|
Checksum,
|
||||||
|
CompositePrincipal,
|
||||||
ENCTYPE,
|
ENCTYPE,
|
||||||
ETYPE-INFO,
|
ETYPE-INFO,
|
||||||
ETYPE-INFO-ENTRY,
|
ETYPE-INFO-ENTRY,
|
||||||
@@ -440,9 +441,9 @@ Checksum ::= SEQUENCE {
|
|||||||
--
|
--
|
||||||
-- Attributes have three possible sources in Heimdal Kerberos at this time:
|
-- Attributes have three possible sources in Heimdal Kerberos at this time:
|
||||||
--
|
--
|
||||||
-- - the EncKDCRepPart
|
-- - the EncKDCRepPart (for the client's attributes on the client side)
|
||||||
-- - the EncTicketPart
|
-- - the EncTicketPart (for the client's attributes on the server side)
|
||||||
-- - the Authenticator's AuthorizationData (if any)
|
-- - the Authenticator's AuthorizationData (if any; server-side)
|
||||||
--
|
--
|
||||||
-- In principle there can be more:
|
-- In principle there can be more:
|
||||||
--
|
--
|
||||||
@@ -464,15 +465,39 @@ PrincipalNameAttrs ::= SEQUENCE {
|
|||||||
authenticated [0] BOOLEAN,
|
authenticated [0] BOOLEAN,
|
||||||
-- These are compiled from the Ticket and Authenticator:
|
-- These are compiled from the Ticket and Authenticator:
|
||||||
source [1] PrincipalNameAttrSrc OPTIONAL,
|
source [1] PrincipalNameAttrSrc OPTIONAL,
|
||||||
authenticator-ad [2] AuthorizationData OPTIONAL
|
authenticator-ad [2] AuthorizationData OPTIONAL,
|
||||||
|
-- For the server on the client side we should keep track of the
|
||||||
|
-- transit path taken to reach it (if absent -> unknown).
|
||||||
|
--
|
||||||
|
-- We don't learn much more about the server from the KDC.
|
||||||
|
peer-realm [3] Realm OPTIONAL,
|
||||||
|
transited [4] TransitedEncoding OPTIONAL,
|
||||||
|
pac-verified [5] BOOLEAN
|
||||||
|
-- TODO: Add requested attributes, for gss_set_name_attribute(), which
|
||||||
|
-- should cause corresponding authz-data elements to be added to
|
||||||
|
-- any TGS-REQ or to the AP-REQ's Authenticator as appropriate.
|
||||||
|
}
|
||||||
|
-- This is our type for exported composite name tokens for GSS [RFC6680].
|
||||||
|
-- It's the same as Principal (below) as decorated with (see krb5.opt file and
|
||||||
|
-- asn1_compile usage), except it's not decorated, so the name attributes are
|
||||||
|
-- encoded/decoded.
|
||||||
|
CompositePrincipal ::= [APPLICATION 48] SEQUENCE {
|
||||||
|
name[0] PrincipalName,
|
||||||
|
realm[1] Realm,
|
||||||
|
nameattrs[2] PrincipalNameAttrs OPTIONAL
|
||||||
}
|
}
|
||||||
|
|
||||||
-- this is not part of RFC1510
|
-- This is not part of RFC1510/RFC4120. We use this internally as our
|
||||||
|
-- krb5_principal (which is a typedef of *Principal), and in HDB entries.
|
||||||
Principal ::= SEQUENCE {
|
Principal ::= SEQUENCE {
|
||||||
name[0] PrincipalName,
|
name[0] PrincipalName,
|
||||||
realm[1] Realm
|
realm[1] Realm
|
||||||
-- This will be decorated with a name-attrs field of
|
-- This will be decorated with an optional nameattrs field of
|
||||||
-- PrincipalNameAttrs type that doesn't get encoded
|
-- PrincipalNameAttrs type that doesn't get encoded. Same as
|
||||||
|
-- CompositePrincipal above, except that CompositePrincipal's
|
||||||
|
-- nameattrs field does get encoded, while Principal's does not:
|
||||||
|
--
|
||||||
|
-- nameattrs[2] PrincipalNameAttrs OPTIONAL
|
||||||
}
|
}
|
||||||
|
|
||||||
Principals ::= SEQUENCE OF Principal
|
Principals ::= SEQUENCE OF Principal
|
||||||
|
@@ -70,3 +70,93 @@ _krb5_principalname2krb5_principal (krb5_context context,
|
|||||||
*principal = p;
|
*principal = p;
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
@@ -837,6 +837,8 @@ EXPORTS
|
|||||||
_krb5_enctype_requires_random_salt
|
_krb5_enctype_requires_random_salt
|
||||||
_krb5_principal2principalname
|
_krb5_principal2principalname
|
||||||
_krb5_principalname2krb5_principal
|
_krb5_principalname2krb5_principal
|
||||||
|
_krb5_kdcrep2krb5_principal
|
||||||
|
_krb5_ticket2krb5_principal
|
||||||
_krb5_put_int
|
_krb5_put_int
|
||||||
_krb5_s4u2self_to_checksumdata
|
_krb5_s4u2self_to_checksumdata
|
||||||
_krb5_HMAC_MD5_checksum
|
_krb5_HMAC_MD5_checksum
|
||||||
|
@@ -351,11 +351,6 @@ krb5_verify_ap_req2(krb5_context context,
|
|||||||
ap_req->ticket.sname,
|
ap_req->ticket.sname,
|
||||||
ap_req->ticket.realm);
|
ap_req->ticket.realm);
|
||||||
if (ret) goto out;
|
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,
|
ret = decrypt_authenticator (context,
|
||||||
&t->ticket.key,
|
&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 */
|
/* check addresses */
|
||||||
|
|
||||||
if (t->ticket.caddr
|
if (t->ticket.caddr
|
||||||
@@ -1042,6 +1058,8 @@ krb5_rd_req_ctx(krb5_context context,
|
|||||||
o->ticket->client,
|
o->ticket->client,
|
||||||
o->keyblock,
|
o->keyblock,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (ret == 0)
|
||||||
|
o->ticket->client->nameattrs->pac_verified = 1;
|
||||||
if (ret == 0 && (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME)) {
|
if (ret == 0 && (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME)) {
|
||||||
krb5_error_code ret2;
|
krb5_error_code ret2;
|
||||||
krb5_principal canon_name;
|
krb5_principal canon_name;
|
||||||
|
@@ -785,12 +785,19 @@ _krb5_extract_ticket(krb5_context context,
|
|||||||
creds->client = tmp_principal;
|
creds->client = tmp_principal;
|
||||||
|
|
||||||
/* check server referral and save principal */
|
/* check server referral and save principal */
|
||||||
ret = _krb5_principalname2krb5_principal (context,
|
ret = _krb5_kdcrep2krb5_principal(context, &tmp_principal, &rep->enc_part);
|
||||||
&tmp_principal,
|
|
||||||
rep->enc_part.sname,
|
|
||||||
rep->enc_part.srealm);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
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){
|
if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
|
||||||
ret = check_server_referral(context,
|
ret = check_server_referral(context,
|
||||||
rep,
|
rep,
|
||||||
|
@@ -828,6 +828,8 @@ HEIMDAL_KRB5_2.0 {
|
|||||||
_krb5_plugin_run_f;
|
_krb5_plugin_run_f;
|
||||||
_krb5_principal2principalname;
|
_krb5_principal2principalname;
|
||||||
_krb5_principalname2krb5_principal;
|
_krb5_principalname2krb5_principal;
|
||||||
|
_krb5_kdcrep2krb5_principal;
|
||||||
|
_krb5_ticket2krb5_principal;
|
||||||
_krb5_put_int;
|
_krb5_put_int;
|
||||||
_krb5_s4u2self_to_checksumdata;
|
_krb5_s4u2self_to_checksumdata;
|
||||||
_krb5_HMAC_MD5_checksum;
|
_krb5_HMAC_MD5_checksum;
|
||||||
|
Reference in New Issue
Block a user