1e1dd0a2fSth160488 /* 2e1dd0a2fSth160488 * CDDL HEADER START 3e1dd0a2fSth160488 * 4e1dd0a2fSth160488 * The contents of this file are subject to the terms of the 5e1dd0a2fSth160488 * Common Development and Distribution License (the "License"). 6e1dd0a2fSth160488 * You may not use this file except in compliance with the License. 7e1dd0a2fSth160488 * 8e1dd0a2fSth160488 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9e1dd0a2fSth160488 * or http://www.opensolaris.org/os/licensing. 10e1dd0a2fSth160488 * See the License for the specific language governing permissions 11e1dd0a2fSth160488 * and limitations under the License. 12e1dd0a2fSth160488 * 13e1dd0a2fSth160488 * When distributing Covered Code, include this CDDL HEADER in each 14e1dd0a2fSth160488 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15e1dd0a2fSth160488 * If applicable, add the following below this CDDL HEADER, with the 16e1dd0a2fSth160488 * fields enclosed by brackets "[]" replaced with your own identifying 17e1dd0a2fSth160488 * information: Portions Copyright [yyyy] [name of copyright owner] 18e1dd0a2fSth160488 * 19e1dd0a2fSth160488 * CDDL HEADER END 20e1dd0a2fSth160488 */ 21e1dd0a2fSth160488 /* 22434c5a06SMilan Jurik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23e1dd0a2fSth160488 * Use is subject to license terms. 2433f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 25*b3b48d8eSHans Rosenfeld * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 26e1dd0a2fSth160488 */ 27e1dd0a2fSth160488 28e1dd0a2fSth160488 #define __STANDALONE_MODULE__ 29e1dd0a2fSth160488 30e1dd0a2fSth160488 #include <stdio.h> 31e1dd0a2fSth160488 #include <sys/types.h> 32e1dd0a2fSth160488 #include <stdlib.h> 33e1dd0a2fSth160488 #include <libintl.h> 34e1dd0a2fSth160488 #include <string.h> 35e1dd0a2fSth160488 #include <ctype.h> 36e1dd0a2fSth160488 37e1dd0a2fSth160488 #include <sys/stat.h> 38e1dd0a2fSth160488 #include <fcntl.h> 39e1dd0a2fSth160488 #include <unistd.h> 40e1dd0a2fSth160488 #include <syslog.h> 41e1dd0a2fSth160488 #include <locale.h> 42e1dd0a2fSth160488 #include <errno.h> 43e1dd0a2fSth160488 #include <sys/time.h> 44e1dd0a2fSth160488 45e1dd0a2fSth160488 #include <arpa/inet.h> 46e1dd0a2fSth160488 #include <netdb.h> 47e1dd0a2fSth160488 #include <strings.h> 48e1dd0a2fSth160488 49e1dd0a2fSth160488 #include <thread.h> 50e1dd0a2fSth160488 51e1dd0a2fSth160488 #include <nsswitch.h> 52e1dd0a2fSth160488 #include <nss_dbdefs.h> 53e1dd0a2fSth160488 #include <nss.h> 54e1dd0a2fSth160488 55e1dd0a2fSth160488 #include "ns_cache_door.h" 56e1dd0a2fSth160488 #include "ns_internal.h" 57ca190d8dSmichen #include "ns_connmgmt.h" 58e1dd0a2fSth160488 59e1dd0a2fSth160488 typedef enum { 60e1dd0a2fSth160488 INFO_SERVER_JUST_INITED = -1, 61e1dd0a2fSth160488 INFO_SERVER_UNKNOWN = 0, 62e1dd0a2fSth160488 INFO_SERVER_CONNECTING = 1, 63e1dd0a2fSth160488 INFO_SERVER_UP = 2, 64e1dd0a2fSth160488 INFO_SERVER_ERROR = 3, 65e1dd0a2fSth160488 INFO_SERVER_REMOVED = 4 66e1dd0a2fSth160488 } dir_server_status_t; 67e1dd0a2fSth160488 68e1dd0a2fSth160488 typedef enum { 69e1dd0a2fSth160488 INFO_STATUS_NEW = 2, 70e1dd0a2fSth160488 INFO_STATUS_OLD = 3 71e1dd0a2fSth160488 } dir_server_info_t; 72e1dd0a2fSth160488 73e1dd0a2fSth160488 typedef struct dir_server { 74e1dd0a2fSth160488 char *ip; 75e1dd0a2fSth160488 char **controls; 76e1dd0a2fSth160488 char **saslMech; 77e1dd0a2fSth160488 dir_server_status_t status; 78e1dd0a2fSth160488 mutex_t updateStatus; 79e1dd0a2fSth160488 dir_server_info_t info; 80e1dd0a2fSth160488 } dir_server_t; 81e1dd0a2fSth160488 82e1dd0a2fSth160488 typedef struct dir_server_list { 83e1dd0a2fSth160488 dir_server_t **nsServers; 84e1dd0a2fSth160488 85e1dd0a2fSth160488 rwlock_t listDestroyLock; 86e1dd0a2fSth160488 } dir_server_list_t; 87e1dd0a2fSth160488 88e1dd0a2fSth160488 struct { 89e1dd0a2fSth160488 /* The local list of the directory servers' root DSEs. */ 90e1dd0a2fSth160488 dir_server_list_t *list; 91e1dd0a2fSth160488 /* The flag indicating if libsldap is in the 'Standalone' mode. */ 92e1dd0a2fSth160488 int standalone; 93e1dd0a2fSth160488 /* 94e1dd0a2fSth160488 * The mutex ensuring that only one thread performs 95e1dd0a2fSth160488 * the initialization of the list. 96e1dd0a2fSth160488 */ 97e1dd0a2fSth160488 mutex_t listReplaceLock; 98e1dd0a2fSth160488 /* 99e1dd0a2fSth160488 * A flag indicating that a particular thread is 100e1dd0a2fSth160488 * in the 'ldap_cachemgr' mode. It is stored by thread as 101e1dd0a2fSth160488 * a thread specific data. 102e1dd0a2fSth160488 */ 103e1dd0a2fSth160488 const int initFlag; 104e1dd0a2fSth160488 /* 105e1dd0a2fSth160488 * A thread specific key storing 106e1dd0a2fSth160488 * the the 'ldap_cachemgr' mode indicator. 107e1dd0a2fSth160488 */ 108e1dd0a2fSth160488 thread_key_t standaloneInitKey; 109e1dd0a2fSth160488 } dir_servers = {NULL, 0, DEFAULTMUTEX, '1'}; 110e1dd0a2fSth160488 111e1dd0a2fSth160488 typedef struct switchDatabase { 112e1dd0a2fSth160488 char *conf; 113e1dd0a2fSth160488 uint32_t alloced; 114e1dd0a2fSth160488 } switch_database_t; 115e1dd0a2fSth160488 116e1dd0a2fSth160488 static thread_key_t switchConfigKey; 117e1dd0a2fSth160488 118e1dd0a2fSth160488 #pragma init(createStandaloneKey) 119e1dd0a2fSth160488 120e1dd0a2fSth160488 #define DONT_INCLUDE_ATTR_NAMES 0 121e1dd0a2fSth160488 #define INCLUDE_ATTR_NAMES 1 122e1dd0a2fSth160488 #define IS_PROFILE 1 123e1dd0a2fSth160488 #define NOT_PROFILE 0 124e1dd0a2fSth160488 /* INET6_ADDRSTRLEN + ":" + <5-digit port> + some round-up */ 125e1dd0a2fSth160488 #define MAX_HOSTADDR_LEN (INET6_ADDRSTRLEN + 6 + 12) 126e1dd0a2fSth160488 127e1dd0a2fSth160488 static 128e1dd0a2fSth160488 void 129e1dd0a2fSth160488 switch_conf_disposer(void *data) 130e1dd0a2fSth160488 { 131e1dd0a2fSth160488 switch_database_t *localData = (switch_database_t *)data; 132e1dd0a2fSth160488 133e1dd0a2fSth160488 free(localData->conf); 134e1dd0a2fSth160488 free(localData); 135e1dd0a2fSth160488 } 136e1dd0a2fSth160488 137e1dd0a2fSth160488 /* 138e1dd0a2fSth160488 * This function initializes an indication that a thread obtaining a root DSE 139e1dd0a2fSth160488 * will be switched to the 'ldap_cachemgr' mode. Within the thread libsldap 140e1dd0a2fSth160488 * will not invoke the __s_api_requestServer function. Instead, the library 141e1dd0a2fSth160488 * will establish a connection to the server specified by 142e1dd0a2fSth160488 * the __ns_ldap_getRootDSE function. 143e1dd0a2fSth160488 * Since ldap_cachmgr can obtain a DUAProfile and root DSEs at the same time 144e1dd0a2fSth160488 * and we do not want to affect a thread obtaining a DUAProfile, 145e1dd0a2fSth160488 * the 'ldap_cachemgr' mode is thread private. 146e1dd0a2fSth160488 * In addition, this function creates a key holding temporary configuration 147e1dd0a2fSth160488 * for the "hosts" and "ipnodes" databases which is used by the "SKIPDB" 148e1dd0a2fSth160488 * mechanism (__s_api_ip2hostname() & _s_api_hostname2ip()). 149e1dd0a2fSth160488 */ 150e1dd0a2fSth160488 static 151e1dd0a2fSth160488 void 152e1dd0a2fSth160488 createStandaloneKey() 153e1dd0a2fSth160488 { 154e1dd0a2fSth160488 if (thr_keycreate(&dir_servers.standaloneInitKey, NULL) != 0) { 155e1dd0a2fSth160488 syslog(LOG_ERR, gettext("libsldap: unable to create a thread " 156e1dd0a2fSth160488 "key needed for sharing ldap connections")); 157e1dd0a2fSth160488 } 158e1dd0a2fSth160488 if (thr_keycreate(&switchConfigKey, switch_conf_disposer) != 0) { 159e1dd0a2fSth160488 syslog(LOG_ERR, gettext("libsldap: unable to create a thread " 160e1dd0a2fSth160488 "key containing current nsswitch configuration")); 161e1dd0a2fSth160488 } 162e1dd0a2fSth160488 } 163e1dd0a2fSth160488 164e1dd0a2fSth160488 /* 165e1dd0a2fSth160488 * This function sets the 'ldap_cachemgr' mode indication. 166e1dd0a2fSth160488 */ 167e1dd0a2fSth160488 void 168e1dd0a2fSth160488 __s_api_setInitMode() 169e1dd0a2fSth160488 { 170e1dd0a2fSth160488 (void) thr_setspecific(dir_servers.standaloneInitKey, 171e1dd0a2fSth160488 (void *) &dir_servers.initFlag); 172e1dd0a2fSth160488 } 173e1dd0a2fSth160488 174e1dd0a2fSth160488 /* 175e1dd0a2fSth160488 * This function unset the 'ldap_cachemgr' mode indication. 176e1dd0a2fSth160488 */ 177e1dd0a2fSth160488 void 178e1dd0a2fSth160488 __s_api_unsetInitMode() 179e1dd0a2fSth160488 { 180e1dd0a2fSth160488 (void) thr_setspecific(dir_servers.standaloneInitKey, NULL); 181e1dd0a2fSth160488 } 182e1dd0a2fSth160488 183e1dd0a2fSth160488 /* 184e1dd0a2fSth160488 * This function checks if the 'ldap_cachemgr' mode indication is set. 185e1dd0a2fSth160488 */ 186e1dd0a2fSth160488 int 187e1dd0a2fSth160488 __s_api_isInitializing() { 188e1dd0a2fSth160488 int *flag = NULL; 189e1dd0a2fSth160488 190e1dd0a2fSth160488 (void) thr_getspecific(dir_servers.standaloneInitKey, (void **) &flag); 191e1dd0a2fSth160488 192e1dd0a2fSth160488 return (flag != NULL && *flag == dir_servers.initFlag); 193e1dd0a2fSth160488 } 194e1dd0a2fSth160488 195e1dd0a2fSth160488 /* 196e1dd0a2fSth160488 * This function checks if the process runs in the 'Standalone' mode. 197e1dd0a2fSth160488 * In this mode libsldap will check the local, process private list of root DSEs 198e1dd0a2fSth160488 * instead of requesting them via a door call to ldap_cachemgr. 199e1dd0a2fSth160488 */ 200e1dd0a2fSth160488 int 201e1dd0a2fSth160488 __s_api_isStandalone() 202e1dd0a2fSth160488 { 203e1dd0a2fSth160488 int mode; 204e1dd0a2fSth160488 205e1dd0a2fSth160488 (void) mutex_lock(&dir_servers.listReplaceLock); 206e1dd0a2fSth160488 mode = dir_servers.standalone; 207e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 208e1dd0a2fSth160488 209e1dd0a2fSth160488 return (mode); 210e1dd0a2fSth160488 } 211e1dd0a2fSth160488 212e1dd0a2fSth160488 213e1dd0a2fSth160488 static 214e1dd0a2fSth160488 int 215e1dd0a2fSth160488 remove_ldap(char *dst, char *src, int dst_buf_len) 216e1dd0a2fSth160488 { 217e1dd0a2fSth160488 int i = 0; 218e1dd0a2fSth160488 219e1dd0a2fSth160488 if (strlen(src) >= dst_buf_len) 220e1dd0a2fSth160488 return (0); 221e1dd0a2fSth160488 222e1dd0a2fSth160488 while (*src != '\0') { 223e1dd0a2fSth160488 /* Copy up to one space from source. */ 224e1dd0a2fSth160488 if (isspace(*src)) { 225e1dd0a2fSth160488 dst[i++] = *src; 226e1dd0a2fSth160488 while (isspace(*src)) 227e1dd0a2fSth160488 src++; 228e1dd0a2fSth160488 } 229e1dd0a2fSth160488 230e1dd0a2fSth160488 /* If not "ldap", just copy. */ 231e1dd0a2fSth160488 if (strncmp(src, "ldap", 4) != 0) { 232e1dd0a2fSth160488 while (!isspace(*src)) { 233e1dd0a2fSth160488 dst[i++] = *src++; 234e1dd0a2fSth160488 /* At the end of string? */ 235e1dd0a2fSth160488 if (dst[i-1] == '\0') 236e1dd0a2fSth160488 return (1); 237e1dd0a2fSth160488 } 238e1dd0a2fSth160488 /* Copy up to one space from source. */ 239e1dd0a2fSth160488 if (isspace(*src)) { 240e1dd0a2fSth160488 dst[i++] = *src; 241e1dd0a2fSth160488 while (isspace(*src)) 242e1dd0a2fSth160488 src++; 243e1dd0a2fSth160488 } 244e1dd0a2fSth160488 /* Copy also the criteria section */ 245e1dd0a2fSth160488 if (*src == '[') 246e1dd0a2fSth160488 while (*src != ']') { 247e1dd0a2fSth160488 dst[i++] = *src++; 248e1dd0a2fSth160488 /* Shouln't happen if format is right */ 249e1dd0a2fSth160488 if (dst[i-1] == '\0') 250e1dd0a2fSth160488 return (1); 251e1dd0a2fSth160488 } 252e1dd0a2fSth160488 } 253e1dd0a2fSth160488 254e1dd0a2fSth160488 /* If next part is ldap, skip over it ... */ 255e1dd0a2fSth160488 if (strncmp(src, "ldap", 4) == 0) { 256e1dd0a2fSth160488 if (isspace(*(src+4)) || *(src+4) == '\0') { 257e1dd0a2fSth160488 src += 4; 258e1dd0a2fSth160488 while (isspace(*src)) 259e1dd0a2fSth160488 src++; 260e1dd0a2fSth160488 if (*src == '[') { 261e1dd0a2fSth160488 while (*src++ != ']') { 262e1dd0a2fSth160488 /* 263e1dd0a2fSth160488 * See comment above about 264e1dd0a2fSth160488 * correct format. 265e1dd0a2fSth160488 */ 266e1dd0a2fSth160488 if (*src == '\0') { 267e1dd0a2fSth160488 dst[i++] = '\0'; 268e1dd0a2fSth160488 return (1); 269e1dd0a2fSth160488 } 270e1dd0a2fSth160488 } 271e1dd0a2fSth160488 } 272e1dd0a2fSth160488 while (isspace(*src)) 273e1dd0a2fSth160488 src++; 274e1dd0a2fSth160488 } 275e1dd0a2fSth160488 } 276e1dd0a2fSth160488 if (*src == '\0') 277e1dd0a2fSth160488 dst[i++] = '\0'; 278e1dd0a2fSth160488 } 279e1dd0a2fSth160488 280e1dd0a2fSth160488 return (1); 281e1dd0a2fSth160488 } 282e1dd0a2fSth160488 283e1dd0a2fSth160488 static 284e1dd0a2fSth160488 char * 285e1dd0a2fSth160488 get_db(const char *db_name) 286e1dd0a2fSth160488 { 287e1dd0a2fSth160488 char *ptr; 288e1dd0a2fSth160488 switch_database_t *hostService = NULL; 289e1dd0a2fSth160488 FILE *fp = fopen(__NSW_CONFIG_FILE, "rF"); 290e1dd0a2fSth160488 char *linep, line[NSS_BUFSIZ]; 291e1dd0a2fSth160488 292e1dd0a2fSth160488 if (fp == NULL) { 293e1dd0a2fSth160488 syslog(LOG_WARNING, gettext("libsldap: can not read %s"), 294e1dd0a2fSth160488 __NSW_CONFIG_FILE); 295e1dd0a2fSth160488 return (NULL); 296e1dd0a2fSth160488 } 297e1dd0a2fSth160488 298e1dd0a2fSth160488 while ((linep = fgets(line, NSS_BUFSIZ, fp)) != NULL) { 299e1dd0a2fSth160488 while (isspace(*linep)) { 300e1dd0a2fSth160488 ++linep; 301e1dd0a2fSth160488 } 302e1dd0a2fSth160488 if (*linep == '#') { 303e1dd0a2fSth160488 continue; 304e1dd0a2fSth160488 } 305e1dd0a2fSth160488 if (strncmp(linep, db_name, strlen(db_name)) != 0) { 306e1dd0a2fSth160488 continue; 307e1dd0a2fSth160488 } 308e1dd0a2fSth160488 if ((linep = strchr(linep, ':')) != NULL) { 309e1dd0a2fSth160488 if (linep[strlen(linep) - 1] == '\n') { 310e1dd0a2fSth160488 linep[strlen(linep) - 1] = '\0'; 311e1dd0a2fSth160488 } 312e1dd0a2fSth160488 313e1dd0a2fSth160488 while (isspace(*++linep)) 314e1dd0a2fSth160488 ; 315e1dd0a2fSth160488 316e1dd0a2fSth160488 if ((ptr = strchr(linep, '#')) != NULL) { 317e1dd0a2fSth160488 while (--ptr >= linep && isspace(*ptr)) 318e1dd0a2fSth160488 ; 319e1dd0a2fSth160488 *(ptr + 1) = '\0'; 320e1dd0a2fSth160488 } 321e1dd0a2fSth160488 322e1dd0a2fSth160488 if (strlen(linep) == 0) { 323e1dd0a2fSth160488 continue; 324e1dd0a2fSth160488 } 325e1dd0a2fSth160488 break; 326e1dd0a2fSth160488 } 327e1dd0a2fSth160488 } 328e1dd0a2fSth160488 329e1dd0a2fSth160488 (void) fclose(fp); 330e1dd0a2fSth160488 331e1dd0a2fSth160488 if (linep == NULL) { 332e1dd0a2fSth160488 syslog(LOG_WARNING, 333e1dd0a2fSth160488 gettext("libsldap: the %s database " 334e1dd0a2fSth160488 "is missing from %s"), 335e1dd0a2fSth160488 db_name, 336e1dd0a2fSth160488 __NSW_CONFIG_FILE); 337e1dd0a2fSth160488 return (NULL); 338e1dd0a2fSth160488 } 339e1dd0a2fSth160488 340e1dd0a2fSth160488 (void) thr_getspecific(switchConfigKey, (void **) &hostService); 341e1dd0a2fSth160488 if (hostService == NULL) { 342e1dd0a2fSth160488 hostService = calloc(1, sizeof (switch_database_t)); 343e1dd0a2fSth160488 if (hostService == NULL) { 344e1dd0a2fSth160488 return (NULL); 345e1dd0a2fSth160488 } 346e1dd0a2fSth160488 (void) thr_setspecific(switchConfigKey, hostService); 347e1dd0a2fSth160488 } 348e1dd0a2fSth160488 349e1dd0a2fSth160488 /* 350e1dd0a2fSth160488 * In a long-living process threads can perform several 351e1dd0a2fSth160488 * getXbyY requests. And the windows between those requests 352e1dd0a2fSth160488 * can be long. The nsswitch configuration can change from time 353e1dd0a2fSth160488 * to time. So instead of allocating/freeing memory every time 354e1dd0a2fSth160488 * the API is called, reallocate memory only when the current 355e1dd0a2fSth160488 * configuration for the database being used is longer than 356e1dd0a2fSth160488 * the previous one. 357e1dd0a2fSth160488 */ 358e1dd0a2fSth160488 if (strlen(linep) >= hostService->alloced) { 359e1dd0a2fSth160488 ptr = (char *)realloc((void *)hostService->conf, 360e1dd0a2fSth160488 strlen(linep) + 1); 361e1dd0a2fSth160488 if (ptr == NULL) { 362e1dd0a2fSth160488 free((void *)hostService->conf); 363e1dd0a2fSth160488 hostService->conf = NULL; 364e1dd0a2fSth160488 hostService->alloced = 0; 365e1dd0a2fSth160488 return (NULL); 366e1dd0a2fSth160488 } 367e1dd0a2fSth160488 bzero(ptr, strlen(linep) + 1); 368e1dd0a2fSth160488 hostService->conf = ptr; 369e1dd0a2fSth160488 hostService->alloced = strlen(linep) + 1; 370e1dd0a2fSth160488 } 371e1dd0a2fSth160488 372e1dd0a2fSth160488 if (remove_ldap(hostService->conf, linep, hostService->alloced)) 373e1dd0a2fSth160488 return (hostService->conf); 374e1dd0a2fSth160488 else 375e1dd0a2fSth160488 return (NULL); 376e1dd0a2fSth160488 } 377e1dd0a2fSth160488 378e1dd0a2fSth160488 static 379e1dd0a2fSth160488 void 380e1dd0a2fSth160488 _initf_ipnodes(nss_db_params_t *p) 381e1dd0a2fSth160488 { 382e1dd0a2fSth160488 char *services = get_db("ipnodes"); 383e1dd0a2fSth160488 384e1dd0a2fSth160488 p->name = NSS_DBNAM_IPNODES; 385e1dd0a2fSth160488 p->flags |= NSS_USE_DEFAULT_CONFIG; 386e1dd0a2fSth160488 p->default_config = services == NULL ? "" : services; 387e1dd0a2fSth160488 } 388e1dd0a2fSth160488 389e1dd0a2fSth160488 static 390e1dd0a2fSth160488 void 391e1dd0a2fSth160488 _initf_hosts(nss_db_params_t *p) 392e1dd0a2fSth160488 { 393e1dd0a2fSth160488 char *services = get_db("hosts"); 394e1dd0a2fSth160488 395e1dd0a2fSth160488 p->name = NSS_DBNAM_HOSTS; 396e1dd0a2fSth160488 p->flags |= NSS_USE_DEFAULT_CONFIG; 397e1dd0a2fSth160488 p->default_config = services == NULL ? "" : services; 398e1dd0a2fSth160488 } 399e1dd0a2fSth160488 400e1dd0a2fSth160488 /* 401e1dd0a2fSth160488 * This function is an analog of the standard gethostbyaddr_r() 402e1dd0a2fSth160488 * function with an exception that it removes the 'ldap' back-end 403e1dd0a2fSth160488 * (if any) from the host/ipnodes nsswitch's databases and then 404e1dd0a2fSth160488 * looks up using remaining back-ends. 405e1dd0a2fSth160488 */ 406e1dd0a2fSth160488 static 407e1dd0a2fSth160488 struct hostent * 408e1dd0a2fSth160488 _filter_gethostbyaddr_r(const char *addr, int len, int type, 409e1dd0a2fSth160488 struct hostent *result, char *buffer, int buflen, 410e1dd0a2fSth160488 int *h_errnop) 411e1dd0a2fSth160488 { 412e1dd0a2fSth160488 DEFINE_NSS_DB_ROOT(db_root_hosts); 413e1dd0a2fSth160488 DEFINE_NSS_DB_ROOT(db_root_ipnodes); 414e1dd0a2fSth160488 nss_XbyY_args_t arg; 415e1dd0a2fSth160488 nss_status_t res; 416e1dd0a2fSth160488 int (*str2ent)(); 417e1dd0a2fSth160488 void (*nss_initf)(); 418e1dd0a2fSth160488 nss_db_root_t *nss_db_root; 419e1dd0a2fSth160488 int dbop; 420e1dd0a2fSth160488 421e1dd0a2fSth160488 switch (type) { 422e1dd0a2fSth160488 case AF_INET: 423e1dd0a2fSth160488 str2ent = str2hostent; 424e1dd0a2fSth160488 nss_initf = _initf_hosts; 425e1dd0a2fSth160488 nss_db_root = &db_root_hosts; 426e1dd0a2fSth160488 dbop = NSS_DBOP_HOSTS_BYADDR; 427e1dd0a2fSth160488 break; 428e1dd0a2fSth160488 case AF_INET6: 429e1dd0a2fSth160488 str2ent = str2hostent6; 430e1dd0a2fSth160488 nss_initf = _initf_ipnodes; 431e1dd0a2fSth160488 nss_db_root = &db_root_ipnodes; 432e1dd0a2fSth160488 dbop = NSS_DBOP_IPNODES_BYADDR; 433e1dd0a2fSth160488 default: 434e1dd0a2fSth160488 return (NULL); 435e1dd0a2fSth160488 } 436e1dd0a2fSth160488 437e1dd0a2fSth160488 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2ent); 438e1dd0a2fSth160488 439e1dd0a2fSth160488 arg.key.hostaddr.addr = addr; 440e1dd0a2fSth160488 arg.key.hostaddr.len = len; 441e1dd0a2fSth160488 arg.key.hostaddr.type = type; 442e1dd0a2fSth160488 arg.stayopen = 0; 443e1dd0a2fSth160488 arg.h_errno = NETDB_SUCCESS; 444e1dd0a2fSth160488 445e1dd0a2fSth160488 res = nss_search(nss_db_root, nss_initf, dbop, &arg); 446e1dd0a2fSth160488 arg.status = res; 447e1dd0a2fSth160488 *h_errnop = arg.h_errno; 448e1dd0a2fSth160488 return (struct hostent *)NSS_XbyY_FINI(&arg); 449e1dd0a2fSth160488 } 450e1dd0a2fSth160488 451e1dd0a2fSth160488 /* 452e1dd0a2fSth160488 * This routine is an analog of gethostbyaddr_r(). 453e1dd0a2fSth160488 * But in addition __s_api_hostname2ip() performs the "LDAP SKIPDB" activity 454e1dd0a2fSth160488 * prior to querying the name services. 455e1dd0a2fSth160488 * If the buffer is not big enough to accommodate a returning data, 456e1dd0a2fSth160488 * NULL is returned and h_errnop is set to TRY_AGAIN. 457e1dd0a2fSth160488 */ 458e1dd0a2fSth160488 struct hostent * 459e1dd0a2fSth160488 __s_api_hostname2ip(const char *name, 460e1dd0a2fSth160488 struct hostent *result, char *buffer, int buflen, 461e1dd0a2fSth160488 int *h_errnop) 462e1dd0a2fSth160488 { 463e1dd0a2fSth160488 DEFINE_NSS_DB_ROOT(db_root_ipnodes); 464e1dd0a2fSth160488 DEFINE_NSS_DB_ROOT(db_root_hosts); 465e1dd0a2fSth160488 nss_XbyY_args_t arg; 466e1dd0a2fSth160488 nss_status_t res; 467e1dd0a2fSth160488 struct in_addr addr; 468e1dd0a2fSth160488 struct in6_addr addr6; 469e1dd0a2fSth160488 470e1dd0a2fSth160488 if (inet_pton(AF_INET, name, &addr) > 0) { 471e1dd0a2fSth160488 if (buflen < strlen(name) + 1 + 472e1dd0a2fSth160488 sizeof (char *) * 2 + /* The h_aliases member */ 473e1dd0a2fSth160488 sizeof (struct in_addr) + 474e1dd0a2fSth160488 sizeof (struct in_addr *) * 2) { 475e1dd0a2fSth160488 *h_errnop = TRY_AGAIN; 476e1dd0a2fSth160488 return (NULL); 477e1dd0a2fSth160488 } 478e1dd0a2fSth160488 479e1dd0a2fSth160488 result->h_addrtype = AF_INET; 480e1dd0a2fSth160488 result->h_length = sizeof (struct in_addr); 481e1dd0a2fSth160488 (void) strncpy(buffer, name, buflen); 482e1dd0a2fSth160488 483e1dd0a2fSth160488 result->h_addr_list = (char **)ROUND_UP( 484e1dd0a2fSth160488 buffer + strlen(name) + 1, 485e1dd0a2fSth160488 sizeof (char *)); 486e1dd0a2fSth160488 result->h_aliases = (char **)ROUND_UP(result->h_addr_list, 487e1dd0a2fSth160488 sizeof (char *)); 488e1dd0a2fSth160488 result->h_aliases[0] = buffer; 489e1dd0a2fSth160488 result->h_aliases[1] = NULL; 490e1dd0a2fSth160488 bcopy(&addr, 491e1dd0a2fSth160488 buffer + buflen - sizeof (struct in_addr), 492e1dd0a2fSth160488 sizeof (struct in_addr)); 493e1dd0a2fSth160488 result->h_addr_list[0] = buffer + buflen - 494e1dd0a2fSth160488 sizeof (struct in_addr); 495e1dd0a2fSth160488 result->h_addr_list[1] = NULL; 496e1dd0a2fSth160488 result->h_aliases = result->h_addr_list; 497e1dd0a2fSth160488 result->h_name = buffer; 498e1dd0a2fSth160488 499e1dd0a2fSth160488 *h_errnop = NETDB_SUCCESS; 500e1dd0a2fSth160488 return (result); 501e1dd0a2fSth160488 } 502e1dd0a2fSth160488 if (inet_pton(AF_INET6, name, &addr6) > 0) { 503e1dd0a2fSth160488 if (buflen < strlen(name) + 1 + 504e1dd0a2fSth160488 sizeof (char *) * 2 + /* The h_aliases member */ 505e1dd0a2fSth160488 sizeof (struct in6_addr) + 506e1dd0a2fSth160488 sizeof (struct in6_addr *) * 2) { 507e1dd0a2fSth160488 *h_errnop = TRY_AGAIN; 508e1dd0a2fSth160488 return (NULL); 509e1dd0a2fSth160488 } 510e1dd0a2fSth160488 511e1dd0a2fSth160488 result->h_addrtype = AF_INET6; 512e1dd0a2fSth160488 result->h_length = sizeof (struct in6_addr); 513e1dd0a2fSth160488 (void) strncpy(buffer, name, buflen); 514e1dd0a2fSth160488 515e1dd0a2fSth160488 result->h_addr_list = (char **)ROUND_UP( 516e1dd0a2fSth160488 buffer + strlen(name) + 1, 517e1dd0a2fSth160488 sizeof (char *)); 518e1dd0a2fSth160488 result->h_aliases = (char **)ROUND_UP(result->h_addr_list, 519e1dd0a2fSth160488 sizeof (char *)); 520e1dd0a2fSth160488 result->h_aliases[0] = buffer; 521e1dd0a2fSth160488 result->h_aliases[1] = NULL; 522e1dd0a2fSth160488 bcopy(&addr6, 523e1dd0a2fSth160488 buffer + buflen - sizeof (struct in6_addr), 524e1dd0a2fSth160488 sizeof (struct in6_addr)); 525e1dd0a2fSth160488 result->h_addr_list[0] = buffer + buflen - 526e1dd0a2fSth160488 sizeof (struct in6_addr); 527e1dd0a2fSth160488 result->h_addr_list[1] = NULL; 528e1dd0a2fSth160488 result->h_aliases = result->h_addr_list; 529e1dd0a2fSth160488 result->h_name = buffer; 530e1dd0a2fSth160488 531e1dd0a2fSth160488 *h_errnop = NETDB_SUCCESS; 532e1dd0a2fSth160488 return (result); 533e1dd0a2fSth160488 } 534e1dd0a2fSth160488 535e1dd0a2fSth160488 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent); 536e1dd0a2fSth160488 537e1dd0a2fSth160488 arg.key.name = name; 538e1dd0a2fSth160488 arg.stayopen = 0; 539e1dd0a2fSth160488 arg.h_errno = NETDB_SUCCESS; 540e1dd0a2fSth160488 541e1dd0a2fSth160488 res = nss_search(&db_root_ipnodes, _initf_ipnodes, 542e1dd0a2fSth160488 NSS_DBOP_IPNODES_BYNAME, &arg); 543e1dd0a2fSth160488 if (res == NSS_NOTFOUND || res == NSS_UNAVAIL) { 544e1dd0a2fSth160488 arg.h_errno = NETDB_SUCCESS; 545e1dd0a2fSth160488 res = nss_search(&db_root_hosts, _initf_hosts, 546e1dd0a2fSth160488 NSS_DBOP_HOSTS_BYNAME, &arg); 547e1dd0a2fSth160488 } 548e1dd0a2fSth160488 arg.status = res; 549e1dd0a2fSth160488 *h_errnop = arg.h_errno; 550e1dd0a2fSth160488 return ((struct hostent *)NSS_XbyY_FINI(&arg)); 551e1dd0a2fSth160488 } 552e1dd0a2fSth160488 553e1dd0a2fSth160488 /* 554e1dd0a2fSth160488 * Convert an IP to a host name. 555e1dd0a2fSth160488 */ 556e1dd0a2fSth160488 ns_ldap_return_code 557e1dd0a2fSth160488 __s_api_ip2hostname(char *ipaddr, char **hostname) { 558e1dd0a2fSth160488 struct in_addr in; 559e1dd0a2fSth160488 struct in6_addr in6; 560e1dd0a2fSth160488 struct hostent *hp = NULL, hostEnt; 561e1dd0a2fSth160488 char buffer[NSS_BUFLEN_HOSTS]; 562e1dd0a2fSth160488 int buflen = NSS_BUFLEN_HOSTS; 563e1dd0a2fSth160488 char *start = NULL, 564e1dd0a2fSth160488 *end = NULL, 565e1dd0a2fSth160488 delim = '\0'; 566e1dd0a2fSth160488 char *port = NULL, 567e1dd0a2fSth160488 *addr = NULL; 568e1dd0a2fSth160488 int errorNum = 0, 569e1dd0a2fSth160488 len = 0; 570e1dd0a2fSth160488 571e1dd0a2fSth160488 if (ipaddr == NULL || hostname == NULL) 572e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 573e1dd0a2fSth160488 *hostname = NULL; 574e1dd0a2fSth160488 if ((addr = strdup(ipaddr)) == NULL) 575e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 576e1dd0a2fSth160488 577e1dd0a2fSth160488 if (addr[0] == '[') { 578e1dd0a2fSth160488 /* 579e1dd0a2fSth160488 * Assume it's [ipv6]:port 580e1dd0a2fSth160488 * Extract ipv6 IP 581e1dd0a2fSth160488 */ 582e1dd0a2fSth160488 start = &addr[1]; 583e1dd0a2fSth160488 if ((end = strchr(addr, ']')) != NULL) { 584e1dd0a2fSth160488 *end = '\0'; 585e1dd0a2fSth160488 delim = ']'; 586e1dd0a2fSth160488 if (*(end + 1) == ':') 587e1dd0a2fSth160488 /* extract port */ 588e1dd0a2fSth160488 port = end + 2; 589e1dd0a2fSth160488 } else { 590e1dd0a2fSth160488 free(addr); 591e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 592e1dd0a2fSth160488 } 593e1dd0a2fSth160488 } else if ((end = strchr(addr, ':')) != NULL) { 594e1dd0a2fSth160488 /* assume it's ipv4:port */ 595e1dd0a2fSth160488 *end = '\0'; 596e1dd0a2fSth160488 delim = ':'; 597e1dd0a2fSth160488 start = addr; 598e1dd0a2fSth160488 port = end + 1; 599e1dd0a2fSth160488 } else 600e1dd0a2fSth160488 /* No port */ 601e1dd0a2fSth160488 start = addr; 602e1dd0a2fSth160488 603e1dd0a2fSth160488 604e1dd0a2fSth160488 if (inet_pton(AF_INET, start, &in) == 1) { 605e1dd0a2fSth160488 /* IPv4 */ 606e1dd0a2fSth160488 hp = _filter_gethostbyaddr_r((char *)&in, 607e1dd0a2fSth160488 sizeof (in.s_addr), 608e1dd0a2fSth160488 AF_INET, 609e1dd0a2fSth160488 &hostEnt, 610e1dd0a2fSth160488 buffer, 611e1dd0a2fSth160488 buflen, 612e1dd0a2fSth160488 &errorNum); 613e1dd0a2fSth160488 if (hp && hp->h_name) { 614e1dd0a2fSth160488 /* hostname + '\0' */ 615e1dd0a2fSth160488 len = strlen(hp->h_name) + 1; 616e1dd0a2fSth160488 if (port) 617e1dd0a2fSth160488 /* ':' + port */ 618e1dd0a2fSth160488 len += strlen(port) + 1; 619e1dd0a2fSth160488 if ((*hostname = malloc(len)) == NULL) { 620e1dd0a2fSth160488 free(addr); 621e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 622e1dd0a2fSth160488 } 623e1dd0a2fSth160488 624e1dd0a2fSth160488 if (port) 625e1dd0a2fSth160488 (void) snprintf(*hostname, len, "%s:%s", 626e1dd0a2fSth160488 hp->h_name, port); 627e1dd0a2fSth160488 else 628e1dd0a2fSth160488 (void) strlcpy(*hostname, hp->h_name, len); 629e1dd0a2fSth160488 630e1dd0a2fSth160488 free(addr); 631e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 632e1dd0a2fSth160488 } else { 633e1dd0a2fSth160488 free(addr); 634e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 635e1dd0a2fSth160488 } 636e1dd0a2fSth160488 } else if (inet_pton(AF_INET6, start, &in6) == 1) { 637e1dd0a2fSth160488 /* IPv6 */ 638e1dd0a2fSth160488 hp = _filter_gethostbyaddr_r((char *)&in6, 639e1dd0a2fSth160488 sizeof (in6.s6_addr), 640e1dd0a2fSth160488 AF_INET6, 641e1dd0a2fSth160488 &hostEnt, 642e1dd0a2fSth160488 buffer, 643e1dd0a2fSth160488 buflen, 644e1dd0a2fSth160488 &errorNum); 645e1dd0a2fSth160488 if (hp && hp->h_name) { 646e1dd0a2fSth160488 /* hostname + '\0' */ 647e1dd0a2fSth160488 len = strlen(hp->h_name) + 1; 648e1dd0a2fSth160488 if (port) 649e1dd0a2fSth160488 /* ':' + port */ 650e1dd0a2fSth160488 len += strlen(port) + 1; 651e1dd0a2fSth160488 if ((*hostname = malloc(len)) == NULL) { 652e1dd0a2fSth160488 free(addr); 653e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 654e1dd0a2fSth160488 } 655e1dd0a2fSth160488 656e1dd0a2fSth160488 if (port) 657e1dd0a2fSth160488 (void) snprintf(*hostname, len, "%s:%s", 658e1dd0a2fSth160488 hp->h_name, port); 659e1dd0a2fSth160488 else 660e1dd0a2fSth160488 (void) strlcpy(*hostname, hp->h_name, len); 661e1dd0a2fSth160488 662e1dd0a2fSth160488 free(addr); 663e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 664e1dd0a2fSth160488 } else { 665e1dd0a2fSth160488 free(addr); 666e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 667e1dd0a2fSth160488 } 668e1dd0a2fSth160488 } else { 669e1dd0a2fSth160488 /* 670e1dd0a2fSth160488 * A hostname 671e1dd0a2fSth160488 * Return it as is 672e1dd0a2fSth160488 */ 673e1dd0a2fSth160488 if (end) 674e1dd0a2fSth160488 *end = delim; 675e1dd0a2fSth160488 *hostname = addr; 676e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 677e1dd0a2fSth160488 } 678e1dd0a2fSth160488 } 679e1dd0a2fSth160488 680e1dd0a2fSth160488 /* 681e1dd0a2fSth160488 * This function obtains data returned by an LDAP search request and puts it 682e1dd0a2fSth160488 * in a string in the ldap_cachmgr(1) door call format. 683e1dd0a2fSth160488 * 684e1dd0a2fSth160488 * INPUT: 685e1dd0a2fSth160488 * ld - a pointer to an LDAP structure used for a search operation, 686e1dd0a2fSth160488 * result_msg - a pointer to an LDAPMessage returned by the search, 687e1dd0a2fSth160488 * include_names - if set to INCLUDE_ATTR_NAMES, the output buffer will 688e1dd0a2fSth160488 * contain attribute names. 689e1dd0a2fSth160488 * Otherwise, only values will be return. 690e1dd0a2fSth160488 * 691e1dd0a2fSth160488 * OUTPUT: 692e1dd0a2fSth160488 * a buffer containing server info in the following format: 693e1dd0a2fSth160488 * [<attribute name>=]value [DOORLINESEP [<attribute name>=]value ]...] 694e1dd0a2fSth160488 * Should be free'ed by the caller. 695e1dd0a2fSth160488 */ 696e1dd0a2fSth160488 static 697e1dd0a2fSth160488 ns_ldap_return_code 698e1dd0a2fSth160488 convert_to_door_line(LDAP* ld, 699e1dd0a2fSth160488 LDAPMessage *result_msg, 700e1dd0a2fSth160488 int include_names, 701e1dd0a2fSth160488 int is_profile, 702e1dd0a2fSth160488 char **door_line) 703e1dd0a2fSth160488 { 704e1dd0a2fSth160488 uint32_t total_length = 0, attr_len = 0, i; 705e1dd0a2fSth160488 LDAPMessage *e; 706e1dd0a2fSth160488 char *a, **vals; 707e1dd0a2fSth160488 BerElement *ber; 708e1dd0a2fSth160488 int seen_objectclass = 0, rewind = 0; 709e1dd0a2fSth160488 710e1dd0a2fSth160488 if (!door_line) { 711e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 712e1dd0a2fSth160488 } 713e1dd0a2fSth160488 *door_line = NULL; 714e1dd0a2fSth160488 715e1dd0a2fSth160488 if ((e = ldap_first_entry(ld, result_msg)) == NULL) { 716e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 717e1dd0a2fSth160488 } 718e1dd0a2fSth160488 719e1dd0a2fSth160488 /* calculate length of received data */ 720e1dd0a2fSth160488 for (a = ldap_first_attribute(ld, e, &ber); 721e1dd0a2fSth160488 a != NULL; 722e1dd0a2fSth160488 a = ldap_next_attribute(ld, e, ber)) { 723e1dd0a2fSth160488 724e1dd0a2fSth160488 if ((vals = ldap_get_values(ld, e, a)) != NULL) { 725e1dd0a2fSth160488 for (i = 0; vals[i] != NULL; i++) { 726e1dd0a2fSth160488 total_length += (include_names ? 727e1dd0a2fSth160488 strlen(a) : 0) + 728e1dd0a2fSth160488 strlen(vals[i]) + 729e1dd0a2fSth160488 strlen(DOORLINESEP) +1; 730e1dd0a2fSth160488 } 731e1dd0a2fSth160488 ldap_value_free(vals); 732e1dd0a2fSth160488 } 733e1dd0a2fSth160488 ldap_memfree(a); 734e1dd0a2fSth160488 } 735e1dd0a2fSth160488 if (ber != NULL) { 736e1dd0a2fSth160488 ber_free(ber, 0); 737e1dd0a2fSth160488 } 738e1dd0a2fSth160488 739e1dd0a2fSth160488 if (total_length == 0) { 740e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 741e1dd0a2fSth160488 } 742e1dd0a2fSth160488 743e1dd0a2fSth160488 /* copy the data */ 744e1dd0a2fSth160488 /* add 1 for the last '\0' */ 745e1dd0a2fSth160488 *door_line = (char *)malloc(total_length + 1); 746e1dd0a2fSth160488 if (*door_line == NULL) { 747e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 748e1dd0a2fSth160488 } 749e1dd0a2fSth160488 750e1dd0a2fSth160488 /* make it an empty string first */ 751e1dd0a2fSth160488 **door_line = '\0'; 752e1dd0a2fSth160488 a = ldap_first_attribute(ld, e, &ber); 753e1dd0a2fSth160488 while (a != NULL) { 754e1dd0a2fSth160488 if (is_profile) { 755e1dd0a2fSth160488 /* 756e1dd0a2fSth160488 * If we're processing DUAConfigProfile, we need to make 757e1dd0a2fSth160488 * sure we put objectclass attribute first. 758e1dd0a2fSth160488 * __s_api_create_config_door_str depends on that. 759e1dd0a2fSth160488 */ 760e1dd0a2fSth160488 if (seen_objectclass) { 761e1dd0a2fSth160488 if (strcasecmp(a, "objectclass") == 0) { 762e1dd0a2fSth160488 /* Skip objectclass now. */ 763e1dd0a2fSth160488 a = ldap_next_attribute(ld, e, ber); 764e1dd0a2fSth160488 continue; 765e1dd0a2fSth160488 } 766e1dd0a2fSth160488 } else { 767e1dd0a2fSth160488 if (strcasecmp(a, "objectclass") == 0) { 768e1dd0a2fSth160488 seen_objectclass = 1; 769e1dd0a2fSth160488 rewind = 1; 770e1dd0a2fSth160488 } else { 771e1dd0a2fSth160488 /* Skip all but objectclass first. */ 772e1dd0a2fSth160488 a = ldap_next_attribute(ld, e, ber); 773e1dd0a2fSth160488 continue; 774e1dd0a2fSth160488 } 775e1dd0a2fSth160488 } 776e1dd0a2fSth160488 } 777e1dd0a2fSth160488 778e1dd0a2fSth160488 if ((vals = ldap_get_values(ld, e, a)) != NULL) { 779e1dd0a2fSth160488 for (i = 0; vals[i] != NULL; i++) { 780e1dd0a2fSth160488 if (include_names) { 781e1dd0a2fSth160488 attr_len += strlen(a); 782e1dd0a2fSth160488 } 783e1dd0a2fSth160488 attr_len += strlen(vals[i]) + 784e1dd0a2fSth160488 strlen(DOORLINESEP) + 2; 785e1dd0a2fSth160488 if (include_names) { 786e1dd0a2fSth160488 (void) snprintf(*door_line + 787e1dd0a2fSth160488 strlen(*door_line), 788e1dd0a2fSth160488 attr_len, 789e1dd0a2fSth160488 "%s=%s%s", 790e1dd0a2fSth160488 a, vals[i], 791e1dd0a2fSth160488 DOORLINESEP); 792e1dd0a2fSth160488 } else { 793e1dd0a2fSth160488 (void) snprintf(*door_line + 794e1dd0a2fSth160488 strlen(*door_line), 795e1dd0a2fSth160488 attr_len, 796e1dd0a2fSth160488 "%s%s", 797e1dd0a2fSth160488 vals[i], 798e1dd0a2fSth160488 DOORLINESEP); 799e1dd0a2fSth160488 } 800e1dd0a2fSth160488 } 801e1dd0a2fSth160488 ldap_value_free(vals); 802e1dd0a2fSth160488 } 803e1dd0a2fSth160488 ldap_memfree(a); 804e1dd0a2fSth160488 805e1dd0a2fSth160488 /* Rewind */ 806e1dd0a2fSth160488 if (rewind) { 807e1dd0a2fSth160488 if (ber != NULL) { 808e1dd0a2fSth160488 ber_free(ber, 0); 809e1dd0a2fSth160488 } 810e1dd0a2fSth160488 a = ldap_first_attribute(ld, e, &ber); 811e1dd0a2fSth160488 rewind = 0; 812e1dd0a2fSth160488 } else { 813e1dd0a2fSth160488 a = ldap_next_attribute(ld, e, ber); 814e1dd0a2fSth160488 } 815e1dd0a2fSth160488 } 816e1dd0a2fSth160488 if (ber != NULL) { 817e1dd0a2fSth160488 ber_free(ber, 0); 818e1dd0a2fSth160488 } 819e1dd0a2fSth160488 820e1dd0a2fSth160488 if (e != result_msg) { 821e1dd0a2fSth160488 (void) ldap_msgfree(e); 822e1dd0a2fSth160488 } 823e1dd0a2fSth160488 824e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 825e1dd0a2fSth160488 } 826e1dd0a2fSth160488 827e1dd0a2fSth160488 /* 828e1dd0a2fSth160488 * This function looks up the base DN of a directory serving 829e1dd0a2fSth160488 * a specified domain name. 830e1dd0a2fSth160488 * 831e1dd0a2fSth160488 * INPUT: 832e1dd0a2fSth160488 * ld - a pointer to an LDAP structure used for the search operation, 833e1dd0a2fSth160488 * domain_name - the name of a domain. 834e1dd0a2fSth160488 * 835e1dd0a2fSth160488 * OUTPUT: 836e1dd0a2fSth160488 * a buffer containing a directory's base DN found. 837e1dd0a2fSth160488 * Should be free'ed by the caller. 838e1dd0a2fSth160488 */ 839e1dd0a2fSth160488 static 840e1dd0a2fSth160488 ns_ldap_return_code 841e1dd0a2fSth160488 getDirBaseDN(LDAP *ld, const char *domain_name, char **dir_base_dn) 842e1dd0a2fSth160488 { 843e1dd0a2fSth160488 struct timeval tv = {NS_DEFAULT_SEARCH_TIMEOUT, 0}; 844e1dd0a2fSth160488 char *attrs[2], *DNlist, *rest, *ptr; 845e1dd0a2fSth160488 char filter[BUFSIZ], *a = NULL; 846e1dd0a2fSth160488 int ldap_rc; 847e1dd0a2fSth160488 LDAPMessage *resultMsg = NULL; 848e1dd0a2fSth160488 ns_ldap_return_code ret_code; 849e1dd0a2fSth160488 850e1dd0a2fSth160488 /* Get the whole list of naming contexts residing on the server */ 851e1dd0a2fSth160488 attrs[0] = "namingcontexts"; 852e1dd0a2fSth160488 attrs[1] = NULL; 853e1dd0a2fSth160488 ldap_rc = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE, "(objectclass=*)", 854e1dd0a2fSth160488 attrs, 0, NULL, NULL, &tv, 0, &resultMsg); 855e1dd0a2fSth160488 switch (ldap_rc) { 856e1dd0a2fSth160488 /* If successful, the root DSE was found. */ 857e1dd0a2fSth160488 case LDAP_SUCCESS: 858e1dd0a2fSth160488 break; 859e1dd0a2fSth160488 /* 860e1dd0a2fSth160488 * If the root DSE was not found, the server does 861e1dd0a2fSth160488 * not comply with the LDAP v3 protocol. 862e1dd0a2fSth160488 */ 863e1dd0a2fSth160488 default: 864e1dd0a2fSth160488 if (resultMsg) { 865e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 866e1dd0a2fSth160488 resultMsg = NULL; 867e1dd0a2fSth160488 } 868e1dd0a2fSth160488 869e1dd0a2fSth160488 return (NS_LDAP_OP_FAILED); 870e1dd0a2fSth160488 } 871e1dd0a2fSth160488 872e1dd0a2fSth160488 if ((ret_code = convert_to_door_line(ld, 873e1dd0a2fSth160488 resultMsg, 874e1dd0a2fSth160488 DONT_INCLUDE_ATTR_NAMES, 875e1dd0a2fSth160488 NOT_PROFILE, 876e1dd0a2fSth160488 &DNlist)) != NS_LDAP_SUCCESS) { 877e1dd0a2fSth160488 if (resultMsg) { 878e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 879e1dd0a2fSth160488 resultMsg = NULL; 880e1dd0a2fSth160488 } 881e1dd0a2fSth160488 return (ret_code); 882e1dd0a2fSth160488 } 883e1dd0a2fSth160488 884e1dd0a2fSth160488 if (resultMsg) { 885e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 886e1dd0a2fSth160488 resultMsg = NULL; 887e1dd0a2fSth160488 } 888e1dd0a2fSth160488 889e1dd0a2fSth160488 if (DNlist == NULL || 890e1dd0a2fSth160488 (ptr = strtok_r(DNlist, DOORLINESEP, &rest)) == NULL) { 891e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 892e1dd0a2fSth160488 } 893e1dd0a2fSth160488 attrs[0] = "dn"; 894e1dd0a2fSth160488 do { 895e1dd0a2fSth160488 /* 896e1dd0a2fSth160488 * For each context try to find a NIS domain object 897e1dd0a2fSth160488 * which 'nisdomain' attribute's value matches the domain name 898e1dd0a2fSth160488 */ 899e1dd0a2fSth160488 (void) snprintf(filter, 900e1dd0a2fSth160488 BUFSIZ, 901e1dd0a2fSth160488 "(&(objectclass=nisDomainObject)" 902e1dd0a2fSth160488 "(nisdomain=%s))", 903e1dd0a2fSth160488 domain_name); 904e1dd0a2fSth160488 ldap_rc = ldap_search_ext_s(ld, 905e1dd0a2fSth160488 ptr, 906e1dd0a2fSth160488 LDAP_SCOPE_SUBTREE, 907e1dd0a2fSth160488 filter, 908e1dd0a2fSth160488 attrs, 909e1dd0a2fSth160488 0, 910e1dd0a2fSth160488 NULL, 911e1dd0a2fSth160488 NULL, 912e1dd0a2fSth160488 &tv, 913e1dd0a2fSth160488 0, 914e1dd0a2fSth160488 &resultMsg); 915e1dd0a2fSth160488 if (ldap_rc != LDAP_SUCCESS) { 916e1dd0a2fSth160488 if (resultMsg) { 917e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 918e1dd0a2fSth160488 resultMsg = NULL; 919e1dd0a2fSth160488 } 920e1dd0a2fSth160488 continue; 921e1dd0a2fSth160488 } 922e1dd0a2fSth160488 if ((a = ldap_get_dn(ld, resultMsg)) != NULL) { 923e1dd0a2fSth160488 *dir_base_dn = strdup(a); 924e1dd0a2fSth160488 ldap_memfree(a); 925e1dd0a2fSth160488 926e1dd0a2fSth160488 if (resultMsg) { 927e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 928e1dd0a2fSth160488 resultMsg = NULL; 929e1dd0a2fSth160488 } 930e1dd0a2fSth160488 931e1dd0a2fSth160488 if (!*dir_base_dn) { 932e1dd0a2fSth160488 free(DNlist); 933e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 934e1dd0a2fSth160488 } 935e1dd0a2fSth160488 break; 936e1dd0a2fSth160488 } 937e1dd0a2fSth160488 938e1dd0a2fSth160488 if (resultMsg) { 939e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 940e1dd0a2fSth160488 resultMsg = NULL; 941e1dd0a2fSth160488 } 942e1dd0a2fSth160488 } while (ptr = strtok_r(NULL, DOORLINESEP, &rest)); 943e1dd0a2fSth160488 944e1dd0a2fSth160488 free(DNlist); 945e1dd0a2fSth160488 946e1dd0a2fSth160488 if (!*dir_base_dn) { 947e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 948e1dd0a2fSth160488 } 949e1dd0a2fSth160488 950e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 951e1dd0a2fSth160488 } 952e1dd0a2fSth160488 953e1dd0a2fSth160488 /* 954e1dd0a2fSth160488 * This function parses the results of a search operation 955e1dd0a2fSth160488 * requesting a DUAProfile. 956e1dd0a2fSth160488 * 957e1dd0a2fSth160488 * INPUT: 958e1dd0a2fSth160488 * ld - a pointer to an LDAP structure used for the search operation, 959e1dd0a2fSth160488 * dir_base_dn - the name of a directory's base DN, 960e1dd0a2fSth160488 * profile_name - the name of a DUAProfile to be obtained. 961e1dd0a2fSth160488 * 962e1dd0a2fSth160488 * OUTPUT: 963e1dd0a2fSth160488 * a buffer containing the DUAProfile in the following format: 964e1dd0a2fSth160488 * [<attribute name>=]value [DOORLINESEP [<attribute name>=]value ]...] 965e1dd0a2fSth160488 * Should be free'ed by the caller. 966e1dd0a2fSth160488 */ 967e1dd0a2fSth160488 static 968e1dd0a2fSth160488 ns_ldap_return_code 969e1dd0a2fSth160488 getDUAProfile(LDAP *ld, 970e1dd0a2fSth160488 const char *dir_base_dn, 971e1dd0a2fSth160488 const char *profile_name, 972e1dd0a2fSth160488 char **profile) 973e1dd0a2fSth160488 { 974e1dd0a2fSth160488 char searchBaseDN[BUFSIZ], filter[BUFSIZ]; 975e1dd0a2fSth160488 LDAPMessage *resultMsg = NULL; 976e1dd0a2fSth160488 struct timeval tv = {NS_DEFAULT_SEARCH_TIMEOUT, 0}; 977e1dd0a2fSth160488 int ldap_rc; 978e1dd0a2fSth160488 ns_ldap_return_code ret_code; 979e1dd0a2fSth160488 980e1dd0a2fSth160488 (void) snprintf(searchBaseDN, BUFSIZ, "ou=profile,%s", dir_base_dn); 981e1dd0a2fSth160488 (void) snprintf(filter, 982e1dd0a2fSth160488 BUFSIZ, 983e1dd0a2fSth160488 _PROFILE_FILTER, 984e1dd0a2fSth160488 _PROFILE1_OBJECTCLASS, 985e1dd0a2fSth160488 _PROFILE2_OBJECTCLASS, 986e1dd0a2fSth160488 profile_name); 987e1dd0a2fSth160488 ldap_rc = ldap_search_ext_s(ld, 988e1dd0a2fSth160488 searchBaseDN, 989e1dd0a2fSth160488 LDAP_SCOPE_SUBTREE, 990e1dd0a2fSth160488 filter, 991e1dd0a2fSth160488 NULL, 992e1dd0a2fSth160488 0, 993e1dd0a2fSth160488 NULL, 994e1dd0a2fSth160488 NULL, 995e1dd0a2fSth160488 &tv, 996e1dd0a2fSth160488 0, 997e1dd0a2fSth160488 &resultMsg); 998e1dd0a2fSth160488 999e1dd0a2fSth160488 switch (ldap_rc) { 1000e1dd0a2fSth160488 /* If successful, the DUA profile was found. */ 1001e1dd0a2fSth160488 case LDAP_SUCCESS: 1002e1dd0a2fSth160488 break; 1003e1dd0a2fSth160488 /* 1004e1dd0a2fSth160488 * If the root DSE was not found, the server does 1005e1dd0a2fSth160488 * not comply with the LDAP v3 protocol. 1006e1dd0a2fSth160488 */ 1007e1dd0a2fSth160488 default: 1008e1dd0a2fSth160488 if (resultMsg) { 1009e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 1010e1dd0a2fSth160488 resultMsg = NULL; 1011e1dd0a2fSth160488 } 1012e1dd0a2fSth160488 1013e1dd0a2fSth160488 return (NS_LDAP_OP_FAILED); 1014e1dd0a2fSth160488 } 1015e1dd0a2fSth160488 1016e1dd0a2fSth160488 ret_code = convert_to_door_line(ld, 1017e1dd0a2fSth160488 resultMsg, 1018e1dd0a2fSth160488 INCLUDE_ATTR_NAMES, 1019e1dd0a2fSth160488 IS_PROFILE, 1020e1dd0a2fSth160488 profile); 1021e1dd0a2fSth160488 if (resultMsg) { 1022e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 1023e1dd0a2fSth160488 resultMsg = NULL; 1024e1dd0a2fSth160488 } 1025e1dd0a2fSth160488 return (ret_code); 1026e1dd0a2fSth160488 } 1027e1dd0a2fSth160488 1028e1dd0a2fSth160488 /* 1029e1dd0a2fSth160488 * This function derives the directory's base DN from a provided domain name. 1030e1dd0a2fSth160488 * 1031e1dd0a2fSth160488 * INPUT: 1032e1dd0a2fSth160488 * domain_name - the name of a domain to be converted into a base DN, 1033e1dd0a2fSth160488 * buffer - contains the derived base DN, 1034e1dd0a2fSth160488 * buf_len - the length of the buffer. 1035e1dd0a2fSth160488 * 1036e1dd0a2fSth160488 * OUTPUT: 1037e1dd0a2fSth160488 * The function returns the address of the buffer or NULL. 1038e1dd0a2fSth160488 */ 1039e1dd0a2fSth160488 static 1040e1dd0a2fSth160488 char * 1041e1dd0a2fSth160488 domainname2baseDN(char *domain_name, char *buffer, uint16_t buf_len) 1042e1dd0a2fSth160488 { 1043e1dd0a2fSth160488 char *nextDC, *chr; 1044e1dd0a2fSth160488 uint16_t i, length; 1045e1dd0a2fSth160488 1046e1dd0a2fSth160488 if (!domain_name || !buffer || buf_len == 0) { 1047e1dd0a2fSth160488 return (NULL); 1048e1dd0a2fSth160488 } 1049e1dd0a2fSth160488 1050e1dd0a2fSth160488 buffer[0] = '\0'; 1051e1dd0a2fSth160488 nextDC = chr = domain_name; 1052e1dd0a2fSth160488 length = strlen(domain_name); 1053e1dd0a2fSth160488 for (i = 0; i < length + 1; ++i, ++chr) { 1054e1dd0a2fSth160488 /* Simply replace dots with "dc=" */ 1055e1dd0a2fSth160488 if (*chr != '.' && *chr != '\0') { 1056e1dd0a2fSth160488 continue; 1057e1dd0a2fSth160488 } 1058e1dd0a2fSth160488 *chr = '\0'; 1059e1dd0a2fSth160488 if (strlcat(buffer, "dc=", buf_len) >= buf_len) 1060e1dd0a2fSth160488 return (NULL); 1061e1dd0a2fSth160488 if (strlcat(buffer, nextDC, buf_len) >= buf_len) 1062e1dd0a2fSth160488 return (NULL); 1063e1dd0a2fSth160488 if (i < length) { 1064e1dd0a2fSth160488 /* 1065e1dd0a2fSth160488 * The end of the domain name 1066e1dd0a2fSth160488 * has not been reached yet 1067e1dd0a2fSth160488 */ 1068e1dd0a2fSth160488 if (strlcat(buffer, ",", buf_len) >= buf_len) 1069e1dd0a2fSth160488 return (NULL); 1070e1dd0a2fSth160488 nextDC = chr + 1; 1071e1dd0a2fSth160488 *chr = '.'; 1072e1dd0a2fSth160488 } 1073e1dd0a2fSth160488 } 1074e1dd0a2fSth160488 1075e1dd0a2fSth160488 return (buffer); 1076e1dd0a2fSth160488 } 1077e1dd0a2fSth160488 1078e1dd0a2fSth160488 /* 1079e1dd0a2fSth160488 * This function obtains the directory's base DN and a DUAProfile 1080e1dd0a2fSth160488 * from a specified server. 1081e1dd0a2fSth160488 * 1082e1dd0a2fSth160488 * INPUT: 1083e1dd0a2fSth160488 * server - a structure describing a server to connect to and 1084e1dd0a2fSth160488 * a DUAProfile to be obtained from the server, 1085e1dd0a2fSth160488 * cred - credentials to be used during establishing connections to 1086e1dd0a2fSth160488 * the server. 1087e1dd0a2fSth160488 * 1088e1dd0a2fSth160488 * OUTPUT: 1089e1dd0a2fSth160488 * dua_profile - a buffer containing the DUAProfile in the following format: 1090e1dd0a2fSth160488 * [<attribute name>=]value [DOORLINESEP [<attribute name>=]value ]...] 1091e1dd0a2fSth160488 * dir_base_dn - a buffer containing the base DN, 1092e1dd0a2fSth160488 * errorp - an error object describing an error, if any. 1093e1dd0a2fSth160488 * 1094e1dd0a2fSth160488 * All the output data structures should be free'ed by the caller. 1095e1dd0a2fSth160488 */ 1096e1dd0a2fSth160488 ns_ldap_return_code 1097e1dd0a2fSth160488 __ns_ldap_getConnectionInfoFromDUA(const ns_dir_server_t *server, 1098e1dd0a2fSth160488 const ns_cred_t *cred, 1099e1dd0a2fSth160488 char **dua_profile, 1100e1dd0a2fSth160488 char **dir_base_dn, 1101e1dd0a2fSth160488 ns_ldap_error_t **errorp) 1102e1dd0a2fSth160488 { 1103e1dd0a2fSth160488 char serverAddr[MAX_HOSTADDR_LEN]; 1104e1dd0a2fSth160488 char *dirBaseDN = NULL, *duaProfile = NULL; 1105e1dd0a2fSth160488 ns_cred_t default_cred; 1106e1dd0a2fSth160488 ns_ldap_return_code ret_code; 1107e1dd0a2fSth160488 1108e1dd0a2fSth160488 ns_config_t *config_struct = __s_api_create_config(); 1109e1dd0a2fSth160488 ConnectionID sessionId = 0; 1110e1dd0a2fSth160488 Connection *session = NULL; 1111e1dd0a2fSth160488 char errmsg[MAXERROR]; 1112e1dd0a2fSth160488 char buffer[NSS_BUFLEN_HOSTS]; 111329836b19Smichen ns_conn_user_t *cu = NULL; 1114e1dd0a2fSth160488 1115e1dd0a2fSth160488 if (errorp == NULL) { 1116e1dd0a2fSth160488 __s_api_destroy_config(config_struct); 1117e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1118e1dd0a2fSth160488 } 1119e1dd0a2fSth160488 1120e1dd0a2fSth160488 *errorp = NULL; 1121e1dd0a2fSth160488 1122e1dd0a2fSth160488 if (server == NULL) { 1123e1dd0a2fSth160488 __s_api_destroy_config(config_struct); 1124e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1125e1dd0a2fSth160488 } 1126e1dd0a2fSth160488 1127e1dd0a2fSth160488 if (config_struct == NULL) { 1128e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 1129e1dd0a2fSth160488 } 1130e1dd0a2fSth160488 1131e1dd0a2fSth160488 /* 1132e1dd0a2fSth160488 * If no credentials are specified, try to establish a connection 1133e1dd0a2fSth160488 * as anonymous. 1134e1dd0a2fSth160488 */ 1135e1dd0a2fSth160488 if (!cred) { 1136e1dd0a2fSth160488 default_cred.cred.unix_cred.passwd = NULL; 1137e1dd0a2fSth160488 default_cred.cred.unix_cred.userID = NULL; 1138e1dd0a2fSth160488 default_cred.auth.type = NS_LDAP_AUTH_NONE; 1139e1dd0a2fSth160488 } 1140e1dd0a2fSth160488 1141e1dd0a2fSth160488 /* Now create a default LDAP configuration */ 1142e1dd0a2fSth160488 1143e1dd0a2fSth160488 (void) strncpy(buffer, server->server, sizeof (buffer)); 1144e1dd0a2fSth160488 if (__ns_ldap_setParamValue(config_struct, NS_LDAP_SERVERS_P, buffer, 1145e1dd0a2fSth160488 errorp) != NS_LDAP_SUCCESS) { 1146e1dd0a2fSth160488 __s_api_destroy_config(config_struct); 1147e1dd0a2fSth160488 return (NS_LDAP_CONFIG); 1148e1dd0a2fSth160488 } 1149e1dd0a2fSth160488 1150e1dd0a2fSth160488 /* Put together the address and the port specified by the user app. */ 1151e1dd0a2fSth160488 if (server->port > 0) { 1152e1dd0a2fSth160488 (void) snprintf(serverAddr, 1153e1dd0a2fSth160488 sizeof (serverAddr), 1154e1dd0a2fSth160488 "%s:%hu", 1155e1dd0a2fSth160488 buffer, 1156e1dd0a2fSth160488 server->port); 1157e1dd0a2fSth160488 } else { 1158e1dd0a2fSth160488 (void) strncpy(serverAddr, buffer, sizeof (serverAddr)); 1159e1dd0a2fSth160488 } 1160e1dd0a2fSth160488 1161e1dd0a2fSth160488 /* 1162e1dd0a2fSth160488 * There is no default value for the 'Default Search Base DN' attribute. 1163e1dd0a2fSth160488 * Derive one from the domain name to make __s_api_crosscheck() happy. 1164e1dd0a2fSth160488 */ 1165e1dd0a2fSth160488 if (domainname2baseDN(server->domainName ? 1166e1dd0a2fSth160488 server->domainName : config_struct->domainName, 1167e1dd0a2fSth160488 buffer, NSS_BUFLEN_HOSTS) == NULL) { 1168e1dd0a2fSth160488 (void) snprintf(errmsg, 1169e1dd0a2fSth160488 sizeof (errmsg), 1170e1dd0a2fSth160488 gettext("Can not convert %s into a base DN name"), 1171e1dd0a2fSth160488 server->domainName ? 1172e1dd0a2fSth160488 server->domainName : config_struct->domainName); 1173e1dd0a2fSth160488 MKERROR(LOG_ERR, 1174e1dd0a2fSth160488 *errorp, 1175e1dd0a2fSth160488 NS_LDAP_INTERNAL, 1176e1dd0a2fSth160488 strdup(errmsg), 1177e1dd0a2fSth160488 NS_LDAP_MEMORY); 1178e1dd0a2fSth160488 __s_api_destroy_config(config_struct); 1179e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 1180e1dd0a2fSth160488 } 1181e1dd0a2fSth160488 if (__ns_ldap_setParamValue(config_struct, NS_LDAP_SEARCH_BASEDN_P, 1182e1dd0a2fSth160488 buffer, errorp) != NS_LDAP_SUCCESS) { 1183e1dd0a2fSth160488 __s_api_destroy_config(config_struct); 1184e1dd0a2fSth160488 return (NS_LDAP_CONFIG); 1185e1dd0a2fSth160488 } 1186e1dd0a2fSth160488 1187e1dd0a2fSth160488 if (__s_api_crosscheck(config_struct, errmsg, B_FALSE) != NS_SUCCESS) { 1188e1dd0a2fSth160488 __s_api_destroy_config(config_struct); 1189e1dd0a2fSth160488 return (NS_LDAP_CONFIG); 1190e1dd0a2fSth160488 } 1191e1dd0a2fSth160488 1192e1dd0a2fSth160488 __s_api_init_config(config_struct); 1193e1dd0a2fSth160488 1194e1dd0a2fSth160488 __s_api_setInitMode(); 1195e1dd0a2fSth160488 119629836b19Smichen cu = __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, B_FALSE); 119729836b19Smichen if (cu == NULL) { 119829836b19Smichen return (NS_LDAP_INTERNAL); 119929836b19Smichen } 120029836b19Smichen 1201e1dd0a2fSth160488 if ((ret_code = __s_api_getConnection(serverAddr, 1202e1dd0a2fSth160488 NS_LDAP_NEW_CONN, 1203e1dd0a2fSth160488 cred ? cred : &default_cred, 1204e1dd0a2fSth160488 &sessionId, 1205e1dd0a2fSth160488 &session, 1206e1dd0a2fSth160488 errorp, 1207e1dd0a2fSth160488 0, 1208e1dd0a2fSth160488 0, 120929836b19Smichen cu)) != NS_LDAP_SUCCESS) { 121029836b19Smichen __s_api_conn_user_free(cu); 1211e1dd0a2fSth160488 __s_api_unsetInitMode(); 1212e1dd0a2fSth160488 return (ret_code); 1213e1dd0a2fSth160488 } 1214e1dd0a2fSth160488 1215e1dd0a2fSth160488 __s_api_unsetInitMode(); 1216e1dd0a2fSth160488 1217e1dd0a2fSth160488 if ((ret_code = getDirBaseDN(session->ld, 1218e1dd0a2fSth160488 server->domainName ? 1219e1dd0a2fSth160488 server->domainName : 1220e1dd0a2fSth160488 config_struct->domainName, 1221e1dd0a2fSth160488 &dirBaseDN)) != NS_LDAP_SUCCESS) { 1222e1dd0a2fSth160488 (void) snprintf(errmsg, 1223e1dd0a2fSth160488 sizeof (errmsg), 1224e1dd0a2fSth160488 gettext("Can not find the " 1225e1dd0a2fSth160488 "nisDomainObject for domain %s\n"), 1226e1dd0a2fSth160488 server->domainName ? 1227e1dd0a2fSth160488 server->domainName : config_struct->domainName); 1228e1dd0a2fSth160488 MKERROR(LOG_ERR, 1229e1dd0a2fSth160488 *errorp, 1230e1dd0a2fSth160488 ret_code, 1231e1dd0a2fSth160488 strdup(errmsg), 1232e1dd0a2fSth160488 NS_LDAP_MEMORY); 123329836b19Smichen __s_api_conn_user_free(cu); 1234e1dd0a2fSth160488 DropConnection(sessionId, NS_LDAP_NEW_CONN); 1235e1dd0a2fSth160488 return (ret_code); 1236e1dd0a2fSth160488 } 1237e1dd0a2fSth160488 1238e1dd0a2fSth160488 /* 1239e1dd0a2fSth160488 * And here obtain a DUAProfile which will be used 1240e1dd0a2fSth160488 * as a real configuration. 1241e1dd0a2fSth160488 */ 1242e1dd0a2fSth160488 if ((ret_code = getDUAProfile(session->ld, 1243e1dd0a2fSth160488 dirBaseDN, 1244e1dd0a2fSth160488 server->profileName ? 1245e1dd0a2fSth160488 server->profileName : "default", 1246e1dd0a2fSth160488 &duaProfile)) != NS_LDAP_SUCCESS) { 1247e1dd0a2fSth160488 (void) snprintf(errmsg, 1248e1dd0a2fSth160488 sizeof (errmsg), 1249e1dd0a2fSth160488 gettext("Can not find the " 1250e1dd0a2fSth160488 "%s DUAProfile\n"), 1251e1dd0a2fSth160488 server->profileName ? 1252e1dd0a2fSth160488 server->profileName : "default"); 1253e1dd0a2fSth160488 MKERROR(LOG_ERR, 1254e1dd0a2fSth160488 *errorp, 1255e1dd0a2fSth160488 ret_code, 1256e1dd0a2fSth160488 strdup(errmsg), 1257e1dd0a2fSth160488 NS_LDAP_MEMORY); 125829836b19Smichen __s_api_conn_user_free(cu); 1259e1dd0a2fSth160488 DropConnection(sessionId, NS_LDAP_NEW_CONN); 1260e1dd0a2fSth160488 return (ret_code); 1261e1dd0a2fSth160488 } 1262e1dd0a2fSth160488 1263e1dd0a2fSth160488 if (dir_base_dn) { 1264e1dd0a2fSth160488 *dir_base_dn = dirBaseDN; 1265e1dd0a2fSth160488 } else { 1266e1dd0a2fSth160488 free(dirBaseDN); 1267e1dd0a2fSth160488 } 1268e1dd0a2fSth160488 1269e1dd0a2fSth160488 if (dua_profile) { 1270e1dd0a2fSth160488 *dua_profile = duaProfile; 1271e1dd0a2fSth160488 } else { 1272e1dd0a2fSth160488 free(duaProfile); 1273e1dd0a2fSth160488 } 1274e1dd0a2fSth160488 127529836b19Smichen __s_api_conn_user_free(cu); 1276e1dd0a2fSth160488 DropConnection(sessionId, NS_LDAP_NEW_CONN); 1277e1dd0a2fSth160488 1278e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 1279e1dd0a2fSth160488 } 1280e1dd0a2fSth160488 1281e1dd0a2fSth160488 /* 1282e1dd0a2fSth160488 * This function obtains the root DSE from a specified server. 1283e1dd0a2fSth160488 * 1284e1dd0a2fSth160488 * INPUT: 1285e1dd0a2fSth160488 * server_addr - an adress of a server to be connected to. 1286e1dd0a2fSth160488 * 1287e1dd0a2fSth160488 * OUTPUT: 1288e1dd0a2fSth160488 * root_dse - a buffer containing the root DSE in the following format: 1289e1dd0a2fSth160488 * [<attribute name>=]value [DOORLINESEP [<attribute name>=]value ]...] 1290e1dd0a2fSth160488 * For example: ( here | used as DOORLINESEP for visual purposes) 1291e1dd0a2fSth160488 * supportedControl=1.1.1.1|supportedSASLmechanisms=EXTERNAL 1292e1dd0a2fSth160488 * Should be free'ed by the caller. 1293e1dd0a2fSth160488 */ 1294e1dd0a2fSth160488 ns_ldap_return_code 1295e1dd0a2fSth160488 __ns_ldap_getRootDSE(const char *server_addr, 1296e1dd0a2fSth160488 char **root_dse, 1297e1dd0a2fSth160488 ns_ldap_error_t **errorp, 1298e1dd0a2fSth160488 int anon_fallback) 1299e1dd0a2fSth160488 { 1300e1dd0a2fSth160488 char errmsg[MAXERROR]; 1301e1dd0a2fSth160488 ns_ldap_return_code ret_code; 1302e1dd0a2fSth160488 1303e1dd0a2fSth160488 ConnectionID sessionId = 0; 1304e1dd0a2fSth160488 Connection *session = NULL; 1305e1dd0a2fSth160488 1306e1dd0a2fSth160488 struct timeval tv = {NS_DEFAULT_SEARCH_TIMEOUT, 0}; 1307e1dd0a2fSth160488 char *attrs[3]; 1308e1dd0a2fSth160488 int ldap_rc, ldaperrno = 0; 1309e1dd0a2fSth160488 LDAPMessage *resultMsg = NULL; 1310e1dd0a2fSth160488 void **paramVal = NULL; 1311e1dd0a2fSth160488 1312e1dd0a2fSth160488 ns_cred_t anon; 131329836b19Smichen ns_conn_user_t *cu = NULL; 1314e1dd0a2fSth160488 1315e1dd0a2fSth160488 if (errorp == NULL) { 1316e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1317e1dd0a2fSth160488 } 1318e1dd0a2fSth160488 1319e1dd0a2fSth160488 *errorp = NULL; 1320e1dd0a2fSth160488 1321e1dd0a2fSth160488 if (!root_dse) { 1322e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1323e1dd0a2fSth160488 } 1324e1dd0a2fSth160488 1325e1dd0a2fSth160488 if (!server_addr) { 1326e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1327e1dd0a2fSth160488 } 1328e1dd0a2fSth160488 1329e1dd0a2fSth160488 __s_api_setInitMode(); 1330e1dd0a2fSth160488 133129836b19Smichen cu = __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, B_FALSE); 133229836b19Smichen if (cu == NULL) { 133329836b19Smichen return (NS_LDAP_INTERNAL); 133429836b19Smichen } 133529836b19Smichen 1336e1dd0a2fSth160488 /* 1337e1dd0a2fSth160488 * All the credentials will be taken from the current 1338e1dd0a2fSth160488 * libsldap configuration. 1339e1dd0a2fSth160488 */ 1340e1dd0a2fSth160488 if ((ret_code = __s_api_getConnection(server_addr, 1341e1dd0a2fSth160488 NS_LDAP_NEW_CONN, 1342e1dd0a2fSth160488 NULL, 1343e1dd0a2fSth160488 &sessionId, 1344e1dd0a2fSth160488 &session, 1345e1dd0a2fSth160488 errorp, 1346e1dd0a2fSth160488 0, 1347e1dd0a2fSth160488 0, 134829836b19Smichen cu)) != NS_LDAP_SUCCESS) { 1349e1dd0a2fSth160488 /* Fallback to anonymous mode is disabled. Stop. */ 1350e1dd0a2fSth160488 if (anon_fallback == 0) { 1351e1dd0a2fSth160488 syslog(LOG_WARNING, 1352e1dd0a2fSth160488 gettext("libsldap: can not get the root DSE from " 1353e1dd0a2fSth160488 " the %s server: %s. " 1354e1dd0a2fSth160488 "Falling back to anonymous disabled.\n"), 1355e1dd0a2fSth160488 server_addr, 1356e1dd0a2fSth160488 errorp && *errorp && (*errorp)->message ? 1357e1dd0a2fSth160488 (*errorp)->message : ""); 1358e1dd0a2fSth160488 if (errorp != NULL && *errorp != NULL) { 1359e1dd0a2fSth160488 (void) __ns_ldap_freeError(errorp); 1360e1dd0a2fSth160488 } 1361e1dd0a2fSth160488 __s_api_unsetInitMode(); 1362e1dd0a2fSth160488 return (ret_code); 1363e1dd0a2fSth160488 } 1364e1dd0a2fSth160488 1365e1dd0a2fSth160488 /* 1366e1dd0a2fSth160488 * Fallback to anonymous, non-SSL mode for backward 1367e1dd0a2fSth160488 * compatibility reasons. This mode should only be used when 1368e1dd0a2fSth160488 * this function (__ns_ldap_getRootDSE) is called from 1369e1dd0a2fSth160488 * ldap_cachemgr(1M). 1370e1dd0a2fSth160488 */ 1371e1dd0a2fSth160488 syslog(LOG_WARNING, 1372e1dd0a2fSth160488 gettext("libsldap: Falling back to anonymous, non-SSL" 1373e1dd0a2fSth160488 " mode for __ns_ldap_getRootDSE. %s\n"), 1374e1dd0a2fSth160488 errorp && *errorp && (*errorp)->message ? 1375e1dd0a2fSth160488 (*errorp)->message : ""); 1376e1dd0a2fSth160488 1377e1dd0a2fSth160488 /* Setup the anon credential for anonymous connection. */ 1378e1dd0a2fSth160488 (void) memset(&anon, 0, sizeof (ns_cred_t)); 1379e1dd0a2fSth160488 anon.auth.type = NS_LDAP_AUTH_NONE; 1380e1dd0a2fSth160488 1381e1dd0a2fSth160488 if (*errorp != NULL) { 1382e1dd0a2fSth160488 (void) __ns_ldap_freeError(errorp); 1383e1dd0a2fSth160488 } 1384e1dd0a2fSth160488 *errorp = NULL; 1385e1dd0a2fSth160488 1386e1dd0a2fSth160488 ret_code = __s_api_getConnection(server_addr, 1387e1dd0a2fSth160488 NS_LDAP_NEW_CONN, 1388e1dd0a2fSth160488 &anon, 1389e1dd0a2fSth160488 &sessionId, 1390e1dd0a2fSth160488 &session, 1391e1dd0a2fSth160488 errorp, 1392e1dd0a2fSth160488 0, 1393e1dd0a2fSth160488 0, 139429836b19Smichen cu); 1395e1dd0a2fSth160488 1396e1dd0a2fSth160488 if (ret_code != NS_LDAP_SUCCESS) { 139729836b19Smichen __s_api_conn_user_free(cu); 1398e1dd0a2fSth160488 __s_api_unsetInitMode(); 1399e1dd0a2fSth160488 return (ret_code); 1400e1dd0a2fSth160488 } 1401e1dd0a2fSth160488 } 1402e1dd0a2fSth160488 1403e1dd0a2fSth160488 __s_api_unsetInitMode(); 1404e1dd0a2fSth160488 1405e1dd0a2fSth160488 /* get search timeout value */ 1406e1dd0a2fSth160488 (void) __ns_ldap_getParam(NS_LDAP_SEARCH_TIME_P, ¶mVal, errorp); 1407e1dd0a2fSth160488 if (paramVal != NULL && *paramVal != NULL) { 1408e1dd0a2fSth160488 tv.tv_sec = **((int **)paramVal); 1409e1dd0a2fSth160488 (void) __ns_ldap_freeParam(¶mVal); 1410e1dd0a2fSth160488 } 1411e1dd0a2fSth160488 if (*errorp != NULL) { 1412e1dd0a2fSth160488 (void) __ns_ldap_freeError(errorp); 1413e1dd0a2fSth160488 } 1414e1dd0a2fSth160488 1415e1dd0a2fSth160488 /* Get root DSE from the server specified by the caller. */ 1416e1dd0a2fSth160488 attrs[0] = "supportedControl"; 1417e1dd0a2fSth160488 attrs[1] = "supportedsaslmechanisms"; 1418e1dd0a2fSth160488 attrs[2] = NULL; 1419e1dd0a2fSth160488 ldap_rc = ldap_search_ext_s(session->ld, 1420e1dd0a2fSth160488 "", 1421e1dd0a2fSth160488 LDAP_SCOPE_BASE, 1422e1dd0a2fSth160488 "(objectclass=*)", 1423e1dd0a2fSth160488 attrs, 1424e1dd0a2fSth160488 0, 1425e1dd0a2fSth160488 NULL, 1426e1dd0a2fSth160488 NULL, 1427e1dd0a2fSth160488 &tv, 1428e1dd0a2fSth160488 0, 1429e1dd0a2fSth160488 &resultMsg); 1430e1dd0a2fSth160488 1431e1dd0a2fSth160488 if (ldap_rc != LDAP_SUCCESS) { 1432e1dd0a2fSth160488 /* 1433e1dd0a2fSth160488 * If the root DSE was not found, the server does 1434e1dd0a2fSth160488 * not comply with the LDAP v3 protocol. 1435e1dd0a2fSth160488 */ 1436e1dd0a2fSth160488 (void) ldap_get_option(session->ld, 1437e1dd0a2fSth160488 LDAP_OPT_ERROR_NUMBER, 1438e1dd0a2fSth160488 &ldaperrno); 1439e1dd0a2fSth160488 (void) snprintf(errmsg, 1440e1dd0a2fSth160488 sizeof (errmsg), 1441e1dd0a2fSth160488 gettext(ldap_err2string(ldaperrno))); 1442e1dd0a2fSth160488 MKERROR(LOG_ERR, 1443e1dd0a2fSth160488 *errorp, 1444e1dd0a2fSth160488 NS_LDAP_OP_FAILED, 1445e1dd0a2fSth160488 strdup(errmsg), 1446e1dd0a2fSth160488 NS_LDAP_MEMORY); 1447e1dd0a2fSth160488 1448e1dd0a2fSth160488 if (resultMsg) { 1449e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 1450e1dd0a2fSth160488 resultMsg = NULL; 1451e1dd0a2fSth160488 } 1452e1dd0a2fSth160488 145329836b19Smichen __s_api_conn_user_free(cu); 1454*b3b48d8eSHans Rosenfeld DropConnection(sessionId, NS_LDAP_NEW_CONN); 1455e1dd0a2fSth160488 return (NS_LDAP_OP_FAILED); 1456e1dd0a2fSth160488 } 145729836b19Smichen __s_api_conn_user_free(cu); 1458e1dd0a2fSth160488 1459e1dd0a2fSth160488 ret_code = convert_to_door_line(session->ld, 1460e1dd0a2fSth160488 resultMsg, 1461e1dd0a2fSth160488 INCLUDE_ATTR_NAMES, 1462e1dd0a2fSth160488 NOT_PROFILE, 1463e1dd0a2fSth160488 root_dse); 1464e1dd0a2fSth160488 if (ret_code == NS_LDAP_NOTFOUND) { 1465e1dd0a2fSth160488 (void) snprintf(errmsg, 1466e1dd0a2fSth160488 sizeof (errmsg), 1467e1dd0a2fSth160488 gettext("No root DSE data " 1468e1dd0a2fSth160488 "for server %s returned."), 1469e1dd0a2fSth160488 server_addr); 1470e1dd0a2fSth160488 MKERROR(LOG_ERR, 1471e1dd0a2fSth160488 *errorp, 1472e1dd0a2fSth160488 NS_LDAP_NOTFOUND, 1473e1dd0a2fSth160488 strdup(errmsg), 1474e1dd0a2fSth160488 NS_LDAP_MEMORY); 1475e1dd0a2fSth160488 } 1476e1dd0a2fSth160488 1477e1dd0a2fSth160488 if (resultMsg) { 1478e1dd0a2fSth160488 (void) ldap_msgfree(resultMsg); 1479e1dd0a2fSth160488 resultMsg = NULL; 1480e1dd0a2fSth160488 } 1481e1dd0a2fSth160488 1482e1dd0a2fSth160488 DropConnection(sessionId, NS_LDAP_NEW_CONN); 1483e1dd0a2fSth160488 1484e1dd0a2fSth160488 return (ret_code); 1485e1dd0a2fSth160488 } 1486e1dd0a2fSth160488 1487e1dd0a2fSth160488 /* 1488e1dd0a2fSth160488 * This function destroys the local list of root DSEs. The input parameter is 1489e1dd0a2fSth160488 * a pointer to the list to be erased. 1490e1dd0a2fSth160488 * The type of the pointer passed to this function should be 1491e1dd0a2fSth160488 * (dir_server_list_t *). 1492e1dd0a2fSth160488 */ 1493e1dd0a2fSth160488 static 1494e1dd0a2fSth160488 void * 1495e1dd0a2fSth160488 disposeOfOldList(void *param) 1496e1dd0a2fSth160488 { 1497e1dd0a2fSth160488 dir_server_list_t *old_list = (dir_server_list_t *)param; 1498e1dd0a2fSth160488 long i = 0, j; 1499e1dd0a2fSth160488 1500e1dd0a2fSth160488 (void) rw_wrlock(&old_list->listDestroyLock); 1501e1dd0a2fSth160488 /* Destroy the old list */ 1502e1dd0a2fSth160488 while (old_list->nsServers[i]) { 1503e1dd0a2fSth160488 free(old_list->nsServers[i]->ip); 1504e1dd0a2fSth160488 j = 0; 1505e1dd0a2fSth160488 while (old_list->nsServers[i]->controls && 1506e1dd0a2fSth160488 old_list->nsServers[i]->controls[j]) { 1507e1dd0a2fSth160488 free(old_list->nsServers[i]->controls[j]); 1508e1dd0a2fSth160488 ++j; 1509e1dd0a2fSth160488 } 1510e1dd0a2fSth160488 free(old_list->nsServers[i]->controls); 1511e1dd0a2fSth160488 j = 0; 1512e1dd0a2fSth160488 while (old_list->nsServers[i]->saslMech && 1513e1dd0a2fSth160488 old_list->nsServers[i]->saslMech[j]) { 1514e1dd0a2fSth160488 free(old_list->nsServers[i]->saslMech[j]); 1515e1dd0a2fSth160488 ++j; 1516e1dd0a2fSth160488 } 1517e1dd0a2fSth160488 free(old_list->nsServers[i]->saslMech); 1518e1dd0a2fSth160488 ++i; 1519e1dd0a2fSth160488 } 1520e1dd0a2fSth160488 /* 1521e1dd0a2fSth160488 * All the structures pointed by old_list->nsServers were allocated 1522e1dd0a2fSth160488 * in one chunck. The nsServers[0] pointer points to the beginning 1523e1dd0a2fSth160488 * of that chunck. 1524e1dd0a2fSth160488 */ 1525e1dd0a2fSth160488 free(old_list->nsServers[0]); 1526e1dd0a2fSth160488 free(old_list->nsServers); 1527e1dd0a2fSth160488 (void) rw_unlock(&old_list->listDestroyLock); 1528e1dd0a2fSth160488 (void) rwlock_destroy(&old_list->listDestroyLock); 1529e1dd0a2fSth160488 free(old_list); 1530e1dd0a2fSth160488 1531e1dd0a2fSth160488 return (NULL); 1532e1dd0a2fSth160488 } 1533e1dd0a2fSth160488 1534e1dd0a2fSth160488 /* 1535e1dd0a2fSth160488 * This function cancels the Standalone mode and destroys the list of root DSEs. 1536e1dd0a2fSth160488 */ 1537e1dd0a2fSth160488 void 1538e1dd0a2fSth160488 __ns_ldap_cancelStandalone(void) 1539e1dd0a2fSth160488 { 1540e1dd0a2fSth160488 dir_server_list_t *old_list; 1541e1dd0a2fSth160488 1542e1dd0a2fSth160488 (void) mutex_lock(&dir_servers.listReplaceLock); 1543e1dd0a2fSth160488 dir_servers.standalone = 0; 1544e1dd0a2fSth160488 if (!dir_servers.list) { 1545e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 1546e1dd0a2fSth160488 return; 1547e1dd0a2fSth160488 } 1548e1dd0a2fSth160488 old_list = dir_servers.list; 1549e1dd0a2fSth160488 dir_servers.list = NULL; 1550e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 1551e1dd0a2fSth160488 1552e1dd0a2fSth160488 (void) disposeOfOldList(old_list); 1553e1dd0a2fSth160488 } 1554e1dd0a2fSth160488 1555e1dd0a2fSth160488 1556e1dd0a2fSth160488 static 1557e1dd0a2fSth160488 void* 1558e1dd0a2fSth160488 create_ns_servers_entry(void *param) 1559e1dd0a2fSth160488 { 1560e1dd0a2fSth160488 #define CHUNK_SIZE 16 1561e1dd0a2fSth160488 1562e1dd0a2fSth160488 dir_server_t *server = (dir_server_t *)param; 1563e1dd0a2fSth160488 ns_ldap_return_code *retCode = calloc(1, 1564e1dd0a2fSth160488 sizeof (ns_ldap_return_code)); 1565e1dd0a2fSth160488 uint32_t sc_counter = 0, sm_counter = 0; 1566e1dd0a2fSth160488 uint32_t sc_mem_blocks = 1, sm_mem_blocks = 1; 1567e1dd0a2fSth160488 char *rootDSE = NULL, *attr, *val, *rest, **ptr; 1568e1dd0a2fSth160488 ns_ldap_error_t *error = NULL; 1569e1dd0a2fSth160488 1570e1dd0a2fSth160488 if (retCode == NULL) { 1571e1dd0a2fSth160488 return (NULL); 1572e1dd0a2fSth160488 } 1573e1dd0a2fSth160488 1574e1dd0a2fSth160488 /* 1575e1dd0a2fSth160488 * We call this function in non anon-fallback mode because we 1576e1dd0a2fSth160488 * want the whole procedure to fail as soon as possible to 1577e1dd0a2fSth160488 * indicate there are problems with connecting to the server. 1578e1dd0a2fSth160488 */ 1579e1dd0a2fSth160488 *retCode = __ns_ldap_getRootDSE(server->ip, 1580e1dd0a2fSth160488 &rootDSE, 1581e1dd0a2fSth160488 &error, 1582e1dd0a2fSth160488 SA_ALLOW_FALLBACK); 1583e1dd0a2fSth160488 1584e1dd0a2fSth160488 if (*retCode == NS_LDAP_MEMORY) { 1585e1dd0a2fSth160488 free(retCode); 1586e1dd0a2fSth160488 return (NULL); 1587e1dd0a2fSth160488 } 1588e1dd0a2fSth160488 1589e1dd0a2fSth160488 /* 1590e1dd0a2fSth160488 * If the root DSE can not be obtained, log an error and keep the 1591e1dd0a2fSth160488 * server. 1592e1dd0a2fSth160488 */ 1593e1dd0a2fSth160488 if (*retCode != NS_LDAP_SUCCESS) { 1594e1dd0a2fSth160488 server->status = INFO_SERVER_ERROR; 1595e1dd0a2fSth160488 syslog(LOG_WARNING, 1596e1dd0a2fSth160488 gettext("libsldap (\"standalone\" mode): " 1597e1dd0a2fSth160488 "can not obtain the root DSE from %s. %s"), 1598e1dd0a2fSth160488 server->ip, 1599e1dd0a2fSth160488 error && error->message ? error->message : ""); 1600e1dd0a2fSth160488 if (error) { 1601e1dd0a2fSth160488 (void) __ns_ldap_freeError(&error); 1602e1dd0a2fSth160488 } 1603e1dd0a2fSth160488 return (retCode); 1604e1dd0a2fSth160488 } 1605e1dd0a2fSth160488 1606e1dd0a2fSth160488 /* Get the first attribute of the root DSE. */ 1607e1dd0a2fSth160488 attr = strtok_r(rootDSE, DOORLINESEP, &rest); 1608e1dd0a2fSth160488 if (attr == NULL) { 1609e1dd0a2fSth160488 free(rootDSE); 1610e1dd0a2fSth160488 server->status = INFO_SERVER_ERROR; 1611e1dd0a2fSth160488 syslog(LOG_WARNING, 1612e1dd0a2fSth160488 gettext("libsldap (\"standalone\" mode): " 1613e1dd0a2fSth160488 "the root DSE from %s is empty or corrupted."), 1614e1dd0a2fSth160488 server->ip); 1615e1dd0a2fSth160488 *retCode = NS_LDAP_INTERNAL; 1616e1dd0a2fSth160488 return (retCode); 1617e1dd0a2fSth160488 } 1618e1dd0a2fSth160488 1619e1dd0a2fSth160488 server->controls = (char **)calloc(CHUNK_SIZE, sizeof (char *)); 1620e1dd0a2fSth160488 server->saslMech = (char **)calloc(CHUNK_SIZE, sizeof (char *)); 1621e1dd0a2fSth160488 if (server->controls == NULL || server->saslMech == NULL) { 1622e1dd0a2fSth160488 free(rootDSE); 1623e1dd0a2fSth160488 free(retCode); 1624e1dd0a2fSth160488 return (NULL); 1625e1dd0a2fSth160488 } 1626e1dd0a2fSth160488 1627e1dd0a2fSth160488 do { 1628e1dd0a2fSth160488 if ((val = strchr(attr, '=')) == NULL) { 1629e1dd0a2fSth160488 continue; 1630e1dd0a2fSth160488 } 1631e1dd0a2fSth160488 ++val; 1632e1dd0a2fSth160488 1633e1dd0a2fSth160488 if (strncasecmp(attr, 1634e1dd0a2fSth160488 _SASLMECHANISM, 1635e1dd0a2fSth160488 _SASLMECHANISM_LEN) == 0) { 1636e1dd0a2fSth160488 if (sm_counter == CHUNK_SIZE * sm_mem_blocks - 1) { 1637e1dd0a2fSth160488 ptr = (char **)realloc(server->saslMech, 1638e1dd0a2fSth160488 CHUNK_SIZE * 1639e1dd0a2fSth160488 ++sm_mem_blocks * 1640e1dd0a2fSth160488 sizeof (char *)); 1641e1dd0a2fSth160488 if (ptr == NULL) { 1642e1dd0a2fSth160488 *retCode = NS_LDAP_MEMORY; 1643e1dd0a2fSth160488 break; 1644e1dd0a2fSth160488 } 1645e1dd0a2fSth160488 bzero((char *)ptr + 1646e1dd0a2fSth160488 (sm_counter + 1) * 1647e1dd0a2fSth160488 sizeof (char *), 1648e1dd0a2fSth160488 CHUNK_SIZE * 1649e1dd0a2fSth160488 sm_mem_blocks * 1650e1dd0a2fSth160488 sizeof (char *) - 1651e1dd0a2fSth160488 (sm_counter + 1) * 1652e1dd0a2fSth160488 sizeof (char *)); 1653e1dd0a2fSth160488 server->saslMech = ptr; 1654e1dd0a2fSth160488 } 1655e1dd0a2fSth160488 server->saslMech[sm_counter] = strdup(val); 1656e1dd0a2fSth160488 if (server->saslMech[sm_counter] == NULL) { 1657e1dd0a2fSth160488 *retCode = NS_LDAP_MEMORY; 1658e1dd0a2fSth160488 break; 1659e1dd0a2fSth160488 } 1660e1dd0a2fSth160488 ++sm_counter; 1661e1dd0a2fSth160488 continue; 1662e1dd0a2fSth160488 } 1663e1dd0a2fSth160488 if (strncasecmp(attr, 1664e1dd0a2fSth160488 _SUPPORTEDCONTROL, 1665e1dd0a2fSth160488 _SUPPORTEDCONTROL_LEN) == 0) { 1666e1dd0a2fSth160488 if (sc_counter == CHUNK_SIZE * sc_mem_blocks - 1) { 1667e1dd0a2fSth160488 ptr = (char **)realloc(server->controls, 1668e1dd0a2fSth160488 CHUNK_SIZE * 1669e1dd0a2fSth160488 ++sc_mem_blocks * 1670e1dd0a2fSth160488 sizeof (char *)); 1671e1dd0a2fSth160488 if (ptr == NULL) { 1672e1dd0a2fSth160488 *retCode = NS_LDAP_MEMORY; 1673e1dd0a2fSth160488 break; 1674e1dd0a2fSth160488 } 1675e1dd0a2fSth160488 bzero((char *)ptr + 1676e1dd0a2fSth160488 (sc_counter + 1) * 1677e1dd0a2fSth160488 sizeof (char *), 1678e1dd0a2fSth160488 CHUNK_SIZE * 1679e1dd0a2fSth160488 sc_mem_blocks * 1680e1dd0a2fSth160488 sizeof (char *) - 1681e1dd0a2fSth160488 (sc_counter + 1) * 1682e1dd0a2fSth160488 sizeof (char *)); 1683e1dd0a2fSth160488 server->controls = ptr; 1684e1dd0a2fSth160488 } 1685e1dd0a2fSth160488 1686e1dd0a2fSth160488 server->controls[sc_counter] = strdup(val); 1687e1dd0a2fSth160488 if (server->controls[sc_counter] == NULL) { 1688e1dd0a2fSth160488 *retCode = NS_LDAP_MEMORY; 1689e1dd0a2fSth160488 break; 1690e1dd0a2fSth160488 } 1691e1dd0a2fSth160488 ++sc_counter; 1692e1dd0a2fSth160488 continue; 1693e1dd0a2fSth160488 } 1694e1dd0a2fSth160488 1695e1dd0a2fSth160488 } while (attr = strtok_r(NULL, DOORLINESEP, &rest)); 1696e1dd0a2fSth160488 1697e1dd0a2fSth160488 free(rootDSE); 1698e1dd0a2fSth160488 1699e1dd0a2fSth160488 if (*retCode == NS_LDAP_MEMORY) { 1700e1dd0a2fSth160488 free(retCode); 1701e1dd0a2fSth160488 return (NULL); 1702e1dd0a2fSth160488 } 1703e1dd0a2fSth160488 1704e1dd0a2fSth160488 server->controls[sc_counter] = NULL; 1705e1dd0a2fSth160488 server->saslMech[sm_counter] = NULL; 1706e1dd0a2fSth160488 1707e1dd0a2fSth160488 server->status = INFO_SERVER_UP; 1708e1dd0a2fSth160488 1709e1dd0a2fSth160488 return (retCode); 1710e1dd0a2fSth160488 #undef CHUNK_SIZE 1711e1dd0a2fSth160488 } 1712e1dd0a2fSth160488 1713e1dd0a2fSth160488 1714e1dd0a2fSth160488 /* 1715e1dd0a2fSth160488 * This function creates a new local list of root DSEs from all the servers 1716e1dd0a2fSth160488 * mentioned in the DUAProfile (or local NS BEC) and returns 1717e1dd0a2fSth160488 * a pointer to the list. 1718e1dd0a2fSth160488 */ 1719e1dd0a2fSth160488 static 1720e1dd0a2fSth160488 ns_ldap_return_code 1721e1dd0a2fSth160488 createDirServerList(dir_server_list_t **new_list, 1722e1dd0a2fSth160488 ns_ldap_error_t **errorp) 1723e1dd0a2fSth160488 { 1724e1dd0a2fSth160488 char **serverList; 1725e1dd0a2fSth160488 ns_ldap_return_code retCode = NS_LDAP_SUCCESS; 1726e1dd0a2fSth160488 dir_server_t *tmpSrvArray; 1727e1dd0a2fSth160488 long srvListLength, i; 1728e1dd0a2fSth160488 thread_t *thrPool, thrID; 1729e1dd0a2fSth160488 void *status = NULL; 1730e1dd0a2fSth160488 1731e1dd0a2fSth160488 if (errorp == NULL) { 1732e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1733e1dd0a2fSth160488 } 1734e1dd0a2fSth160488 1735e1dd0a2fSth160488 *errorp = NULL; 1736e1dd0a2fSth160488 1737e1dd0a2fSth160488 if (new_list == NULL) { 1738e1dd0a2fSth160488 return (NS_LDAP_INVALID_PARAM); 1739e1dd0a2fSth160488 } 1740e1dd0a2fSth160488 1741e1dd0a2fSth160488 retCode = __s_api_getServers(&serverList, errorp); 1742e1dd0a2fSth160488 if (retCode != NS_LDAP_SUCCESS || serverList == NULL) { 1743e1dd0a2fSth160488 return (retCode); 1744e1dd0a2fSth160488 } 1745e1dd0a2fSth160488 1746e1dd0a2fSth160488 for (i = 0; serverList[i]; ++i) { 1747e1dd0a2fSth160488 ; 1748e1dd0a2fSth160488 } 1749e1dd0a2fSth160488 srvListLength = i; 1750e1dd0a2fSth160488 1751e1dd0a2fSth160488 thrPool = calloc(srvListLength, sizeof (thread_t)); 1752e1dd0a2fSth160488 if (thrPool == NULL) { 1753e1dd0a2fSth160488 __s_api_free2dArray(serverList); 1754e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 1755e1dd0a2fSth160488 } 1756e1dd0a2fSth160488 1757e1dd0a2fSth160488 *new_list = (dir_server_list_t *)calloc(1, 1758e1dd0a2fSth160488 sizeof (dir_server_list_t)); 1759e1dd0a2fSth160488 if (*new_list == NULL) { 1760e1dd0a2fSth160488 __s_api_free2dArray(serverList); 1761e1dd0a2fSth160488 free(thrPool); 1762e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 1763e1dd0a2fSth160488 } 1764e1dd0a2fSth160488 (void) rwlock_init(&(*new_list)->listDestroyLock, USYNC_THREAD, NULL); 1765e1dd0a2fSth160488 1766e1dd0a2fSth160488 (*new_list)->nsServers = (dir_server_t **)calloc(srvListLength + 1, 1767e1dd0a2fSth160488 sizeof (dir_server_t *)); 1768e1dd0a2fSth160488 if ((*new_list)->nsServers == NULL) { 1769e1dd0a2fSth160488 free(*new_list); 1770e1dd0a2fSth160488 *new_list = NULL; 1771e1dd0a2fSth160488 __s_api_free2dArray(serverList); 1772e1dd0a2fSth160488 free(thrPool); 1773e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 1774e1dd0a2fSth160488 } 1775e1dd0a2fSth160488 1776e1dd0a2fSth160488 /* 1777e1dd0a2fSth160488 * Allocate a set of dir_server_t structures as an array, 1778e1dd0a2fSth160488 * with one alloc call and then initialize the nsServers pointers 1779e1dd0a2fSth160488 * with the addresses of the array's members. 1780e1dd0a2fSth160488 */ 1781e1dd0a2fSth160488 tmpSrvArray = (dir_server_t *)calloc(srvListLength, 1782e1dd0a2fSth160488 sizeof (dir_server_t)); 1783e1dd0a2fSth160488 for (i = 0; i < srvListLength; ++i) { 1784e1dd0a2fSth160488 (*new_list)->nsServers[i] = &tmpSrvArray[i]; 1785e1dd0a2fSth160488 1786e1dd0a2fSth160488 (*new_list)->nsServers[i]->info = INFO_STATUS_NEW; 1787e1dd0a2fSth160488 (void) mutex_init(&(*new_list)->nsServers[i]->updateStatus, 1788e1dd0a2fSth160488 USYNC_THREAD, 1789e1dd0a2fSth160488 NULL); 1790e1dd0a2fSth160488 1791e1dd0a2fSth160488 (*new_list)->nsServers[i]->ip = strdup(serverList[i]); 1792e1dd0a2fSth160488 if ((*new_list)->nsServers[i]->ip == NULL) { 1793e1dd0a2fSth160488 retCode = NS_LDAP_MEMORY; 1794e1dd0a2fSth160488 break; 1795e1dd0a2fSth160488 } 1796e1dd0a2fSth160488 1797e1dd0a2fSth160488 (*new_list)->nsServers[i]->status = INFO_SERVER_CONNECTING; 1798e1dd0a2fSth160488 1799e1dd0a2fSth160488 switch (thr_create(NULL, 1800e1dd0a2fSth160488 0, 1801e1dd0a2fSth160488 create_ns_servers_entry, 1802e1dd0a2fSth160488 (*new_list)->nsServers[i], 1803e1dd0a2fSth160488 0, 1804e1dd0a2fSth160488 &thrID)) { 1805e1dd0a2fSth160488 case EAGAIN: 1806e1dd0a2fSth160488 (*new_list)->nsServers[i]->status = 1807e1dd0a2fSth160488 INFO_SERVER_ERROR; 1808e1dd0a2fSth160488 continue; 1809e1dd0a2fSth160488 case ENOMEM: 1810e1dd0a2fSth160488 (*new_list)->nsServers[i]->status = 1811e1dd0a2fSth160488 INFO_SERVER_ERROR; 1812e1dd0a2fSth160488 continue; 1813e1dd0a2fSth160488 default: 1814e1dd0a2fSth160488 thrPool[i] = thrID; 1815e1dd0a2fSth160488 continue; 1816e1dd0a2fSth160488 } 1817e1dd0a2fSth160488 } 1818e1dd0a2fSth160488 1819e1dd0a2fSth160488 for (i = 0; i < srvListLength; ++i) { 1820e1dd0a2fSth160488 if (thrPool[i] != 0 && 1821e1dd0a2fSth160488 thr_join(thrPool[i], NULL, &status) == 0) { 1822e1dd0a2fSth160488 if (status == NULL) { 1823e1dd0a2fSth160488 /* 1824e1dd0a2fSth160488 * Some memory allocation problems occured. Just 1825e1dd0a2fSth160488 * ignore the server and hope there will be some 1826e1dd0a2fSth160488 * other good ones. 1827e1dd0a2fSth160488 */ 1828e1dd0a2fSth160488 (*new_list)->nsServers[i]->status = 1829e1dd0a2fSth160488 INFO_SERVER_ERROR; 1830e1dd0a2fSth160488 } 1831e1dd0a2fSth160488 free(status); 1832e1dd0a2fSth160488 } 1833e1dd0a2fSth160488 } 1834e1dd0a2fSth160488 1835e1dd0a2fSth160488 __s_api_free2dArray(serverList); 1836e1dd0a2fSth160488 free(thrPool); 1837e1dd0a2fSth160488 1838e1dd0a2fSth160488 if (retCode == NS_LDAP_MEMORY) { 1839e1dd0a2fSth160488 (void) disposeOfOldList(*new_list); 1840e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 1841e1dd0a2fSth160488 } 1842e1dd0a2fSth160488 1843e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 1844e1dd0a2fSth160488 } 1845e1dd0a2fSth160488 1846e1dd0a2fSth160488 /* 1847e1dd0a2fSth160488 * This functions replaces the local list of root DSEs with a new one and starts 1848e1dd0a2fSth160488 * a thread destroying the old list. There is no need for other threads to wait 1849e1dd0a2fSth160488 * until the old list will be destroyed. 1850e1dd0a2fSth160488 * Since it is possible that more than one thread can start creating the list, 1851e1dd0a2fSth160488 * this function should be protected by mutexes to be sure that only one thread 1852e1dd0a2fSth160488 * performs the initialization. 1853e1dd0a2fSth160488 */ 1854e1dd0a2fSth160488 static 1855e1dd0a2fSth160488 ns_ldap_return_code 1856e1dd0a2fSth160488 initGlobalList(ns_ldap_error_t **error) 1857e1dd0a2fSth160488 { 1858e1dd0a2fSth160488 dir_server_list_t *new_list, *old_list; 1859e1dd0a2fSth160488 ns_ldap_return_code ret_code; 1860e1dd0a2fSth160488 thread_t tid; 1861e1dd0a2fSth160488 1862e1dd0a2fSth160488 ret_code = createDirServerList(&new_list, error); 1863e1dd0a2fSth160488 if (ret_code != NS_LDAP_SUCCESS) { 1864e1dd0a2fSth160488 return (ret_code); 1865e1dd0a2fSth160488 } 1866e1dd0a2fSth160488 1867e1dd0a2fSth160488 old_list = dir_servers.list; 1868e1dd0a2fSth160488 dir_servers.list = new_list; 1869e1dd0a2fSth160488 1870e1dd0a2fSth160488 if (old_list) { 1871e1dd0a2fSth160488 (void) thr_create(NULL, 1872e1dd0a2fSth160488 0, 1873e1dd0a2fSth160488 disposeOfOldList, 1874e1dd0a2fSth160488 old_list, 1875e1dd0a2fSth160488 THR_DETACHED, 1876e1dd0a2fSth160488 &tid); 1877e1dd0a2fSth160488 } 1878e1dd0a2fSth160488 1879e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 1880e1dd0a2fSth160488 } 1881e1dd0a2fSth160488 1882e1dd0a2fSth160488 static 1883e1dd0a2fSth160488 struct { 1884e1dd0a2fSth160488 char *authMech; 1885e1dd0a2fSth160488 ns_auth_t auth; 1886e1dd0a2fSth160488 } authArray[] = {{"none", {NS_LDAP_AUTH_NONE, 1887e1dd0a2fSth160488 NS_LDAP_TLS_NONE, 1888e1dd0a2fSth160488 NS_LDAP_SASL_NONE, 1889e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1890e1dd0a2fSth160488 {"simple", {NS_LDAP_AUTH_SIMPLE, 1891e1dd0a2fSth160488 NS_LDAP_TLS_NONE, 1892e1dd0a2fSth160488 NS_LDAP_SASL_NONE, 1893e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1894e1dd0a2fSth160488 {"tls:simple", {NS_LDAP_AUTH_TLS, 1895e1dd0a2fSth160488 NS_LDAP_TLS_SIMPLE, 1896e1dd0a2fSth160488 NS_LDAP_SASL_NONE, 1897e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1898e1dd0a2fSth160488 {"tls:sasl/CRAM-MD5", {NS_LDAP_AUTH_TLS, 1899e1dd0a2fSth160488 NS_LDAP_TLS_SASL, 1900e1dd0a2fSth160488 NS_LDAP_SASL_CRAM_MD5, 1901e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1902e1dd0a2fSth160488 {"tls:sasl/DIGEST-MD5", {NS_LDAP_AUTH_TLS, 1903e1dd0a2fSth160488 NS_LDAP_TLS_SASL, 1904e1dd0a2fSth160488 NS_LDAP_SASL_DIGEST_MD5, 1905e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1906e1dd0a2fSth160488 {"sasl/CRAM-MD5", {NS_LDAP_AUTH_SASL, 1907e1dd0a2fSth160488 NS_LDAP_TLS_SASL, 1908e1dd0a2fSth160488 NS_LDAP_SASL_CRAM_MD5, 1909e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1910e1dd0a2fSth160488 {"sasl/DIGEST-MD5", {NS_LDAP_AUTH_SASL, 1911e1dd0a2fSth160488 NS_LDAP_TLS_SASL, 1912e1dd0a2fSth160488 NS_LDAP_SASL_DIGEST_MD5, 1913e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}, 1914e1dd0a2fSth160488 {"sasl/GSSAPI", {NS_LDAP_AUTH_SASL, 1915e1dd0a2fSth160488 NS_LDAP_TLS_SASL, 1916e1dd0a2fSth160488 NS_LDAP_SASL_GSSAPI, 1917e1dd0a2fSth160488 NS_LDAP_SASLOPT_PRIV | NS_LDAP_SASLOPT_INT}}, 1918e1dd0a2fSth160488 {NULL, {NS_LDAP_AUTH_NONE, 1919e1dd0a2fSth160488 NS_LDAP_TLS_NONE, 1920e1dd0a2fSth160488 NS_LDAP_SASL_NONE, 1921e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}}}; 1922e1dd0a2fSth160488 1923e1dd0a2fSth160488 ns_ldap_return_code 1924e1dd0a2fSth160488 __ns_ldap_initAuth(const char *auth_mech, 1925e1dd0a2fSth160488 ns_auth_t *auth, 1926e1dd0a2fSth160488 ns_ldap_error_t **errorp) 1927e1dd0a2fSth160488 { 1928e1dd0a2fSth160488 uint32_t i; 1929e1dd0a2fSth160488 char errmsg[MAXERROR]; 1930e1dd0a2fSth160488 1931e1dd0a2fSth160488 if (auth_mech == NULL) { 1932e1dd0a2fSth160488 (void) snprintf(errmsg, 1933e1dd0a2fSth160488 sizeof (errmsg), 1934e1dd0a2fSth160488 gettext("Invalid authentication method specified\n")); 1935e1dd0a2fSth160488 MKERROR(LOG_WARNING, 1936e1dd0a2fSth160488 *errorp, 1937e1dd0a2fSth160488 NS_LDAP_INTERNAL, 1938e1dd0a2fSth160488 strdup(errmsg), 1939e1dd0a2fSth160488 NS_LDAP_MEMORY); 1940e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 1941e1dd0a2fSth160488 } 1942e1dd0a2fSth160488 1943e1dd0a2fSth160488 for (i = 0; authArray[i].authMech != NULL; ++i) { 1944e1dd0a2fSth160488 if (strcasecmp(auth_mech, authArray[i].authMech) == 0) { 1945e1dd0a2fSth160488 *auth = authArray[i].auth; 1946e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 1947e1dd0a2fSth160488 } 1948e1dd0a2fSth160488 } 1949e1dd0a2fSth160488 1950e1dd0a2fSth160488 (void) snprintf(errmsg, 1951e1dd0a2fSth160488 sizeof (errmsg), 1952e1dd0a2fSth160488 gettext("Invalid authentication method specified\n")); 1953e1dd0a2fSth160488 MKERROR(LOG_WARNING, 1954e1dd0a2fSth160488 *errorp, 1955e1dd0a2fSth160488 NS_LDAP_INTERNAL, 1956e1dd0a2fSth160488 strdup(errmsg), 1957e1dd0a2fSth160488 NS_LDAP_MEMORY); 1958e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 1959e1dd0a2fSth160488 } 1960e1dd0a2fSth160488 1961e1dd0a2fSth160488 /* 1962e1dd0a2fSth160488 * This function "informs" libsldap that a client application has specified 1963e1dd0a2fSth160488 * a directory to use. The function obtains a DUAProfile, credentials, 1964e1dd0a2fSth160488 * and naming context. During all further operations on behalf 1965e1dd0a2fSth160488 * of the application requested a standalone schema libsldap will use 1966e1dd0a2fSth160488 * the information obtained by __ns_ldap_initStandalone() instead of 1967e1dd0a2fSth160488 * door_call(3C)ing ldap_cachemgr(1M). 1968e1dd0a2fSth160488 * 1969e1dd0a2fSth160488 * INPUT: 1970e1dd0a2fSth160488 * sa_conf - a structure describing where and in which way to obtain all 1971e1dd0a2fSth160488 * the configuration describing how to communicate to 1972e1dd0a2fSth160488 * a choosen LDAP directory, 1973e1dd0a2fSth160488 * errorp - an error object describing an error occured. 1974e1dd0a2fSth160488 */ 1975e1dd0a2fSth160488 ns_ldap_return_code 1976e1dd0a2fSth160488 __ns_ldap_initStandalone(const ns_standalone_conf_t *sa_conf, 1977e1dd0a2fSth160488 ns_ldap_error_t **errorp) { 1978e1dd0a2fSth160488 1979e1dd0a2fSth160488 ns_cred_t user_cred = {{NS_LDAP_AUTH_NONE, 1980e1dd0a2fSth160488 NS_LDAP_TLS_NONE, 1981e1dd0a2fSth160488 NS_LDAP_SASL_NONE, 1982e1dd0a2fSth160488 NS_LDAP_SASLOPT_NONE}, 1983e1dd0a2fSth160488 NULL, 1984e1dd0a2fSth160488 {NULL, NULL}}; 1985e1dd0a2fSth160488 char *dua_profile = NULL; 1986e1dd0a2fSth160488 char errmsg[MAXERROR]; 1987e1dd0a2fSth160488 ns_config_t *cfg; 1988e1dd0a2fSth160488 int ret_code; 1989e1dd0a2fSth160488 1990e1dd0a2fSth160488 if (sa_conf->SA_BIND_DN == NULL && sa_conf->SA_BIND_PWD != NULL || 1991e1dd0a2fSth160488 sa_conf->SA_BIND_DN != NULL && sa_conf->SA_BIND_PWD == NULL) { 1992e1dd0a2fSth160488 (void) snprintf(errmsg, 1993e1dd0a2fSth160488 sizeof (errmsg), 1994e1dd0a2fSth160488 gettext("Bind DN and bind password" 1995e1dd0a2fSth160488 " must both be provided\n")); 1996e1dd0a2fSth160488 MKERROR(LOG_ERR, 1997e1dd0a2fSth160488 *errorp, 1998e1dd0a2fSth160488 NS_CONFIG_NOTLOADED, 1999e1dd0a2fSth160488 strdup(errmsg), 2000e1dd0a2fSth160488 NS_LDAP_MEMORY); 2001e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 2002e1dd0a2fSth160488 } 2003e1dd0a2fSth160488 2004e1dd0a2fSth160488 switch (sa_conf->type) { 2005e1dd0a2fSth160488 case NS_LDAP_SERVER: 2006e1dd0a2fSth160488 if (sa_conf->SA_BIND_DN != NULL) { 2007e1dd0a2fSth160488 user_cred.cred.unix_cred.userID = sa_conf->SA_BIND_DN; 2008e1dd0a2fSth160488 user_cred.auth.type = NS_LDAP_AUTH_SIMPLE; 2009e1dd0a2fSth160488 } 2010e1dd0a2fSth160488 2011e1dd0a2fSth160488 if (sa_conf->SA_BIND_PWD != NULL) { 2012e1dd0a2fSth160488 user_cred.cred.unix_cred.passwd = sa_conf->SA_BIND_PWD; 2013e1dd0a2fSth160488 } 2014e1dd0a2fSth160488 2015e1dd0a2fSth160488 if (sa_conf->SA_AUTH != NULL) { 2016e1dd0a2fSth160488 user_cred.auth.type = sa_conf->SA_AUTH->type; 2017e1dd0a2fSth160488 user_cred.auth.tlstype = sa_conf->SA_AUTH->tlstype; 2018e1dd0a2fSth160488 user_cred.auth.saslmech = sa_conf->SA_AUTH->saslmech; 2019e1dd0a2fSth160488 user_cred.auth.saslopt = sa_conf->SA_AUTH->saslopt; 2020e1dd0a2fSth160488 } 2021e1dd0a2fSth160488 2022e1dd0a2fSth160488 if (sa_conf->SA_CERT_PATH != NULL) { 2023e1dd0a2fSth160488 user_cred.hostcertpath = sa_conf->SA_CERT_PATH; 2024e1dd0a2fSth160488 } 2025e1dd0a2fSth160488 2026e1dd0a2fSth160488 ret_code = __ns_ldap_getConnectionInfoFromDUA( 2027e1dd0a2fSth160488 &sa_conf->ds_profile.server, 2028e1dd0a2fSth160488 &user_cred, 2029e1dd0a2fSth160488 &dua_profile, 2030e1dd0a2fSth160488 NULL, 2031e1dd0a2fSth160488 errorp); 2032e1dd0a2fSth160488 if (ret_code != NS_LDAP_SUCCESS) { 2033e1dd0a2fSth160488 return (ret_code); 2034e1dd0a2fSth160488 } 2035e1dd0a2fSth160488 2036e1dd0a2fSth160488 cfg = __s_api_create_config_door_str(dua_profile, errorp); 2037e1dd0a2fSth160488 if (cfg == NULL) { 2038e1dd0a2fSth160488 free(dua_profile); 2039e1dd0a2fSth160488 return (NS_LDAP_CONFIG); 2040e1dd0a2fSth160488 } 2041e1dd0a2fSth160488 2042e1dd0a2fSth160488 if (sa_conf->SA_CERT_PATH != NULL) { 2043e1dd0a2fSth160488 char *certPathAttr; 2044e1dd0a2fSth160488 ParamIndexType type; 2045e1dd0a2fSth160488 2046e1dd0a2fSth160488 switch (cfg->version) { 2047e1dd0a2fSth160488 case NS_LDAP_V1: 2048e1dd0a2fSth160488 certPathAttr = "NS_LDAP_CERT_PATH"; 2049e1dd0a2fSth160488 break; 2050e1dd0a2fSth160488 default: /* Version 2 */ 2051e1dd0a2fSth160488 certPathAttr = "NS_LDAP_HOST_CERTPATH"; 2052e1dd0a2fSth160488 break; 2053e1dd0a2fSth160488 } 2054e1dd0a2fSth160488 2055e1dd0a2fSth160488 if (__s_api_get_versiontype(cfg, 2056e1dd0a2fSth160488 certPathAttr, 2057e1dd0a2fSth160488 &type) == 0 && 2058e1dd0a2fSth160488 (ret_code = __ns_ldap_setParamValue(cfg, 2059e1dd0a2fSth160488 type, 2060e1dd0a2fSth160488 sa_conf->SA_CERT_PATH, 2061e1dd0a2fSth160488 errorp)) != NS_LDAP_SUCCESS) { 2062e1dd0a2fSth160488 __s_api_destroy_config(cfg); 2063e1dd0a2fSth160488 return (ret_code); 2064e1dd0a2fSth160488 } 2065e1dd0a2fSth160488 } 2066e1dd0a2fSth160488 2067e1dd0a2fSth160488 if (sa_conf->SA_BIND_DN != NULL && 2068e1dd0a2fSth160488 sa_conf->SA_BIND_PWD != NULL) { 2069434c5a06SMilan Jurik char *authMethods; 2070e1dd0a2fSth160488 2071434c5a06SMilan Jurik authMethods = __s_api_strValue(cfg, NS_LDAP_AUTH_P, 2072e1dd0a2fSth160488 NS_FILE_FMT); 2073e1dd0a2fSth160488 if (authMethods != NULL && 2074e1dd0a2fSth160488 strstr(authMethods, "sasl/GSSAPI") != NULL) { 2075e1dd0a2fSth160488 /* 2076e1dd0a2fSth160488 * The received DUAProfile specifies 2077e1dd0a2fSth160488 * sasl/GSSAPI as an auth. mechanism. 2078e1dd0a2fSth160488 * The bind DN and password will be 2079e1dd0a2fSth160488 * ignored. 2080e1dd0a2fSth160488 */ 2081e1dd0a2fSth160488 syslog(LOG_INFO, gettext("sasl/GSSAPI will be " 2082e1dd0a2fSth160488 "used as an authentication method. " 2083e1dd0a2fSth160488 "The bind DN and password will " 2084e1dd0a2fSth160488 "be ignored.\n")); 2085434c5a06SMilan Jurik free(authMethods); 2086e1dd0a2fSth160488 break; 2087e1dd0a2fSth160488 } 2088e1dd0a2fSth160488 2089434c5a06SMilan Jurik if (authMethods != NULL) 2090434c5a06SMilan Jurik free(authMethods); 2091434c5a06SMilan Jurik 2092e1dd0a2fSth160488 if (__ns_ldap_setParamValue(cfg, 2093e1dd0a2fSth160488 NS_LDAP_BINDDN_P, 2094e1dd0a2fSth160488 sa_conf->SA_BIND_DN, 2095e1dd0a2fSth160488 errorp) != NS_LDAP_SUCCESS) { 2096e1dd0a2fSth160488 __s_api_destroy_config(cfg); 2097e1dd0a2fSth160488 return (NS_LDAP_CONFIG); 2098e1dd0a2fSth160488 } 2099e1dd0a2fSth160488 2100e1dd0a2fSth160488 if (__ns_ldap_setParamValue(cfg, 2101e1dd0a2fSth160488 NS_LDAP_BINDPASSWD_P, 2102e1dd0a2fSth160488 sa_conf->SA_BIND_PWD, 2103e1dd0a2fSth160488 errorp) != NS_LDAP_SUCCESS) { 2104e1dd0a2fSth160488 __s_api_destroy_config(cfg); 2105e1dd0a2fSth160488 return (NS_LDAP_CONFIG); 2106e1dd0a2fSth160488 } 2107e1dd0a2fSth160488 } 2108e1dd0a2fSth160488 2109e1dd0a2fSth160488 break; 2110e1dd0a2fSth160488 default: /* NS_CACHEMGR */ 2111e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 2112e1dd0a2fSth160488 } 2113e1dd0a2fSth160488 2114e1dd0a2fSth160488 __s_api_init_config(cfg); 2115ca190d8dSmichen /* Connection management should use the new config now. */ 2116ca190d8dSmichen __s_api_reinit_conn_mgmt_new_config(cfg); 2117e1dd0a2fSth160488 __ns_ldap_setServer(TRUE); 2118e1dd0a2fSth160488 2119e1dd0a2fSth160488 (void) mutex_lock(&dir_servers.listReplaceLock); 2120e1dd0a2fSth160488 if ((ret_code = initGlobalList(errorp)) != NS_SUCCESS) { 2121e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 2122e1dd0a2fSth160488 return (ret_code); 2123e1dd0a2fSth160488 } 2124e1dd0a2fSth160488 dir_servers.standalone = 1; 2125e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 2126e1dd0a2fSth160488 2127e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 2128e1dd0a2fSth160488 } 2129e1dd0a2fSth160488 2130e1dd0a2fSth160488 /* 2131e1dd0a2fSth160488 * INPUT: 2132e1dd0a2fSth160488 * serverAddr is the address of a server and 2133e1dd0a2fSth160488 * request is one of the following: 2134e1dd0a2fSth160488 * NS_CACHE_NEW: get a new server address, addr is ignored. 2135e1dd0a2fSth160488 * NS_CACHE_NORESP: get the next one, remove addr from list. 2136e1dd0a2fSth160488 * NS_CACHE_NEXT: get the next one, keep addr on list. 2137e1dd0a2fSth160488 * NS_CACHE_WRITE: get a non-replica server, if possible, if not, same 2138e1dd0a2fSth160488 * as NS_CACHE_NEXT. 2139e1dd0a2fSth160488 * addrType: 2140e1dd0a2fSth160488 * NS_CACHE_ADDR_IP: return server address as is, this is default. 2141e1dd0a2fSth160488 * NS_CACHE_ADDR_HOSTNAME: return server addess as FQDN format, only 2142e1dd0a2fSth160488 * self credential case requires such format. 2143e1dd0a2fSth160488 * OUTPUT: 2144e1dd0a2fSth160488 * ret 2145e1dd0a2fSth160488 * 2146e1dd0a2fSth160488 * a structure of type ns_server_info_t containing the server address 2147e1dd0a2fSth160488 * or name, server controls and supported SASL mechanisms. 2148e1dd0a2fSth160488 * NOTE: Caller should allocate space for the structure and free 2149e1dd0a2fSth160488 * all the space allocated by the function for the information contained 2150e1dd0a2fSth160488 * in the structure. 2151e1dd0a2fSth160488 * 2152e1dd0a2fSth160488 * error - an error object describing an error, if any. 2153e1dd0a2fSth160488 */ 2154e1dd0a2fSth160488 ns_ldap_return_code 2155e1dd0a2fSth160488 __s_api_findRootDSE(const char *request, 2156e1dd0a2fSth160488 const char *serverAddr, 2157e1dd0a2fSth160488 const char *addrType, 2158e1dd0a2fSth160488 ns_server_info_t *ret, 2159e1dd0a2fSth160488 ns_ldap_error_t **error) 2160e1dd0a2fSth160488 { 2161e1dd0a2fSth160488 dir_server_list_t *current_list = NULL; 2162e1dd0a2fSth160488 ns_ldap_return_code ret_code; 2163e1dd0a2fSth160488 long i = 0; 2164e1dd0a2fSth160488 int matched = FALSE; 2165e1dd0a2fSth160488 dir_server_t *server = NULL; 2166e1dd0a2fSth160488 char errmsg[MAXERROR]; 2167e1dd0a2fSth160488 2168e1dd0a2fSth160488 (void) mutex_lock(&dir_servers.listReplaceLock); 2169e1dd0a2fSth160488 if (dir_servers.list == NULL) { 2170e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 2171e1dd0a2fSth160488 (void) snprintf(errmsg, 2172e1dd0a2fSth160488 sizeof (errmsg), 2173e1dd0a2fSth160488 gettext("The list of root DSEs is empty: " 2174e1dd0a2fSth160488 "the Standalone mode was not properly initialized")); 2175e1dd0a2fSth160488 MKERROR(LOG_ERR, 2176e1dd0a2fSth160488 *error, 2177e1dd0a2fSth160488 NS_CONFIG_NOTLOADED, 2178e1dd0a2fSth160488 strdup(errmsg), 2179e1dd0a2fSth160488 NS_LDAP_MEMORY); 2180e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 2181e1dd0a2fSth160488 } 2182e1dd0a2fSth160488 2183e1dd0a2fSth160488 current_list = dir_servers.list; 2184e1dd0a2fSth160488 (void) rw_rdlock(¤t_list->listDestroyLock); 2185e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 2186e1dd0a2fSth160488 2187e1dd0a2fSth160488 /* 2188e1dd0a2fSth160488 * The code below is mostly the clone of the 2189e1dd0a2fSth160488 * ldap_cachemgr::cachemgr_getldap.c::getldap_get_serverInfo() function. 2190e1dd0a2fSth160488 * Currently we have two different server lists: one is maintained 2191e1dd0a2fSth160488 * by libsldap ('standalone' mode), the other is in ldap_cachemgr 2192e1dd0a2fSth160488 * (a part of its standard functionality). 2193e1dd0a2fSth160488 */ 2194e1dd0a2fSth160488 2195e1dd0a2fSth160488 /* 2196e1dd0a2fSth160488 * If NS_CACHE_NEW, or the server info is new, 2197e1dd0a2fSth160488 * starts from the beginning of the list. 2198e1dd0a2fSth160488 */ 2199e1dd0a2fSth160488 (void) mutex_lock(¤t_list->nsServers[0]->updateStatus); 2200e1dd0a2fSth160488 if (strcmp(request, NS_CACHE_NEW) == 0 || 2201e1dd0a2fSth160488 current_list->nsServers[0]->info == INFO_STATUS_NEW) { 2202e1dd0a2fSth160488 matched = TRUE; 2203e1dd0a2fSth160488 } 2204e1dd0a2fSth160488 (void) mutex_unlock(¤t_list->nsServers[i]->updateStatus); 2205e1dd0a2fSth160488 2206e1dd0a2fSth160488 for (i = 0; current_list->nsServers[i]; ++i) { 2207e1dd0a2fSth160488 /* 2208e1dd0a2fSth160488 * Lock the updateStatus mutex to 2209e1dd0a2fSth160488 * make sure the server status stays the same 2210e1dd0a2fSth160488 * while the data is being processed. 2211e1dd0a2fSth160488 */ 2212e1dd0a2fSth160488 if (matched == FALSE && 2213e1dd0a2fSth160488 strcmp(current_list->nsServers[i]->ip, 2214e1dd0a2fSth160488 serverAddr) == 0) { 2215e1dd0a2fSth160488 matched = TRUE; 2216e1dd0a2fSth160488 if (strcmp(request, NS_CACHE_NORESP) == 0) { 2217e1dd0a2fSth160488 2218e1dd0a2fSth160488 /* 2219e1dd0a2fSth160488 * if the server has already been removed, 2220e1dd0a2fSth160488 * don't bother. 2221e1dd0a2fSth160488 */ 2222e1dd0a2fSth160488 (void) mutex_lock(¤t_list-> 2223e1dd0a2fSth160488 nsServers[i]->updateStatus); 2224e1dd0a2fSth160488 if (current_list->nsServers[i]->status == 2225e1dd0a2fSth160488 INFO_SERVER_REMOVED) { 2226e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2227e1dd0a2fSth160488 nsServers[i]-> 2228e1dd0a2fSth160488 updateStatus); 2229e1dd0a2fSth160488 continue; 2230e1dd0a2fSth160488 } 2231e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2232e1dd0a2fSth160488 nsServers[i]-> 2233e1dd0a2fSth160488 updateStatus); 2234e1dd0a2fSth160488 2235e1dd0a2fSth160488 /* 2236e1dd0a2fSth160488 * if the information is new, 2237e1dd0a2fSth160488 * give this server one more chance. 2238e1dd0a2fSth160488 */ 2239e1dd0a2fSth160488 (void) mutex_lock(¤t_list-> 2240e1dd0a2fSth160488 nsServers[i]-> 2241e1dd0a2fSth160488 updateStatus); 2242e1dd0a2fSth160488 if (current_list->nsServers[i]->info == 2243e1dd0a2fSth160488 INFO_STATUS_NEW && 2244e1dd0a2fSth160488 current_list->nsServers[i]->status == 2245e1dd0a2fSth160488 INFO_SERVER_UP) { 2246e1dd0a2fSth160488 server = current_list->nsServers[i]; 2247e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2248e1dd0a2fSth160488 nsServers[i]-> 2249e1dd0a2fSth160488 updateStatus); 2250e1dd0a2fSth160488 break; 2251e1dd0a2fSth160488 } else { 2252e1dd0a2fSth160488 /* 2253e1dd0a2fSth160488 * it is recommended that 2254e1dd0a2fSth160488 * before removing the 2255e1dd0a2fSth160488 * server from the list, 2256e1dd0a2fSth160488 * the server should be 2257e1dd0a2fSth160488 * contacted one more time 2258e1dd0a2fSth160488 * to make sure that it is 2259e1dd0a2fSth160488 * really unavailable. 2260e1dd0a2fSth160488 * For now, just trust the client 2261e1dd0a2fSth160488 * (i.e., the sldap library) 2262e1dd0a2fSth160488 * that it knows what it is 2263e1dd0a2fSth160488 * doing and would not try 2264e1dd0a2fSth160488 * to mess up the server 2265e1dd0a2fSth160488 * list. 2266e1dd0a2fSth160488 */ 2267e1dd0a2fSth160488 current_list->nsServers[i]->status = 2268e1dd0a2fSth160488 INFO_SERVER_REMOVED; 2269e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2270e1dd0a2fSth160488 nsServers[i]-> 2271e1dd0a2fSth160488 updateStatus); 2272e1dd0a2fSth160488 continue; 2273e1dd0a2fSth160488 } 2274e1dd0a2fSth160488 } else { 2275e1dd0a2fSth160488 /* 2276e1dd0a2fSth160488 * req == NS_CACHE_NEXT or NS_CACHE_WRITE 2277e1dd0a2fSth160488 */ 2278e1dd0a2fSth160488 continue; 2279e1dd0a2fSth160488 } 2280e1dd0a2fSth160488 } 2281e1dd0a2fSth160488 2282e1dd0a2fSth160488 if (matched) { 2283e1dd0a2fSth160488 if (strcmp(request, NS_CACHE_WRITE) == 0) { 2284e1dd0a2fSth160488 /* 2285e1dd0a2fSth160488 * ldap_cachemgr checks here if the server 2286e1dd0a2fSth160488 * is not a non-replica server (a server 2287e1dd0a2fSth160488 * of type INFO_RW_WRITEABLE). But currently 2288e1dd0a2fSth160488 * it considers all the servers in its list 2289e1dd0a2fSth160488 * as those. 2290e1dd0a2fSth160488 */ 2291e1dd0a2fSth160488 (void) mutex_lock(¤t_list-> 2292e1dd0a2fSth160488 nsServers[i]-> 2293e1dd0a2fSth160488 updateStatus); 2294e1dd0a2fSth160488 if (current_list->nsServers[i]->status == 2295e1dd0a2fSth160488 INFO_SERVER_UP) { 2296e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2297e1dd0a2fSth160488 nsServers[i]-> 2298e1dd0a2fSth160488 updateStatus); 2299e1dd0a2fSth160488 server = current_list->nsServers[i]; 2300e1dd0a2fSth160488 break; 2301e1dd0a2fSth160488 } 2302e1dd0a2fSth160488 } else { 2303e1dd0a2fSth160488 (void) mutex_lock(¤t_list-> 2304e1dd0a2fSth160488 nsServers[i]-> 2305e1dd0a2fSth160488 updateStatus); 2306e1dd0a2fSth160488 if (current_list->nsServers[i]->status == 2307e1dd0a2fSth160488 INFO_SERVER_UP) { 2308e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2309e1dd0a2fSth160488 nsServers[i]-> 2310e1dd0a2fSth160488 updateStatus); 2311e1dd0a2fSth160488 server = current_list->nsServers[i]; 2312e1dd0a2fSth160488 break; 2313e1dd0a2fSth160488 } 2314e1dd0a2fSth160488 } 2315e1dd0a2fSth160488 2316e1dd0a2fSth160488 (void) mutex_unlock(¤t_list-> 2317e1dd0a2fSth160488 nsServers[i]-> 2318e1dd0a2fSth160488 updateStatus); 2319e1dd0a2fSth160488 } 2320e1dd0a2fSth160488 } 2321e1dd0a2fSth160488 2322e1dd0a2fSth160488 if (server == NULL) { 2323e1dd0a2fSth160488 (void) rw_unlock(¤t_list->listDestroyLock); 2324e1dd0a2fSth160488 (void) snprintf(errmsg, 2325e1dd0a2fSth160488 sizeof (errmsg), 2326e1dd0a2fSth160488 gettext("No servers are available")); 2327e1dd0a2fSth160488 MKERROR(LOG_ERR, 2328e1dd0a2fSth160488 *error, 2329e1dd0a2fSth160488 NS_CONFIG_NOTLOADED, 2330e1dd0a2fSth160488 strdup(errmsg), 2331e1dd0a2fSth160488 NS_LDAP_MEMORY); 2332e1dd0a2fSth160488 return (NS_LDAP_NOTFOUND); 2333e1dd0a2fSth160488 } 2334e1dd0a2fSth160488 2335e1dd0a2fSth160488 (void) mutex_lock(&server->updateStatus); 2336e1dd0a2fSth160488 server->info = INFO_STATUS_OLD; 2337e1dd0a2fSth160488 (void) mutex_unlock(&server->updateStatus); 2338e1dd0a2fSth160488 2339e1dd0a2fSth160488 if (ret == NULL) { 2340e1dd0a2fSth160488 (void) rw_unlock(¤t_list->listDestroyLock); 2341e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 2342e1dd0a2fSth160488 } 2343e1dd0a2fSth160488 2344e1dd0a2fSth160488 if (strcmp(addrType, NS_CACHE_ADDR_HOSTNAME) == 0) { 2345e1dd0a2fSth160488 ret_code = __s_api_ip2hostname(server->ip, &ret->serverFQDN); 2346e1dd0a2fSth160488 if (ret_code != NS_LDAP_SUCCESS) { 2347e1dd0a2fSth160488 (void) snprintf(errmsg, 2348e1dd0a2fSth160488 sizeof (errmsg), 2349e1dd0a2fSth160488 gettext("The %s address " 2350e1dd0a2fSth160488 "can not be resolved into " 2351e1dd0a2fSth160488 "a host name. Returning " 2352e1dd0a2fSth160488 "the address as it is."), 2353e1dd0a2fSth160488 server->ip); 2354e1dd0a2fSth160488 MKERROR(LOG_ERR, 2355e1dd0a2fSth160488 *error, 2356e1dd0a2fSth160488 NS_CONFIG_NOTLOADED, 2357e1dd0a2fSth160488 strdup(errmsg), 2358e1dd0a2fSth160488 NS_LDAP_MEMORY); 2359e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 2360e1dd0a2fSth160488 } 2361e1dd0a2fSth160488 } 2362e1dd0a2fSth160488 2363e1dd0a2fSth160488 ret->server = strdup(server->ip); 2364e1dd0a2fSth160488 2365e1dd0a2fSth160488 ret->controls = __s_api_cp2dArray(server->controls); 2366e1dd0a2fSth160488 ret->saslMechanisms = __s_api_cp2dArray(server->saslMech); 2367e1dd0a2fSth160488 2368e1dd0a2fSth160488 (void) rw_unlock(¤t_list->listDestroyLock); 2369e1dd0a2fSth160488 2370e1dd0a2fSth160488 return (NS_LDAP_SUCCESS); 2371e1dd0a2fSth160488 } 2372e1dd0a2fSth160488 2373e1dd0a2fSth160488 /* 2374e1dd0a2fSth160488 * This function iterates through the list of the configured LDAP servers 2375e1dd0a2fSth160488 * and "pings" those which are marked as removed or if any error occurred 2376e1dd0a2fSth160488 * during the previous receiving of the server's root DSE. If the 2377e1dd0a2fSth160488 * function is able to reach such a server and get its root DSE, it 2378e1dd0a2fSth160488 * marks the server as on-line. Otherwise, the server's status is set 2379e1dd0a2fSth160488 * to "Error". 2380e1dd0a2fSth160488 * For each server the function tries to connect to, it fires up 2381e1dd0a2fSth160488 * a separate thread and then waits until all the treads finish. 2382e1dd0a2fSth160488 * The function returns NS_LDAP_INTERNAL if the Standalone mode was not 2383e1dd0a2fSth160488 * initialized or was canceled prior to an invocation of 2384e1dd0a2fSth160488 * __ns_ldap_pingOfflineServers(). 2385e1dd0a2fSth160488 */ 2386e1dd0a2fSth160488 ns_ldap_return_code 2387e1dd0a2fSth160488 __ns_ldap_pingOfflineServers(void) 2388e1dd0a2fSth160488 { 2389e1dd0a2fSth160488 dir_server_list_t *current_list = NULL; 2390e1dd0a2fSth160488 ns_ldap_return_code retCode = NS_LDAP_SUCCESS; 2391e1dd0a2fSth160488 long srvListLength, i = 0; 2392e1dd0a2fSth160488 thread_t *thrPool, thrID; 2393e1dd0a2fSth160488 void *status = NULL; 2394e1dd0a2fSth160488 2395e1dd0a2fSth160488 (void) mutex_lock(&dir_servers.listReplaceLock); 2396e1dd0a2fSth160488 if (dir_servers.list == NULL) { 2397e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 2398e1dd0a2fSth160488 return (NS_LDAP_INTERNAL); 2399e1dd0a2fSth160488 } 2400e1dd0a2fSth160488 2401e1dd0a2fSth160488 current_list = dir_servers.list; 2402e1dd0a2fSth160488 (void) rw_wrlock(¤t_list->listDestroyLock); 2403e1dd0a2fSth160488 (void) mutex_unlock(&dir_servers.listReplaceLock); 2404e1dd0a2fSth160488 2405e1dd0a2fSth160488 while (current_list->nsServers[i] != NULL) { 2406e1dd0a2fSth160488 ++i; 2407e1dd0a2fSth160488 } 2408e1dd0a2fSth160488 srvListLength = i; 2409e1dd0a2fSth160488 2410e1dd0a2fSth160488 thrPool = calloc(srvListLength, sizeof (thread_t)); 2411e1dd0a2fSth160488 if (thrPool == NULL) { 2412e1dd0a2fSth160488 (void) rw_unlock(¤t_list->listDestroyLock); 2413e1dd0a2fSth160488 return (NS_LDAP_MEMORY); 2414e1dd0a2fSth160488 } 2415e1dd0a2fSth160488 2416e1dd0a2fSth160488 for (i = 0; i < srvListLength; ++i) { 2417e1dd0a2fSth160488 if (current_list->nsServers[i]->status != INFO_SERVER_REMOVED && 2418e1dd0a2fSth160488 current_list->nsServers[i]->status != INFO_SERVER_ERROR) { 2419e1dd0a2fSth160488 continue; 2420e1dd0a2fSth160488 } 2421e1dd0a2fSth160488 current_list->nsServers[i]->status = INFO_SERVER_CONNECTING; 2422e1dd0a2fSth160488 current_list->nsServers[i]->info = INFO_STATUS_NEW; 2423e1dd0a2fSth160488 2424e1dd0a2fSth160488 __s_api_free2dArray(current_list->nsServers[i]->controls); 2425e1dd0a2fSth160488 current_list->nsServers[i]->controls = NULL; 2426e1dd0a2fSth160488 __s_api_free2dArray(current_list->nsServers[i]->saslMech); 2427e1dd0a2fSth160488 current_list->nsServers[i]->saslMech = NULL; 2428e1dd0a2fSth160488 2429e1dd0a2fSth160488 switch (thr_create(NULL, 2430e1dd0a2fSth160488 0, 2431e1dd0a2fSth160488 create_ns_servers_entry, 2432e1dd0a2fSth160488 current_list->nsServers[i], 2433e1dd0a2fSth160488 0, 2434e1dd0a2fSth160488 &thrID)) { 2435e1dd0a2fSth160488 case EAGAIN: 2436e1dd0a2fSth160488 current_list->nsServers[i]->status = INFO_SERVER_ERROR; 2437e1dd0a2fSth160488 continue; 2438e1dd0a2fSth160488 case ENOMEM: 2439e1dd0a2fSth160488 current_list->nsServers[i]->status = INFO_SERVER_ERROR; 2440e1dd0a2fSth160488 retCode = NS_LDAP_MEMORY; 2441e1dd0a2fSth160488 break; 2442e1dd0a2fSth160488 default: 2443e1dd0a2fSth160488 thrPool[i] = thrID; 2444e1dd0a2fSth160488 continue; 2445e1dd0a2fSth160488 } 2446e1dd0a2fSth160488 /* A memory allocation error has occured */ 2447e1dd0a2fSth160488 break; 2448e1dd0a2fSth160488 2449e1dd0a2fSth160488 } 2450e1dd0a2fSth160488 2451e1dd0a2fSth160488 for (i = 0; i < srvListLength; ++i) { 2452e1dd0a2fSth160488 if (thrPool[i] != 0 && 2453e1dd0a2fSth160488 thr_join(thrPool[i], NULL, &status) == 0) { 2454e1dd0a2fSth160488 if (status == NULL) { 2455e1dd0a2fSth160488 current_list->nsServers[i]->status = 2456e1dd0a2fSth160488 INFO_SERVER_ERROR; 2457e1dd0a2fSth160488 retCode = NS_LDAP_MEMORY; 2458e1dd0a2fSth160488 } 2459e1dd0a2fSth160488 free(status); 2460e1dd0a2fSth160488 } 2461e1dd0a2fSth160488 } 2462e1dd0a2fSth160488 2463e1dd0a2fSth160488 (void) rw_unlock(¤t_list->listDestroyLock); 2464e1dd0a2fSth160488 2465e1dd0a2fSth160488 free(thrPool); 2466e1dd0a2fSth160488 2467e1dd0a2fSth160488 return (retCode); 2468e1dd0a2fSth160488 } 2469