1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <stdlib.h> 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <errno.h> 32*0Sstevel@tonic-gate #include <string.h> 33*0Sstevel@tonic-gate #include <synch.h> 34*0Sstevel@tonic-gate #include <time.h> 35*0Sstevel@tonic-gate #include <libintl.h> 36*0Sstevel@tonic-gate #include <thread.h> 37*0Sstevel@tonic-gate #include <syslog.h> 38*0Sstevel@tonic-gate #include <sys/mman.h> 39*0Sstevel@tonic-gate #include <nsswitch.h> 40*0Sstevel@tonic-gate #include <nss_dbdefs.h> 41*0Sstevel@tonic-gate #include "solaris-priv.h" 42*0Sstevel@tonic-gate #include "ns_sldap.h" 43*0Sstevel@tonic-gate #include "ns_internal.h" 44*0Sstevel@tonic-gate #include "ns_cache_door.h" 45*0Sstevel@tonic-gate #include <sys/stat.h> 46*0Sstevel@tonic-gate #include <fcntl.h> 47*0Sstevel@tonic-gate #include <procfs.h> 48*0Sstevel@tonic-gate #include <unistd.h> 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate extern unsigned int _sleep(unsigned int); 51*0Sstevel@tonic-gate extern int ldap_sasl_cram_md5_bind_s(LDAP *, char *, struct berval *, 52*0Sstevel@tonic-gate LDAPControl **, LDAPControl **); 53*0Sstevel@tonic-gate extern int ldapssl_install_gethostbyaddr(LDAP *ld, const char *skip); 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate static int openConnection(LDAP **, const char *, const ns_cred_t *, 56*0Sstevel@tonic-gate int, ns_ldap_error_t **, int, int); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate static mutex_t sessionPoolLock = DEFAULTMUTEX; 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate static Connection **sessionPool = NULL; 61*0Sstevel@tonic-gate static int sessionPoolSize = 0; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate static mutex_t nscdLock = DEFAULTMUTEX; 65*0Sstevel@tonic-gate static int nscdChecked = 0; 66*0Sstevel@tonic-gate static pid_t checkedPid = -1; 67*0Sstevel@tonic-gate static int isNscd = 0; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* 71*0Sstevel@tonic-gate * Check /proc/PID/psinfo to see if this process is nscd 72*0Sstevel@tonic-gate * If it is, treat connection as NS_LDAP_KEEP_CONN, to reduce 73*0Sstevel@tonic-gate * constant reconnects for many operations. 74*0Sstevel@tonic-gate * A more complete solution is to develop true connection pooling. 75*0Sstevel@tonic-gate * However, this is much better than a new connection for every request. 76*0Sstevel@tonic-gate */ 77*0Sstevel@tonic-gate static int 78*0Sstevel@tonic-gate nscd_proc() 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate pid_t my_pid; 81*0Sstevel@tonic-gate psinfo_t pinfo; 82*0Sstevel@tonic-gate char fname[BUFSIZ]; 83*0Sstevel@tonic-gate int ret; 84*0Sstevel@tonic-gate int fd; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate /* Don't bother checking if this process isn't root. */ 87*0Sstevel@tonic-gate /* It can't be nscd */ 88*0Sstevel@tonic-gate if (getuid() != 0) 89*0Sstevel@tonic-gate return (0); 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate my_pid = getpid(); 92*0Sstevel@tonic-gate if (nscdChecked && (my_pid == checkedPid)) { 93*0Sstevel@tonic-gate return (isNscd); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate (void) mutex_lock(&nscdLock); 96*0Sstevel@tonic-gate if (nscdChecked && (my_pid == checkedPid)) { 97*0Sstevel@tonic-gate (void) mutex_unlock(&nscdLock); 98*0Sstevel@tonic-gate return (isNscd); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate nscdChecked = 1; 101*0Sstevel@tonic-gate checkedPid = my_pid; 102*0Sstevel@tonic-gate isNscd = 0; 103*0Sstevel@tonic-gate if (snprintf(fname, BUFSIZ, "/proc/%d/psinfo", my_pid) != 0) { 104*0Sstevel@tonic-gate if ((fd = open(fname, O_RDONLY)) > 0) { 105*0Sstevel@tonic-gate ret = read(fd, &pinfo, sizeof (psinfo_t)); 106*0Sstevel@tonic-gate (void) close(fd); 107*0Sstevel@tonic-gate if (ret == sizeof (psinfo_t) && 108*0Sstevel@tonic-gate (strcmp(pinfo.pr_fname, "nscd") == 0)) { 109*0Sstevel@tonic-gate /* process runs as root and is named nscd */ 110*0Sstevel@tonic-gate /* that's good enough for now */ 111*0Sstevel@tonic-gate isNscd = 1; 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate (void) mutex_unlock(&nscdLock); 116*0Sstevel@tonic-gate return (isNscd); 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * This function requests a server from the cache manager through 121*0Sstevel@tonic-gate * the door functionality 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate static int 125*0Sstevel@tonic-gate __s_api_requestServer(const char *request, const char *server, 126*0Sstevel@tonic-gate ns_server_info_t *ret, ns_ldap_error_t **error) 127*0Sstevel@tonic-gate { 128*0Sstevel@tonic-gate union { 129*0Sstevel@tonic-gate ldap_data_t s_d; 130*0Sstevel@tonic-gate char s_b[DOORBUFFERSIZE]; 131*0Sstevel@tonic-gate } space; 132*0Sstevel@tonic-gate ldap_data_t *sptr; 133*0Sstevel@tonic-gate int ndata; 134*0Sstevel@tonic-gate int adata; 135*0Sstevel@tonic-gate char errstr[MAXERROR]; 136*0Sstevel@tonic-gate const char *ireq; 137*0Sstevel@tonic-gate char *rbuf, *ptr, *rest; 138*0Sstevel@tonic-gate char *dptr; 139*0Sstevel@tonic-gate char **mptr, **mptr1, **cptr, **cptr1; 140*0Sstevel@tonic-gate int mcnt, ccnt; 141*0Sstevel@tonic-gate char **servers; 142*0Sstevel@tonic-gate int rc; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate if (ret == NULL || error == NULL) { 145*0Sstevel@tonic-gate return (NS_LDAP_OP_FAILED); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate (void) memset(ret, 0, sizeof (ns_server_info_t)); 148*0Sstevel@tonic-gate *error = NULL; 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate (void) memset(space.s_b, 0, DOORBUFFERSIZE); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate if (request == NULL) 153*0Sstevel@tonic-gate ireq = NS_CACHE_NEW; 154*0Sstevel@tonic-gate else 155*0Sstevel@tonic-gate ireq = request; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate adata = (sizeof (ldap_call_t) + strlen(ireq) +1); 158*0Sstevel@tonic-gate if (server != NULL) { 159*0Sstevel@tonic-gate adata += strlen(DOORLINESEP) + 1; 160*0Sstevel@tonic-gate adata += strlen(server) + 1; 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate ndata = sizeof (space); 163*0Sstevel@tonic-gate space.s_d.ldap_call.ldap_callnumber = GETLDAPSERVER; 164*0Sstevel@tonic-gate (void) strcpy(space.s_d.ldap_call.ldap_u.domainname, ireq); 165*0Sstevel@tonic-gate if (server != NULL) { 166*0Sstevel@tonic-gate (void) strcat(space.s_d.ldap_call.ldap_u.domainname, 167*0Sstevel@tonic-gate DOORLINESEP); 168*0Sstevel@tonic-gate (void) strcat(space.s_d.ldap_call.ldap_u.domainname, server); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate sptr = &space.s_d; 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) { 173*0Sstevel@tonic-gate case SUCCESS: 174*0Sstevel@tonic-gate break; 175*0Sstevel@tonic-gate /* this case is for when the $mgr is not running, but ldapclient */ 176*0Sstevel@tonic-gate /* is trying to initialize things */ 177*0Sstevel@tonic-gate case NOSERVER: 178*0Sstevel@tonic-gate /* get first server from config list unavailable otherwise */ 179*0Sstevel@tonic-gate servers = NULL; 180*0Sstevel@tonic-gate rc = __s_api_getServers(&servers, error); 181*0Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) { 182*0Sstevel@tonic-gate if (servers != NULL) { 183*0Sstevel@tonic-gate __s_api_free2dArray(servers); 184*0Sstevel@tonic-gate servers = NULL; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate return (rc); 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate if (servers == NULL || servers[0] == NULL) { 189*0Sstevel@tonic-gate __s_api_free2dArray(servers); 190*0Sstevel@tonic-gate servers = NULL; 191*0Sstevel@tonic-gate (void) sprintf(errstr, 192*0Sstevel@tonic-gate gettext("No server found in configuration")); 193*0Sstevel@tonic-gate MKERROR(LOG_ERR, *error, NS_CONFIG_NODEFAULT, 194*0Sstevel@tonic-gate strdup(errstr), NULL); 195*0Sstevel@tonic-gate return (NS_LDAP_CONFIG); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate ret->server = strdup(servers[0]); 198*0Sstevel@tonic-gate if (ret->server == NULL) { 199*0Sstevel@tonic-gate __s_api_free2dArray(servers); 200*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate ret->saslMechanisms = NULL; 203*0Sstevel@tonic-gate ret->controls = NULL; 204*0Sstevel@tonic-gate __s_api_free2dArray(servers); 205*0Sstevel@tonic-gate servers = NULL; 206*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 207*0Sstevel@tonic-gate case NOTFOUND: 208*0Sstevel@tonic-gate default: 209*0Sstevel@tonic-gate return (NS_LDAP_OP_FAILED); 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate /* copy info from door call return structure here */ 213*0Sstevel@tonic-gate rbuf = space.s_d.ldap_ret.ldap_u.config; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* Get the host */ 216*0Sstevel@tonic-gate ptr = strtok_r(rbuf, DOORLINESEP, &rest); 217*0Sstevel@tonic-gate if (ptr == NULL) { 218*0Sstevel@tonic-gate (void) sprintf(errstr, gettext("No server returned from " 219*0Sstevel@tonic-gate "ldap_cachemgr")); 220*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *error, NS_CONFIG_CACHEMGR, 221*0Sstevel@tonic-gate strdup(errstr), NULL); 222*0Sstevel@tonic-gate return (NS_LDAP_OP_FAILED); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate ret->server = strdup(ptr); 225*0Sstevel@tonic-gate if (ret->server == NULL) { 226*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* get the Supported Controls/SASL mechs */ 230*0Sstevel@tonic-gate mptr = NULL; 231*0Sstevel@tonic-gate mcnt = 0; 232*0Sstevel@tonic-gate cptr = NULL; 233*0Sstevel@tonic-gate ccnt = 0; 234*0Sstevel@tonic-gate for (; ; ) { 235*0Sstevel@tonic-gate ptr = strtok_r(NULL, DOORLINESEP, &rest); 236*0Sstevel@tonic-gate if (ptr == NULL) 237*0Sstevel@tonic-gate break; 238*0Sstevel@tonic-gate if (strncasecmp(ptr, _SASLMECHANISM, 239*0Sstevel@tonic-gate _SASLMECHANISM_LEN) == 0) { 240*0Sstevel@tonic-gate dptr = strchr(ptr, '='); 241*0Sstevel@tonic-gate if (dptr == NULL) 242*0Sstevel@tonic-gate continue; 243*0Sstevel@tonic-gate dptr++; 244*0Sstevel@tonic-gate mptr1 = (char **)realloc((void *)mptr, 245*0Sstevel@tonic-gate sizeof (char *) * (mcnt+2)); 246*0Sstevel@tonic-gate if (mptr1 == NULL) { 247*0Sstevel@tonic-gate __s_api_free2dArray(mptr); 248*0Sstevel@tonic-gate if (sptr != &space.s_d) { 249*0Sstevel@tonic-gate (void) munmap((char *)sptr, ndata); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate __s_api_free2dArray(cptr); 252*0Sstevel@tonic-gate free(ret->server); 253*0Sstevel@tonic-gate ret->server = NULL; 254*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate mptr = mptr1; 257*0Sstevel@tonic-gate mptr[mcnt] = strdup(dptr); 258*0Sstevel@tonic-gate if (mptr[mcnt] == NULL) { 259*0Sstevel@tonic-gate if (sptr != &space.s_d) { 260*0Sstevel@tonic-gate (void) munmap((char *)sptr, ndata); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate __s_api_free2dArray(cptr); 263*0Sstevel@tonic-gate cptr = NULL; 264*0Sstevel@tonic-gate __s_api_free2dArray(mptr); 265*0Sstevel@tonic-gate mptr = NULL; 266*0Sstevel@tonic-gate free(ret->server); 267*0Sstevel@tonic-gate ret->server = NULL; 268*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate mcnt++; 271*0Sstevel@tonic-gate mptr[mcnt] = NULL; 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate if (strncasecmp(ptr, _SUPPORTEDCONTROL, 274*0Sstevel@tonic-gate _SUPPORTEDCONTROL_LEN) == 0) { 275*0Sstevel@tonic-gate dptr = strchr(ptr, '='); 276*0Sstevel@tonic-gate if (dptr == NULL) 277*0Sstevel@tonic-gate continue; 278*0Sstevel@tonic-gate dptr++; 279*0Sstevel@tonic-gate cptr1 = (char **)realloc((void *)cptr, 280*0Sstevel@tonic-gate sizeof (char *) * (ccnt+2)); 281*0Sstevel@tonic-gate if (cptr1 == NULL) { 282*0Sstevel@tonic-gate if (sptr != &space.s_d) { 283*0Sstevel@tonic-gate (void) munmap((char *)sptr, ndata); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate __s_api_free2dArray(cptr); 286*0Sstevel@tonic-gate __s_api_free2dArray(mptr); 287*0Sstevel@tonic-gate mptr = NULL; 288*0Sstevel@tonic-gate free(ret->server); 289*0Sstevel@tonic-gate ret->server = NULL; 290*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate cptr = cptr1; 293*0Sstevel@tonic-gate cptr[ccnt] = strdup(dptr); 294*0Sstevel@tonic-gate if (cptr[ccnt] == NULL) { 295*0Sstevel@tonic-gate if (sptr != &space.s_d) { 296*0Sstevel@tonic-gate (void) munmap((char *)sptr, ndata); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate __s_api_free2dArray(cptr); 299*0Sstevel@tonic-gate cptr = NULL; 300*0Sstevel@tonic-gate __s_api_free2dArray(mptr); 301*0Sstevel@tonic-gate mptr = NULL; 302*0Sstevel@tonic-gate free(ret->server); 303*0Sstevel@tonic-gate ret->server = NULL; 304*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate ccnt++; 307*0Sstevel@tonic-gate cptr[ccnt] = NULL; 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate if (mptr != NULL) { 311*0Sstevel@tonic-gate ret->saslMechanisms = mptr; 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate if (cptr != NULL) { 314*0Sstevel@tonic-gate ret->controls = cptr; 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate /* clean up door call */ 319*0Sstevel@tonic-gate if (sptr != &space.s_d) { 320*0Sstevel@tonic-gate (void) munmap((char *)sptr, ndata); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate *error = NULL; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate #ifdef DEBUG 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* 330*0Sstevel@tonic-gate * printCred(): prints the credential structure 331*0Sstevel@tonic-gate */ 332*0Sstevel@tonic-gate static void 333*0Sstevel@tonic-gate printCred(FILE *fp, const ns_cred_t *cred) 334*0Sstevel@tonic-gate { 335*0Sstevel@tonic-gate if (fp == NULL) { 336*0Sstevel@tonic-gate (void) fprintf(fp, "printCred: fp is NULL\n"); 337*0Sstevel@tonic-gate return; 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate if (cred == NULL) { 340*0Sstevel@tonic-gate (void) fprintf(fp, "printCred: cred is NULL\n"); 341*0Sstevel@tonic-gate return; 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate (void) fprintf(fp, "AuthType=%d\n", cred->auth.type); 345*0Sstevel@tonic-gate (void) fprintf(fp, "TlsType=%d\n", cred->auth.tlstype); 346*0Sstevel@tonic-gate (void) fprintf(fp, "SaslMech=%d\n", cred->auth.saslmech); 347*0Sstevel@tonic-gate (void) fprintf(fp, "SaslOpt=%d\n", cred->auth.saslopt); 348*0Sstevel@tonic-gate if (cred->hostcertpath) 349*0Sstevel@tonic-gate (void) fprintf(fp, "hostCertPath=%s\n", cred->hostcertpath); 350*0Sstevel@tonic-gate if (cred->cred.unix_cred.userID) 351*0Sstevel@tonic-gate (void) fprintf(fp, "userID=%s\n", cred->cred.unix_cred.userID); 352*0Sstevel@tonic-gate if (cred->cred.unix_cred.passwd) 353*0Sstevel@tonic-gate (void) fprintf(fp, "passwd=%s\n", cred->cred.unix_cred.passwd); 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate /* 357*0Sstevel@tonic-gate * printConnection(): prints the connection structure 358*0Sstevel@tonic-gate */ 359*0Sstevel@tonic-gate static void 360*0Sstevel@tonic-gate printConnection(FILE *fp, Connection *con) 361*0Sstevel@tonic-gate { 362*0Sstevel@tonic-gate if (fp == NULL || con == NULL) 363*0Sstevel@tonic-gate return; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate (void) fprintf(fp, "connectionID=%d\n", con->connectionId); 366*0Sstevel@tonic-gate (void) fprintf(fp, "usedBit=%d\n", con->usedBit); 367*0Sstevel@tonic-gate (void) fprintf(fp, "threadID=%d\n", con->threadID); 368*0Sstevel@tonic-gate if (con->serverAddr) { 369*0Sstevel@tonic-gate (void) fprintf(fp, "serverAddr=%s\n", con->serverAddr); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate printCred(fp, con->auth); 372*0Sstevel@tonic-gate (void) fprintf(fp, "-----------------------------------------------\n"); 373*0Sstevel@tonic-gate fflush(fp); 374*0Sstevel@tonic-gate } 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate #endif /* DEBUG */ 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* 380*0Sstevel@tonic-gate * addConnection(): inserts a connection in the connection list. 381*0Sstevel@tonic-gate * It will also sets use bit and the thread Id for the thread 382*0Sstevel@tonic-gate * using the connection for the first time. 383*0Sstevel@tonic-gate * Returns: -1 = failure, new Connection ID = success 384*0Sstevel@tonic-gate */ 385*0Sstevel@tonic-gate static int 386*0Sstevel@tonic-gate addConnection(Connection *con) 387*0Sstevel@tonic-gate { 388*0Sstevel@tonic-gate int i; 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate if (!con) 391*0Sstevel@tonic-gate return (-1); 392*0Sstevel@tonic-gate #ifdef DEBUG 393*0Sstevel@tonic-gate (void) fprintf(stderr, "Adding connection thrid=%d\n", con->threadID); 394*0Sstevel@tonic-gate #endif /* DEBUG */ 395*0Sstevel@tonic-gate (void) mutex_lock(&sessionPoolLock); 396*0Sstevel@tonic-gate if (sessionPool == NULL) { 397*0Sstevel@tonic-gate sessionPoolSize = SESSION_CACHE_INC; 398*0Sstevel@tonic-gate sessionPool = calloc(sessionPoolSize, 399*0Sstevel@tonic-gate sizeof (struct connection **)); 400*0Sstevel@tonic-gate if (!sessionPool) { 401*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 402*0Sstevel@tonic-gate return (-1); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate #ifdef DEBUG 405*0Sstevel@tonic-gate (void) fprintf(stderr, "Initialized sessionPool\n"); 406*0Sstevel@tonic-gate #endif /* DEBUG */ 407*0Sstevel@tonic-gate } 408*0Sstevel@tonic-gate for (i = 0; (i < sessionPoolSize) && (sessionPool[i] != NULL); ++i) 409*0Sstevel@tonic-gate ; 410*0Sstevel@tonic-gate if (i == sessionPoolSize) { 411*0Sstevel@tonic-gate /* run out of array, need to increase sessionPool */ 412*0Sstevel@tonic-gate Connection **cl; 413*0Sstevel@tonic-gate cl = (Connection **) realloc(sessionPool, 414*0Sstevel@tonic-gate (sessionPoolSize + SESSION_CACHE_INC) * 415*0Sstevel@tonic-gate sizeof (Connection *)); 416*0Sstevel@tonic-gate if (!cl) { 417*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 418*0Sstevel@tonic-gate return (-1); 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate (void) memset(cl + sessionPoolSize, 0, 421*0Sstevel@tonic-gate SESSION_CACHE_INC * sizeof (struct connection *)); 422*0Sstevel@tonic-gate sessionPool = cl; 423*0Sstevel@tonic-gate sessionPoolSize += SESSION_CACHE_INC; 424*0Sstevel@tonic-gate #ifdef DEBUG 425*0Sstevel@tonic-gate (void) fprintf(stderr, "Increased sessionPoolSize to: %d\n", 426*0Sstevel@tonic-gate sessionPoolSize); 427*0Sstevel@tonic-gate #endif /* DEBUG */ 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate sessionPool[i] = con; 430*0Sstevel@tonic-gate con->usedBit = B_TRUE; 431*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 432*0Sstevel@tonic-gate con->connectionId = i + CONID_OFFSET; 433*0Sstevel@tonic-gate #ifdef DEBUG 434*0Sstevel@tonic-gate (void) fprintf(stderr, "Connection added [%d]\n", i); 435*0Sstevel@tonic-gate printConnection(stderr, con); 436*0Sstevel@tonic-gate #endif /* DEBUG */ 437*0Sstevel@tonic-gate return (i + CONID_OFFSET); 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate /* 441*0Sstevel@tonic-gate * See if the specified session matches a currently available 442*0Sstevel@tonic-gate */ 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate static int 445*0Sstevel@tonic-gate findConnectionById(int flags, const ns_cred_t *auth, ConnectionID cID, 446*0Sstevel@tonic-gate Connection **conp) 447*0Sstevel@tonic-gate { 448*0Sstevel@tonic-gate Connection *cp; 449*0Sstevel@tonic-gate int id; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if ((conp == NULL) || (auth == NULL) || cID < CONID_OFFSET) 452*0Sstevel@tonic-gate return (-1); 453*0Sstevel@tonic-gate *conp = NULL; 454*0Sstevel@tonic-gate if (sessionPool == NULL) 455*0Sstevel@tonic-gate return (-1); 456*0Sstevel@tonic-gate id = cID - CONID_OFFSET; 457*0Sstevel@tonic-gate if (id < 0 || id >= sessionPoolSize) 458*0Sstevel@tonic-gate return (-1); 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate (void) mutex_lock(&sessionPoolLock); 461*0Sstevel@tonic-gate if (sessionPool[id] == NULL) { 462*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 463*0Sstevel@tonic-gate return (-1); 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate cp = sessionPool[id]; 466*0Sstevel@tonic-gate 467*0Sstevel@tonic-gate /* 468*0Sstevel@tonic-gate * Make sure the connection has the same type of authentication method 469*0Sstevel@tonic-gate */ 470*0Sstevel@tonic-gate if ((cp->usedBit) || 471*0Sstevel@tonic-gate (cp->auth->auth.type != auth->auth.type) || 472*0Sstevel@tonic-gate (cp->auth->auth.tlstype != auth->auth.tlstype) || 473*0Sstevel@tonic-gate (cp->auth->auth.saslmech != auth->auth.saslmech) || 474*0Sstevel@tonic-gate (cp->auth->auth.saslopt != auth->auth.saslopt)) { 475*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 476*0Sstevel@tonic-gate return (-1); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate if ((((cp->auth->auth.type == NS_LDAP_AUTH_SASL) && 479*0Sstevel@tonic-gate ((cp->auth->auth.saslmech == NS_LDAP_SASL_CRAM_MD5) || 480*0Sstevel@tonic-gate (cp->auth->auth.saslmech == NS_LDAP_SASL_DIGEST_MD5))) || 481*0Sstevel@tonic-gate (cp->auth->auth.type == NS_LDAP_AUTH_SIMPLE)) && 482*0Sstevel@tonic-gate ((cp->auth->cred.unix_cred.userID == NULL) || 483*0Sstevel@tonic-gate (strcasecmp(cp->auth->cred.unix_cred.userID, 484*0Sstevel@tonic-gate auth->cred.unix_cred.userID) != 0))) { 485*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 486*0Sstevel@tonic-gate return (-1); 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate /* An existing connection is found but it needs to be reset */ 489*0Sstevel@tonic-gate if (flags & NS_LDAP_NEW_CONN) { 490*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 491*0Sstevel@tonic-gate DropConnection(cID, 0); 492*0Sstevel@tonic-gate return (-1); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate /* found an available connection */ 495*0Sstevel@tonic-gate cp->usedBit = B_TRUE; 496*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 497*0Sstevel@tonic-gate cp->threadID = thr_self(); 498*0Sstevel@tonic-gate *conp = cp; 499*0Sstevel@tonic-gate return (cID); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate /* 503*0Sstevel@tonic-gate * findConnection(): find an available connection from the list 504*0Sstevel@tonic-gate * that matches the criteria specified in Connection structure. 505*0Sstevel@tonic-gate * If serverAddr is NULL, then find a connection to any server 506*0Sstevel@tonic-gate * as long as it matches the rest of the parameters. 507*0Sstevel@tonic-gate * Returns: -1 = failure, the Connection ID found = success. 508*0Sstevel@tonic-gate */ 509*0Sstevel@tonic-gate static int 510*0Sstevel@tonic-gate findConnection(const char *serverAddr, const ns_cred_t *auth, Connection **conp) 511*0Sstevel@tonic-gate { 512*0Sstevel@tonic-gate Connection *cp; 513*0Sstevel@tonic-gate int i; 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate if (auth == NULL || conp == NULL) 516*0Sstevel@tonic-gate return (-1); 517*0Sstevel@tonic-gate *conp = NULL; 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate #ifdef DEBUG 520*0Sstevel@tonic-gate (void) fprintf(stderr, "Find connection\n"); 521*0Sstevel@tonic-gate (void) fprintf(stderr, "Looking for ....\n"); 522*0Sstevel@tonic-gate if (serverAddr && *serverAddr) 523*0Sstevel@tonic-gate (void) fprintf(stderr, "serverAddr=%s\n", serverAddr); 524*0Sstevel@tonic-gate else 525*0Sstevel@tonic-gate (void) fprintf(stderr, "serverAddr=NULL\n"); 526*0Sstevel@tonic-gate printCred(stderr, auth); 527*0Sstevel@tonic-gate fflush(stderr); 528*0Sstevel@tonic-gate #endif /* DEBUG */ 529*0Sstevel@tonic-gate if (sessionPool == NULL) 530*0Sstevel@tonic-gate return (-1); 531*0Sstevel@tonic-gate (void) mutex_lock(&sessionPoolLock); 532*0Sstevel@tonic-gate for (i = 0; i < sessionPoolSize; ++i) { 533*0Sstevel@tonic-gate if (sessionPool[i] == NULL) 534*0Sstevel@tonic-gate continue; 535*0Sstevel@tonic-gate cp = sessionPool[i]; 536*0Sstevel@tonic-gate #ifdef DEBUG 537*0Sstevel@tonic-gate (void) fprintf(stderr, "checking connection [%d] ....\n", i); 538*0Sstevel@tonic-gate printConnection(stderr, cp); 539*0Sstevel@tonic-gate #endif /* DEBUG */ 540*0Sstevel@tonic-gate if ((cp->usedBit) || 541*0Sstevel@tonic-gate (cp->auth->auth.type != auth->auth.type) || 542*0Sstevel@tonic-gate (cp->auth->auth.tlstype != auth->auth.tlstype) || 543*0Sstevel@tonic-gate (cp->auth->auth.saslmech != auth->auth.saslmech) || 544*0Sstevel@tonic-gate (cp->auth->auth.saslopt != auth->auth.saslopt) || 545*0Sstevel@tonic-gate (serverAddr && *serverAddr && 546*0Sstevel@tonic-gate (strcasecmp(serverAddr, cp->serverAddr) != 0))) 547*0Sstevel@tonic-gate continue; 548*0Sstevel@tonic-gate if ((((cp->auth->auth.type == NS_LDAP_AUTH_SASL) && 549*0Sstevel@tonic-gate ((cp->auth->auth.saslmech == NS_LDAP_SASL_CRAM_MD5) || 550*0Sstevel@tonic-gate (cp->auth->auth.saslmech == NS_LDAP_SASL_DIGEST_MD5))) || 551*0Sstevel@tonic-gate (cp->auth->auth.type == NS_LDAP_AUTH_SIMPLE)) && 552*0Sstevel@tonic-gate ((cp->auth->cred.unix_cred.userID == NULL) || 553*0Sstevel@tonic-gate (cp->auth->cred.unix_cred.passwd == NULL) || 554*0Sstevel@tonic-gate ((strcasecmp(cp->auth->cred.unix_cred.userID, 555*0Sstevel@tonic-gate auth->cred.unix_cred.userID) != 0)) || 556*0Sstevel@tonic-gate ((strcmp(cp->auth->cred.unix_cred.passwd, 557*0Sstevel@tonic-gate auth->cred.unix_cred.passwd) != 0)))) 558*0Sstevel@tonic-gate continue; 559*0Sstevel@tonic-gate /* found an available connection */ 560*0Sstevel@tonic-gate cp->usedBit = B_TRUE; 561*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 562*0Sstevel@tonic-gate cp->threadID = thr_self(); 563*0Sstevel@tonic-gate *conp = cp; 564*0Sstevel@tonic-gate #ifdef DEBUG 565*0Sstevel@tonic-gate (void) fprintf(stderr, "Connection found cID=%d\n", i); 566*0Sstevel@tonic-gate fflush(stderr); 567*0Sstevel@tonic-gate #endif /* DEBUG */ 568*0Sstevel@tonic-gate return (i + CONID_OFFSET); 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 571*0Sstevel@tonic-gate return (-1); 572*0Sstevel@tonic-gate } 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * Free a Connection structure 576*0Sstevel@tonic-gate */ 577*0Sstevel@tonic-gate static void 578*0Sstevel@tonic-gate freeConnection(Connection *con) 579*0Sstevel@tonic-gate { 580*0Sstevel@tonic-gate if (con == NULL) 581*0Sstevel@tonic-gate return; 582*0Sstevel@tonic-gate if (con->serverAddr) 583*0Sstevel@tonic-gate free(con->serverAddr); 584*0Sstevel@tonic-gate if (con->auth) 585*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(&(con->auth)); 586*0Sstevel@tonic-gate if (con->saslMechanisms) { 587*0Sstevel@tonic-gate __s_api_free2dArray(con->saslMechanisms); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate if (con->controls) { 590*0Sstevel@tonic-gate __s_api_free2dArray(con->controls); 591*0Sstevel@tonic-gate } 592*0Sstevel@tonic-gate free(con); 593*0Sstevel@tonic-gate } 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate /* 596*0Sstevel@tonic-gate * Find a connection matching the passed in criteria. If an open 597*0Sstevel@tonic-gate * connection with that criteria exists use it, otherwise open a 598*0Sstevel@tonic-gate * new connection. 599*0Sstevel@tonic-gate * Success: returns the pointer to the Connection structure 600*0Sstevel@tonic-gate * Failure: returns NULL, error code and message should be in errorp 601*0Sstevel@tonic-gate */ 602*0Sstevel@tonic-gate static int 603*0Sstevel@tonic-gate makeConnection(Connection **conp, const char *serverAddr, 604*0Sstevel@tonic-gate const ns_cred_t *auth, ConnectionID *cID, int timeoutSec, 605*0Sstevel@tonic-gate ns_ldap_error_t **errorp, int fail_if_new_pwd_reqd) 606*0Sstevel@tonic-gate { 607*0Sstevel@tonic-gate Connection *con = NULL; 608*0Sstevel@tonic-gate ConnectionID id; 609*0Sstevel@tonic-gate char errmsg[MAXERROR]; 610*0Sstevel@tonic-gate int rc, exit_rc = NS_LDAP_SUCCESS; 611*0Sstevel@tonic-gate ns_server_info_t sinfo; 612*0Sstevel@tonic-gate char *hReq, *host = NULL; 613*0Sstevel@tonic-gate LDAP *ld = NULL; 614*0Sstevel@tonic-gate int passwd_mgmt = 0; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate if (conp == NULL || errorp == NULL || auth == NULL) 617*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 618*0Sstevel@tonic-gate *errorp = NULL; 619*0Sstevel@tonic-gate *conp = NULL; 620*0Sstevel@tonic-gate sinfo.server = NULL; 621*0Sstevel@tonic-gate sinfo.controls = NULL; 622*0Sstevel@tonic-gate sinfo.saslMechanisms = NULL; 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate if ((id = findConnection(serverAddr, auth, &con)) != -1) { 625*0Sstevel@tonic-gate /* connection found in cache */ 626*0Sstevel@tonic-gate #ifdef DEBUG 627*0Sstevel@tonic-gate (void) fprintf(stderr, "connection found in cache %d\n", id); 628*0Sstevel@tonic-gate fflush(stderr); 629*0Sstevel@tonic-gate #endif /* DEBUG */ 630*0Sstevel@tonic-gate *cID = id; 631*0Sstevel@tonic-gate *conp = con; 632*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate if (serverAddr) { 636*0Sstevel@tonic-gate rc = openConnection(&ld, serverAddr, auth, timeoutSec, errorp, 637*0Sstevel@tonic-gate fail_if_new_pwd_reqd, passwd_mgmt); 638*0Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS || rc == 639*0Sstevel@tonic-gate NS_LDAP_SUCCESS_WITH_INFO) { 640*0Sstevel@tonic-gate exit_rc = rc; 641*0Sstevel@tonic-gate rc = __s_api_requestServer(NS_CACHE_NEW, serverAddr, 642*0Sstevel@tonic-gate &sinfo, errorp); 643*0Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS || sinfo.server == NULL) { 644*0Sstevel@tonic-gate (void) snprintf(errmsg, sizeof (errmsg), 645*0Sstevel@tonic-gate gettext("makeConnection: unable to get " 646*0Sstevel@tonic-gate "server information for %s"), serverAddr); 647*0Sstevel@tonic-gate syslog(LOG_ERR, "libsldap: %s", errmsg); 648*0Sstevel@tonic-gate return (NS_LDAP_OP_FAILED); 649*0Sstevel@tonic-gate } 650*0Sstevel@tonic-gate goto create_con; 651*0Sstevel@tonic-gate } else { 652*0Sstevel@tonic-gate return (rc); 653*0Sstevel@tonic-gate } 654*0Sstevel@tonic-gate } 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* No cached connection, create one */ 657*0Sstevel@tonic-gate for (; ; ) { 658*0Sstevel@tonic-gate if (host == NULL) 659*0Sstevel@tonic-gate hReq = NS_CACHE_NEW; 660*0Sstevel@tonic-gate else 661*0Sstevel@tonic-gate hReq = NS_CACHE_NEXT; 662*0Sstevel@tonic-gate rc = __s_api_requestServer(hReq, host, &sinfo, errorp); 663*0Sstevel@tonic-gate if ((rc != NS_LDAP_SUCCESS) || (sinfo.server == NULL) || 664*0Sstevel@tonic-gate (host && (strcasecmp(host, sinfo.server) == 0))) { 665*0Sstevel@tonic-gate /* Log the error */ 666*0Sstevel@tonic-gate if (*errorp) { 667*0Sstevel@tonic-gate (void) snprintf(errmsg, sizeof (errmsg), 668*0Sstevel@tonic-gate "%s: (%s)", gettext("makeConnection: " 669*0Sstevel@tonic-gate "unable to make LDAP connection, " 670*0Sstevel@tonic-gate "request for a server failed"), 671*0Sstevel@tonic-gate (*errorp)->message); 672*0Sstevel@tonic-gate syslog(LOG_ERR, "libsldap: %s", errmsg); 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate if (sinfo.server) 676*0Sstevel@tonic-gate free(sinfo.server); 677*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.saslMechanisms); 678*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.controls); 679*0Sstevel@tonic-gate if (host) 680*0Sstevel@tonic-gate free(host); 681*0Sstevel@tonic-gate return (NS_LDAP_OP_FAILED); 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate if (host) 684*0Sstevel@tonic-gate free(host); 685*0Sstevel@tonic-gate host = strdup(sinfo.server); 686*0Sstevel@tonic-gate if (host == NULL) { 687*0Sstevel@tonic-gate free(sinfo.server); 688*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.saslMechanisms); 689*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.controls); 690*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate /* check if server supports password management */ 694*0Sstevel@tonic-gate passwd_mgmt = __s_api_contain_passwd_control_oid( 695*0Sstevel@tonic-gate sinfo.controls); 696*0Sstevel@tonic-gate /* make the connection */ 697*0Sstevel@tonic-gate rc = openConnection(&ld, host, auth, timeoutSec, errorp, 698*0Sstevel@tonic-gate fail_if_new_pwd_reqd, passwd_mgmt); 699*0Sstevel@tonic-gate /* if success, go to create connection structure */ 700*0Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS || 701*0Sstevel@tonic-gate rc == NS_LDAP_SUCCESS_WITH_INFO) { 702*0Sstevel@tonic-gate exit_rc = rc; 703*0Sstevel@tonic-gate break; 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate /* 707*0Sstevel@tonic-gate * If not able to reach the server, inform the ldap 708*0Sstevel@tonic-gate * cache manager that the server should be removed 709*0Sstevel@tonic-gate * from its server list. Thus, the manager will not 710*0Sstevel@tonic-gate * return this server on the next get-server request 711*0Sstevel@tonic-gate * and will also reduce the server list refresh TTL, 712*0Sstevel@tonic-gate * so that it will find out sooner when the server 713*0Sstevel@tonic-gate * is up again. 714*0Sstevel@tonic-gate */ 715*0Sstevel@tonic-gate if (rc == NS_LDAP_INTERNAL && *errorp != NULL) { 716*0Sstevel@tonic-gate if ((*errorp)->status == LDAP_CONNECT_ERROR || 717*0Sstevel@tonic-gate (*errorp)->status == LDAP_SERVER_DOWN) 718*0Sstevel@tonic-gate __s_api_removeServer(host); 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate /* else, cleanup and go for the next server */ 722*0Sstevel@tonic-gate if (sinfo.server) { 723*0Sstevel@tonic-gate free(sinfo.server); 724*0Sstevel@tonic-gate sinfo.server = NULL; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.saslMechanisms); 727*0Sstevel@tonic-gate sinfo.saslMechanisms = NULL; 728*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.controls); 729*0Sstevel@tonic-gate sinfo.controls = NULL; 730*0Sstevel@tonic-gate if (*errorp) { 731*0Sstevel@tonic-gate /* 732*0Sstevel@tonic-gate * If openConnection() failed due to 733*0Sstevel@tonic-gate * password policy, or invalid credential, 734*0Sstevel@tonic-gate * keep *errorp and exit 735*0Sstevel@tonic-gate */ 736*0Sstevel@tonic-gate if ((*errorp)->pwd_mgmt.status != NS_PASSWD_GOOD || 737*0Sstevel@tonic-gate (*errorp)->status == LDAP_INVALID_CREDENTIALS) { 738*0Sstevel@tonic-gate free(host); 739*0Sstevel@tonic-gate return (rc); 740*0Sstevel@tonic-gate } else { 741*0Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp); 742*0Sstevel@tonic-gate *errorp = NULL; 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate create_con: 748*0Sstevel@tonic-gate /* we have created ld, setup con structure */ 749*0Sstevel@tonic-gate if (host) 750*0Sstevel@tonic-gate free(host); 751*0Sstevel@tonic-gate if ((con = calloc(1, sizeof (Connection))) == NULL) { 752*0Sstevel@tonic-gate if (sinfo.server) 753*0Sstevel@tonic-gate free(sinfo.server); 754*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.saslMechanisms); 755*0Sstevel@tonic-gate __s_api_free2dArray(sinfo.controls); 756*0Sstevel@tonic-gate /* 757*0Sstevel@tonic-gate * If password control attached in **errorp, 758*0Sstevel@tonic-gate * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 759*0Sstevel@tonic-gate * free the error structure 760*0Sstevel@tonic-gate */ 761*0Sstevel@tonic-gate if (*errorp) { 762*0Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp); 763*0Sstevel@tonic-gate *errorp = NULL; 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate con->serverAddr = sinfo.server; 769*0Sstevel@tonic-gate con->saslMechanisms = sinfo.saslMechanisms; 770*0Sstevel@tonic-gate con->controls = sinfo.controls; 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate con->auth = __ns_ldap_dupAuth(auth); 773*0Sstevel@tonic-gate if (con->auth == NULL) { 774*0Sstevel@tonic-gate free(con); 775*0Sstevel@tonic-gate /* 776*0Sstevel@tonic-gate * If password control attached in **errorp, 777*0Sstevel@tonic-gate * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 778*0Sstevel@tonic-gate * free the error structure 779*0Sstevel@tonic-gate */ 780*0Sstevel@tonic-gate if (*errorp) { 781*0Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp); 782*0Sstevel@tonic-gate *errorp = NULL; 783*0Sstevel@tonic-gate } 784*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate con->threadID = thr_self(); 788*0Sstevel@tonic-gate con->ld = ld; 789*0Sstevel@tonic-gate if ((id = addConnection(con)) == -1) { 790*0Sstevel@tonic-gate freeConnection(con); 791*0Sstevel@tonic-gate /* 792*0Sstevel@tonic-gate * If password control attached in **errorp, 793*0Sstevel@tonic-gate * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 794*0Sstevel@tonic-gate * free the error structure 795*0Sstevel@tonic-gate */ 796*0Sstevel@tonic-gate if (*errorp) { 797*0Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp); 798*0Sstevel@tonic-gate *errorp = NULL; 799*0Sstevel@tonic-gate } 800*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 801*0Sstevel@tonic-gate } 802*0Sstevel@tonic-gate #ifdef DEBUG 803*0Sstevel@tonic-gate (void) fprintf(stderr, "connection added into cache %d\n", id); 804*0Sstevel@tonic-gate fflush(stderr); 805*0Sstevel@tonic-gate #endif /* DEBUG */ 806*0Sstevel@tonic-gate *cID = id; 807*0Sstevel@tonic-gate *conp = con; 808*0Sstevel@tonic-gate return (exit_rc); 809*0Sstevel@tonic-gate } 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate /* 812*0Sstevel@tonic-gate * Return the specified connection to the pool. If necessary 813*0Sstevel@tonic-gate * delete the connection. 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate 816*0Sstevel@tonic-gate static void 817*0Sstevel@tonic-gate _DropConnection(ConnectionID cID, int flag, int fini) 818*0Sstevel@tonic-gate { 819*0Sstevel@tonic-gate Connection *cp; 820*0Sstevel@tonic-gate int id; 821*0Sstevel@tonic-gate int use_mutex = !fini; 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate id = cID - CONID_OFFSET; 824*0Sstevel@tonic-gate if (id < 0 || id >= sessionPoolSize) 825*0Sstevel@tonic-gate return; 826*0Sstevel@tonic-gate #ifdef DEBUG 827*0Sstevel@tonic-gate (void) fprintf(stderr, 828*0Sstevel@tonic-gate "Dropping connection cID=%d flag=0x%x\n", cID, flag); 829*0Sstevel@tonic-gate fflush(stderr); 830*0Sstevel@tonic-gate #endif /* DEBUG */ 831*0Sstevel@tonic-gate if (use_mutex) 832*0Sstevel@tonic-gate (void) mutex_lock(&sessionPoolLock); 833*0Sstevel@tonic-gate 834*0Sstevel@tonic-gate cp = sessionPool[id]; 835*0Sstevel@tonic-gate /* sanity check before removing */ 836*0Sstevel@tonic-gate if (!cp || (!fini && (!cp->usedBit || cp->threadID != thr_self()))) { 837*0Sstevel@tonic-gate if (use_mutex) 838*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 839*0Sstevel@tonic-gate return; 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate if (!fini && 843*0Sstevel@tonic-gate ((flag & NS_LDAP_NEW_CONN) == 0) && 844*0Sstevel@tonic-gate ((flag & NS_LDAP_KEEP_CONN) || nscd_proc())) { 845*0Sstevel@tonic-gate /* release Connection (keep alive) */ 846*0Sstevel@tonic-gate cp->usedBit = B_FALSE; 847*0Sstevel@tonic-gate cp->threadID = 0; /* unmark the threadID */ 848*0Sstevel@tonic-gate if (use_mutex) 849*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 850*0Sstevel@tonic-gate } else { 851*0Sstevel@tonic-gate /* delete Connection (disconnect) */ 852*0Sstevel@tonic-gate sessionPool[id] = NULL; 853*0Sstevel@tonic-gate if (use_mutex) 854*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 855*0Sstevel@tonic-gate (void) ldap_unbind(cp->ld); 856*0Sstevel@tonic-gate freeConnection(cp); 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate void 861*0Sstevel@tonic-gate DropConnection(ConnectionID cID, int flag) 862*0Sstevel@tonic-gate { 863*0Sstevel@tonic-gate _DropConnection(cID, flag, 0); 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate /* 867*0Sstevel@tonic-gate * This routine is called after a bind operation is 868*0Sstevel@tonic-gate * done in openConnection() to process the password 869*0Sstevel@tonic-gate * management information, if any. 870*0Sstevel@tonic-gate * 871*0Sstevel@tonic-gate * Input: 872*0Sstevel@tonic-gate * bind_type: "simple" or "sasl/DIGEST-MD5" 873*0Sstevel@tonic-gate * ldaprc : ldap rc from the ldap bind operation 874*0Sstevel@tonic-gate * controls : controls returned by the server 875*0Sstevel@tonic-gate * errmsg : error message from the server 876*0Sstevel@tonic-gate * fail_if_new_pwd_reqd: 877*0Sstevel@tonic-gate * flag indicating if connection should be open 878*0Sstevel@tonic-gate * when password needs to change immediately 879*0Sstevel@tonic-gate * passwd_mgmt: 880*0Sstevel@tonic-gate * flag indicating if server supports password 881*0Sstevel@tonic-gate * policy/management 882*0Sstevel@tonic-gate * 883*0Sstevel@tonic-gate * Output : ns_ldap_error structure, which may contain 884*0Sstevel@tonic-gate * password status and number of seconds until 885*0Sstevel@tonic-gate * expired 886*0Sstevel@tonic-gate * 887*0Sstevel@tonic-gate * return rc: 888*0Sstevel@tonic-gate * NS_LDAP_EXTERNAL: error, connection should not open 889*0Sstevel@tonic-gate * NS_LDAP_SUCCESS_WITH_INFO: OK to open but password info attached 890*0Sstevel@tonic-gate * NS_LDAP_SUCCESS: OK to open connection 891*0Sstevel@tonic-gate * 892*0Sstevel@tonic-gate */ 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate static int 895*0Sstevel@tonic-gate process_pwd_mgmt(char *bind_type, int ldaprc, 896*0Sstevel@tonic-gate LDAPControl **controls, 897*0Sstevel@tonic-gate char *errmsg, ns_ldap_error_t **errorp, 898*0Sstevel@tonic-gate int fail_if_new_pwd_reqd, 899*0Sstevel@tonic-gate int passwd_mgmt) 900*0Sstevel@tonic-gate { 901*0Sstevel@tonic-gate char errstr[MAXERROR]; 902*0Sstevel@tonic-gate LDAPControl **ctrl = NULL; 903*0Sstevel@tonic-gate int exit_rc; 904*0Sstevel@tonic-gate ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD; 905*0Sstevel@tonic-gate int sec_until_exp = 0; 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate /* 908*0Sstevel@tonic-gate * errmsg may be an empty string, 909*0Sstevel@tonic-gate * even if ldaprc is LDAP_SUCCESS, 910*0Sstevel@tonic-gate * free the empty string if that's the case 911*0Sstevel@tonic-gate */ 912*0Sstevel@tonic-gate if (errmsg && 913*0Sstevel@tonic-gate (*errmsg == '\0' || ldaprc == LDAP_SUCCESS)) { 914*0Sstevel@tonic-gate ldap_memfree(errmsg); 915*0Sstevel@tonic-gate errmsg = NULL; 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate if (ldaprc != LDAP_SUCCESS) { 919*0Sstevel@tonic-gate /* 920*0Sstevel@tonic-gate * try to map ldap rc and error message to 921*0Sstevel@tonic-gate * a password status 922*0Sstevel@tonic-gate */ 923*0Sstevel@tonic-gate if (errmsg) { 924*0Sstevel@tonic-gate if (passwd_mgmt) 925*0Sstevel@tonic-gate pwd_status = 926*0Sstevel@tonic-gate __s_api_set_passwd_status( 927*0Sstevel@tonic-gate ldaprc, errmsg); 928*0Sstevel@tonic-gate ldap_memfree(errmsg); 929*0Sstevel@tonic-gate } 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 932*0Sstevel@tonic-gate gettext("openConnection: " 933*0Sstevel@tonic-gate "%s bind failed " 934*0Sstevel@tonic-gate "- %s"), bind_type, ldap_err2string(ldaprc)); 935*0Sstevel@tonic-gate 936*0Sstevel@tonic-gate if (pwd_status != NS_PASSWD_GOOD) { 937*0Sstevel@tonic-gate MKERROR_PWD_MGMT(*errorp, 938*0Sstevel@tonic-gate ldaprc, strdup(errstr), 939*0Sstevel@tonic-gate pwd_status, 0, NULL); 940*0Sstevel@tonic-gate } else { 941*0Sstevel@tonic-gate MKERROR(LOG_ERR, *errorp, ldaprc, strdup(errstr), 942*0Sstevel@tonic-gate NULL); 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate if (controls) 945*0Sstevel@tonic-gate ldap_controls_free(controls); 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 948*0Sstevel@tonic-gate } 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate /* 951*0Sstevel@tonic-gate * ldaprc is LDAP_SUCCESS, 952*0Sstevel@tonic-gate * process the password management controls, if any 953*0Sstevel@tonic-gate */ 954*0Sstevel@tonic-gate exit_rc = NS_LDAP_SUCCESS; 955*0Sstevel@tonic-gate if (controls && passwd_mgmt) { 956*0Sstevel@tonic-gate /* 957*0Sstevel@tonic-gate * The control with the OID 958*0Sstevel@tonic-gate * 2.16.840.1.113730.3.4.4 (or 959*0Sstevel@tonic-gate * LDAP_CONTROL_PWEXPIRED, as defined 960*0Sstevel@tonic-gate * in the ldap.h header file) is the 961*0Sstevel@tonic-gate * expired password control. 962*0Sstevel@tonic-gate * 963*0Sstevel@tonic-gate * This control is used if the server 964*0Sstevel@tonic-gate * is configured to require users to 965*0Sstevel@tonic-gate * change their passwords when first 966*0Sstevel@tonic-gate * logging in and whenever the 967*0Sstevel@tonic-gate * passwords are reset. 968*0Sstevel@tonic-gate * 969*0Sstevel@tonic-gate * If the user is logging in for the 970*0Sstevel@tonic-gate * first time or if the user's 971*0Sstevel@tonic-gate * password has been reset, the 972*0Sstevel@tonic-gate * server sends this control to 973*0Sstevel@tonic-gate * indicate that the client needs to 974*0Sstevel@tonic-gate * change the password immediately. 975*0Sstevel@tonic-gate * 976*0Sstevel@tonic-gate * At this point, the only operation 977*0Sstevel@tonic-gate * that the client can perform is to 978*0Sstevel@tonic-gate * change the user's password. If the 979*0Sstevel@tonic-gate * client requests any other LDAP 980*0Sstevel@tonic-gate * operation, the server sends back 981*0Sstevel@tonic-gate * an LDAP_UNWILLING_TO_PERFORM 982*0Sstevel@tonic-gate * result code with an expired 983*0Sstevel@tonic-gate * password control. 984*0Sstevel@tonic-gate * 985*0Sstevel@tonic-gate * The control with the OID 986*0Sstevel@tonic-gate * 2.16.840.1.113730.3.4.5 (or 987*0Sstevel@tonic-gate * LDAP_CONTROL_PWEXPIRING, as 988*0Sstevel@tonic-gate * defined in the ldap.h header file) 989*0Sstevel@tonic-gate * is the password expiration warning 990*0Sstevel@tonic-gate * control. 991*0Sstevel@tonic-gate * 992*0Sstevel@tonic-gate * This control is used if the server 993*0Sstevel@tonic-gate * is configured to expire user 994*0Sstevel@tonic-gate * passwords after a certain amount 995*0Sstevel@tonic-gate * of time. 996*0Sstevel@tonic-gate * 997*0Sstevel@tonic-gate * The server sends this control back 998*0Sstevel@tonic-gate * to the client if the client binds 999*0Sstevel@tonic-gate * using a password that will soon 1000*0Sstevel@tonic-gate * expire. The ldctl_value field of 1001*0Sstevel@tonic-gate * the LDAPControl structure 1002*0Sstevel@tonic-gate * specifies the number of seconds 1003*0Sstevel@tonic-gate * before the password will expire. 1004*0Sstevel@tonic-gate */ 1005*0Sstevel@tonic-gate for (ctrl = controls; *ctrl; ctrl++) { 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate if (strcmp((*ctrl)->ldctl_oid, 1008*0Sstevel@tonic-gate LDAP_CONTROL_PWEXPIRED) == 0) { 1009*0Sstevel@tonic-gate /* 1010*0Sstevel@tonic-gate * if the caller wants this bind 1011*0Sstevel@tonic-gate * to fail, set up the error info. 1012*0Sstevel@tonic-gate * If call to this function is 1013*0Sstevel@tonic-gate * for searching the LDAP directory, 1014*0Sstevel@tonic-gate * e.g., __ns_ldap_list(), 1015*0Sstevel@tonic-gate * there's really no sense to 1016*0Sstevel@tonic-gate * let a connection open and 1017*0Sstevel@tonic-gate * then fail immediately afterward 1018*0Sstevel@tonic-gate * on the LDAP search operation with 1019*0Sstevel@tonic-gate * the LDAP_UNWILLING_TO_PERFORM rc 1020*0Sstevel@tonic-gate */ 1021*0Sstevel@tonic-gate pwd_status = 1022*0Sstevel@tonic-gate NS_PASSWD_CHANGE_NEEDED; 1023*0Sstevel@tonic-gate if (fail_if_new_pwd_reqd) { 1024*0Sstevel@tonic-gate (void) snprintf(errstr, 1025*0Sstevel@tonic-gate sizeof (errstr), 1026*0Sstevel@tonic-gate gettext( 1027*0Sstevel@tonic-gate "openConnection: " 1028*0Sstevel@tonic-gate "%s bind " 1029*0Sstevel@tonic-gate "failed " 1030*0Sstevel@tonic-gate "- password " 1031*0Sstevel@tonic-gate "expired. It " 1032*0Sstevel@tonic-gate " needs to change " 1033*0Sstevel@tonic-gate "immediately!"), 1034*0Sstevel@tonic-gate bind_type); 1035*0Sstevel@tonic-gate MKERROR_PWD_MGMT(*errorp, 1036*0Sstevel@tonic-gate LDAP_SUCCESS, 1037*0Sstevel@tonic-gate strdup(errstr), 1038*0Sstevel@tonic-gate pwd_status, 1039*0Sstevel@tonic-gate 0, 1040*0Sstevel@tonic-gate NULL); 1041*0Sstevel@tonic-gate exit_rc = NS_LDAP_INTERNAL; 1042*0Sstevel@tonic-gate } else { 1043*0Sstevel@tonic-gate MKERROR_PWD_MGMT(*errorp, 1044*0Sstevel@tonic-gate LDAP_SUCCESS, 1045*0Sstevel@tonic-gate NULL, 1046*0Sstevel@tonic-gate pwd_status, 1047*0Sstevel@tonic-gate 0, 1048*0Sstevel@tonic-gate NULL); 1049*0Sstevel@tonic-gate exit_rc = 1050*0Sstevel@tonic-gate NS_LDAP_SUCCESS_WITH_INFO; 1051*0Sstevel@tonic-gate } 1052*0Sstevel@tonic-gate break; 1053*0Sstevel@tonic-gate } else if (strcmp((*ctrl)->ldctl_oid, 1054*0Sstevel@tonic-gate LDAP_CONTROL_PWEXPIRING) == 0) { 1055*0Sstevel@tonic-gate pwd_status = 1056*0Sstevel@tonic-gate NS_PASSWD_ABOUT_TO_EXPIRE; 1057*0Sstevel@tonic-gate if ((*ctrl)-> 1058*0Sstevel@tonic-gate ldctl_value.bv_len > 0 && 1059*0Sstevel@tonic-gate (*ctrl)-> 1060*0Sstevel@tonic-gate ldctl_value.bv_val) 1061*0Sstevel@tonic-gate sec_until_exp = 1062*0Sstevel@tonic-gate atoi((*ctrl)-> 1063*0Sstevel@tonic-gate ldctl_value.bv_val); 1064*0Sstevel@tonic-gate MKERROR_PWD_MGMT(*errorp, 1065*0Sstevel@tonic-gate LDAP_SUCCESS, 1066*0Sstevel@tonic-gate NULL, 1067*0Sstevel@tonic-gate pwd_status, 1068*0Sstevel@tonic-gate sec_until_exp, 1069*0Sstevel@tonic-gate NULL); 1070*0Sstevel@tonic-gate exit_rc = 1071*0Sstevel@tonic-gate NS_LDAP_SUCCESS_WITH_INFO; 1072*0Sstevel@tonic-gate break; 1073*0Sstevel@tonic-gate } 1074*0Sstevel@tonic-gate } 1075*0Sstevel@tonic-gate } 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate if (controls) 1078*0Sstevel@tonic-gate ldap_controls_free(controls); 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate return (exit_rc); 1081*0Sstevel@tonic-gate } 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate static int 1084*0Sstevel@tonic-gate ldap_in_hosts_switch() 1085*0Sstevel@tonic-gate { 1086*0Sstevel@tonic-gate enum __nsw_parse_err pserr; 1087*0Sstevel@tonic-gate struct __nsw_switchconfig *conf; 1088*0Sstevel@tonic-gate struct __nsw_lookup *lkp; 1089*0Sstevel@tonic-gate const char *name; 1090*0Sstevel@tonic-gate int found = 0; 1091*0Sstevel@tonic-gate 1092*0Sstevel@tonic-gate conf = __nsw_getconfig("hosts", &pserr); 1093*0Sstevel@tonic-gate if (conf == NULL) { 1094*0Sstevel@tonic-gate return (-1); 1095*0Sstevel@tonic-gate } 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate /* check for skip and count other backends */ 1098*0Sstevel@tonic-gate for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) { 1099*0Sstevel@tonic-gate name = lkp->service_name; 1100*0Sstevel@tonic-gate if (strcmp(name, "ldap") == 0) { 1101*0Sstevel@tonic-gate found = 1; 1102*0Sstevel@tonic-gate break; 1103*0Sstevel@tonic-gate } 1104*0Sstevel@tonic-gate } 1105*0Sstevel@tonic-gate __nsw_freeconfig(conf); 1106*0Sstevel@tonic-gate return (found); 1107*0Sstevel@tonic-gate } 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate static int 1110*0Sstevel@tonic-gate openConnection(LDAP **ldp, const char *serverAddr, const ns_cred_t *auth, 1111*0Sstevel@tonic-gate int timeoutSec, ns_ldap_error_t **errorp, 1112*0Sstevel@tonic-gate int fail_if_new_pwd_reqd, int passwd_mgmt) 1113*0Sstevel@tonic-gate { 1114*0Sstevel@tonic-gate LDAP *ld = NULL; 1115*0Sstevel@tonic-gate char *binddn, *passwd; 1116*0Sstevel@tonic-gate char *digest_md5_name; 1117*0Sstevel@tonic-gate const char *s; 1118*0Sstevel@tonic-gate int ldapVersion = LDAP_VERSION3; 1119*0Sstevel@tonic-gate int derefOption = LDAP_DEREF_ALWAYS; 1120*0Sstevel@tonic-gate int zero = 0; 1121*0Sstevel@tonic-gate int rc; 1122*0Sstevel@tonic-gate char errstr[MAXERROR]; 1123*0Sstevel@tonic-gate int errnum = 0; 1124*0Sstevel@tonic-gate LDAPMessage *resultMsg; 1125*0Sstevel@tonic-gate int msgId; 1126*0Sstevel@tonic-gate int useSSL = 0; 1127*0Sstevel@tonic-gate struct timeval tv; 1128*0Sstevel@tonic-gate AuthType_t bindType; 1129*0Sstevel@tonic-gate int timeoutMilliSec = timeoutSec * 1000; 1130*0Sstevel@tonic-gate struct berval cred; 1131*0Sstevel@tonic-gate char *sslServerAddr; 1132*0Sstevel@tonic-gate char *s1; 1133*0Sstevel@tonic-gate char *errmsg; 1134*0Sstevel@tonic-gate LDAPControl **controls; 1135*0Sstevel@tonic-gate int pwd_rc; 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate *errorp = NULL; 1138*0Sstevel@tonic-gate *ldp = NULL; 1139*0Sstevel@tonic-gate 1140*0Sstevel@tonic-gate switch (auth->auth.type) { 1141*0Sstevel@tonic-gate case NS_LDAP_AUTH_NONE: 1142*0Sstevel@tonic-gate case NS_LDAP_AUTH_SIMPLE: 1143*0Sstevel@tonic-gate case NS_LDAP_AUTH_SASL: 1144*0Sstevel@tonic-gate bindType = auth->auth.type; 1145*0Sstevel@tonic-gate break; 1146*0Sstevel@tonic-gate case NS_LDAP_AUTH_TLS: 1147*0Sstevel@tonic-gate useSSL = 1; 1148*0Sstevel@tonic-gate switch (auth->auth.tlstype) { 1149*0Sstevel@tonic-gate case NS_LDAP_TLS_NONE: 1150*0Sstevel@tonic-gate bindType = NS_LDAP_AUTH_NONE; 1151*0Sstevel@tonic-gate break; 1152*0Sstevel@tonic-gate case NS_LDAP_TLS_SIMPLE: 1153*0Sstevel@tonic-gate bindType = NS_LDAP_AUTH_SIMPLE; 1154*0Sstevel@tonic-gate break; 1155*0Sstevel@tonic-gate case NS_LDAP_TLS_SASL: 1156*0Sstevel@tonic-gate bindType = NS_LDAP_AUTH_SASL; 1157*0Sstevel@tonic-gate break; 1158*0Sstevel@tonic-gate default: 1159*0Sstevel@tonic-gate (void) sprintf(errstr, 1160*0Sstevel@tonic-gate gettext("openConnection: unsupported " 1161*0Sstevel@tonic-gate "TLS authentication method " 1162*0Sstevel@tonic-gate "(%d)"), auth->auth.tlstype); 1163*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, 1164*0Sstevel@tonic-gate LDAP_AUTH_METHOD_NOT_SUPPORTED, 1165*0Sstevel@tonic-gate strdup(errstr), NULL); 1166*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1167*0Sstevel@tonic-gate } 1168*0Sstevel@tonic-gate break; 1169*0Sstevel@tonic-gate default: 1170*0Sstevel@tonic-gate (void) sprintf(errstr, 1171*0Sstevel@tonic-gate gettext("openConnection: unsupported " 1172*0Sstevel@tonic-gate "authentication method (%d)"), auth->auth.type); 1173*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, 1174*0Sstevel@tonic-gate LDAP_AUTH_METHOD_NOT_SUPPORTED, strdup(errstr), 1175*0Sstevel@tonic-gate NULL); 1176*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1177*0Sstevel@tonic-gate } 1178*0Sstevel@tonic-gate 1179*0Sstevel@tonic-gate if (useSSL) { 1180*0Sstevel@tonic-gate const char *hostcertpath; 1181*0Sstevel@tonic-gate char *alloc_hcp = NULL; 1182*0Sstevel@tonic-gate #ifdef DEBUG 1183*0Sstevel@tonic-gate (void) fprintf(stderr, "+++TLS transport\n"); 1184*0Sstevel@tonic-gate #endif /* DEBUG */ 1185*0Sstevel@tonic-gate hostcertpath = auth->hostcertpath; 1186*0Sstevel@tonic-gate if (hostcertpath == NULL) { 1187*0Sstevel@tonic-gate alloc_hcp = __s_get_hostcertpath(); 1188*0Sstevel@tonic-gate hostcertpath = alloc_hcp; 1189*0Sstevel@tonic-gate } 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate if (hostcertpath == NULL) 1192*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate if ((rc = ldapssl_client_init(hostcertpath, NULL)) < 0) { 1195*0Sstevel@tonic-gate if (alloc_hcp) 1196*0Sstevel@tonic-gate free(alloc_hcp); 1197*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1198*0Sstevel@tonic-gate gettext("openConnection: failed to initialize " 1199*0Sstevel@tonic-gate "TLS security (%s)"), 1200*0Sstevel@tonic-gate ldapssl_err2string(rc)); 1201*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, LDAP_CONNECT_ERROR, 1202*0Sstevel@tonic-gate strdup(errstr), NULL); 1203*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1204*0Sstevel@tonic-gate } 1205*0Sstevel@tonic-gate if (alloc_hcp) 1206*0Sstevel@tonic-gate free(alloc_hcp); 1207*0Sstevel@tonic-gate 1208*0Sstevel@tonic-gate /* determine if the host name contains a port number */ 1209*0Sstevel@tonic-gate s = strchr(serverAddr, ']'); /* skip over ipv6 addr */ 1210*0Sstevel@tonic-gate if (s == NULL) 1211*0Sstevel@tonic-gate s = serverAddr; 1212*0Sstevel@tonic-gate s = strchr(s, ':'); 1213*0Sstevel@tonic-gate if (s != NULL) { 1214*0Sstevel@tonic-gate /* 1215*0Sstevel@tonic-gate * If we do get a port number, we will try stripping 1216*0Sstevel@tonic-gate * it. At present, referrals will always have a 1217*0Sstevel@tonic-gate * port number. 1218*0Sstevel@tonic-gate */ 1219*0Sstevel@tonic-gate sslServerAddr = strdup(serverAddr); 1220*0Sstevel@tonic-gate if (sslServerAddr == NULL) 1221*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1222*0Sstevel@tonic-gate s1 = strrchr(sslServerAddr, ':'); 1223*0Sstevel@tonic-gate if (s1 != NULL) 1224*0Sstevel@tonic-gate *s1 = '\0'; 1225*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1226*0Sstevel@tonic-gate gettext("openConnection: cannot use tls with %s. " 1227*0Sstevel@tonic-gate "Trying %s"), 1228*0Sstevel@tonic-gate serverAddr, sslServerAddr); 1229*0Sstevel@tonic-gate syslog(LOG_ERR, "libsldap: %s", errstr); 1230*0Sstevel@tonic-gate } else 1231*0Sstevel@tonic-gate sslServerAddr = (char *)serverAddr; 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate ld = ldapssl_init(sslServerAddr, LDAPS_PORT, 1); 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate if (sslServerAddr != serverAddr) 1236*0Sstevel@tonic-gate free(sslServerAddr); 1237*0Sstevel@tonic-gate 1238*0Sstevel@tonic-gate if (ld == NULL || 1239*0Sstevel@tonic-gate ldapssl_install_gethostbyaddr(ld, "ldap") != 0) { 1240*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1241*0Sstevel@tonic-gate gettext("openConnection: failed to connect " 1242*0Sstevel@tonic-gate "using TLS (%s)"), strerror(errno)); 1243*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, LDAP_CONNECT_ERROR, 1244*0Sstevel@tonic-gate strdup(errstr), NULL); 1245*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1246*0Sstevel@tonic-gate } 1247*0Sstevel@tonic-gate } else { 1248*0Sstevel@tonic-gate #ifdef DEBUG 1249*0Sstevel@tonic-gate (void) fprintf(stderr, "+++Unsecure transport\n"); 1250*0Sstevel@tonic-gate #endif /* DEBUG */ 1251*0Sstevel@tonic-gate /* Warning message IF cannot connect to host(s) */ 1252*0Sstevel@tonic-gate if ((ld = ldap_init((char *)serverAddr, LDAP_PORT)) == NULL) { 1253*0Sstevel@tonic-gate char *p = strerror(errno); 1254*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, LDAP_CONNECT_ERROR, 1255*0Sstevel@tonic-gate strdup(p), NULL); 1256*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1257*0Sstevel@tonic-gate } else { 1258*0Sstevel@tonic-gate /* check and avoid gethostname recursion */ 1259*0Sstevel@tonic-gate if (ldap_in_hosts_switch() > 0 && 1260*0Sstevel@tonic-gate ! __s_api_isipv4((char *)serverAddr) && 1261*0Sstevel@tonic-gate ! __s_api_isipv6((char *)serverAddr)) { 1262*0Sstevel@tonic-gate /* host: ldap - found, attempt to recover */ 1263*0Sstevel@tonic-gate if (ldap_set_option(ld, LDAP_X_OPT_DNS_SKIPDB, 1264*0Sstevel@tonic-gate "ldap") != 0) { 1265*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1266*0Sstevel@tonic-gate gettext("openConnection: " 1267*0Sstevel@tonic-gate "unrecoverable gethostname " 1268*0Sstevel@tonic-gate "recursion detected " 1269*0Sstevel@tonic-gate "in /etc/nsswitch.conf")); 1270*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, 1271*0Sstevel@tonic-gate LDAP_CONNECT_ERROR, 1272*0Sstevel@tonic-gate strdup(errstr), NULL); 1273*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1274*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1275*0Sstevel@tonic-gate } 1276*0Sstevel@tonic-gate } 1277*0Sstevel@tonic-gate } 1278*0Sstevel@tonic-gate } 1279*0Sstevel@tonic-gate 1280*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion); 1281*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_DEREF, &derefOption); 1282*0Sstevel@tonic-gate /* 1283*0Sstevel@tonic-gate * set LDAP_OPT_REFERRALS to OFF. 1284*0Sstevel@tonic-gate * This library will handle the referral itself 1285*0Sstevel@tonic-gate * based on API flags or configuration file 1286*0Sstevel@tonic-gate * specification. If this option is not set 1287*0Sstevel@tonic-gate * to OFF, libldap will never pass the 1288*0Sstevel@tonic-gate * referral info up to this library 1289*0Sstevel@tonic-gate */ 1290*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 1291*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &zero); 1292*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &zero); 1293*0Sstevel@tonic-gate /* setup TCP/IP connect timeout */ 1294*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, 1295*0Sstevel@tonic-gate &timeoutMilliSec); 1296*0Sstevel@tonic-gate /* retry if LDAP I/O was interrupted */ 1297*0Sstevel@tonic-gate (void) ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate switch (bindType) { 1300*0Sstevel@tonic-gate case NS_LDAP_AUTH_NONE: 1301*0Sstevel@tonic-gate #ifdef DEBUG 1302*0Sstevel@tonic-gate (void) fprintf(stderr, "+++Anonymous bind\n"); 1303*0Sstevel@tonic-gate #endif /* DEBUG */ 1304*0Sstevel@tonic-gate break; 1305*0Sstevel@tonic-gate case NS_LDAP_AUTH_SIMPLE: 1306*0Sstevel@tonic-gate binddn = auth->cred.unix_cred.userID; 1307*0Sstevel@tonic-gate passwd = auth->cred.unix_cred.passwd; 1308*0Sstevel@tonic-gate if (passwd == NULL || *passwd == '\0' || 1309*0Sstevel@tonic-gate binddn == NULL || *binddn == '\0') { 1310*0Sstevel@tonic-gate (void) sprintf(errstr, gettext("openConnection: " 1311*0Sstevel@tonic-gate "missing credentials for Simple bind")); 1312*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, LDAP_INVALID_CREDENTIALS, 1313*0Sstevel@tonic-gate strdup(errstr), NULL); 1314*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1315*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1316*0Sstevel@tonic-gate } 1317*0Sstevel@tonic-gate 1318*0Sstevel@tonic-gate #ifdef DEBUG 1319*0Sstevel@tonic-gate (void) fprintf(stderr, "+++Simple bind\n"); 1320*0Sstevel@tonic-gate #endif /* DEBUG */ 1321*0Sstevel@tonic-gate msgId = ldap_simple_bind(ld, binddn, passwd); 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate if (msgId == -1) { 1324*0Sstevel@tonic-gate (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, 1325*0Sstevel@tonic-gate (void *)&errnum); 1326*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1327*0Sstevel@tonic-gate gettext("openConnection: simple bind failed " 1328*0Sstevel@tonic-gate "- %s"), ldap_err2string(errnum)); 1329*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1330*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, errnum, strdup(errstr), 1331*0Sstevel@tonic-gate NULL); 1332*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1333*0Sstevel@tonic-gate } 1334*0Sstevel@tonic-gate 1335*0Sstevel@tonic-gate tv.tv_sec = timeoutSec; 1336*0Sstevel@tonic-gate tv.tv_usec = 0; 1337*0Sstevel@tonic-gate rc = ldap_result(ld, msgId, 0, &tv, &resultMsg); 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate if ((rc == -1) || (rc == 0)) { 1340*0Sstevel@tonic-gate (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, 1341*0Sstevel@tonic-gate (void *)&errnum); 1342*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1343*0Sstevel@tonic-gate gettext("openConnection: simple bind failed " 1344*0Sstevel@tonic-gate "- %s"), ldap_err2string(errnum)); 1345*0Sstevel@tonic-gate (void) ldap_msgfree(resultMsg); 1346*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1347*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, errnum, strdup(errstr), 1348*0Sstevel@tonic-gate NULL); 1349*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1350*0Sstevel@tonic-gate } 1351*0Sstevel@tonic-gate 1352*0Sstevel@tonic-gate /* 1353*0Sstevel@tonic-gate * get ldaprc, controls, and error msg 1354*0Sstevel@tonic-gate */ 1355*0Sstevel@tonic-gate rc = ldap_parse_result(ld, resultMsg, &errnum, NULL, 1356*0Sstevel@tonic-gate &errmsg, NULL, &controls, 1); 1357*0Sstevel@tonic-gate 1358*0Sstevel@tonic-gate if (rc != LDAP_SUCCESS) { 1359*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1360*0Sstevel@tonic-gate gettext("openConnection: simple bind failed " 1361*0Sstevel@tonic-gate "- unable to parse result")); 1362*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1363*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, 1364*0Sstevel@tonic-gate strdup(errstr), NULL); 1365*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1366*0Sstevel@tonic-gate } 1367*0Sstevel@tonic-gate 1368*0Sstevel@tonic-gate /* process the password management info, if any */ 1369*0Sstevel@tonic-gate pwd_rc = process_pwd_mgmt("simple", 1370*0Sstevel@tonic-gate errnum, controls, errmsg, 1371*0Sstevel@tonic-gate errorp, 1372*0Sstevel@tonic-gate fail_if_new_pwd_reqd, 1373*0Sstevel@tonic-gate passwd_mgmt); 1374*0Sstevel@tonic-gate 1375*0Sstevel@tonic-gate if (pwd_rc == NS_LDAP_INTERNAL) { 1376*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1377*0Sstevel@tonic-gate return (pwd_rc); 1378*0Sstevel@tonic-gate } 1379*0Sstevel@tonic-gate 1380*0Sstevel@tonic-gate if (pwd_rc == NS_LDAP_SUCCESS_WITH_INFO) { 1381*0Sstevel@tonic-gate *ldp = ld; 1382*0Sstevel@tonic-gate return (pwd_rc); 1383*0Sstevel@tonic-gate } 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate break; 1386*0Sstevel@tonic-gate case NS_LDAP_AUTH_SASL: 1387*0Sstevel@tonic-gate /* We don't support any sasl options yet */ 1388*0Sstevel@tonic-gate if (auth->auth.saslopt != NS_LDAP_SASLOPT_NONE) { 1389*0Sstevel@tonic-gate (void) sprintf(errstr, 1390*0Sstevel@tonic-gate gettext("openConnection: SASL options are " 1391*0Sstevel@tonic-gate "not supported (%d)"), auth->auth.saslopt); 1392*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, 1393*0Sstevel@tonic-gate LDAP_AUTH_METHOD_NOT_SUPPORTED, 1394*0Sstevel@tonic-gate strdup(errstr), NULL); 1395*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1396*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate binddn = auth->cred.unix_cred.userID; 1399*0Sstevel@tonic-gate passwd = auth->cred.unix_cred.passwd; 1400*0Sstevel@tonic-gate if (passwd == NULL || *passwd == '\0' || 1401*0Sstevel@tonic-gate binddn == NULL || *binddn == '\0') { 1402*0Sstevel@tonic-gate (void) sprintf(errstr, 1403*0Sstevel@tonic-gate gettext("openConnection: missing credentials " 1404*0Sstevel@tonic-gate "for SASL bind")); 1405*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, LDAP_INVALID_CREDENTIALS, 1406*0Sstevel@tonic-gate strdup(errstr), NULL); 1407*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1408*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1409*0Sstevel@tonic-gate } 1410*0Sstevel@tonic-gate cred.bv_val = passwd; 1411*0Sstevel@tonic-gate cred.bv_len = strlen(passwd); 1412*0Sstevel@tonic-gate 1413*0Sstevel@tonic-gate switch (auth->auth.saslmech) { 1414*0Sstevel@tonic-gate case NS_LDAP_SASL_CRAM_MD5: 1415*0Sstevel@tonic-gate /* 1416*0Sstevel@tonic-gate * NOTE: if iDS changes to support cram_md5, 1417*0Sstevel@tonic-gate * please add password management code here. 1418*0Sstevel@tonic-gate * Since ldap_sasl_cram_md5_bind_s does not 1419*0Sstevel@tonic-gate * return anything that could be used to 1420*0Sstevel@tonic-gate * extract the ldap rc/errmsg/control to 1421*0Sstevel@tonic-gate * determine if bind failed due to password 1422*0Sstevel@tonic-gate * policy, a new cram_md5_bind API will need 1423*0Sstevel@tonic-gate * to be introduced. See 1424*0Sstevel@tonic-gate * ldap_x_sasl_digest_md5_bind() and case 1425*0Sstevel@tonic-gate * NS_LDAP_SASL_DIGEST_MD5 below for details. 1426*0Sstevel@tonic-gate */ 1427*0Sstevel@tonic-gate if ((rc = ldap_sasl_cram_md5_bind_s(ld, binddn, 1428*0Sstevel@tonic-gate &cred, NULL, NULL)) != LDAP_SUCCESS) { 1429*0Sstevel@tonic-gate (void) ldap_get_option(ld, 1430*0Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, (void *)&errnum); 1431*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1432*0Sstevel@tonic-gate gettext("openConnection: " 1433*0Sstevel@tonic-gate "sasl/CRAM-MD5 bind failed - %s"), 1434*0Sstevel@tonic-gate ldap_err2string(errnum)); 1435*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, errnum, 1436*0Sstevel@tonic-gate strdup(errstr), NULL); 1437*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1438*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate break; 1441*0Sstevel@tonic-gate case NS_LDAP_SASL_DIGEST_MD5: 1442*0Sstevel@tonic-gate digest_md5_name = malloc(strlen(binddn) + 5); 1443*0Sstevel@tonic-gate /* 5 = strlen("dn: ") + 1 */ 1444*0Sstevel@tonic-gate if (digest_md5_name == NULL) { 1445*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1446*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1447*0Sstevel@tonic-gate } 1448*0Sstevel@tonic-gate (void) strcpy(digest_md5_name, "dn: "); 1449*0Sstevel@tonic-gate (void) strcat(digest_md5_name, binddn); 1450*0Sstevel@tonic-gate 1451*0Sstevel@tonic-gate tv.tv_sec = timeoutSec; 1452*0Sstevel@tonic-gate tv.tv_usec = 0; 1453*0Sstevel@tonic-gate rc = ldap_x_sasl_digest_md5_bind(ld, 1454*0Sstevel@tonic-gate digest_md5_name, &cred, NULL, NULL, 1455*0Sstevel@tonic-gate &tv, &resultMsg); 1456*0Sstevel@tonic-gate 1457*0Sstevel@tonic-gate if (resultMsg == NULL) { 1458*0Sstevel@tonic-gate free(digest_md5_name); 1459*0Sstevel@tonic-gate (void) ldap_get_option(ld, 1460*0Sstevel@tonic-gate LDAP_OPT_ERROR_NUMBER, (void *)&errnum); 1461*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1462*0Sstevel@tonic-gate gettext("openConnection: " 1463*0Sstevel@tonic-gate "DIGEST-MD5 bind failed - %s"), 1464*0Sstevel@tonic-gate ldap_err2string(errnum)); 1465*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1466*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, errnum, 1467*0Sstevel@tonic-gate strdup(errstr), NULL); 1468*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1469*0Sstevel@tonic-gate } 1470*0Sstevel@tonic-gate 1471*0Sstevel@tonic-gate /* 1472*0Sstevel@tonic-gate * get ldaprc, controls, and error msg 1473*0Sstevel@tonic-gate */ 1474*0Sstevel@tonic-gate rc = ldap_parse_result(ld, resultMsg, &errnum, NULL, 1475*0Sstevel@tonic-gate &errmsg, NULL, &controls, 1); 1476*0Sstevel@tonic-gate 1477*0Sstevel@tonic-gate if (rc != LDAP_SUCCESS) { 1478*0Sstevel@tonic-gate free(digest_md5_name); 1479*0Sstevel@tonic-gate (void) snprintf(errstr, sizeof (errstr), 1480*0Sstevel@tonic-gate gettext("openConnection: " 1481*0Sstevel@tonic-gate "DIGEST-MD5 bind failed " 1482*0Sstevel@tonic-gate "- unable to parse result")); 1483*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1484*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, 1485*0Sstevel@tonic-gate strdup(errstr), NULL); 1486*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1487*0Sstevel@tonic-gate } 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate /* process the password management info, if any */ 1490*0Sstevel@tonic-gate pwd_rc = process_pwd_mgmt("sasl/DIGEST-MD5", 1491*0Sstevel@tonic-gate errnum, controls, errmsg, 1492*0Sstevel@tonic-gate errorp, 1493*0Sstevel@tonic-gate fail_if_new_pwd_reqd, 1494*0Sstevel@tonic-gate passwd_mgmt); 1495*0Sstevel@tonic-gate 1496*0Sstevel@tonic-gate if (pwd_rc == NS_LDAP_INTERNAL) { 1497*0Sstevel@tonic-gate free(digest_md5_name); 1498*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1499*0Sstevel@tonic-gate return (pwd_rc); 1500*0Sstevel@tonic-gate } 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate if (pwd_rc == NS_LDAP_SUCCESS_WITH_INFO) { 1503*0Sstevel@tonic-gate *ldp = ld; 1504*0Sstevel@tonic-gate return (pwd_rc); 1505*0Sstevel@tonic-gate } 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate free(digest_md5_name); 1508*0Sstevel@tonic-gate break; 1509*0Sstevel@tonic-gate default: 1510*0Sstevel@tonic-gate (void) ldap_unbind(ld); 1511*0Sstevel@tonic-gate (void) sprintf(errstr, 1512*0Sstevel@tonic-gate gettext("openConnection: unsupported SASL " 1513*0Sstevel@tonic-gate "mechanism (%d)"), auth->auth.saslmech); 1514*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, 1515*0Sstevel@tonic-gate LDAP_AUTH_METHOD_NOT_SUPPORTED, strdup(errstr), 1516*0Sstevel@tonic-gate NULL); 1517*0Sstevel@tonic-gate return (NS_LDAP_INTERNAL); 1518*0Sstevel@tonic-gate } 1519*0Sstevel@tonic-gate } 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gate *ldp = ld; 1522*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 1523*0Sstevel@tonic-gate } 1524*0Sstevel@tonic-gate 1525*0Sstevel@tonic-gate /* 1526*0Sstevel@tonic-gate * FUNCTION: __s_api_getDefaultAuth 1527*0Sstevel@tonic-gate * 1528*0Sstevel@tonic-gate * Constructs a credential for authentication using the config module. 1529*0Sstevel@tonic-gate * 1530*0Sstevel@tonic-gate * RETURN VALUES: 1531*0Sstevel@tonic-gate * 1532*0Sstevel@tonic-gate * NS_LDAP_SUCCESS If successful 1533*0Sstevel@tonic-gate * NS_LDAP_CONFIG If there are any config errors. 1534*0Sstevel@tonic-gate * NS_LDAP_MEMORY Memory errors. 1535*0Sstevel@tonic-gate * NS_LDAP_OP_FAILED If there are no more authentication methods so can 1536*0Sstevel@tonic-gate * not build a new authp. 1537*0Sstevel@tonic-gate * NS_LDAP_INVALID_PARAM This overloaded return value means that some of the 1538*0Sstevel@tonic-gate * necessary fields of a cred for a given auth method 1539*0Sstevel@tonic-gate * are not provided. 1540*0Sstevel@tonic-gate * INPUT: 1541*0Sstevel@tonic-gate * 1542*0Sstevel@tonic-gate * cLevel Currently requested credential level to be tried 1543*0Sstevel@tonic-gate * 1544*0Sstevel@tonic-gate * aMethod Currently requested authentication method to be tried 1545*0Sstevel@tonic-gate * 1546*0Sstevel@tonic-gate * OUTPUT: 1547*0Sstevel@tonic-gate * 1548*0Sstevel@tonic-gate * authp authentication method to use. 1549*0Sstevel@tonic-gate */ 1550*0Sstevel@tonic-gate static int 1551*0Sstevel@tonic-gate __s_api_getDefaultAuth( 1552*0Sstevel@tonic-gate int *cLevel, 1553*0Sstevel@tonic-gate ns_auth_t *aMethod, 1554*0Sstevel@tonic-gate ns_cred_t **authp) 1555*0Sstevel@tonic-gate { 1556*0Sstevel@tonic-gate void **paramVal = NULL; 1557*0Sstevel@tonic-gate char *modparamVal = NULL; 1558*0Sstevel@tonic-gate int getUid = 0; 1559*0Sstevel@tonic-gate int getPasswd = 0; 1560*0Sstevel@tonic-gate int getCertpath = 0; 1561*0Sstevel@tonic-gate int rc = 0; 1562*0Sstevel@tonic-gate ns_ldap_error_t *errorp = NULL; 1563*0Sstevel@tonic-gate 1564*0Sstevel@tonic-gate #ifdef DEBUG 1565*0Sstevel@tonic-gate (void) fprintf(stderr, "__s_api_getDefaultAuth START\n"); 1566*0Sstevel@tonic-gate #endif 1567*0Sstevel@tonic-gate 1568*0Sstevel@tonic-gate if (aMethod == NULL) { 1569*0Sstevel@tonic-gate /* Require an Auth */ 1570*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1571*0Sstevel@tonic-gate 1572*0Sstevel@tonic-gate } 1573*0Sstevel@tonic-gate 1574*0Sstevel@tonic-gate /* 1575*0Sstevel@tonic-gate * Do not differentiate between (proxy/self) at this time, but 1576*0Sstevel@tonic-gate * reject self credential levels at this time 1577*0Sstevel@tonic-gate */ 1578*0Sstevel@tonic-gate if (cLevel && *cLevel == NS_LDAP_CRED_SELF) 1579*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1580*0Sstevel@tonic-gate 1581*0Sstevel@tonic-gate *authp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t)); 1582*0Sstevel@tonic-gate if ((*authp) == NULL) 1583*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1584*0Sstevel@tonic-gate 1585*0Sstevel@tonic-gate (*authp)->auth = *aMethod; 1586*0Sstevel@tonic-gate 1587*0Sstevel@tonic-gate switch (aMethod->type) { 1588*0Sstevel@tonic-gate case NS_LDAP_AUTH_NONE: 1589*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 1590*0Sstevel@tonic-gate case NS_LDAP_AUTH_SIMPLE: 1591*0Sstevel@tonic-gate getUid++; 1592*0Sstevel@tonic-gate getPasswd++; 1593*0Sstevel@tonic-gate break; 1594*0Sstevel@tonic-gate case NS_LDAP_AUTH_SASL: 1595*0Sstevel@tonic-gate if ((aMethod->saslmech == NS_LDAP_SASL_DIGEST_MD5) || 1596*0Sstevel@tonic-gate (aMethod->saslmech == NS_LDAP_SASL_CRAM_MD5)) { 1597*0Sstevel@tonic-gate getUid++; 1598*0Sstevel@tonic-gate getPasswd++; 1599*0Sstevel@tonic-gate } else { 1600*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1601*0Sstevel@tonic-gate *authp = NULL; 1602*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1603*0Sstevel@tonic-gate } 1604*0Sstevel@tonic-gate break; 1605*0Sstevel@tonic-gate case NS_LDAP_AUTH_TLS: 1606*0Sstevel@tonic-gate if ((aMethod->tlstype == NS_LDAP_TLS_SIMPLE) || 1607*0Sstevel@tonic-gate ((aMethod->tlstype == NS_LDAP_TLS_SASL) && 1608*0Sstevel@tonic-gate ((aMethod->saslmech == NS_LDAP_SASL_DIGEST_MD5) || 1609*0Sstevel@tonic-gate (aMethod->saslmech == NS_LDAP_SASL_CRAM_MD5)))) { 1610*0Sstevel@tonic-gate getUid++; 1611*0Sstevel@tonic-gate getPasswd++; 1612*0Sstevel@tonic-gate getCertpath++; 1613*0Sstevel@tonic-gate } else if (aMethod->tlstype == NS_LDAP_TLS_NONE) { 1614*0Sstevel@tonic-gate getCertpath++; 1615*0Sstevel@tonic-gate } else { 1616*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1617*0Sstevel@tonic-gate *authp = NULL; 1618*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1619*0Sstevel@tonic-gate } 1620*0Sstevel@tonic-gate break; 1621*0Sstevel@tonic-gate } 1622*0Sstevel@tonic-gate 1623*0Sstevel@tonic-gate if (getUid) { 1624*0Sstevel@tonic-gate paramVal = NULL; 1625*0Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_BINDDN_P, 1626*0Sstevel@tonic-gate ¶mVal, &errorp)) != NS_LDAP_SUCCESS) { 1627*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1628*0Sstevel@tonic-gate (void) __ns_ldap_freeError(&errorp); 1629*0Sstevel@tonic-gate *authp = NULL; 1630*0Sstevel@tonic-gate return (rc); 1631*0Sstevel@tonic-gate } 1632*0Sstevel@tonic-gate 1633*0Sstevel@tonic-gate if (paramVal == NULL || *paramVal == NULL) { 1634*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1635*0Sstevel@tonic-gate *authp = NULL; 1636*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1637*0Sstevel@tonic-gate } 1638*0Sstevel@tonic-gate 1639*0Sstevel@tonic-gate (*authp)->cred.unix_cred.userID = strdup((char *)*paramVal); 1640*0Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 1641*0Sstevel@tonic-gate if ((*authp)->cred.unix_cred.userID == NULL) { 1642*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1643*0Sstevel@tonic-gate *authp = NULL; 1644*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1645*0Sstevel@tonic-gate } 1646*0Sstevel@tonic-gate } 1647*0Sstevel@tonic-gate if (getPasswd) { 1648*0Sstevel@tonic-gate paramVal = NULL; 1649*0Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_BINDPASSWD_P, 1650*0Sstevel@tonic-gate ¶mVal, &errorp)) != NS_LDAP_SUCCESS) { 1651*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1652*0Sstevel@tonic-gate (void) __ns_ldap_freeError(&errorp); 1653*0Sstevel@tonic-gate *authp = NULL; 1654*0Sstevel@tonic-gate return (rc); 1655*0Sstevel@tonic-gate } 1656*0Sstevel@tonic-gate 1657*0Sstevel@tonic-gate if (paramVal == NULL || *paramVal == NULL) { 1658*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1659*0Sstevel@tonic-gate *authp = NULL; 1660*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1661*0Sstevel@tonic-gate } 1662*0Sstevel@tonic-gate 1663*0Sstevel@tonic-gate modparamVal = dvalue((char *)*paramVal); 1664*0Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 1665*0Sstevel@tonic-gate if (modparamVal == NULL || (strlen((char *)modparamVal) == 0)) { 1666*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1667*0Sstevel@tonic-gate if (modparamVal != NULL) 1668*0Sstevel@tonic-gate free(modparamVal); 1669*0Sstevel@tonic-gate *authp = NULL; 1670*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1671*0Sstevel@tonic-gate } 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate (*authp)->cred.unix_cred.passwd = modparamVal; 1674*0Sstevel@tonic-gate } 1675*0Sstevel@tonic-gate if (getCertpath) { 1676*0Sstevel@tonic-gate paramVal = NULL; 1677*0Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P, 1678*0Sstevel@tonic-gate ¶mVal, &errorp)) != NS_LDAP_SUCCESS) { 1679*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1680*0Sstevel@tonic-gate (void) __ns_ldap_freeError(&errorp); 1681*0Sstevel@tonic-gate *authp = NULL; 1682*0Sstevel@tonic-gate return (rc); 1683*0Sstevel@tonic-gate } 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gate if (paramVal == NULL || *paramVal == NULL) { 1686*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1687*0Sstevel@tonic-gate *authp = NULL; 1688*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1689*0Sstevel@tonic-gate } 1690*0Sstevel@tonic-gate 1691*0Sstevel@tonic-gate (*authp)->hostcertpath = strdup((char *)*paramVal); 1692*0Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 1693*0Sstevel@tonic-gate if ((*authp)->hostcertpath == NULL) { 1694*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(authp); 1695*0Sstevel@tonic-gate *authp = NULL; 1696*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1697*0Sstevel@tonic-gate } 1698*0Sstevel@tonic-gate } 1699*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 1700*0Sstevel@tonic-gate } 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate /* 1703*0Sstevel@tonic-gate * FUNCTION: __s_api_getConnection 1704*0Sstevel@tonic-gate * 1705*0Sstevel@tonic-gate * Bind to the specified server or one from the server 1706*0Sstevel@tonic-gate * list and return the pointer. 1707*0Sstevel@tonic-gate * 1708*0Sstevel@tonic-gate * This function can rebind or not (NS_LDAP_HARD), it can require a 1709*0Sstevel@tonic-gate * credential or bind anonymously 1710*0Sstevel@tonic-gate * 1711*0Sstevel@tonic-gate * This function follows the DUA configuration schema algorithm 1712*0Sstevel@tonic-gate * 1713*0Sstevel@tonic-gate * RETURN VALUES: 1714*0Sstevel@tonic-gate * 1715*0Sstevel@tonic-gate * NS_LDAP_SUCCESS A connection was made successfully. 1716*0Sstevel@tonic-gate * NS_LDAP_SUCCESS_WITH_INFO 1717*0Sstevel@tonic-gate * A connection was made successfully, but with 1718*0Sstevel@tonic-gate * password management info in *errorp 1719*0Sstevel@tonic-gate * NS_LDAP_INVALID_PARAM If any invalid arguments were passed to the function. 1720*0Sstevel@tonic-gate * NS_LDAP_CONFIG If there are any config errors. 1721*0Sstevel@tonic-gate * NS_LDAP_MEMORY Memory errors. 1722*0Sstevel@tonic-gate * NS_LDAP_INTERNAL If there was a ldap error. 1723*0Sstevel@tonic-gate * 1724*0Sstevel@tonic-gate * INPUT: 1725*0Sstevel@tonic-gate * 1726*0Sstevel@tonic-gate * server Bind to this LDAP server only 1727*0Sstevel@tonic-gate * flags If NS_LDAP_HARD is set function will not return until it has 1728*0Sstevel@tonic-gate * a connection unless there is a authentication problem. 1729*0Sstevel@tonic-gate * If NS_LDAP_NEW_CONN is set the function must force a new 1730*0Sstevel@tonic-gate * connection to be created 1731*0Sstevel@tonic-gate * If NS_LDAP_KEEP_CONN is set the connection is to be kept open 1732*0Sstevel@tonic-gate * auth Credentials for bind. This could be NULL in which case 1733*0Sstevel@tonic-gate * a default cred built from the config module is used. 1734*0Sstevel@tonic-gate * sessionId cookie that points to a previous session 1735*0Sstevel@tonic-gate * fail_if_new_pwd_reqd 1736*0Sstevel@tonic-gate * a flag indicating this function should fail if the passwd 1737*0Sstevel@tonic-gate * in auth needs to change immediately 1738*0Sstevel@tonic-gate * 1739*0Sstevel@tonic-gate * OUTPUT: 1740*0Sstevel@tonic-gate * 1741*0Sstevel@tonic-gate * session pointer to a session with connection information 1742*0Sstevel@tonic-gate * errorp Set if there are any INTERNAL, or CONFIG error. 1743*0Sstevel@tonic-gate */ 1744*0Sstevel@tonic-gate int 1745*0Sstevel@tonic-gate __s_api_getConnection( 1746*0Sstevel@tonic-gate const char *server, 1747*0Sstevel@tonic-gate const int flags, 1748*0Sstevel@tonic-gate const ns_cred_t *cred, /* credentials for bind */ 1749*0Sstevel@tonic-gate ConnectionID *sessionId, 1750*0Sstevel@tonic-gate Connection **session, 1751*0Sstevel@tonic-gate ns_ldap_error_t **errorp, 1752*0Sstevel@tonic-gate int fail_if_new_pwd_reqd) 1753*0Sstevel@tonic-gate { 1754*0Sstevel@tonic-gate char errmsg[MAXERROR]; 1755*0Sstevel@tonic-gate ns_auth_t **aMethod = NULL; 1756*0Sstevel@tonic-gate ns_auth_t **aNext = NULL; 1757*0Sstevel@tonic-gate int **cLevel = NULL; 1758*0Sstevel@tonic-gate int **cNext = NULL; 1759*0Sstevel@tonic-gate int timeoutSec = NS_DEFAULT_BIND_TIMEOUT; 1760*0Sstevel@tonic-gate int rc; 1761*0Sstevel@tonic-gate Connection *con = NULL; 1762*0Sstevel@tonic-gate int sec = 1; 1763*0Sstevel@tonic-gate ns_cred_t *authp = NULL; 1764*0Sstevel@tonic-gate ns_cred_t anon; 1765*0Sstevel@tonic-gate int version = NS_LDAP_V2; 1766*0Sstevel@tonic-gate void **paramVal = NULL; 1767*0Sstevel@tonic-gate 1768*0Sstevel@tonic-gate if ((session == NULL) || (sessionId == NULL)) { 1769*0Sstevel@tonic-gate return (NS_LDAP_INVALID_PARAM); 1770*0Sstevel@tonic-gate } 1771*0Sstevel@tonic-gate *session = NULL; 1772*0Sstevel@tonic-gate 1773*0Sstevel@tonic-gate /* if we already have a session id try to reuse connection */ 1774*0Sstevel@tonic-gate if (*sessionId > 0) { 1775*0Sstevel@tonic-gate rc = findConnectionById(flags, cred, *sessionId, &con); 1776*0Sstevel@tonic-gate if (rc == *sessionId && con) { 1777*0Sstevel@tonic-gate *session = con; 1778*0Sstevel@tonic-gate return (NS_LDAP_SUCCESS); 1779*0Sstevel@tonic-gate } 1780*0Sstevel@tonic-gate *sessionId = 0; 1781*0Sstevel@tonic-gate } 1782*0Sstevel@tonic-gate 1783*0Sstevel@tonic-gate /* get profile version number */ 1784*0Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, 1785*0Sstevel@tonic-gate ¶mVal, errorp)) != NS_LDAP_SUCCESS) 1786*0Sstevel@tonic-gate return (rc); 1787*0Sstevel@tonic-gate if (paramVal == NULL) { 1788*0Sstevel@tonic-gate (void) sprintf(errmsg, gettext("getConnection: no file " 1789*0Sstevel@tonic-gate "version")); 1790*0Sstevel@tonic-gate MKERROR(LOG_WARNING, *errorp, NS_CONFIG_FILE, strdup(errmsg), 1791*0Sstevel@tonic-gate NS_LDAP_CONFIG); 1792*0Sstevel@tonic-gate return (NS_LDAP_CONFIG); 1793*0Sstevel@tonic-gate } 1794*0Sstevel@tonic-gate if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_1) == 0) 1795*0Sstevel@tonic-gate version = NS_LDAP_V1; 1796*0Sstevel@tonic-gate (void) __ns_ldap_freeParam((void ***)¶mVal); 1797*0Sstevel@tonic-gate 1798*0Sstevel@tonic-gate /* Get the bind timeout value */ 1799*0Sstevel@tonic-gate (void) __ns_ldap_getParam(NS_LDAP_BIND_TIME_P, ¶mVal, errorp); 1800*0Sstevel@tonic-gate if (paramVal != NULL && *paramVal != NULL) { 1801*0Sstevel@tonic-gate timeoutSec = **((int **)paramVal); 1802*0Sstevel@tonic-gate (void) __ns_ldap_freeParam(¶mVal); 1803*0Sstevel@tonic-gate } 1804*0Sstevel@tonic-gate if (*errorp) 1805*0Sstevel@tonic-gate (void) __ns_ldap_freeError(errorp); 1806*0Sstevel@tonic-gate 1807*0Sstevel@tonic-gate if (cred == NULL) { 1808*0Sstevel@tonic-gate /* Get the authentication method list */ 1809*0Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_AUTH_P, 1810*0Sstevel@tonic-gate (void ***)&aMethod, errorp)) != NS_LDAP_SUCCESS) 1811*0Sstevel@tonic-gate return (rc); 1812*0Sstevel@tonic-gate if (aMethod == NULL) { 1813*0Sstevel@tonic-gate aMethod = (ns_auth_t **)calloc(2, sizeof (ns_auth_t *)); 1814*0Sstevel@tonic-gate if (aMethod == NULL) 1815*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1816*0Sstevel@tonic-gate aMethod[0] = (ns_auth_t *)calloc(1, sizeof (ns_auth_t)); 1817*0Sstevel@tonic-gate if (aMethod[0] == NULL) { 1818*0Sstevel@tonic-gate free(aMethod); 1819*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1820*0Sstevel@tonic-gate } 1821*0Sstevel@tonic-gate if (version == NS_LDAP_V1) 1822*0Sstevel@tonic-gate (aMethod[0])->type = NS_LDAP_AUTH_SIMPLE; 1823*0Sstevel@tonic-gate else { 1824*0Sstevel@tonic-gate (aMethod[0])->type = NS_LDAP_AUTH_SASL; 1825*0Sstevel@tonic-gate (aMethod[0])->saslmech = 1826*0Sstevel@tonic-gate NS_LDAP_SASL_DIGEST_MD5; 1827*0Sstevel@tonic-gate (aMethod[0])->saslopt = NS_LDAP_SASLOPT_NONE; 1828*0Sstevel@tonic-gate } 1829*0Sstevel@tonic-gate } 1830*0Sstevel@tonic-gate 1831*0Sstevel@tonic-gate /* Get the credential level list */ 1832*0Sstevel@tonic-gate if ((rc = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P, 1833*0Sstevel@tonic-gate (void ***)&cLevel, errorp)) != NS_LDAP_SUCCESS) { 1834*0Sstevel@tonic-gate (void) __ns_ldap_freeParam((void ***)&aMethod); 1835*0Sstevel@tonic-gate return (rc); 1836*0Sstevel@tonic-gate } 1837*0Sstevel@tonic-gate if (cLevel == NULL) { 1838*0Sstevel@tonic-gate cLevel = (int **)calloc(2, sizeof (int *)); 1839*0Sstevel@tonic-gate if (cLevel == NULL) 1840*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1841*0Sstevel@tonic-gate cLevel[0] = (int *)calloc(1, sizeof (int)); 1842*0Sstevel@tonic-gate if (cLevel[0] == NULL) 1843*0Sstevel@tonic-gate return (NS_LDAP_MEMORY); 1844*0Sstevel@tonic-gate if (version == NS_LDAP_V1) 1845*0Sstevel@tonic-gate *(cLevel[0]) = NS_LDAP_CRED_PROXY; 1846*0Sstevel@tonic-gate else 1847*0Sstevel@tonic-gate *(cLevel[0]) = NS_LDAP_CRED_ANON; 1848*0Sstevel@tonic-gate } 1849*0Sstevel@tonic-gate } 1850*0Sstevel@tonic-gate 1851*0Sstevel@tonic-gate /* setup the anon credential for anonymous connection */ 1852*0Sstevel@tonic-gate (void) memset(&anon, 0, sizeof (ns_cred_t)); 1853*0Sstevel@tonic-gate anon.auth.type = NS_LDAP_AUTH_NONE; 1854*0Sstevel@tonic-gate 1855*0Sstevel@tonic-gate for (; ; ) { 1856*0Sstevel@tonic-gate if (cred != NULL) { 1857*0Sstevel@tonic-gate /* using specified auth method */ 1858*0Sstevel@tonic-gate rc = makeConnection(&con, server, cred, 1859*0Sstevel@tonic-gate sessionId, timeoutSec, errorp, 1860*0Sstevel@tonic-gate fail_if_new_pwd_reqd); 1861*0Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS || 1862*0Sstevel@tonic-gate rc == NS_LDAP_SUCCESS_WITH_INFO) { 1863*0Sstevel@tonic-gate *session = con; 1864*0Sstevel@tonic-gate break; 1865*0Sstevel@tonic-gate } 1866*0Sstevel@tonic-gate } else { 1867*0Sstevel@tonic-gate /* for every cred level */ 1868*0Sstevel@tonic-gate for (cNext = cLevel; *cNext != NULL; cNext++) { 1869*0Sstevel@tonic-gate if (**cNext == NS_LDAP_CRED_ANON) { 1870*0Sstevel@tonic-gate /* make connection anonymously */ 1871*0Sstevel@tonic-gate rc = makeConnection(&con, server, &anon, 1872*0Sstevel@tonic-gate sessionId, timeoutSec, errorp, 1873*0Sstevel@tonic-gate fail_if_new_pwd_reqd); 1874*0Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS || 1875*0Sstevel@tonic-gate rc == 1876*0Sstevel@tonic-gate NS_LDAP_SUCCESS_WITH_INFO) { 1877*0Sstevel@tonic-gate *session = con; 1878*0Sstevel@tonic-gate goto done; 1879*0Sstevel@tonic-gate } 1880*0Sstevel@tonic-gate continue; 1881*0Sstevel@tonic-gate } 1882*0Sstevel@tonic-gate /* for each cred level */ 1883*0Sstevel@tonic-gate for (aNext = aMethod; *aNext != NULL; aNext++) { 1884*0Sstevel@tonic-gate /* make connection and authenticate */ 1885*0Sstevel@tonic-gate /* with default credentials */ 1886*0Sstevel@tonic-gate authp = NULL; 1887*0Sstevel@tonic-gate rc = __s_api_getDefaultAuth(*cNext, 1888*0Sstevel@tonic-gate *aNext, &authp); 1889*0Sstevel@tonic-gate if (rc != NS_LDAP_SUCCESS) { 1890*0Sstevel@tonic-gate continue; 1891*0Sstevel@tonic-gate } 1892*0Sstevel@tonic-gate rc = makeConnection(&con, server, authp, 1893*0Sstevel@tonic-gate sessionId, timeoutSec, errorp, 1894*0Sstevel@tonic-gate fail_if_new_pwd_reqd); 1895*0Sstevel@tonic-gate (void) __ns_ldap_freeCred(&authp); 1896*0Sstevel@tonic-gate if (rc == NS_LDAP_SUCCESS || 1897*0Sstevel@tonic-gate rc == 1898*0Sstevel@tonic-gate NS_LDAP_SUCCESS_WITH_INFO) { 1899*0Sstevel@tonic-gate *session = con; 1900*0Sstevel@tonic-gate goto done; 1901*0Sstevel@tonic-gate } 1902*0Sstevel@tonic-gate } 1903*0Sstevel@tonic-gate } 1904*0Sstevel@tonic-gate } 1905*0Sstevel@tonic-gate if (flags & NS_LDAP_HARD) { 1906*0Sstevel@tonic-gate if (sec < LDAPMAXHARDLOOKUPTIME) 1907*0Sstevel@tonic-gate sec *= 2; 1908*0Sstevel@tonic-gate _sleep(sec); 1909*0Sstevel@tonic-gate } else { 1910*0Sstevel@tonic-gate break; 1911*0Sstevel@tonic-gate } 1912*0Sstevel@tonic-gate } 1913*0Sstevel@tonic-gate 1914*0Sstevel@tonic-gate done: 1915*0Sstevel@tonic-gate (void) __ns_ldap_freeParam((void ***)&aMethod); 1916*0Sstevel@tonic-gate (void) __ns_ldap_freeParam((void ***)&cLevel); 1917*0Sstevel@tonic-gate return (rc); 1918*0Sstevel@tonic-gate } 1919*0Sstevel@tonic-gate 1920*0Sstevel@tonic-gate #pragma fini(_free_sessionPool) 1921*0Sstevel@tonic-gate static void 1922*0Sstevel@tonic-gate _free_sessionPool() 1923*0Sstevel@tonic-gate { 1924*0Sstevel@tonic-gate int id; 1925*0Sstevel@tonic-gate 1926*0Sstevel@tonic-gate (void) mutex_lock(&sessionPoolLock); 1927*0Sstevel@tonic-gate if (sessionPool != NULL) { 1928*0Sstevel@tonic-gate for (id = 0; id < sessionPoolSize; id++) 1929*0Sstevel@tonic-gate _DropConnection(id + CONID_OFFSET, 0, 1); 1930*0Sstevel@tonic-gate free(sessionPool); 1931*0Sstevel@tonic-gate sessionPool = NULL; 1932*0Sstevel@tonic-gate sessionPoolSize = 0; 1933*0Sstevel@tonic-gate } 1934*0Sstevel@tonic-gate (void) mutex_unlock(&sessionPoolLock); 1935*0Sstevel@tonic-gate } 1936