[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