changeset 12981:9fda0aeb1cb6

6959739 libsldap does not follow referrals correctly 6943753 Pam_ldap bind does not follow referrals during a login
author Julian Pullen <Julian.Pullen@Sun.COM>
date Fri, 30 Jul 2010 14:57:39 +0100
parents 4de81c4d427e
children 5d7f2db1e620
files usr/src/lib/libsldap/common/ns_common.c usr/src/lib/libsldap/common/ns_connect.c
diffstat 2 files changed, 47 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libsldap/common/ns_common.c	Fri Jul 30 14:28:01 2010 +0100
+++ b/usr/src/lib/libsldap/common/ns_common.c	Fri Jul 30 14:57:39 2010 +0100
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 
@@ -1495,8 +1494,23 @@
 		return (NS_LDAP_MEMORY);
 	}
 
-	if (scope)
+	/*
+	 * If the scope is specified in the URL use it.
+	 * Note if the scope is missing in the URL, ldap_url_parse_nodn()
+	 * returns the scope BASE. We need to check that the scope of BASE
+	 * is actually present in the URL.
+	 * If the scope is missing in the URL then use the passed-in
+	 * scope.
+	 * If there is no passed-in scope, then use the scope SUBTREE.
+	 */
+	if (ludp->lud_dn && ludp->lud_scope != LDAP_SCOPE_BASE)
+		ref->refScope = ludp->lud_scope;
+	else if (ludp->lud_dn && strstr(url, "?base"))
+		ref->refScope = LDAP_SCOPE_BASE;
+	else if (scope)
 		ref->refScope = *scope;
+	else
+		ref->refScope = LDAP_SCOPE_SUBTREE;
 
 	ref->next = NULL;
 
--- a/usr/src/lib/libsldap/common/ns_connect.c	Fri Jul 30 14:28:01 2010 +0100
+++ b/usr/src/lib/libsldap/common/ns_connect.c	Fri Jul 30 14:57:39 2010 +0100
@@ -74,7 +74,7 @@
 		UnixCred_t **cred);
 
 static int openConnection(LDAP **, const char *, const ns_cred_t *,
-		int, ns_ldap_error_t **, int, int, ns_conn_user_t *);
+		int, ns_ldap_error_t **, int, int, ns_conn_user_t *, int);
 static void
 _DropConnection(ConnectionID cID, int flag, int fini);
 
@@ -779,7 +779,7 @@
 			}
 		}
 		rc = openConnection(&ld, *bindHost, auth, timeoutSec, errorp,
-		    fail_if_new_pwd_reqd, passwd_mgmt, conn_user);
+		    fail_if_new_pwd_reqd, passwd_mgmt, conn_user, flags);
 		if (rc == NS_LDAP_SUCCESS || rc ==
 		    NS_LDAP_SUCCESS_WITH_INFO) {
 			exit_rc = rc;
@@ -851,7 +851,7 @@
 		}
 		/* make the connection */
 		rc = openConnection(&ld, *bindHost, auth, timeoutSec, errorp,
-		    fail_if_new_pwd_reqd, passwd_mgmt, conn_user);
+		    fail_if_new_pwd_reqd, passwd_mgmt, conn_user, flags);
 		/* if success, go to create connection structure */
 		if (rc == NS_LDAP_SUCCESS ||
 		    rc == NS_LDAP_SUCCESS_WITH_INFO) {
@@ -1342,7 +1342,7 @@
 openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth,
 	int timeoutSec, ns_ldap_error_t **errorp,
 	int fail_if_new_pwd_reqd, int passwd_mgmt,
-	ns_conn_user_t *conn_user)
+	ns_conn_user_t *conn_user, int flags)
 {
 	LDAP			*ld = NULL;
 	int			ldapVersion = LDAP_VERSION3;
@@ -1352,6 +1352,7 @@
 	uint16_t		port = USE_DEFAULT_PORT;
 	char			*s;
 	char			errstr[MAXERROR];
+	int			followRef;
 
 	ns_ldap_return_code	ret_code = NS_LDAP_SUCCESS;
 
@@ -1406,14 +1407,27 @@
 	(void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion);
 	(void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption);
 	/*
-	 * set LDAP_OPT_REFERRALS to OFF.
-	 * This library will handle the referral itself
-	 * based on API flags or configuration file
-	 * specification. If this option is not set
-	 * to OFF, libldap will never pass the
-	 * referral info up to this library
+	 * This library will handle the referral itself based on API flags or
+	 * configuration file specification. The LDAP bind operation is an
+	 * exception where we rely on the LDAP library to follow the referal.
+	 *
+	 * The LDAP follow referral option must be set to OFF for the libldap5
+	 * to pass the referral info up to this library. This option MUST be
+	 * set to OFF after we have performed a sucessful bind. If we are not
+	 * to follow referrals we MUST also set the LDAP follow referral option
+	 * to OFF before we perform an LDAP bind.
 	 */
-	(void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+	ret_code = __s_api_toFollowReferrals(flags, &followRef, errorp);
+	if (ret_code != NS_LDAP_SUCCESS) {
+		(void) ldap_unbind(ld);
+		return (ret_code);
+	}
+
+	if (followRef)
+		(void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
+	else
+		(void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+
 	(void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero);
 	(void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero);
 	/* setup TCP/IP connect timeout */
@@ -1431,6 +1445,11 @@
 
 	if (ret_code == NS_LDAP_SUCCESS ||
 	    ret_code == NS_LDAP_SUCCESS_WITH_INFO) {
+		/*
+		 * Turn off LDAP referral following so that this library can
+		 * process referrals.
+		 */
+		(void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
 		*ldp = ld;
 	}