svn commit: samba r21241 - in branches/SAMBA_3_0_25/source: include libads libsmb nsswitch rpc_client utils

gd at samba.org gd at samba.org
Thu Feb 8 17:09:57 GMT 2007


Author: gd
Date: 2007-02-08 17:09:56 +0000 (Thu, 08 Feb 2007)
New Revision: 21241

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21241

Log:
Merge from 3_0:

Fix longstanding Bug #4009.

For the winbind cached ADS LDAP connection handling
(ads_cached_connection()) we were (incorrectly) assuming that the
service ticket lifetime equaled the tgt lifetime. For setups where the
service ticket just lives 10 minutes, we were leaving hundreds of LDAP
connections in CLOSE_WAIT state, until we fail to service entirely with
"Too many open files".

Also sequence_number() in winbindd_ads.c needs to delete the cached LDAP
connection after the ads_do_search_retry() has failed to submit the
search request (although the bind succeeded (returning an expired
service ticket that we cannot delete from the memory cred cache - this
will get fixed later)).

Guenther


Modified:
   branches/SAMBA_3_0_25/source/include/ads.h
   branches/SAMBA_3_0_25/source/include/includes.h
   branches/SAMBA_3_0_25/source/libads/kerberos.c
   branches/SAMBA_3_0_25/source/libads/ldap_utils.c
   branches/SAMBA_3_0_25/source/libads/sasl.c
   branches/SAMBA_3_0_25/source/libsmb/cliconnect.c
   branches/SAMBA_3_0_25/source/libsmb/clikrb5.c
   branches/SAMBA_3_0_25/source/libsmb/clispnego.c
   branches/SAMBA_3_0_25/source/nsswitch/idmap_ad.c
   branches/SAMBA_3_0_25/source/nsswitch/winbindd_ads.c
   branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c
   branches/SAMBA_3_0_25/source/rpc_client/cli_pipe.c
   branches/SAMBA_3_0_25/source/utils/ntlm_auth.c


Changeset:
Modified: branches/SAMBA_3_0_25/source/include/ads.h
===================================================================
--- branches/SAMBA_3_0_25/source/include/ads.h	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/include/ads.h	2007-02-08 17:09:56 UTC (rev 21241)
@@ -42,7 +42,8 @@
 		char *kdc_server;
 		unsigned flags;
 		int time_offset;
-		time_t expire;
+		time_t tgt_expire;
+		time_t tgs_expire;
 		time_t renewable;
 	} auth;
 

Modified: branches/SAMBA_3_0_25/source/include/includes.h
===================================================================
--- branches/SAMBA_3_0_25/source/include/includes.h	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/include/includes.h	2007-02-08 17:09:56 UTC (rev 21241)
@@ -1167,7 +1167,7 @@
 					  krb5_const_principal princ1, 
 					  krb5_const_principal princ2);
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
-			DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname);
+			DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname, time_t *tgs_expire);
 PAC_LOGON_INFO *get_logon_info_from_pac(PAC_DATA *pac_data);
 krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, const char *client_string, const char *service_string, time_t *new_start_time);
 krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code);

Modified: branches/SAMBA_3_0_25/source/libads/kerberos.c
===================================================================
--- branches/SAMBA_3_0_25/source/libads/kerberos.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/libads/kerberos.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -110,6 +110,10 @@
 
 	krb5_get_init_creds_opt_set_renew_life(opt, renewable_time);
 	krb5_get_init_creds_opt_set_forwardable(opt, True);
+#if 0
+	/* insane testing */
+	krb5_get_init_creds_opt_set_tkt_life(opt, 60);
+#endif
 
 #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
 	if (request_pac) {
@@ -216,7 +220,7 @@
 	}
 	
 	ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
-			&ads->auth.expire, NULL, NULL, False, False, ads->auth.renewable);
+			&ads->auth.tgt_expire, NULL, NULL, False, False, ads->auth.renewable);
 
 	if (ret) {
 		DEBUG(0,("kerberos_kinit_password %s failed: %s\n", 

Modified: branches/SAMBA_3_0_25/source/libads/ldap_utils.c
===================================================================
--- branches/SAMBA_3_0_25/source/libads/ldap_utils.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/libads/ldap_utils.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -110,10 +110,10 @@
 	}
         SAFE_FREE(bp);
 
-	if (!ADS_ERR_OK(status))
+	if (!ADS_ERR_OK(status)) {
 		DEBUG(1,("ads reopen failed after error %s\n", 
 			 ads_errstr(status)));
-
+	}
 	return status;
 }
 

Modified: branches/SAMBA_3_0_25/source/libads/sasl.c
===================================================================
--- branches/SAMBA_3_0_25/source/libads/sasl.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/libads/sasl.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -147,7 +147,8 @@
 	DATA_BLOB session_key = data_blob(NULL, 0);
 	int rc;
 
-	rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0);
+	rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
+				     &ads->auth.tgs_expire);
 
 	if (rc) {
 		return ADS_ERROR_KRB5(rc);
@@ -218,7 +219,7 @@
 #endif
 		free(OIDs[i]);
 	}
-	DEBUG(3,("ads_sasl_spnego_bind: got server principal name =%s\n", principal));
+	DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", principal));
 
 #ifdef HAVE_KRB5
 	if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
@@ -229,6 +230,9 @@
 			return status;
 		}
 
+		DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
+			  "calling kinit\n", ads_errstr(status)));
+
 		status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 
 
 		if (ADS_ERR_OK(status)) {

Modified: branches/SAMBA_3_0_25/source/libsmb/cliconnect.c
===================================================================
--- branches/SAMBA_3_0_25/source/libsmb/cliconnect.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/libsmb/cliconnect.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -554,7 +554,7 @@
 	DEBUG(2,("Doing kerberos session setup\n"));
 
 	/* generate the encapsulated kerberos5 ticket */
-	rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0);
+	rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
 
 	if (rc) {
 		DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));

Modified: branches/SAMBA_3_0_25/source/libsmb/clikrb5.c
===================================================================
--- branches/SAMBA_3_0_25/source/libsmb/clikrb5.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/libsmb/clikrb5.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -551,7 +551,8 @@
 				       const krb5_flags ap_req_options,
 				       const char *principal,
 				       krb5_ccache ccache, 
-				       krb5_data *outbuf)
+				       krb5_data *outbuf, 
+				       time_t *expire_time)
 {
 	krb5_error_code 	  retval;
 	krb5_principal	  server;
@@ -584,6 +585,7 @@
 	}
 
 	while (!creds_ready && (i < maxtries)) {
+
 		if ((retval = krb5_get_credentials(context, 0, ccache, 
 						   &creds, &credsp))) {
 			DEBUG(1,("ads_krb5_mk_req: krb5_get_credentials failed for %s (%s)\n",
@@ -599,8 +601,9 @@
 			krb5_set_real_time(context, t + time_offset + 1, 0);
 		}
 
-		if (!ads_cleanup_expired_creds(context, ccache, credsp))
+		if (!ads_cleanup_expired_creds(context, ccache, credsp)) {
 			creds_ready = True;
+		}
 
 		i++;
 	}
@@ -610,6 +613,10 @@
 		  http_timestring((unsigned)credsp->times.endtime), 
 		  (unsigned)credsp->times.endtime));
 
+	if (expire_time) {
+		*expire_time = (time_t)credsp->times.endtime;
+	}
+
 	in_data.length = 0;
 	retval = krb5_mk_req_extended(context, auth_context, ap_req_options, 
 				      &in_data, credsp, outbuf);
@@ -634,7 +641,9 @@
 */
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
 			DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, 
-			uint32 extra_ap_opts, const char *ccname)
+			uint32 extra_ap_opts, const char *ccname, 
+			time_t *tgs_expire)
+
 {
 	krb5_error_code retval;
 	krb5_data packet;
@@ -678,7 +687,8 @@
 					&auth_context, 
 					AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
 					principal,
-					ccdef, &packet))) {
+					ccdef, &packet,
+					tgs_expire))) {
 		goto failed;
 	}
 
@@ -1409,7 +1419,7 @@
  /* this saves a few linking headaches */
  int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
 			DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
-			const char *ccname) 
+			const char *ccname, time_t *tgs_expire) 
 {
 	 DEBUG(0,("NO KERBEROS SUPPORT\n"));
 	 return 1;

Modified: branches/SAMBA_3_0_25/source/libsmb/clispnego.c
===================================================================
--- branches/SAMBA_3_0_25/source/libsmb/clispnego.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/libsmb/clispnego.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -343,7 +343,8 @@
 */
 int spnego_gen_negTokenTarg(const char *principal, int time_offset, 
 			    DATA_BLOB *targ, 
-			    DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
+			    DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
+			    time_t *expire_time)
 {
 	int retval;
 	DATA_BLOB tkt, tkt_wrapped;
@@ -351,7 +352,8 @@
 
 	/* get a kerberos ticket for the service and extract the session key */
 	retval = cli_krb5_get_ticket(principal, time_offset,
-					&tkt, session_key_krb5, extra_ap_opts, NULL);
+					&tkt, session_key_krb5, extra_ap_opts, NULL, 
+					expire_time);
 
 	if (retval)
 		return retval;

Modified: branches/SAMBA_3_0_25/source/nsswitch/idmap_ad.c
===================================================================
--- branches/SAMBA_3_0_25/source/nsswitch/idmap_ad.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/nsswitch/idmap_ad.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -64,16 +64,23 @@
 	struct in_addr dc_ip;	
 
 	if (ad_idmap_ads != NULL) {
+
+		time_t expire;
+		time_t now = time(NULL);
+
 		ads = ad_idmap_ads;
 
+		expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
+
 		/* check for a valid structure */
+		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
+			  (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
 
-		DEBUG(7, ("Current tickets expire at %d, time is now %d\n",
-			  (uint32) ads->auth.expire, (uint32) time(NULL)));
-		if ( ads->config.realm && (ads->auth.expire > time(NULL))) {
+		if ( ads->config.realm && (expire > time(NULL))) {
 			return ads;
 		} else {
 			/* we own this ADS_STRUCT so make sure it goes away */
+			DEBUG(7,("Deleting expired krb5 credential cache\n"));
 			ads->is_mine = True;
 			ads_destroy( &ads );
 			ads_kdestroy(WINBIND_CCACHE_NAME);

Modified: branches/SAMBA_3_0_25/source/nsswitch/winbindd_ads.c
===================================================================
--- branches/SAMBA_3_0_25/source/nsswitch/winbindd_ads.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/nsswitch/winbindd_ads.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -44,17 +44,23 @@
 	DEBUG(10,("ads_cached_connection\n"));
 
 	if (domain->private_data) {
-		ads = (ADS_STRUCT *)domain->private_data;
 
+		time_t expire;
+		time_t now = time(NULL);
+
 		/* check for a valid structure */
+		ads = (ADS_STRUCT *)domain->private_data;
 
-		DEBUG(7, ("Current tickets expire at %d, time is now %d\n",
-			  (uint32) ads->auth.expire, (uint32) time(NULL)));
-		if ( ads->config.realm && (ads->auth.expire > time(NULL))) {
+		expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
+
+		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
+			  (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
+
+		if ( ads->config.realm && (expire > now)) {
 			return ads;
-		}
-		else {
+		} else {
 			/* we own this ADS_STRUCT so make sure it goes away */
+			DEBUG(7,("Deleting expired krb5 credential cache\n"));
 			ads->is_mine = True;
 			ads_destroy( &ads );
 			ads_kdestroy("MEMORY:winbind_ccache");
@@ -998,11 +1004,15 @@
 	
 	if (!ADS_ERR_OK(rc)) {
 	
-		/* its a dead connection ; don't destroy it 
-		   through since ads_USN() has already done 
-		   that indirectly */
-		   
-		domain->private_data = NULL;
+		/* its a dead connection, destroy it */
+
+		if (domain->private_data) {
+			ads = (ADS_STRUCT *)domain->private_data;
+			ads->is_mine = True;
+			ads_destroy(&ads);
+			ads_kdestroy("MEMORY:winbind_ccache");
+			domain->private_data = NULL;
+		}
 	}
 	return ads_ntstatus(rc);
 }

Modified: branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c
===================================================================
--- branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -598,7 +598,8 @@
 				       &tkt, 
 				       &session_key_krb5, 
 				       0, 
-				       cc);
+				       cc,
+				       NULL);
 	if (krb5_ret) {
 		DEBUG(1,("winbindd_raw_kerberos_login: failed to get ticket for %s: %s\n", 
 			local_service, error_message(krb5_ret)));

Modified: branches/SAMBA_3_0_25/source/rpc_client/cli_pipe.c
===================================================================
--- branches/SAMBA_3_0_25/source/rpc_client/cli_pipe.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/rpc_client/cli_pipe.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -927,7 +927,7 @@
 	/* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
 
 	ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
-			&a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL);
+			&a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
 
 	if (ret) {
 		DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "

Modified: branches/SAMBA_3_0_25/source/utils/ntlm_auth.c
===================================================================
--- branches/SAMBA_3_0_25/source/utils/ntlm_auth.c	2007-02-08 17:02:39 UTC (rev 21240)
+++ branches/SAMBA_3_0_25/source/utils/ntlm_auth.c	2007-02-08 17:09:56 UTC (rev 21241)
@@ -1424,7 +1424,7 @@
 	       spnego.negTokenInit.mechListMIC.length);
 	principal[spnego.negTokenInit.mechListMIC.length] = '\0';
 
-	retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
+	retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL, NULL);
 
 	if (retval) {
 
@@ -1446,7 +1446,7 @@
 			return False;
 		}
 
-		retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
+		retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL, NULL);
 
 		if (retval) {
 			DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));



More information about the samba-cvs mailing list