diff options
-rw-r--r-- | usr/src/cmd/ldap/ns_ldap/ldapaddent.c | 62 | ||||
-rw-r--r-- | usr/src/cmd/ldap/ns_ldap/ldaplist.c | 59 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/llib-lsldap | 19 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/mapfile-vers | 1 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/ns_internal.h | 22 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/ns_mapping.c | 57 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/ns_reads.c | 216 | ||||
-rw-r--r-- | usr/src/lib/libsldap/common/ns_sldap.h | 19 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/ldap/common/ldap_common.c | 198 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/ldap/common/ldap_common.h | 5 |
10 files changed, 493 insertions, 165 deletions
diff --git a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c index ac077dcf01..a721ba4308 100644 --- a/usr/src/cmd/ldap/ns_ldap/ldapaddent.c +++ b/usr/src/cmd/ldap/ns_ldap/ldapaddent.c @@ -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 @@ static struct ttypelist_t { /* 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 @@ filedbmline_plus(struct line_buf *line, FILE *etcf, int *lineno, 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 @@ dumptable(char *service) /* 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: diff --git a/usr/src/cmd/ldap/ns_ldap/ldaplist.c b/usr/src/cmd/ldap/ns_ldap/ldaplist.c index a75f39f5dd..cfa74ae7f2 100644 --- a/usr/src/cmd/ldap/ns_ldap/ldaplist.c +++ b/usr/src/cmd/ldap/ns_ldap/ldaplist.c @@ -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 @@ extern void printMapping(); 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 @@ char **err, char *userdata) 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; diff --git a/usr/src/lib/libsldap/common/llib-lsldap b/usr/src/lib/libsldap/common/llib-lsldap index 466116a856..5f59110773 100644 --- a/usr/src/lib/libsldap/common/llib-lsldap +++ b/usr/src/lib/libsldap/common/llib-lsldap @@ -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 __ns_ldap_list( 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_delEntry( 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, diff --git a/usr/src/lib/libsldap/common/mapfile-vers b/usr/src/lib/libsldap/common/mapfile-vers index e511edf76b..8c88eb55bb 100644 --- a/usr/src/lib/libsldap/common/mapfile-vers +++ b/usr/src/lib/libsldap/common/mapfile-vers @@ -55,6 +55,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { __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; diff --git a/usr/src/lib/libsldap/common/ns_internal.h b/usr/src/lib/libsldap/common/ns_internal.h index 7e2bbafaba..8026f150bc 100644 --- a/usr/src/lib/libsldap/common/ns_internal.h +++ b/usr/src/lib/libsldap/common/ns_internal.h @@ -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 @@ extern "C" { #define LISTPAGESIZE 1000 #define ENUMPAGESIZE 100 -#define SORTKEYLIST "cn uid" #define DEFMAX 8 #define TOKENSEPARATOR '=' @@ -553,6 +551,19 @@ typedef enum { 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 @@ typedef struct ns_ldap_cookie { 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 @@ typedef struct ns_ldap_cookie { int listType; unsigned long index; LDAPControl **p_serverctrls; + ns_srvsidesort_t sortTypeTry; + int entryCount; int scope; char *basedn; @@ -825,6 +839,8 @@ int __s_api_parse_map(char *cp, char **sid, 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); diff --git a/usr/src/lib/libsldap/common/ns_mapping.c b/usr/src/lib/libsldap/common/ns_mapping.c index 686a57ddb9..1ceb035941 100644 --- a/usr/src/lib/libsldap/common/ns_mapping.c +++ b/usr/src/lib/libsldap/common/ns_mapping.c @@ -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 @@ __s_api_parseASearchDesc(const char *service, 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 @@ __s_api_parseASearchDesc(const char *service, /* 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 @@ __ns_ldap_saveSearchDesc(ns_ldap_search_desc_t ***sdlist, *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 @@ int __ns_ldap_getSearchDescriptors( *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 @@ int __ns_ldap_getSearchDescriptors( (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 @@ int __ns_ldap_getSearchDescriptors( /* 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 @@ int __ns_ldap_getSearchDescriptors( /* 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 @@ int __ns_ldap_getSearchDescriptors( 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 @@ char **__ns_ldap_mapAttributeList( } 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); +} diff --git a/usr/src/lib/libsldap/common/ns_reads.c b/usr/src/lib/libsldap/common/ns_reads.c index cda5b344fe..61a59e16db 100644 --- a/usr/src/lib/libsldap/common/ns_reads.c +++ b/usr/src/lib/libsldap/common/ns_reads.c @@ -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 @@ paging_supported(ns_ldap_cookie_t *cookie) 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 @@ setup_vlv_params(ns_ldap_cookie_t *cookie) 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 @@ multi_result(ns_ldap_cookie_t *cookie) 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 @@ clear_results(ns_ldap_cookie_t *cookie) 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 @@ search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle) 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 @@ search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle) 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 @@ search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle) NEXT_SESSION; break; } + if ((rc == LDAP_CONNECT_ERROR || rc == LDAP_SERVER_DOWN) && cookie->reinit_on_retriable_err) { @@ -2657,6 +2789,7 @@ search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle) 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 @@ search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle) 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 @@ ldap_list( 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 @@ ldap_list( 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 @@ ldap_list( * 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 @@ __ns_ldap_list( 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 @@ __ns_ldap_list( 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_ldap_list_batch_add( { 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 @@ __ns_ldap_list_batch_add( 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 @@ static int 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 @@ firstEntry( cookie->i_filter = strdup(filter); cookie->i_attr = attribute; + cookie->i_sortattr = sortattr; cookie->i_auth = auth; state = INIT; @@ -3732,6 +3918,7 @@ int __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 @@ __ns_ldap_firstEntry( 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); } diff --git a/usr/src/lib/libsldap/common/ns_sldap.h b/usr/src/lib/libsldap/common/ns_sldap.h index a540e7d2f1..434c2806ad 100644 --- a/usr/src/lib/libsldap/common/ns_sldap.h +++ b/usr/src/lib/libsldap/common/ns_sldap.h @@ -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 __ns_ldap_list( 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_delEntry( 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, diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_common.c b/usr/src/lib/nsswitch/ldap/common/ldap_common.c index 46284899c8..c4103ef03e 100644 --- a/usr/src/lib/nsswitch/ldap/common/ldap_common.c +++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.c @@ -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 @@ _nss_ldap_setent(ldap_backend_ptr be, void *a) 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 @@ _nss_ldap_endent(ldap_backend_ptr be, void *a) 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 @@ _nss_ldap_getent(ldap_backend_ptr be, void *a) 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 @@ next_entry: (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); } + } 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; } + } error_out: - if (be->buffer != NULL) { - free(be->buffer); - be->buffer = NULL; - be->buflen = 0; - } - be->result = NULL; - if (parsestat == NSS_STR_PARSE_PARSE) { - argp->returnval = 0; - (void) _nss_ldap_endent(be, a); - return ((nss_status_t)NSS_NOTFOUND); - } + 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); } diff --git a/usr/src/lib/nsswitch/ldap/common/ldap_common.h b/usr/src/lib/nsswitch/ldap/common/ldap_common.h index 7d9b56613a..690dd15adc 100644 --- a/usr/src/lib/nsswitch/ldap/common/ldap_common.h +++ b/usr/src/lib/nsswitch/ldap/common/ldap_common.h @@ -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 @@ extern "C" { #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 @@ struct ldap_backend { char *tablename; void *enumcookie; char *filter; + char *sortattr; int setcalled; const char **attrs; ns_ldap_result_t *result; |