[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Problems with kpasswdd handling multiple realms...
Hi Sean
> Howdy. I'm in a situation where I have multiple realms on the same
> KDC, which is working flawlessly... except for changing passwords.
Ok, I see why you have a problem. If you add multiple
[libdefaults]default_realm stanzas the patch below should do what you want.
I've not tested the patch (except compiling), I feel I need to digest it
for a day for two more before commit it.
Love
--- kpasswd/kpasswdd.c 15 Apr 2005 11:14:20 -0000
+++ kpasswd/kpasswdd.c 15 Apr 2005 19:44:18 -0000
@@ -410,6 +410,7 @@
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 +425,7 @@
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]);
@@ -448,23 +450,52 @@
ret = krb5_rd_req (context,
auth_context,
&ap_req_data,
- server,
+ /* 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");
return 1;
}
+ /* verify realm and principal */
+ for (r = realms; *r != NULL; r++) {
+ krb5_principal principal;
+
+ ret = krb5_make_principal (context,
+ &principal,
+ *r,
+ "kadmin",
+ "changepw",
+ NULL);
+ if (ret)
+ krb5_err (context, 1, ret, "krb5_make_principal");
+
+ ret = krb5_principal_compare(context, principal, (*ticket)->server);
+ krb5_free_principal(context, principal);
+ if (ret == 0)
+ 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 (server, 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 (server, 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,
@@ -494,6 +525,7 @@
static void
process (krb5_principal server,
+ krb5_realm *realms,
krb5_keytab keytab,
int s,
krb5_address *this_addr,
@@ -537,7 +569,7 @@
goto out;
}
- if (verify (&auth_context, server, keytab, &ticket, &out_data,
+ if (verify (&auth_context, server, realms, keytab, &ticket, &out_data,
&version, s, sa, sa_size, msg, len) == 0) {
change (auth_context,
ticket->client,
@@ -561,28 +593,25 @@
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");
+ krb5_err (context, 1, ret, "krb5_get_default_realms");
- ret = krb5_build_principal (context,
+ ret = krb5_make_principal (context,
&server,
- strlen(realm),
- realm,
+ realms[0],
"kadmin",
"changepw",
NULL);
if (ret)
- krb5_err (context, 1, ret, "krb5_build_principal");
-
- free (realm);
+ krb5_err (context, 1, ret, "krb5_make_principal");
if (explicit_addresses.len) {
addrs = explicit_addresses;
@@ -650,7 +679,7 @@
krb5_err (context, 1, errno, "recvfrom");
}
- process (server, keytab, sockets[i],
+ process (server, realms, keytab, sockets[i],
&addrs.val[i],
sa, addrlen,
buf, ret);
@@ -658,6 +687,7 @@
}
krb5_free_addresses (context, &addrs);
krb5_free_principal (context, server);
+ krb5_free_host_realm (context, realms);
krb5_free_context (context);
return 0;
}
PGP signature