Support multi-realms databases, requires that all the realms are
configured on the KDC in krb5.conf with [libdefaults]default_realm stanzas. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@14884 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -139,7 +139,7 @@ make_result (krb5_data *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reply_error (krb5_principal server,
|
reply_error (krb5_realm realm,
|
||||||
int s,
|
int s,
|
||||||
struct sockaddr *sa,
|
struct sockaddr *sa,
|
||||||
int sa_size,
|
int sa_size,
|
||||||
@@ -150,10 +150,20 @@ reply_error (krb5_principal server,
|
|||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_data error_data;
|
krb5_data error_data;
|
||||||
krb5_data e_data;
|
krb5_data e_data;
|
||||||
|
krb5_principal server = NULL;
|
||||||
|
|
||||||
if (make_result(&e_data, result_code, expl))
|
if (make_result(&e_data, result_code, expl))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (realm) {
|
||||||
|
ret = krb5_make_principal (context, &server, realm,
|
||||||
|
"kadmin", "changepw", NULL);
|
||||||
|
if (ret) {
|
||||||
|
krb5_data_free (&e_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = krb5_mk_error (context,
|
ret = krb5_mk_error (context,
|
||||||
error_code,
|
error_code,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -163,6 +173,8 @@ reply_error (krb5_principal server,
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&error_data);
|
&error_data);
|
||||||
|
if (server)
|
||||||
|
krb5_free_principal(context, server);
|
||||||
krb5_data_free (&e_data);
|
krb5_data_free (&e_data);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
krb5_warn (context, ret, "Could not even generate error reply");
|
krb5_warn (context, ret, "Could not even generate error reply");
|
||||||
@@ -409,7 +421,7 @@ out:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
verify (krb5_auth_context *auth_context,
|
verify (krb5_auth_context *auth_context,
|
||||||
krb5_principal server,
|
krb5_realm *realms,
|
||||||
krb5_keytab keytab,
|
krb5_keytab keytab,
|
||||||
krb5_ticket **ticket,
|
krb5_ticket **ticket,
|
||||||
krb5_data *out_data,
|
krb5_data *out_data,
|
||||||
@@ -424,6 +436,7 @@ verify (krb5_auth_context *auth_context,
|
|||||||
u_int16_t pkt_len, pkt_ver, ap_req_len;
|
u_int16_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;
|
||||||
|
|
||||||
pkt_len = (msg[0] << 8) | (msg[1]);
|
pkt_len = (msg[0] << 8) | (msg[1]);
|
||||||
pkt_ver = (msg[2] << 8) | (msg[3]);
|
pkt_ver = (msg[2] << 8) | (msg[3]);
|
||||||
@@ -431,13 +444,13 @@ verify (krb5_auth_context *auth_context,
|
|||||||
if (pkt_len != len) {
|
if (pkt_len != len) {
|
||||||
krb5_warnx (context, "Strange len: %ld != %ld",
|
krb5_warnx (context, "Strange len: %ld != %ld",
|
||||||
(long)pkt_len, (long)len);
|
(long)pkt_len, (long)len);
|
||||||
reply_error (server, s, sa, sa_size, 0, 1, "Bad request");
|
reply_error (NULL, s, sa, sa_size, 0, 1, "Bad request");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW &&
|
if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW &&
|
||||||
pkt_ver != KRB5_KPASSWD_VERS_SETPW) {
|
pkt_ver != KRB5_KPASSWD_VERS_SETPW) {
|
||||||
krb5_warnx (context, "Bad version (%d)", pkt_ver);
|
krb5_warnx (context, "Bad version (%d)", pkt_ver);
|
||||||
reply_error (server, s, sa, sa_size, 0, 1, "Wrong program version");
|
reply_error (NULL, s, sa, sa_size, 0, 1, "Wrong program version");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
*version = pkt_ver;
|
*version = pkt_ver;
|
||||||
@@ -448,26 +461,56 @@ verify (krb5_auth_context *auth_context,
|
|||||||
ret = krb5_rd_req (context,
|
ret = krb5_rd_req (context,
|
||||||
auth_context,
|
auth_context,
|
||||||
&ap_req_data,
|
&ap_req_data,
|
||||||
server,
|
NULL,
|
||||||
keytab,
|
keytab,
|
||||||
NULL,
|
NULL,
|
||||||
ticket);
|
ticket);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if(ret == KRB5_KT_NOTFOUND) {
|
krb5_warn (context, ret, "krb5_rd_req");
|
||||||
char *name;
|
reply_error (NULL, s, sa, sa_size, ret, 3, "Authentication failed");
|
||||||
krb5_unparse_name(context, server, &name);
|
|
||||||
krb5_warnx (context, "krb5_rd_req: %s (%s)",
|
|
||||||
krb5_get_err_text(context, ret), name);
|
|
||||||
free(name);
|
|
||||||
} else
|
|
||||||
krb5_warn (context, ret, "krb5_rd_req");
|
|
||||||
reply_error (server, s, sa, sa_size, ret, 3, "Authentication failed");
|
|
||||||
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 (server, 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;
|
||||||
}
|
}
|
||||||
@@ -482,7 +525,8 @@ verify (krb5_auth_context *auth_context,
|
|||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
krb5_warn (context, ret, "krb5_rd_priv");
|
krb5_warn (context, ret, "krb5_rd_priv");
|
||||||
reply_error (server, s, sa, sa_size, ret, 3, "Bad request");
|
reply_error ((*ticket)->server->realm, s, sa, sa_size, ret, 3,
|
||||||
|
"Bad request");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -493,7 +537,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process (krb5_principal server,
|
process (krb5_realm *realms,
|
||||||
krb5_keytab keytab,
|
krb5_keytab keytab,
|
||||||
int s,
|
int s,
|
||||||
krb5_address *this_addr,
|
krb5_address *this_addr,
|
||||||
@@ -537,7 +581,7 @@ process (krb5_principal server,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verify (&auth_context, server, keytab, &ticket, &out_data,
|
if (verify (&auth_context, realms, keytab, &ticket, &out_data,
|
||||||
&version, s, sa, sa_size, msg, len) == 0) {
|
&version, s, sa, sa_size, msg, len) == 0) {
|
||||||
change (auth_context,
|
change (auth_context,
|
||||||
ticket->client,
|
ticket->client,
|
||||||
@@ -558,31 +602,18 @@ static int
|
|||||||
doit (krb5_keytab keytab, int port)
|
doit (krb5_keytab keytab, int port)
|
||||||
{
|
{
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_principal server;
|
|
||||||
int *sockets;
|
int *sockets;
|
||||||
int maxfd;
|
int maxfd;
|
||||||
char *realm;
|
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_realm (context, &realm);
|
ret = krb5_get_default_realms(context, &realms);
|
||||||
if (ret)
|
if (ret)
|
||||||
krb5_err (context, 1, ret, "krb5_get_default_realm");
|
krb5_err (context, 1, ret, "krb5_get_default_realms");
|
||||||
|
|
||||||
ret = krb5_build_principal (context,
|
|
||||||
&server,
|
|
||||||
strlen(realm),
|
|
||||||
realm,
|
|
||||||
"kadmin",
|
|
||||||
"changepw",
|
|
||||||
NULL);
|
|
||||||
if (ret)
|
|
||||||
krb5_err (context, 1, ret, "krb5_build_principal");
|
|
||||||
|
|
||||||
free (realm);
|
|
||||||
|
|
||||||
if (explicit_addresses.len) {
|
if (explicit_addresses.len) {
|
||||||
addrs = explicit_addresses;
|
addrs = explicit_addresses;
|
||||||
@@ -650,14 +681,14 @@ doit (krb5_keytab keytab, int port)
|
|||||||
krb5_err (context, 1, errno, "recvfrom");
|
krb5_err (context, 1, errno, "recvfrom");
|
||||||
}
|
}
|
||||||
|
|
||||||
process (server, keytab, sockets[i],
|
process (realms, keytab, sockets[i],
|
||||||
&addrs.val[i],
|
&addrs.val[i],
|
||||||
sa, addrlen,
|
sa, addrlen,
|
||||||
buf, ret);
|
buf, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
krb5_free_addresses (context, &addrs);
|
krb5_free_addresses (context, &addrs);
|
||||||
krb5_free_principal (context, server);
|
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