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
|
||||
reply_error (krb5_principal server,
|
||||
reply_error (krb5_realm realm,
|
||||
int s,
|
||||
struct sockaddr *sa,
|
||||
int sa_size,
|
||||
@@ -150,10 +150,20 @@ reply_error (krb5_principal server,
|
||||
krb5_error_code ret;
|
||||
krb5_data error_data;
|
||||
krb5_data e_data;
|
||||
krb5_principal server = NULL;
|
||||
|
||||
if (make_result(&e_data, result_code, expl))
|
||||
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,
|
||||
error_code,
|
||||
NULL,
|
||||
@@ -163,6 +173,8 @@ reply_error (krb5_principal server,
|
||||
NULL,
|
||||
NULL,
|
||||
&error_data);
|
||||
if (server)
|
||||
krb5_free_principal(context, server);
|
||||
krb5_data_free (&e_data);
|
||||
if (ret) {
|
||||
krb5_warn (context, ret, "Could not even generate error reply");
|
||||
@@ -409,7 +421,7 @@ out:
|
||||
|
||||
static int
|
||||
verify (krb5_auth_context *auth_context,
|
||||
krb5_principal server,
|
||||
krb5_realm *realms,
|
||||
krb5_keytab keytab,
|
||||
krb5_ticket **ticket,
|
||||
krb5_data *out_data,
|
||||
@@ -424,6 +436,7 @@ verify (krb5_auth_context *auth_context,
|
||||
u_int16_t pkt_len, pkt_ver, ap_req_len;
|
||||
krb5_data ap_req_data;
|
||||
krb5_data krb_priv_data;
|
||||
krb5_realm *r;
|
||||
|
||||
pkt_len = (msg[0] << 8) | (msg[1]);
|
||||
pkt_ver = (msg[2] << 8) | (msg[3]);
|
||||
@@ -431,13 +444,13 @@ verify (krb5_auth_context *auth_context,
|
||||
if (pkt_len != len) {
|
||||
krb5_warnx (context, "Strange len: %ld != %ld",
|
||||
(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;
|
||||
}
|
||||
if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW &&
|
||||
pkt_ver != KRB5_KPASSWD_VERS_SETPW) {
|
||||
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;
|
||||
}
|
||||
*version = pkt_ver;
|
||||
@@ -448,26 +461,56 @@ verify (krb5_auth_context *auth_context,
|
||||
ret = krb5_rd_req (context,
|
||||
auth_context,
|
||||
&ap_req_data,
|
||||
server,
|
||||
NULL,
|
||||
keytab,
|
||||
NULL,
|
||||
ticket);
|
||||
if (ret) {
|
||||
if(ret == KRB5_KT_NOTFOUND) {
|
||||
char *name;
|
||||
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");
|
||||
krb5_warn (context, ret, "krb5_rd_req");
|
||||
reply_error (NULL, s, sa, sa_size, ret, 3, "Authentication failed");
|
||||
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) {
|
||||
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");
|
||||
goto out;
|
||||
}
|
||||
@@ -482,7 +525,8 @@ verify (krb5_auth_context *auth_context,
|
||||
|
||||
if (ret) {
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
@@ -493,7 +537,7 @@ out:
|
||||
}
|
||||
|
||||
static void
|
||||
process (krb5_principal server,
|
||||
process (krb5_realm *realms,
|
||||
krb5_keytab keytab,
|
||||
int s,
|
||||
krb5_address *this_addr,
|
||||
@@ -537,7 +581,7 @@ process (krb5_principal server,
|
||||
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) {
|
||||
change (auth_context,
|
||||
ticket->client,
|
||||
@@ -558,31 +602,18 @@ static int
|
||||
doit (krb5_keytab keytab, int port)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_principal server;
|
||||
int *sockets;
|
||||
int maxfd;
|
||||
char *realm;
|
||||
krb5_realm *realms;
|
||||
krb5_addresses addrs;
|
||||
unsigned n, i;
|
||||
fd_set real_fdset;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr *sa = (struct sockaddr *)&__ss;
|
||||
|
||||
ret = krb5_get_default_realm (context, &realm);
|
||||
ret = krb5_get_default_realms(context, &realms);
|
||||
if (ret)
|
||||
krb5_err (context, 1, ret, "krb5_get_default_realm");
|
||||
|
||||
ret = krb5_build_principal (context,
|
||||
&server,
|
||||
strlen(realm),
|
||||
realm,
|
||||
"kadmin",
|
||||
"changepw",
|
||||
NULL);
|
||||
if (ret)
|
||||
krb5_err (context, 1, ret, "krb5_build_principal");
|
||||
|
||||
free (realm);
|
||||
krb5_err (context, 1, ret, "krb5_get_default_realms");
|
||||
|
||||
if (explicit_addresses.len) {
|
||||
addrs = explicit_addresses;
|
||||
@@ -650,14 +681,14 @@ doit (krb5_keytab keytab, int port)
|
||||
krb5_err (context, 1, errno, "recvfrom");
|
||||
}
|
||||
|
||||
process (server, keytab, sockets[i],
|
||||
process (realms, keytab, sockets[i],
|
||||
&addrs.val[i],
|
||||
sa, addrlen,
|
||||
buf, ret);
|
||||
}
|
||||
}
|
||||
krb5_free_addresses (context, &addrs);
|
||||
krb5_free_principal (context, server);
|
||||
krb5_free_host_realm (context, realms);
|
||||
krb5_free_context (context);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user