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;
|
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_auth_context ac = NULL;
|
||||||
krb5_keytab id = NULL;
|
krb5_keytab id = NULL;
|
||||||
krb5_principal sprincipal = NULL, cprincipal = NULL;
|
krb5_principal sprincipal = NULL, cprincipal = NULL;
|
||||||
krb5_principal principal = NULL;
|
|
||||||
char *cname = NULL;
|
char *cname = NULL;
|
||||||
Kx509Response rep;
|
Kx509Response rep;
|
||||||
size_t size;
|
size_t size;
|
||||||
@@ -392,40 +438,14 @@ _kdc_do_kx509(krb5_context context,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* verify server principal */
|
ret = krb5_ticket_get_server(context, ticket, &sprincipal);
|
||||||
|
|
||||||
ret = krb5_sname_to_principal(context, NULL, "kca_service",
|
|
||||||
KRB5_NT_UNKNOWN, &sprincipal);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = krb5_ticket_get_server(context, ticket, &principal);
|
ret = kdc_kx509_verify_service_principal(context, cname, sprincipal);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
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);
|
ret = krb5_auth_con_getkey(context, ac, &key);
|
||||||
if (ret == 0 && key == NULL)
|
if (ret == 0 && key == NULL)
|
||||||
ret = KRB5KDC_ERR_NULL_KEY;
|
ret = KRB5KDC_ERR_NULL_KEY;
|
||||||
@@ -515,8 +535,6 @@ out:
|
|||||||
krb5_free_principal(context, sprincipal);
|
krb5_free_principal(context, sprincipal);
|
||||||
if (cprincipal)
|
if (cprincipal)
|
||||||
krb5_free_principal(context, cprincipal);
|
krb5_free_principal(context, cprincipal);
|
||||||
if (principal)
|
|
||||||
krb5_free_principal(context, principal);
|
|
||||||
if (key)
|
if (key)
|
||||||
krb5_free_keyblock (context, key);
|
krb5_free_keyblock (context, key);
|
||||||
if (cname)
|
if (cname)
|
||||||
|
@@ -70,6 +70,8 @@ set_default_princ_type(krb5_principal p, NAME_TYPE defnt)
|
|||||||
princ_type(p) = KRB5_NT_SRV_INST;
|
princ_type(p) = KRB5_NT_SRV_INST;
|
||||||
else if (princ_num_comp(p) > 1 && strcmp(princ_ncomp(p, 0), "host") == 0)
|
else if (princ_num_comp(p) > 1 && strcmp(princ_ncomp(p, 0), "host") == 0)
|
||||||
princ_type(p) = KRB5_NT_SRV_HST;
|
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 &&
|
else if (princ_num_comp(p) == 2 &&
|
||||||
strcmp(princ_ncomp(p, 0), KRB5_WELLKNOWN_NAME) == 0)
|
strcmp(princ_ncomp(p, 0), KRB5_WELLKNOWN_NAME) == 0)
|
||||||
princ_type(p) = KRB5_NT_WELLKNOWN;
|
princ_type(p) = KRB5_NT_WELLKNOWN;
|
||||||
|
Reference in New Issue
Block a user