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
--- 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,
- ¶mVal, errorp)) != NS_LDAP_SUCCESS) {
+ ¶mVal, 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 ***)¶m, errorp);
+ (void ***)¶m, 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,
- ¶mVal, errorp)) != NS_LDAP_SUCCESS) {
+ ¶mVal, 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(¶m);
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;