kpasswdd should not enforce principal realm =~ default realm(s)
Signed-off-by: Love Hornquist Astrand <lha@h5l.org>
This commit is contained in:

committed by
Love Hornquist Astrand

parent
9ca0a2b62f
commit
511cd18458
@@ -436,7 +436,6 @@ out:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
verify (krb5_auth_context *auth_context,
|
verify (krb5_auth_context *auth_context,
|
||||||
krb5_realm *realms,
|
|
||||||
krb5_keytab keytab,
|
krb5_keytab keytab,
|
||||||
krb5_ticket **ticket,
|
krb5_ticket **ticket,
|
||||||
krb5_data *out_data,
|
krb5_data *out_data,
|
||||||
@@ -452,7 +451,9 @@ verify (krb5_auth_context *auth_context,
|
|||||||
uint16_t pkt_len, pkt_ver, ap_req_len;
|
uint16_t pkt_len, pkt_ver, ap_req_len;
|
||||||
krb5_data ap_req_data;
|
krb5_data ap_req_data;
|
||||||
krb5_data krb_priv_data;
|
krb5_data krb_priv_data;
|
||||||
krb5_realm *r;
|
krb5_const_realm client_realm;
|
||||||
|
krb5_principal sprinc;
|
||||||
|
int same;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only send an error reply if the request passes basic length
|
* Only send an error reply if the request passes basic length
|
||||||
@@ -501,49 +502,40 @@ verify (krb5_auth_context *auth_context,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* verify realm and principal */
|
|
||||||
for (r = realms; *r != NULL; r++) {
|
|
||||||
krb5_principal principal;
|
|
||||||
krb5_boolean same;
|
|
||||||
|
|
||||||
ret = krb5_make_principal (context,
|
|
||||||
&principal,
|
|
||||||
*r,
|
|
||||||
"kadmin",
|
|
||||||
"changepw",
|
|
||||||
NULL);
|
|
||||||
if (ret)
|
|
||||||
krb5_err (context, 1, ret, "krb5_make_principal");
|
|
||||||
|
|
||||||
same = krb5_principal_compare(context, principal, (*ticket)->server);
|
|
||||||
krb5_free_principal(context, principal);
|
|
||||||
if (same == TRUE)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (*r == NULL) {
|
|
||||||
char *str;
|
|
||||||
krb5_unparse_name(context, (*ticket)->server, &str);
|
|
||||||
krb5_warnx (context, "client used not valid principal %s", str);
|
|
||||||
free(str);
|
|
||||||
reply_error (NULL, s, sa, sa_size, ret, 1,
|
|
||||||
"Bad request");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp((*ticket)->server->realm, (*ticket)->client->realm) != 0) {
|
|
||||||
krb5_warnx (context, "server realm (%s) not same a client realm (%s)",
|
|
||||||
(*ticket)->server->realm, (*ticket)->client->realm);
|
|
||||||
reply_error ((*ticket)->server->realm, s, sa, sa_size, ret, 1,
|
|
||||||
"Bad request");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(*ticket)->ticket.flags.initial) {
|
if (!(*ticket)->ticket.flags.initial) {
|
||||||
krb5_warnx(context, "initial flag not set");
|
krb5_warnx(context, "initial flag not set");
|
||||||
reply_error((*ticket)->server->realm, s, sa, sa_size, ret, 1,
|
reply_error((*ticket)->server->realm, s, sa, sa_size, ret, 1,
|
||||||
"Bad request");
|
"Bad request");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The service principal must be kadmin/changepw@CLIENT-REALM, there
|
||||||
|
* is no reason to require the KDC's default realm(s) to be the same
|
||||||
|
* as the realm(s) it serves. The only potential issue is when a KDC
|
||||||
|
* is a master for realm A and a slave for realm B, in which case it
|
||||||
|
* should not accept requests to change passwords for realm B, these
|
||||||
|
* should be sent to realm B's master. This same issue is present in
|
||||||
|
* the checks that only accepted local realms, there is no new risk.
|
||||||
|
*/
|
||||||
|
|
||||||
|
client_realm = krb5_principal_get_realm(context, (*ticket)->client);
|
||||||
|
ret = krb5_make_principal(context, &sprinc, client_realm,
|
||||||
|
"kadmin", "changepw", NULL);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
same = krb5_principal_compare(context, sprinc, (*ticket)->server);
|
||||||
|
krb5_free_principal(context, sprinc);
|
||||||
|
|
||||||
|
if (!same) {
|
||||||
|
char *sname;
|
||||||
|
|
||||||
|
krb5_unparse_name(context, (*ticket)->server, &sname);
|
||||||
|
krb5_warnx(context, "Invalid kpasswd service principal %s", sname);
|
||||||
|
free(sname);
|
||||||
|
reply_error(NULL, s, sa, sa_size, ret, 1, "Bad request");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
krb_priv_data.data = msg + 6 + ap_req_len;
|
krb_priv_data.data = msg + 6 + ap_req_len;
|
||||||
krb_priv_data.length = len - 6 - ap_req_len;
|
krb_priv_data.length = len - 6 - ap_req_len;
|
||||||
|
|
||||||
@@ -582,8 +574,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process (krb5_realm *realms,
|
process (krb5_keytab keytab,
|
||||||
krb5_keytab keytab,
|
|
||||||
int s,
|
int s,
|
||||||
krb5_address *this_addr,
|
krb5_address *this_addr,
|
||||||
struct sockaddr *sa,
|
struct sockaddr *sa,
|
||||||
@@ -622,7 +613,7 @@ process (krb5_realm *realms,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verify (&auth_context, realms, keytab, &ticket, &out_data,
|
if (verify (&auth_context, keytab, &ticket, &out_data,
|
||||||
&version, s, sa, sa_size, msg, len, &other_addr) == 0)
|
&version, s, sa, sa_size, msg, len, &other_addr) == 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -659,17 +650,12 @@ doit (krb5_keytab keytab, int port)
|
|||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
int *sockets;
|
int *sockets;
|
||||||
int maxfd;
|
int maxfd;
|
||||||
krb5_realm *realms;
|
|
||||||
krb5_addresses addrs;
|
krb5_addresses addrs;
|
||||||
unsigned n, i;
|
unsigned n, i;
|
||||||
fd_set real_fdset;
|
fd_set real_fdset;
|
||||||
struct sockaddr_storage __ss;
|
struct sockaddr_storage __ss;
|
||||||
struct sockaddr *sa = (struct sockaddr *)&__ss;
|
struct sockaddr *sa = (struct sockaddr *)&__ss;
|
||||||
|
|
||||||
ret = krb5_get_default_realms(context, &realms);
|
|
||||||
if (ret)
|
|
||||||
krb5_err (context, 1, ret, "krb5_get_default_realms");
|
|
||||||
|
|
||||||
if (explicit_addresses.len) {
|
if (explicit_addresses.len) {
|
||||||
addrs = explicit_addresses;
|
addrs = explicit_addresses;
|
||||||
} else {
|
} else {
|
||||||
@@ -736,7 +722,7 @@ doit (krb5_keytab keytab, int port)
|
|||||||
krb5_err (context, 1, errno, "recvfrom");
|
krb5_err (context, 1, errno, "recvfrom");
|
||||||
}
|
}
|
||||||
|
|
||||||
process (realms, keytab, sockets[i],
|
process (keytab, sockets[i],
|
||||||
&addrs.val[i],
|
&addrs.val[i],
|
||||||
sa, addrlen,
|
sa, addrlen,
|
||||||
buf, retx);
|
buf, retx);
|
||||||
@@ -748,7 +734,6 @@ doit (krb5_keytab keytab, int port)
|
|||||||
free(sockets);
|
free(sockets);
|
||||||
|
|
||||||
krb5_free_addresses (context, &addrs);
|
krb5_free_addresses (context, &addrs);
|
||||||
krb5_free_host_realm (context, realms);
|
|
||||||
krb5_free_context (context);
|
krb5_free_context (context);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user