kdc: fix kx509 service principal match
Each KDC is a kx509 server. The service principal must be of the
form
kca_service/<localhost.domain>@<DEFAULT_REALM>
where localhost.domain is the hostname returned by gethostname()
and <DEFAULT_REALM> is one of the realms for which the KDC has a service
principal "kca_service/<localhost.domain>".
The matching code was broken by a5e77c578e
when krb5_sname_to_principal() began to always return a referral
principal.
Since the second component is a host name update the default principal
type for service "kca_service" to be KRB5_NT_SRV_HST.
Change-Id: I6bd5f90b674ebb7220d8efafa6d339fdc21e1a07
This commit is contained in:
80
kdc/kx509.c
80
kdc/kx509.c
@@ -322,6 +322,53 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
kdc_kx509_verify_service_principal(krb5_context context,
|
||||
const char *cname,
|
||||
krb5_principal sprincipal)
|
||||
{
|
||||
krb5_error_code ret, aret;
|
||||
krb5_boolean bret;
|
||||
krb5_principal principal = NULL;
|
||||
char *expected = NULL;
|
||||
char localhost[MAXHOSTNAMELEN];
|
||||
|
||||
ret = gethostname(localhost, sizeof(localhost) - 1);
|
||||
if (ret != 0) {
|
||||
ret = errno;
|
||||
krb5_set_error_message(context, ret,
|
||||
N_("Failed to get local hostname", ""));
|
||||
return ret;
|
||||
}
|
||||
localhost[sizeof(localhost) - 1] = '\0';
|
||||
|
||||
ret = krb5_make_principal(context, &principal, "", "kca_service",
|
||||
localhost, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
bret = krb5_principal_compare_any_realm(context, sprincipal, principal);
|
||||
if (bret == TRUE)
|
||||
goto out; /* found a match */
|
||||
|
||||
ret = KRB5KDC_ERR_SERVER_NOMATCH;
|
||||
|
||||
aret = krb5_unparse_name(context, sprincipal, &expected);
|
||||
if (aret)
|
||||
goto out;
|
||||
|
||||
krb5_set_error_message(context, ret,
|
||||
"User %s used wrong Kx509 service "
|
||||
"principal, expected: %s",
|
||||
cname, expected);
|
||||
|
||||
out:
|
||||
krb5_xfree(expected);
|
||||
krb5_free_principal(context, principal);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
@@ -338,7 +385,6 @@ _kdc_do_kx509(krb5_context context,
|
||||
krb5_auth_context ac = NULL;
|
||||
krb5_keytab id = NULL;
|
||||
krb5_principal sprincipal = NULL, cprincipal = NULL;
|
||||
krb5_principal principal = NULL;
|
||||
char *cname = NULL;
|
||||
Kx509Response rep;
|
||||
size_t size;
|
||||
@@ -392,40 +438,14 @@ _kdc_do_kx509(krb5_context context,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* verify server principal */
|
||||
|
||||
ret = krb5_sname_to_principal(context, NULL, "kca_service",
|
||||
KRB5_NT_UNKNOWN, &sprincipal);
|
||||
ret = krb5_ticket_get_server(context, ticket, &sprincipal);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_ticket_get_server(context, ticket, &principal);
|
||||
ret = kdc_kx509_verify_service_principal(context, cname, sprincipal);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = krb5_principal_compare(context, sprincipal, principal);
|
||||
if (ret != TRUE) {
|
||||
char *expected, *used;
|
||||
|
||||
ret = krb5_unparse_name(context, sprincipal, &expected);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = krb5_unparse_name(context, principal, &used);
|
||||
if (ret) {
|
||||
krb5_xfree(expected);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = KRB5KDC_ERR_SERVER_NOMATCH;
|
||||
krb5_set_error_message(context, ret,
|
||||
"User %s used wrong Kx509 service "
|
||||
"principal, expected: %s, used %s",
|
||||
cname, expected, used);
|
||||
krb5_xfree(expected);
|
||||
krb5_xfree(used);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_auth_con_getkey(context, ac, &key);
|
||||
if (ret == 0 && key == NULL)
|
||||
ret = KRB5KDC_ERR_NULL_KEY;
|
||||
@@ -515,8 +535,6 @@ out:
|
||||
krb5_free_principal(context, sprincipal);
|
||||
if (cprincipal)
|
||||
krb5_free_principal(context, cprincipal);
|
||||
if (principal)
|
||||
krb5_free_principal(context, principal);
|
||||
if (key)
|
||||
krb5_free_keyblock (context, key);
|
||||
if (cname)
|
||||
|
@@ -70,6 +70,8 @@ set_default_princ_type(krb5_principal p, NAME_TYPE defnt)
|
||||
princ_type(p) = KRB5_NT_SRV_INST;
|
||||
else if (princ_num_comp(p) > 1 && strcmp(princ_ncomp(p, 0), "host") == 0)
|
||||
princ_type(p) = KRB5_NT_SRV_HST;
|
||||
else if (princ_num_comp(p) > 1 && strcmp(princ_ncomp(p, 0), "kca_service") == 0)
|
||||
princ_type(p) = KRB5_NT_SRV_HST;
|
||||
else if (princ_num_comp(p) == 2 &&
|
||||
strcmp(princ_ncomp(p, 0), KRB5_WELLKNOWN_NAME) == 0)
|
||||
princ_type(p) = KRB5_NT_WELLKNOWN;
|
||||
|
Reference in New Issue
Block a user