6636343 The SSS control generated by "libsldap.so.1" cannot work with Active Directory in VLV searches
authorJulian Pullen <Julian.Pullen@Sun.COM>
Fri, 02 Jul 2010 10:46:04 +0100
changeset 12758 996c46be076f
parent 12757 e25e7e1b3c65
child 12759 bc1efdc49cca
6636343 The SSS control generated by "libsldap.so.1" cannot work with Active Directory in VLV searches 6929861 NS switch LDAP enumeration terminates prematurely if LDAP mandatory attributes are missing 6963912 libsldap does not work with the VLV response from Active Directory
usr/src/cmd/ldap/ns_ldap/ldapaddent.c
usr/src/cmd/ldap/ns_ldap/ldaplist.c
usr/src/lib/libsldap/common/llib-lsldap
usr/src/lib/libsldap/common/mapfile-vers
usr/src/lib/libsldap/common/ns_internal.h
usr/src/lib/libsldap/common/ns_mapping.c
usr/src/lib/libsldap/common/ns_reads.c
usr/src/lib/libsldap/common/ns_sldap.h
usr/src/lib/nsswitch/ldap/common/ldap_common.c
usr/src/lib/nsswitch/ldap/common/ldap_common.h
--- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c	Fri Jul 02 10:46:04 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) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -68,6 +67,7 @@
 				/* routine to print ldap containers */
 	int (*filedbmline)();	/* routine to turn file line into dbm line */
 	char *objclass;		/* Objectclass for the servicetype */
+	char *sortattr;		/* Sort attr for enumeration */
 } *tt;
 
 char	parse_err_msg [PARSE_ERR_MSG_LEN];
@@ -4033,54 +4033,54 @@
 
 static struct ttypelist_t ttypelist[] = {
 	{ NS_LDAP_TYPE_HOSTS, genent_hosts, dump_hosts,
-		filedbmline_comment, "iphost" },
+		filedbmline_comment, "iphost", "cn" },
 	{ NS_LDAP_TYPE_IPNODES, genent_hosts, dump_hosts,
-		filedbmline_comment, "iphost" },
+		filedbmline_comment, "iphost", "cn" },
 	{ NS_LDAP_TYPE_RPC, genent_rpc, dump_rpc,
-		filedbmline_comment, "oncrpc" },
+		filedbmline_comment, "oncrpc", "cn" },
 	{ NS_LDAP_TYPE_PROTOCOLS, genent_protocols, dump_protocols,
-		filedbmline_comment, "ipprotocol" },
+		filedbmline_comment, "ipprotocol", "cn" },
 	{ NS_LDAP_TYPE_NETWORKS, genent_networks, dump_networks,
-		filedbmline_comment, "ipnetwork"  },
+		filedbmline_comment, "ipnetwork", "ipnetworknumber" },
 	{ NS_LDAP_TYPE_SERVICES, genent_services, dump_services,
-		filedbmline_comment, "ipservice" },
+		filedbmline_comment, "ipservice", "cn" },
 	{ NS_LDAP_TYPE_GROUP, genent_group, dump_group,
-		filedbmline_plus, "posixgroup" },
+		filedbmline_plus, "posixgroup", "gidnumber" },
 	{ NS_LDAP_TYPE_NETMASKS, genent_netmasks, dump_netmasks,
-		filedbmline_comment, "ipnetwork" },
+		filedbmline_comment, "ipnetwork", "ipnetworknumber"},
 	{ NS_LDAP_TYPE_ETHERS, genent_ethers, dump_ethers,
-		filedbmline_comment, "ieee802Device" },
+		filedbmline_comment, "ieee802Device", "cn" },
 	{ NS_LDAP_TYPE_NETGROUP, genent_netgroup, dump_netgroup,
-		filedbmline_comment, "nisnetgroup" },
+		filedbmline_comment, "nisnetgroup", "cn" },
 	{ NS_LDAP_TYPE_BOOTPARAMS, genent_bootparams, dump_bootparams,
-		filedbmline_comment, "bootableDevice" },
+		filedbmline_comment, "bootableDevice", "cn" },
 	{ NS_LDAP_TYPE_PUBLICKEY, genent_publickey, NULL /* dump_publickey */,
-		filedbmline_comment, "niskeyobject" },
+		filedbmline_comment, "niskeyobject", "cn" },
 	{ NS_LDAP_TYPE_PASSWD, genent_passwd, dump_passwd,
-		filedbmline_plus, "posixaccount" },
+		filedbmline_plus, "posixaccount", "uid" },
 	{ NS_LDAP_TYPE_SHADOW, genent_shadow, dump_shadow,
-		filedbmline_plus, "shadowaccount" },
+		filedbmline_plus, "shadowaccount", "uid" },
 	{ NS_LDAP_TYPE_ALIASES, genent_aliases, dump_aliases,
-		filedbmline_plus, "mailGroup" },
+		filedbmline_plus, "mailGroup", "cn" },
 	{ NS_LDAP_TYPE_AUTOMOUNT, genent_automount, dump_automount,
-		filedbmline_comment, "automount" },
+		filedbmline_comment, "automount", "automountKey" },
 	{ NS_LDAP_TYPE_USERATTR, genent_user_attr, dump_user_attr,
-		filedbmline_comment, "SolarisUserAttr" },
+		filedbmline_comment, "SolarisUserAttr", "uid" },
 	{ NS_LDAP_TYPE_PROFILE, genent_prof_attr, dump_prof_attr,
-		filedbmline_comment, "SolarisProfAttr" },
+		filedbmline_comment, "SolarisProfAttr", "cn" },
 	{ NS_LDAP_TYPE_EXECATTR, genent_exec_attr, dump_exec_attr,
-		filedbmline_comment, "SolarisExecAttr" },
+		filedbmline_comment, "SolarisExecAttr", "cn" },
 	{ NS_LDAP_TYPE_AUTHATTR, genent_auth_attr, dump_auth_attr,
-		filedbmline_comment, "SolarisAuthAttr" },
+		filedbmline_comment, "SolarisAuthAttr", "cn" },
 	{ NS_LDAP_TYPE_AUUSER, genent_audit_user, dump_audit_user,
-		filedbmline_comment, "SolarisAuditUser" },
+		filedbmline_comment, "SolarisAuditUser", "uid" },
 	{ NS_LDAP_TYPE_TNRHDB, genent_tnrhdb, dump_tnrhdb,
-		filedbmline_comment, "ipTnetHost" },
+		filedbmline_comment, "ipTnetHost", "ipTnetNumber" },
 	{ NS_LDAP_TYPE_TNRHTP, genent_tnrhtp, dump_tnrhtp,
-		filedbmline_comment, "ipTnetTemplate" },
+		filedbmline_comment, "ipTnetTemplate", "ipTnetTemplateName" },
 	{ NS_LDAP_TYPE_PROJECT, genent_project, dump_project,
-		filedbmline_comment, "SolarisProject" },
-	{ 0, 0, 0, 0, 0 }
+		filedbmline_comment, "SolarisProject", "SolarisProjectName" },
+	{ 0, 0, 0, 0, 0, 0 }
 };
 
 
@@ -4167,11 +4167,11 @@
 	/* Pass cred only if supplied. Cred is not always needed for dump */
 	if (authority.cred.unix_cred.userID == NULL ||
 	    authority.cred.unix_cred.passwd == NULL)
-		rc = __ns_ldap_firstEntry(service, filter, NULL, NULL,
-		    NULL, NS_LDAP_HARD, &cookie, &eres, &err, NULL);
+		rc = __ns_ldap_firstEntry(service, filter, tt->sortattr, NULL,
+		    NULL, NULL, NS_LDAP_HARD, &cookie, &eres, &err, NULL);
 	else
-		rc = __ns_ldap_firstEntry(service, filter, NULL, NULL,
-		    &authority, NS_LDAP_HARD, &cookie, &eres, &err, NULL);
+		rc = __ns_ldap_firstEntry(service, filter, tt->sortattr, NULL,
+		    NULL, &authority, NS_LDAP_HARD, &cookie, &eres, &err, NULL);
 
 	switch (rc) {
 	case NS_LDAP_SUCCESS:
--- a/usr/src/cmd/ldap/ns_ldap/ldaplist.c	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/cmd/ldap/ns_ldap/ldaplist.c	Fri Jul 02 10:46:04 2010 +0100
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 
@@ -40,6 +39,40 @@
 
 int listflag = 0;
 
+
+
+static struct database_t {
+	const char *database;
+	const char *sortattr;
+}databaselist[] = {
+	{ NS_LDAP_TYPE_HOSTS, "cn" },
+	{ NS_LDAP_TYPE_IPNODES, "cn" },
+	{ NS_LDAP_TYPE_RPC, "cn" },
+	{ NS_LDAP_TYPE_PROTOCOLS, "cn" },
+	{ NS_LDAP_TYPE_NETWORKS, "ipnetworknumber" },
+	{ NS_LDAP_TYPE_SERVICES, "cn" },
+	{ NS_LDAP_TYPE_GROUP, "gidnumber" },
+	{ NS_LDAP_TYPE_NETMASKS, "ipnetworknumber"},
+	{ NS_LDAP_TYPE_ETHERS, "cn" },
+	{ NS_LDAP_TYPE_NETGROUP, "cn" },
+	{ NS_LDAP_TYPE_BOOTPARAMS, "cn" },
+	{ NS_LDAP_TYPE_PUBLICKEY, "cn" },
+	{ NS_LDAP_TYPE_PASSWD, "uid" },
+	{ NS_LDAP_TYPE_SHADOW, "uid" },
+	{ NS_LDAP_TYPE_ALIASES, "cn" },
+	{ NS_LDAP_TYPE_AUTOMOUNT, "automountKey" },
+	{ NS_LDAP_TYPE_USERATTR, "uid" },
+	{ NS_LDAP_TYPE_PROFILE, "cn" },
+	{ NS_LDAP_TYPE_EXECATTR, "cn" },
+	{ NS_LDAP_TYPE_AUTHATTR, "cn" },
+	{ NS_LDAP_TYPE_AUUSER, "uid" },
+	{ NS_LDAP_TYPE_TNRHDB, "ipTnetNumber" },
+	{ NS_LDAP_TYPE_TNRHTP, "ipTnetTemplateName" },
+	{ NS_LDAP_TYPE_PROJECT, "SolarisProjectName" },
+	{ 0, 0 }
+};
+
+
 void
 usage(char *msg) {
 	if (msg)
@@ -146,11 +179,29 @@
 	ns_ldap_error_t	*errorp;
 	int		rc;
 	char		buf[500];
+	const char 	*sort = NULL;
+	int		i;
+
+	if (database) {
+		for (i = 0; databaselist[i].database; i++) {
+			if (strcmp(databaselist[i].database, database) == 0) {
+				sort = databaselist[i].sortattr;
+				break;
+			}
+			if (strcmp(databaselist[i].database,
+			    NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
+			    strncmp(database, NS_LDAP_TYPE_AUTOMOUNT,
+			    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
+				sort = databaselist[i].sortattr;
+				break;
+			}
+		}
+	}
 
 	*err = NULL;
 	buf[0] = '\0';
-	rc = __ns_ldap_list(database, (const char *)ldapfilter,
-	    merge_SSD_filter, (const char **)ldapattribute, NULL,
+	rc = __ns_ldap_list_sort(database, (const char *)ldapfilter,
+	    sort, merge_SSD_filter, (const char **)ldapattribute, NULL,
 	    listflag, &result, &errorp, NULL, userdata);
 	if (rc != NS_LDAP_SUCCESS) {
 		char *p;
--- a/usr/src/lib/libsldap/common/llib-lsldap	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/libsldap/common/llib-lsldap	Fri Jul 02 10:46:04 2010 +0100
@@ -22,10 +22,8 @@
 /* PROTOLIB1 */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ *Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -50,6 +48,20 @@
 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
 	const void *userdata);
 
+int __ns_ldap_list_sort(
+	const char *service,
+	const char *filter,
+	const char *sortattr,
+	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
+			      char **realfilter, const void *userdata),
+	const char * const *attribute,
+	const ns_cred_t *cred,
+	const int flags,
+	ns_ldap_result_t ** result,
+	ns_ldap_error_t ** errorp,
+	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
+	const void *userdata);
+
 int  __ns_ldap_addAttr(
 	const char *service,
 	const char *dn,
@@ -101,6 +113,7 @@
 int __ns_ldap_firstEntry(
 	const char *service,
 	const char *filter,
+	const char *sortattr,
 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
 			      char **realfilter, const void *userdata),
 	const char * const *attribute,
--- a/usr/src/lib/libsldap/common/mapfile-vers	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/libsldap/common/mapfile-vers	Fri Jul 02 10:46:04 2010 +0100
@@ -55,6 +55,7 @@
 	__ns_ldap_initAuth;
 	__ns_ldap_initStandalone;
 	__ns_ldap_is_shadow_update_enabled;
+	__ns_ldap_list_sort;
 	__ns_ldap_pingOfflineServers;
 	__ns_ldap_self_gssapi_config;
 	__ns_ldap_self_gssapi_only_set;
--- a/usr/src/lib/libsldap/common/ns_internal.h	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/libsldap/common/ns_internal.h	Fri Jul 02 10:46:04 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.
  */
 
 
@@ -74,7 +73,6 @@
 
 #define	LISTPAGESIZE		1000
 #define	ENUMPAGESIZE		100
-#define	SORTKEYLIST		"cn uid"
 
 #define	DEFMAX			8
 #define	TOKENSEPARATOR		'='
@@ -553,6 +551,19 @@
 typedef int ConnectionID;
 
 /*
+ * Server side sort type. Orginally the server side sort
+ * was set to "cn uid". This did not work with AD and
+ * hence single sort attribute was odopted. We dont
+ * know which server side sort will work with the
+ * Directory and hence we discover which method works.
+ */
+typedef enum {
+	SSS_UNKNOWN		= 0,
+	SSS_SINGLE_ATTR		= 1,
+	SSS_CN_UID_ATTRS	= 2
+} ns_srvsidesort_t;
+
+/*
  * This structure is used by ns_connect to create and manage
  * one or more ldap connections within the library.
  */
@@ -628,6 +639,7 @@
 	char			*service;
 	char			*i_filter;
 	const char * const	*i_attr;
+	const char		*i_sortattr;
 	const ns_cred_t		*i_auth;
 	int 			i_flags;
 
@@ -651,6 +663,8 @@
 	int			listType;
 	unsigned long		index;
 	LDAPControl		**p_serverctrls;
+	ns_srvsidesort_t	sortTypeTry;
+	int			entryCount;
 
 	int			scope;
 	char			*basedn;
@@ -825,6 +839,8 @@
 				char **origA, char ***mapA);
 char		**__ns_ldap_mapAttributeList(const char *service,
 				const char * const *origAttrList);
+char		*__ns_ldap_mapAttribute(const char *service,
+				const char *origAttr);
 
 /* internal configuration APIs */
 void		__ns_ldap_setServer(int set);
--- a/usr/src/lib/libsldap/common/ns_mapping.c	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/libsldap/common/ns_mapping.c	Fri Jul 02 10:46:04 2010 +0100
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2000-2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <stdlib.h>
 #include <strings.h>
 #include <ctype.h>
@@ -350,7 +346,7 @@
 		return (NS_LDAP_INVALID_PARAM);
 
 	ptr = (ns_ldap_search_desc_t *)
-			calloc(1, sizeof (ns_ldap_search_desc_t));
+	    calloc(1, sizeof (ns_ldap_search_desc_t));
 	if (ptr == NULL)
 		return (NS_LDAP_MEMORY);
 
@@ -358,7 +354,7 @@
 
 	/* Get the default scope */
 	if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P,
-		&paramVal, errorp)) != NS_LDAP_SUCCESS) {
+	    &paramVal, errorp)) != NS_LDAP_SUCCESS) {
 		(void) __ns_ldap_freeError(errorp);
 		__ns_ldap_freeASearchDesc(ptr);
 		ptr = NULL;
@@ -629,14 +625,14 @@
 		*cnt = 0;
 		*max = NS_SDESC_MAX;
 		*sdlist = (ns_ldap_search_desc_t **)
-				calloc(*max, sizeof (ns_ldap_search_desc_t *));
+		    calloc(*max, sizeof (ns_ldap_search_desc_t *));
 		if (*sdlist == NULL)
 			return (-1);
 	} else if (*cnt+1 >= *max) {
 		*max += NS_SDESC_MAX;
 		tmplist = (ns_ldap_search_desc_t **)
-				realloc((void *)(*sdlist),
-			*max * sizeof (ns_ldap_search_desc_t *));
+		    realloc((void *)(*sdlist),
+		    *max * sizeof (ns_ldap_search_desc_t *));
 		if (tmplist == NULL)
 			return (-1);
 		else
@@ -677,7 +673,7 @@
 	*errorp = NULL;
 
 	rc = __ns_ldap_getParam(NS_LDAP_SERVICE_SEARCH_DESC_P,
-				(void ***)&param, errorp);
+	    (void ***)&param, errorp);
 	if (rc != NS_LDAP_SUCCESS) {
 		return (rc);
 	}
@@ -692,7 +688,7 @@
 		(void) snprintf(errstr, sizeof (errstr),
 		    gettext("No configuration information available."));
 		MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
-			NULL);
+		    NULL);
 		return (NS_LDAP_CONFIG);
 	}
 
@@ -709,7 +705,7 @@
 		/* Convert a SEARCH_DN to a search descriptor */
 		for (; *sdl; sdl++) {
 			ret = (ns_ldap_search_desc_t *)
-				calloc(1, sizeof (ns_ldap_search_desc_t));
+			    calloc(1, sizeof (ns_ldap_search_desc_t));
 			if (ret == NULL) {
 				(void) __ns_ldap_freeSearchDescriptors(&sdlist);
 				__s_api_free2dArray(sdl_save);
@@ -726,7 +722,7 @@
 
 			/* default scope */
 			if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P,
-				&paramVal, errorp)) != NS_LDAP_SUCCESS) {
+			    &paramVal, errorp)) != NS_LDAP_SUCCESS) {
 				(void) __ns_ldap_freeASearchDesc(ret);
 				(void) __ns_ldap_freeSearchDescriptors(&sdlist);
 				__s_api_free2dArray(sdl_save);
@@ -775,17 +771,17 @@
 			if (rc != NS_LDAP_SUCCESS) {
 				(void) __ns_ldap_freeSearchDescriptors(&sdlist);
 				(void) snprintf(errstr, (2 * MAXERROR), gettext(
-					"Invalid serviceSearchDescriptor (%s). "
-					"Illegal configuration"), *sdl);
+				    "Invalid serviceSearchDescriptor (%s). "
+				    "Illegal configuration"), *sdl);
 				(void) __ns_ldap_freeParam(&param);
 				param = NULL;
 				MKERROR(LOG_ERR, *errorp, NS_CONFIG_SYNTAX,
-					strdup(errstr), NULL);
+				    strdup(errstr), NULL);
 				return (rc);
 			}
 			if (ret != NULL) {
 				rc = __ns_ldap_saveSearchDesc(
-					&sdlist, &cnt, &max, ret);
+				    &sdlist, &cnt, &max, ret);
 			}
 			if (rc < 0) {
 				(void) __ns_ldap_freeSearchDescriptors(&sdlist);
@@ -1028,3 +1024,24 @@
 	}
 	return (cpp);
 }
+
+char *
+__ns_ldap_mapAttribute(
+	const char *service,
+	const char *origAttr)
+{
+	char **npp;
+	char *mappedAttr;
+
+	if (origAttr == NULL)
+		return (NULL);
+
+	npp = __ns_ldap_getMappedAttributes(service, origAttr);
+	if (npp && npp[0]) {
+		mappedAttr = strdup(npp[0]);
+		__s_api_free2dArray(npp);
+	} else {
+		mappedAttr = strdup(origAttr);
+	}
+	return (mappedAttr);
+}
--- a/usr/src/lib/libsldap/common/ns_reads.c	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/libsldap/common/ns_reads.c	Fri Jul 02 10:46:04 2010 +0100
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <stdio.h>
@@ -1746,6 +1745,87 @@
 	return (0);
 }
 
+typedef struct servicesorttype {
+	char *service;
+	ns_srvsidesort_t type;
+} servicesorttype_t;
+
+static servicesorttype_t *sort_type = NULL;
+static int sort_type_size = 0;
+static int sort_type_hwm = 0;
+static mutex_t sort_type_mutex = DEFAULTMUTEX;
+
+
+static ns_srvsidesort_t
+get_srvsidesort_type(char *service)
+{
+	int i;
+	ns_srvsidesort_t type = SSS_UNKNOWN;
+
+	if (service == NULL)
+		return (type);
+
+	(void) mutex_lock(&sort_type_mutex);
+	if (sort_type != NULL) {
+		for (i = 0; i < sort_type_hwm; i++) {
+			if (strcmp(sort_type[i].service, service) == 0) {
+				type = sort_type[i].type;
+				break;
+			}
+		}
+	}
+	(void) mutex_unlock(&sort_type_mutex);
+	return (type);
+}
+
+static void
+update_srvsidesort_type(char *service, ns_srvsidesort_t type)
+{
+	int i, size;
+	servicesorttype_t *tmp;
+
+	if (service == NULL)
+		return;
+
+	(void) mutex_lock(&sort_type_mutex);
+
+	for (i = 0; i < sort_type_hwm; i++) {
+		if (strcmp(sort_type[i].service, service) == 0) {
+			sort_type[i].type = type;
+			(void) mutex_unlock(&sort_type_mutex);
+			return;
+		}
+	}
+	if (sort_type == NULL) {
+		size = 10;
+		tmp = malloc(size * sizeof (servicesorttype_t));
+		if (tmp == NULL) {
+			(void) mutex_unlock(&sort_type_mutex);
+			return;
+		}
+		sort_type = tmp;
+		sort_type_size = size;
+	} else if (sort_type_hwm >= sort_type_size) {
+		size = sort_type_size + 10;
+		tmp = realloc(sort_type, size * sizeof (servicesorttype_t));
+		if (tmp == NULL) {
+			(void) mutex_unlock(&sort_type_mutex);
+			return;
+		}
+		sort_type = tmp;
+		sort_type_size = size;
+	}
+	sort_type[sort_type_hwm].service = strdup(service);
+	if (sort_type[sort_type_hwm].service == NULL) {
+		(void) mutex_unlock(&sort_type_mutex);
+		return;
+	}
+	sort_type[sort_type_hwm].type = type;
+	sort_type_hwm++;
+
+	(void) mutex_unlock(&sort_type_mutex);
+}
+
 static int
 setup_vlv_params(ns_ldap_cookie_t *cookie)
 {
@@ -1754,11 +1834,35 @@
 	LDAPControl	*sortctrl = NULL;
 	LDAPControl	*vlvctrl = NULL;
 	LDAPVirtualList	vlist;
+	char		*sortattr;
 	int		rc;
+	int		free_sort = FALSE;
 
 	_freeControlList(&cookie->p_serverctrls);
 
-	rc = ldap_create_sort_keylist(&sortkeylist, SORTKEYLIST);
+	if (cookie->sortTypeTry == SSS_UNKNOWN)
+		cookie->sortTypeTry = get_srvsidesort_type(cookie->service);
+	if (cookie->sortTypeTry == SSS_UNKNOWN)
+		cookie->sortTypeTry = SSS_SINGLE_ATTR;
+
+	if (cookie->sortTypeTry == SSS_SINGLE_ATTR) {
+		if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
+		    cookie->i_sortattr) {
+			sortattr =  __ns_ldap_mapAttribute(cookie->service,
+			    cookie->i_sortattr);
+			free_sort = TRUE;
+		} else if (cookie->i_sortattr) {
+			sortattr = (char *)cookie->i_sortattr;
+		} else {
+			sortattr = "cn";
+		}
+	} else {
+		sortattr = "cn uid";
+	}
+
+	rc = ldap_create_sort_keylist(&sortkeylist, sortattr);
+	if (free_sort)
+		free(sortattr);
 	if (rc != LDAP_SUCCESS) {
 		(void) ldap_get_option(cookie->conn->ld,
 		    LDAP_OPT_ERROR_NUMBER, &rc);
@@ -1982,9 +2086,21 @@
 			    cookie->conn->ld, retCtrls,
 			    &target_posp, &list_size, &errCode);
 			if (rc == LDAP_SUCCESS) {
-				cookie->index = target_posp + LISTPAGESIZE;
-				if (cookie->index > list_size) {
-					finished = 1;
+				/*
+				 * AD does not return valid target_posp
+				 * and list_size
+				 */
+				if (target_posp != 0 && list_size != 0) {
+					cookie->index =
+					    target_posp + LISTPAGESIZE;
+					if (cookie->index > list_size)
+						finished = 1;
+				} else {
+					if (cookie->entryCount < LISTPAGESIZE)
+						finished = 1;
+					else
+						cookie->index +=
+						    cookie->entryCount;
 				}
 			}
 			ldap_controls_free(retCtrls);
@@ -2095,8 +2211,11 @@
 		rc = ldap_result(cookie->conn->ld, cookie->msgId, LDAP_MSG_ALL,
 		    (struct timeval *)&cookie->search_timeout,
 		    &cookie->resultMsg);
-		if (rc != -1 && rc != 0 && cookie->resultMsg != NULL)
+		if (rc != -1 && rc != 0 && cookie->resultMsg != NULL) {
 			(void) ldap_msgfree(cookie->resultMsg);
+			cookie->resultMsg = NULL;
+		}
+
 		/*
 		 * If there was timeout then we will send  ABANDON request to
 		 * LDAP server to decrease load.
@@ -2315,6 +2434,7 @@
 			cookie->new_state = DO_SEARCH;
 			break;
 		case DO_SEARCH:
+			cookie->entryCount = 0;
 			rc = ldap_search_ext(cookie->conn->ld,
 			    cookie->basedn,
 			    cookie->scope,
@@ -2566,10 +2686,21 @@
 			if (rc == LDAP_RES_SEARCH_RESULT) {
 				rc = ldap_result2error(cookie->conn->ld,
 				    cookie->resultMsg, 0);
+				if (rc == LDAP_ADMINLIMIT_EXCEEDED &&
+				    cookie->listType == VLVCTRLFLAG &&
+				    cookie->sortTypeTry == SSS_SINGLE_ATTR) {
+					/* Try old "cn uid" server side sort */
+					cookie->sortTypeTry = SSS_CN_UID_ATTRS;
+					cookie->new_state = NEXT_VLV;
+					(void) ldap_msgfree(cookie->resultMsg);
+					cookie->resultMsg = NULL;
+					break;
+				}
 				if (rc != LDAP_SUCCESS) {
 					cookie->err_rc = rc;
 					cookie->new_state = LDAP_ERROR;
 					(void) ldap_msgfree(cookie->resultMsg);
+					cookie->resultMsg = NULL;
 					break;
 				}
 				cookie->new_state = multi_result(cookie);
@@ -2634,6 +2765,7 @@
 						    NEXT_SESSION;
 					break;
 				}
+
 				if ((rc == LDAP_CONNECT_ERROR ||
 				    rc == LDAP_SERVER_DOWN) &&
 				    cookie->reinit_on_retriable_err) {
@@ -2657,6 +2789,7 @@
 				break;
 			}
 			/* else LDAP_RES_SEARCH_ENTRY */
+			cookie->entryCount++;
 			rc = __s_api_getEntry(cookie);
 			(void) ldap_msgfree(cookie->resultMsg);
 			cookie->resultMsg = NULL;
@@ -2664,6 +2797,14 @@
 				cookie->new_state = LDAP_ERROR;
 				break;
 			}
+			/*
+			 * If VLV search was successfull save the server
+			 * side sort type tried.
+			 */
+			if (cookie->listType == VLVCTRLFLAG)
+				update_srvsidesort_type(cookie->service,
+				    cookie->sortTypeTry);
+
 			cookie->new_state = PROCESS_RESULT;
 			cookie->next_state = MULTI_RESULT;
 			break;
@@ -2910,6 +3051,7 @@
 	ns_ldap_list_batch_t *batch,
 	const char *service,
 	const char *filter,
+	const char *sortattr,
 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
 	char **realfilter, const void *userdata),
 	const char * const *attribute,
@@ -3065,6 +3207,7 @@
 	cookie->i_filter = strdup(filter);
 	cookie->i_attr = attribute;
 	cookie->i_auth = auth;
+	cookie->i_sortattr = sortattr;
 
 	if (batch != NULL) {
 		cookie->batch = batch;
@@ -3128,7 +3271,6 @@
  * mapping as appropriate. The operation may be retried a
  * couple of times in error situations.
  */
-
 int
 __ns_ldap_list(
 	const char *service,
@@ -3143,6 +3285,40 @@
 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
 	const void *userdata)
 {
+	int mod_flags;
+	/*
+	 * Strip the NS_LDAP_PAGE_CTRL option as this interface does not
+	 * support this. If you want to use this option call the API
+	 * __ns_ldap_list_sort() with has the sort attribute.
+	 */
+	mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
+
+	return (__ns_ldap_list_sort(service, filter, NULL, init_filter_cb,
+	    attribute, auth, mod_flags, rResult, errorp,
+	    callback, userdata));
+}
+
+/*
+ * __ns_ldap_list_sort performs one or more LDAP searches to a given
+ * directory server using service search descriptors and schema
+ * mapping as appropriate. The operation may be retried a
+ * couple of times in error situations.
+ */
+int
+__ns_ldap_list_sort(
+	const char *service,
+	const char *filter,
+	const char *sortattr,
+	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
+	char **realfilter, const void *userdata),
+	const char * const *attribute,
+	const ns_cred_t *auth,
+	const int flags,
+	ns_ldap_result_t **rResult, /* return result entries */
+	ns_ldap_error_t **errorp,
+	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
+	const void *userdata)
+{
 	ns_conn_user_t	*cu = NULL;
 	int		try_cnt = 0;
 	int		rc = NS_LDAP_SUCCESS, trc;
@@ -3151,8 +3327,9 @@
 		if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
 		    &try_cnt, &rc, errorp) == 0)
 			break;
-		rc = ldap_list(NULL, service, filter, init_filter_cb, attribute,
-		    auth, flags, rResult, errorp, &trc, callback, userdata, cu);
+		rc = ldap_list(NULL, service, filter, sortattr, init_filter_cb,
+		    attribute, auth, flags, rResult, errorp, &trc, callback,
+		    userdata, cu);
 	}
 
 	return (rc);
@@ -3192,6 +3369,7 @@
 {
 	ns_conn_user_t	*cu;
 	int		rc;
+	int		mod_flags;
 
 	cu =  __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, 0);
 	if (cu == NULL) {
@@ -3200,8 +3378,14 @@
 		return (NS_LDAP_MEMORY);
 	}
 
-	rc = ldap_list(batch, service, filter, init_filter_cb, attribute, auth,
-	    flags, rResult, errorp, rcp, callback, userdata, cu);
+	/*
+	 * Strip the NS_LDAP_PAGE_CTRL option as the batch interface does not
+	 * support this.
+	 */
+	mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
+
+	rc = ldap_list(batch, service, filter, NULL, init_filter_cb, attribute,
+	    auth, mod_flags, rResult, errorp, rcp, callback, userdata, cu);
 
 	/*
 	 * Free the conn_user if the cookie was not batched. If the cookie
@@ -3531,6 +3715,7 @@
 firstEntry(
     const char *service,
     const char *filter,
+    const char *sortattr,
     int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
     char **realfilter, const void *userdata),
     const char * const *attribute,
@@ -3683,6 +3868,7 @@
 
 	cookie->i_filter = strdup(filter);
 	cookie->i_attr = attribute;
+	cookie->i_sortattr = sortattr;
 	cookie->i_auth = auth;
 
 	state = INIT;
@@ -3732,6 +3918,7 @@
 __ns_ldap_firstEntry(
     const char *service,
     const char *filter,
+    const char *vlv_sort,
     int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
     char **realfilter, const void *userdata),
     const char * const *attribute,
@@ -3750,8 +3937,9 @@
 		if (__s_api_setup_retry_search(&cu, NS_CONN_USER_GETENT,
 		    &try_cnt, &rc, errorp) == 0)
 			break;
-		rc = firstEntry(service, filter, init_filter_cb, attribute,
-		    auth, flags, vcookie, result, errorp, userdata, cu);
+		rc = firstEntry(service, filter, vlv_sort, init_filter_cb,
+		    attribute, auth, flags, vcookie, result, errorp, userdata,
+		    cu);
 	}
 	return (rc);
 }
--- a/usr/src/lib/libsldap/common/ns_sldap.h	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/libsldap/common/ns_sldap.h	Fri Jul 02 10:46:04 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.
  */
 
 
@@ -693,6 +692,21 @@
 	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
 	const void *userdata);
 
+
+int __ns_ldap_list_sort(
+	const char *service,
+	const char *filter,
+	const char *sortattr,
+	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
+			char **realfilter, const void *userdata),
+	const char * const *attribute,
+	const ns_cred_t *cred,
+	const int flags,
+	ns_ldap_result_t ** result,
+	ns_ldap_error_t ** errorp,
+	int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
+	const void *userdata);
+
 int __ns_ldap_list_batch_start(
 	ns_ldap_list_batch_t **batch);
 
@@ -768,6 +782,7 @@
 int __ns_ldap_firstEntry(
 	const char *service,
 	const char *filter,
+	const char *sortattr,
 	int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
 			char **realfilter, const void *userdata),
 	const char * const *attribute,
--- a/usr/src/lib/nsswitch/ldap/common/ldap_common.c	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.c	Fri Jul 02 10:46:04 2010 +0100
@@ -19,12 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include "ldap_common.h"
 #include <malloc.h>
 #include <synch.h>
@@ -60,29 +57,42 @@
 				"(SolarisAttrKeyValue=*))"
 #define	_F_GETENT_SSD		"(%s)"
 
+/* getent sort attributes */
+#define	_A_UID			"uid"
+#define	_A_GIDNUMBER		"gidnumber"
+#define	_A_CN			"cn"
+#define	_A_IPNETWORKNUM		"ipnetworknumber"
+#define	_A_PROJECTNAM		"SolarisProjectName"
+#define	_A_IPTNETNUM		"ipTnetNumber"
+#define	_A_IPTNETTMPLNAM	"ipTnetTemplateName"
+
 static struct gettablefilter {
 	char *tablename;
 	char *tablefilter;
+	char *sortattr;
 } gettablefilterent[] = {
-	{(char *)_PASSWD,	(char *)_F_GETPWENT},
-	{(char *)_SHADOW,	(char *)_F_GETSPENT},
-	{(char *)_GROUP,	(char *)_F_GETGRENT},
-	{(char *)_HOSTS,	(char *)_F_GETHOSTENT},
-	{(char *)_NETWORKS,	(char *)_F_GETNETENT},
-	{(char *)_PROTOCOLS,	(char *)_F_GETPROTOENT},
-	{(char *)_RPC,		(char *)_F_GETRPCENT},
-	{(char *)_ALIASES,	(char *)_F_GETALIASENT},
-	{(char *)_SERVICES,	(char *)_F_GETSERVENT},
-	{(char *)_AUUSER,	(char *)_F_GETAUUSERNAME},
-	{(char *)_AUTHATTR,	(char *)_F_GETAUTHNAME},
-	{(char *)_EXECATTR,	(char *)_F_GETEXECNAME},
-	{(char *)_PROFATTR,	(char *)_F_GETPROFNAME},
-	{(char *)_USERATTR,	(char *)_F_GETUSERNAME},
-	{(char *)_PROJECT,	(char *)_F_GETPROJENT},
-	{(char *)_PRINTERS,	(char *)_F_GETPRINTERENT},
-	{(char *)_TNRHDB,	(char *)_F_GETTNRHDB},
-	{(char *)_TNRHTP,	(char *)_F_GETTNRHTP},
-	{(char *)NULL,		(char *)NULL}
+	{(char *)_PASSWD,	(char *)_F_GETPWENT,	(char *)_A_UID},
+	{(char *)_SHADOW,	(char *)_F_GETSPENT,	(char *)_A_UID},
+	{(char *)_GROUP,	(char *)_F_GETGRENT,	(char *)_A_GIDNUMBER},
+	{(char *)_HOSTS,	(char *)_F_GETHOSTENT,	(char *)_A_CN},
+	{(char *)_NETWORKS,	(char *)_F_GETNETENT,
+						(char *)_A_IPNETWORKNUM},
+	{(char *)_PROTOCOLS,	(char *)_F_GETPROTOENT,	(char *)_A_CN},
+	{(char *)_RPC,		(char *)_F_GETRPCENT,	(char *)_A_CN},
+	{(char *)_ALIASES,	(char *)_F_GETALIASENT,	(char *)_A_CN},
+	{(char *)_SERVICES,	(char *)_F_GETSERVENT,	(char *)_A_CN},
+	{(char *)_AUUSER,	(char *)_F_GETAUUSERNAME,
+							(char *)_A_UID},
+	{(char *)_AUTHATTR,	(char *)_F_GETAUTHNAME,	(char *)_A_CN},
+	{(char *)_EXECATTR,	(char *)_F_GETEXECNAME,	(char *)_A_CN},
+	{(char *)_PROFATTR,	(char *)_F_GETPROFNAME,	(char *)_A_CN},
+	{(char *)_USERATTR,	(char *)_F_GETUSERNAME,	(char *)_A_UID},
+	{(char *)_PROJECT,	(char *)_F_GETPROJENT,	(char *)_A_PROJECTNAM},
+	{(char *)_PRINTERS,	(char *)_F_GETPRINTERENT, (char *)_A_CN},
+	{(char *)_TNRHDB,	(char *)_F_GETTNRHDB,	(char *)_A_IPTNETNUM},
+	{(char *)_TNRHTP,	(char *)_F_GETTNRHTP,
+						(char *)_A_IPTNETTMPLNAM},
+	{(char *)NULL,		(char *)NULL,		(char *)NULL}
 };
 
 
@@ -339,10 +349,12 @@
 	if (be->setcalled == 1)
 		(void) _nss_ldap_endent(be, a);
 	be->filter = NULL;
+	be->sortattr = NULL;
 	for (gtf = gettablefilterent; gtf->tablename != (char *)NULL; gtf++) {
 		if (strcmp(gtf->tablename, be->tablename))
 			continue;
 		be->filter = (char *)gtf->tablefilter;
+		be->sortattr = (char *)gtf->sortattr;
 		break;
 	}
 
@@ -372,6 +384,7 @@
 
 	be->setcalled = 0;
 	be->filter = NULL;
+	be->sortattr = NULL;
 	if (be->enumcookie != NULL) {
 		(void) __ns_ldap_endEntry(&be->enumcookie, &error);
 		(void) __ns_ldap_freeError(&error);
@@ -413,8 +426,8 @@
 next_entry:
 	if (be->enumcookie == NULL) {
 		retcode = __ns_ldap_firstEntry(be->tablename,
-		    be->filter, _merge_SSD_filter, be->attrs, NULL,
-		    0, &be->enumcookie,
+		    be->filter, be->sortattr, _merge_SSD_filter, be->attrs,
+		    NULL, 0, &be->enumcookie,
 		    &be->result, &error, _F_GETENT_SSD);
 	} else {
 		if (be->services_cookie == NULL) {
@@ -427,73 +440,86 @@
 		(void) __ns_ldap_freeError(&error);
 		(void) _nss_ldap_endent(be, a);
 		return (retcode);
-	} else {
-		/* ns_ldap_entry_t -> file format */
-		if ((parsestat = be->ldapobj2str(be, argp))
-		    == NSS_STR_PARSE_SUCCESS) {
-			if (argp->buf.result != NULL) {
-				/* file format -> struct */
-				if (argp->str2ent == NULL) {
-					parsestat = NSS_STR_PARSE_PARSE;
-					goto error_out;
-				}
-				parsestat = (*argp->str2ent)(be->buffer,
-				    be->buflen,
-				    argp->buf.result,
-				    argp->buf.buffer,
-				    argp->buf.buflen);
-				if (parsestat == NSS_STR_PARSE_SUCCESS) {
-					if (be->buffer != NULL) {
-						free(be->buffer);
-						be->buffer = NULL;
-						be->buflen = 0;
-					}
-					be->result = NULL;
-					argp->returnval = argp->buf.result;
-					argp->returnlen = 1; /* irrevelant */
-					return ((nss_status_t)NSS_SUCCESS);
+	}
+
+	if (be->result == NULL) {
+		parsestat = NSS_STR_PARSE_NO_RESULT;
+		goto error_out;
+	}
+	/* ns_ldap_entry_t -> file format */
+	if ((parsestat = be->ldapobj2str(be, argp))
+	    == NSS_STR_PARSE_SUCCESS) {
+		if (argp->buf.result != NULL) {
+			/* file format -> struct */
+			if (argp->str2ent == NULL) {
+				parsestat = NSS_STR_PARSE_NO_RESULT;
+				goto error_out;
+			}
+			parsestat = (*argp->str2ent)(be->buffer,
+			    be->buflen,
+			    argp->buf.result,
+			    argp->buf.buffer,
+			    argp->buf.buflen);
+			if (parsestat == NSS_STR_PARSE_SUCCESS) {
+				if (be->buffer != NULL) {
+					free(be->buffer);
+					be->buffer = NULL;
+					be->buflen = 0;
 				}
-			} else {
-				/*
-				 * nscd is not caching the enumerated
-				 * entries. This code path would be dormant.
-				 * Keep this path for the future references.
-				 */
-				argp->returnval = argp->buf.buffer;
-				argp->returnlen =
-				    strlen(argp->buf.buffer) + 1;
+				be->result = NULL;
+				argp->returnval = argp->buf.result;
+				argp->returnlen = 1; /* irrevelant */
+				return ((nss_status_t)NSS_SUCCESS);
 			}
-		}
-error_out:
-		if (be->buffer != NULL) {
-			free(be->buffer);
-			be->buffer = NULL;
-			be->buflen = 0;
+		} else {
+			/*
+			 * nscd is not caching the enumerated
+			 * entries. This code path would be dormant.
+			 * Keep this path for the future references.
+			 */
+			argp->returnval = argp->buf.buffer;
+			argp->returnlen =
+			    strlen(argp->buf.buffer) + 1;
 		}
-		be->result = NULL;
-		if (parsestat == NSS_STR_PARSE_PARSE) {
-			argp->returnval = 0;
-			(void) _nss_ldap_endent(be, a);
-			return ((nss_status_t)NSS_NOTFOUND);
-		}
+	}
+error_out:
+	if (be->buffer != NULL) {
+		free(be->buffer);
+		be->buffer = NULL;
+		be->buflen = 0;
+	}
+	be->result = NULL;
+	if (parsestat == NSS_STR_PARSE_NO_RESULT) {
+		argp->returnval = 0;
+		(void) _nss_ldap_endent(be, a);
+		return ((nss_status_t)NSS_NOTFOUND);
+	}
 
-		if (parsestat == NSS_STR_PARSE_ERANGE) {
-			argp->erange = 1;
-			(void) _nss_ldap_endent(be, a);
-			return ((nss_status_t)NSS_NOTFOUND);
-		}
-		if (parsestat == NSS_STR_PARSE_NO_ADDR)
-			/*
-			 * No IPV4 address is found in the current entry.
-			 * It indicates that the entry contains IPV6 addresses
-			 * only. Instead of calling _nss_ldap_endent to
-			 * terminate, get next entry to continue enumeration.
-			 * If it returned NSS_NOTFOUND here,
-			 * gethostent() would return NULL
-			 * and the enumeration would stop prematurely.
-			 */
-			goto next_entry;
+	if (parsestat == NSS_STR_PARSE_ERANGE) {
+		argp->erange = 1;
+		(void) _nss_ldap_endent(be, a);
+		return ((nss_status_t)NSS_NOTFOUND);
 	}
+	if (parsestat == NSS_STR_PARSE_NO_ADDR)
+		/*
+		 * No IPV4 address is found in the current entry.
+		 * It indicates that the entry contains IPV6 addresses
+		 * only. Instead of calling _nss_ldap_endent to
+		 * terminate, get next entry to continue enumeration.
+		 * If it returned NSS_NOTFOUND here,
+		 * gethostent() would return NULL
+		 * and the enumeration would stop prematurely.
+		 */
+		goto next_entry;
+
+	if (parsestat == NSS_STR_PARSE_PARSE)
+		/*
+		 * There has been a parse error. Most likely some
+		 * mandatory attributes are missing. Ignore the error
+		 * and get the next entry. If we returned an error the
+		 * enumeration would stop prematurely.
+		 */
+		goto next_entry;
 
 	return ((nss_status_t)NSS_SUCCESS);
 }
--- a/usr/src/lib/nsswitch/ldap/common/ldap_common.h	Fri Jul 02 14:31:43 2010 +0800
+++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.h	Fri Jul 02 10:46:04 2010 +0100
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef	_LDAP_COMMON_H
@@ -69,6 +68,7 @@
 #define	_TNRHTP			"tnrhtp"
 
 #define	NSS_STR_PARSE_NO_ADDR	(NSS_STR_PARSE_ERANGE + 100)
+#define	NSS_STR_PARSE_NO_RESULT	(NSS_STR_PARSE_ERANGE + 101)
 
 #define	DOTTEDSUBDOMAIN(string) \
 	((string != NULL) && (strchr(string, '.') != NULL))
@@ -118,6 +118,7 @@
 	char			*tablename;
 	void			*enumcookie;
 	char			*filter;
+	char			*sortattr;
 	int			setcalled;
 	const char		**attrs;
 	ns_ldap_result_t	*result;