Discussion of krb5_get_init_creds_password() behavior wasRe:problem with the kinit_prompter in kfw 2.5

Ken Hornstein kenh at cmf.nrl.navy.mil
Tue Feb 24 11:51:53 EST 2004


Okay, as we discussed, I've got a patch worked up.  In testing it here,
it seems to do what we want (will only cause the second request to go
to the master KDC if the response that it processed was _not_ from the
master).  Comments are welcome.  It doesn't seem like a whole lot of
code, actually.

--Ken

Index: include/k5-int.h
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/include/k5-int.h,v
retrieving revision 1.11
diff -u -r1.11 k5-int.h
--- include/k5-int.h	31 Dec 2003 21:28:51 -0000	1.11
+++ include/k5-int.h	23 Feb 2004 22:01:42 -0000
@@ -503,10 +503,10 @@
 krb5_error_code krb5_lock_file (krb5_context, int, int);
 krb5_error_code krb5_unlock_file (krb5_context, int);
 krb5_error_code krb5_sendto_kdc (krb5_context, const krb5_data *,
-				 const krb5_data *, krb5_data *, int, int);
+				 const krb5_data *, krb5_data *, int *, int);
 krb5_error_code krb5int_sendto (krb5_context, const krb5_data *,
 				const struct addrlist *, krb5_data *,
-				struct sockaddr *, socklen_t *);
+				struct sockaddr *, socklen_t *, int *);
 krb5_error_code krb5_get_krbhst (krb5_context, const krb5_data *, char *** );
 krb5_error_code krb5_free_krbhst (krb5_context, char * const * );
 krb5_error_code krb5_create_secure_file (krb5_context, const char * pathname);
@@ -938,7 +938,7 @@
 		krb5_get_init_creds_opt *gic_options,
 		krb5_gic_get_as_key_fct gak,
 		void *gak_data,
-		int master,
+		int *master,
 		krb5_kdc_rep **as_reply);
 
 void krb5int_populate_gic_opt (
@@ -1677,7 +1677,7 @@
 				      int, int, int, int);
     krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg,
 				   const struct addrlist *, krb5_data *reply,
-				   struct sockaddr *, socklen_t *);
+				   struct sockaddr *, socklen_t *, int *);
     krb5_error_code (*add_host_to_list)(struct addrlist *lp,
 					const char *hostname,
 					int port, int secport,
Index: lib/krb4/send_to_kdc.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb4/send_to_kdc.c,v
retrieving revision 1.3
diff -u -r1.3 send_to_kdc.c
--- lib/krb4/send_to_kdc.c	22 Dec 2003 19:36:06 -0000	1.3
+++ lib/krb4/send_to_kdc.c	23 Feb 2004 21:34:24 -0000
@@ -181,7 +181,7 @@
     message.length = pkt->length;
     message.data = (char *)pkt->dat; /* XXX yuck */
     retval = internals.sendto_udp(NULL, &message, &al, &reply, addr,
-				  addrlen);
+				  addrlen, NULL);
     DEB(("sendto_udp returns %d\n", retval));
 free_al:
     internals.free_addrlist(&al);
Index: lib/krb5/krb/get_in_tkt.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb5/krb/get_in_tkt.c,v
retrieving revision 1.6
diff -u -r1.6 get_in_tkt.c
--- lib/krb5/krb/get_in_tkt.c	22 Dec 2003 19:36:23 -0000	1.6
+++ lib/krb5/krb/get_in_tkt.c	23 Feb 2004 23:03:04 -0000
@@ -90,7 +90,7 @@
 		krb5_timestamp 		*time_now,
 		krb5_error ** 		ret_err_reply,
 		krb5_kdc_rep ** 	ret_as_reply,
-		int 			use_master)
+		int 			*use_master)
 {
     krb5_kdc_rep *as_reply = 0;
     krb5_error_code retval;
@@ -444,6 +444,7 @@
     krb5_pa_data  **	preauth_to_use = 0;
     int			loopcount = 0;
     krb5_int32		do_more = 0;
+    int			use_master = 0;
 
     if (! krb5_realm_compare(context, creds->client, creds->server))
 	return KRB5_IN_TKT_REALM_MISMATCH;
@@ -535,7 +536,7 @@
 	err_reply = 0;
 	as_reply = 0;
 	if ((retval = send_as_request(context, &request, &time_now, &err_reply,
-				      &as_reply, 0)))
+				      &as_reply, &use_master)))
 	    goto cleanup;
 
 	if (err_reply) {
@@ -738,7 +739,7 @@
 		    krb5_get_init_creds_opt *options,
 		    krb5_gic_get_as_key_fct gak_fct,
 		    void *gak_data,
-		    int  use_master,
+		    int  *use_master,
 		    krb5_kdc_rep **as_reply)
 {
     krb5_error_code ret;
Index: lib/krb5/krb/gic_keytab.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb5/krb/gic_keytab.c,v
retrieving revision 1.3
diff -u -r1.3 gic_keytab.c
--- lib/krb5/krb/gic_keytab.c	22 Dec 2003 19:36:23 -0000	1.3
+++ lib/krb5/krb/gic_keytab.c	23 Feb 2004 22:03:07 -0000
@@ -96,7 +96,7 @@
    ret = krb5_get_init_creds(context, creds, client, NULL, NULL,
 			     start_time, in_tkt_service, options,
 			     krb5_get_as_key_keytab, (void *) keytab,
-			     use_master,NULL);
+			     &use_master,NULL);
 
    /* check for success */
 
Index: lib/krb5/krb/gic_pwd.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb5/krb/gic_pwd.c,v
retrieving revision 1.4
diff -u -r1.4 gic_pwd.c
--- lib/krb5/krb/gic_pwd.c	22 Dec 2003 19:36:23 -0000	1.4
+++ lib/krb5/krb/gic_pwd.c	23 Feb 2004 23:10:05 -0000
@@ -124,7 +124,7 @@
    ret = krb5_get_init_creds(context, creds, client, prompter, data,
 			     start_time, in_tkt_service, options,
 			     krb5_get_as_key_password, (void *) &pw0,
-			     use_master, &as_reply);
+			     &use_master, &as_reply);
 
    /* check for success */
 
@@ -149,7 +149,7 @@
       ret2 = krb5_get_init_creds(context, creds, client, prompter, data,
 				 start_time, in_tkt_service, options,
 				 krb5_get_as_key_password, (void *) &pw0,
-				 use_master, &as_reply);
+				 &use_master, &as_reply);
       
       if (ret2 == 0) {
 	 ret = 0;
@@ -194,7 +194,7 @@
 				  prompter, data,
 				  start_time, "kadmin/changepw", &chpw_opts,
 				  krb5_get_as_key_password, (void *) &pw0,
-				  use_master, NULL)))
+				  &use_master, NULL)))
       goto cleanup;
 
    prompt[0].prompt = "Enter new password";
@@ -282,7 +282,7 @@
    ret = krb5_get_init_creds(context, creds, client, prompter, data,
 			     start_time, in_tkt_service, options,
 			     krb5_get_as_key_password, (void *) &pw0,
-			     use_master, &as_reply);
+			     &use_master, &as_reply);
 
 cleanup:
    krb5int_set_prompt_types(context, 0);
Index: lib/krb5/krb/send_tgs.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb5/krb/send_tgs.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 send_tgs.c
--- lib/krb5/krb/send_tgs.c	16 Dec 2003 19:55:35 -0000	1.1.1.5
+++ lib/krb5/krb/send_tgs.c	23 Feb 2004 23:32:11 -0000
@@ -138,7 +138,7 @@
     krb5_timestamp time_now;
     krb5_pa_data **combined_padata;
     krb5_pa_data ap_req_padata;
-    int tcp_only = 0;
+    int tcp_only = 0, use_master;
 
     /* 
      * in_creds MUST be a valid credential NOT just a partially filled in
@@ -261,9 +261,10 @@
 
     /* now send request & get response from KDC */
 send_again:
+    use_master = 0;
     retval = krb5_sendto_kdc(context, scratch, 
 			     krb5_princ_realm(context, sname),
-			     &rep->response, 0, tcp_only);
+			     &rep->response, &use_master, tcp_only);
     if (retval == 0) {
 	if (krb5_is_krb_error(&rep->response)) {
 	    if (!tcp_only) {
Index: lib/krb5/os/send524.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb5/os/send524.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 send524.c
--- lib/krb5/os/send524.c	16 Dec 2003 19:55:47 -0000	1.1.1.1
+++ lib/krb5/os/send524.c	23 Feb 2004 22:26:45 -0000
@@ -102,7 +102,7 @@
     if (al.naddrs == 0)
 	return KRB5_REALM_UNKNOWN;
 
-    retval = krb5int_sendto (context, message, &al, reply, addr, addrlen);
+    retval = krb5int_sendto (context, message, &al, reply, addr, addrlen, NULL);
     krb5int_free_addrlist (&al);
     return retval;
 #else
Index: lib/krb5/os/sendto_kdc.c
===================================================================
RCS file: /afs/cmf/project/cvsroot/krb5/lib/krb5/os/sendto_kdc.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 sendto_kdc.c
--- lib/krb5/os/sendto_kdc.c	16 Dec 2003 19:55:47 -0000	1.1.1.3
+++ lib/krb5/os/sendto_kdc.c	23 Feb 2004 22:40:45 -0000
@@ -260,11 +260,11 @@
 krb5_error_code
 krb5_sendto_kdc (krb5_context context, const krb5_data *message,
 		 const krb5_data *realm, krb5_data *reply,
-		 int use_master, int tcp_only)
+		 int *use_master, int tcp_only)
 {
     krb5_error_code retval;
     struct addrlist addrs;
-    int socktype1 = 0, socktype2 = 0;
+    int socktype1 = 0, socktype2 = 0, addr_used;
 
     /*
      * find KDC location(s) for realm
@@ -280,7 +280,7 @@
      */
 
     dprint("krb5_sendto_kdc(%d@%p, \"%D\", use_master=%d, tcp_only=%d)\n",
-	   message->length, message->data, realm, use_master, tcp_only);
+	   message->length, message->data, realm, *use_master, tcp_only);
 
     if (!tcp_only && context->udp_pref_limit < 0) {
 	int tmp;
@@ -299,7 +299,7 @@
 	context->udp_pref_limit = tmp;
     }
 
-    retval = (use_master ? KRB5_KDC_UNREACH : KRB5_REALM_UNKNOWN);
+    retval = (*use_master ? KRB5_KDC_UNREACH : KRB5_REALM_UNKNOWN);
 
     if (tcp_only)
 	socktype1 = SOCK_STREAM, socktype2 = 0;
@@ -308,11 +308,11 @@
     else
 	socktype1 = SOCK_STREAM, socktype2 = SOCK_DGRAM;
 
-    retval = krb5_locate_kdc(context, realm, &addrs, use_master, socktype1, 0);
+    retval = krb5_locate_kdc(context, realm, &addrs, *use_master, socktype1, 0);
     if (socktype2) {
 	struct addrlist addrs2;
 
-	retval = krb5_locate_kdc(context, realm, &addrs2, use_master,
+	retval = krb5_locate_kdc(context, realm, &addrs2, *use_master,
 				 socktype2, 0);
 	if (retval == 0) {
 	    (void) merge_addrlists(&addrs, &addrs2);
@@ -321,10 +321,37 @@
     }
 
     if (addrs.naddrs > 0) {
-	retval = krb5int_sendto (context, message, &addrs, reply, 0, 0);
-	krb5int_free_addrlist (&addrs);
-	if (retval == 0)
+	retval = krb5int_sendto (context, message, &addrs, reply, 0, 0,
+				 &addr_used);
+	if (retval == 0) {
+	    /*
+	     * Set use_master to 1 if we ended up talking to a master when
+	     * we didn't explicitly request to
+	     */
+	    if (*use_master == 0) {
+		struct addrlist addrs3;
+		retval = krb5_locate_kdc(context, realm, &addrs3, 1, 
+					 addrs.addrs[addr_used]->ai_socktype,
+					 addrs.addrs[addr_used]->ai_family);
+		if (retval == 0) {
+		    int i;
+		    for (i = 0; i < addrs3.naddrs; i++) {
+			if (addrs.addrs[addr_used]->ai_addrlen ==
+				addrs3.addrs[i]->ai_addrlen &&
+			    memcmp(addrs.addrs[addr_used]->ai_addr,
+				   addrs3.addrs[i]->ai_addr,
+				   addrs.addrs[addr_used]->ai_addrlen) == 0) {
+			    *use_master = 1;
+			    break;
+			}
+		    }
+		    krb5int_free_addrlist (&addrs3);
+		}
+	    }
+	    krb5int_free_addrlist (&addrs);
 	    return 0;
+	}
+	krb5int_free_addrlist (&addrs);
     }
     return retval;
 }
@@ -961,7 +988,8 @@
 krb5_error_code
 krb5int_sendto (krb5_context context, const krb5_data *message,
 		const struct addrlist *addrs, krb5_data *reply,
-		struct sockaddr *localaddr, socklen_t *localaddrlen)
+		struct sockaddr *localaddr, socklen_t *localaddrlen,
+		int *addr_used)
 {
     int i, pass;
     int delay_this_pass = 2;
@@ -1068,6 +1096,8 @@
 	   (int) reply->length, reply->data);
     retval = 0;
     conns[winning_conn].x.in.buf = 0;
+    if (addr_used)
+	*addr_used = winning_conn;
     if (localaddr != 0 && localaddrlen != 0 && *localaddrlen > 0)
 	(void) getsockname(conns[winning_conn].fd, localaddr, localaddrlen);
 egress:


More information about the krbdev mailing list