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 2003 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 <pwd.h> 30*0Sstevel@tonic-gate #include "ldap_common.h" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate /* passwd attributes filters */ 33*0Sstevel@tonic-gate #define _PWD_CN "cn" 34*0Sstevel@tonic-gate #define _PWD_UID "uid" 35*0Sstevel@tonic-gate #define _PWD_USERPASSWORD "userpassword" 36*0Sstevel@tonic-gate #define _PWD_UIDNUMBER "uidnumber" 37*0Sstevel@tonic-gate #define _PWD_GIDNUMBER "gidnumber" 38*0Sstevel@tonic-gate #define _PWD_GECOS "gecos" 39*0Sstevel@tonic-gate #define _PWD_DESCRIPTION "description" 40*0Sstevel@tonic-gate #define _PWD_HOMEDIRECTORY "homedirectory" 41*0Sstevel@tonic-gate #define _PWD_LOGINSHELL "loginshell" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))" 45*0Sstevel@tonic-gate #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))" 46*0Sstevel@tonic-gate #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%ld))" 47*0Sstevel@tonic-gate #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%ld))" 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate static const char *pwd_attrs[] = { 50*0Sstevel@tonic-gate _PWD_CN, 51*0Sstevel@tonic-gate _PWD_UID, 52*0Sstevel@tonic-gate _PWD_UIDNUMBER, 53*0Sstevel@tonic-gate _PWD_GIDNUMBER, 54*0Sstevel@tonic-gate _PWD_GECOS, 55*0Sstevel@tonic-gate _PWD_DESCRIPTION, 56*0Sstevel@tonic-gate _PWD_HOMEDIRECTORY, 57*0Sstevel@tonic-gate _PWD_LOGINSHELL, 58*0Sstevel@tonic-gate (char *)NULL 59*0Sstevel@tonic-gate }; 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate /* 63*0Sstevel@tonic-gate * _nss_ldap_passwd2ent is the data marshaling method for the passwd getXbyY 64*0Sstevel@tonic-gate * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is 65*0Sstevel@tonic-gate * called after a successful ldap search has been performed. This method will 66*0Sstevel@tonic-gate * parse the ldap search values into struct passwd = argp->buf.buffer which 67*0Sstevel@tonic-gate * the frontend process expects. Three error conditions are expected and 68*0Sstevel@tonic-gate * returned to nsswitch. 69*0Sstevel@tonic-gate */ 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate static int 72*0Sstevel@tonic-gate _nss_ldap_passwd2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp) 73*0Sstevel@tonic-gate { 74*0Sstevel@tonic-gate int i = 0; 75*0Sstevel@tonic-gate int nss_result; 76*0Sstevel@tonic-gate int buflen = (int)0; 77*0Sstevel@tonic-gate unsigned long len = 0L; 78*0Sstevel@tonic-gate char *buffer = (char *)NULL; 79*0Sstevel@tonic-gate char *ptr2x; 80*0Sstevel@tonic-gate char *ceiling = (char *)NULL; 81*0Sstevel@tonic-gate char *nullstring = (char *)NULL; 82*0Sstevel@tonic-gate struct passwd *pwd = (struct passwd *)NULL; 83*0Sstevel@tonic-gate ns_ldap_result_t *result = be->result; 84*0Sstevel@tonic-gate ns_ldap_attr_t *attrptr; 85*0Sstevel@tonic-gate int have_uid = 0; 86*0Sstevel@tonic-gate int have_uidn = 0; 87*0Sstevel@tonic-gate int have_gidn = 0; 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate #ifdef DEBUG 90*0Sstevel@tonic-gate (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd2ent]\n"); 91*0Sstevel@tonic-gate #endif /* DEBUG */ 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate buffer = argp->buf.buffer; 94*0Sstevel@tonic-gate buflen = (size_t)argp->buf.buflen; 95*0Sstevel@tonic-gate if (!argp->buf.result) { 96*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 97*0Sstevel@tonic-gate goto result_pwd2ent; 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate pwd = (struct passwd *)argp->buf.result; 100*0Sstevel@tonic-gate ceiling = buffer + buflen; 101*0Sstevel@tonic-gate nullstring = (buffer + (buflen - 1)); 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_SUCCESS; 104*0Sstevel@tonic-gate (void) memset(buffer, 0, buflen); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* 107*0Sstevel@tonic-gate * need to always return password as "x" 108*0Sstevel@tonic-gate * so put "x" at top of the buffer 109*0Sstevel@tonic-gate */ 110*0Sstevel@tonic-gate ptr2x = buffer; 111*0Sstevel@tonic-gate *buffer++ = 'x'; 112*0Sstevel@tonic-gate *buffer++ = '\0'; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate attrptr = getattr(result, 0); 115*0Sstevel@tonic-gate if (attrptr == NULL) { 116*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 117*0Sstevel@tonic-gate goto result_pwd2ent; 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate pwd->pw_gecos = nullstring; 121*0Sstevel@tonic-gate pwd->pw_dir = nullstring; 122*0Sstevel@tonic-gate pwd->pw_shell = nullstring; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate for (i = 0; i < result->entry->attr_count; i++) { 125*0Sstevel@tonic-gate attrptr = getattr(result, i); 126*0Sstevel@tonic-gate if (attrptr == NULL) { 127*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 128*0Sstevel@tonic-gate goto result_pwd2ent; 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate if (strcasecmp(attrptr->attrname, _PWD_UID) == 0) { 131*0Sstevel@tonic-gate if ((attrptr->attrvalue[0] == NULL) || 132*0Sstevel@tonic-gate (len = strlen(attrptr->attrvalue[0])) < 1) { 133*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 134*0Sstevel@tonic-gate goto result_pwd2ent; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate pwd->pw_name = buffer; 137*0Sstevel@tonic-gate buffer += len + 1; 138*0Sstevel@tonic-gate if (buffer >= ceiling) { 139*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 140*0Sstevel@tonic-gate goto result_pwd2ent; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate (void) strcpy(pwd->pw_name, attrptr->attrvalue[0]); 143*0Sstevel@tonic-gate have_uid = 1; 144*0Sstevel@tonic-gate continue; 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate if (strcasecmp(attrptr->attrname, _PWD_UIDNUMBER) == 0) { 147*0Sstevel@tonic-gate if (attrptr->attrvalue[0] == '\0') { 148*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 149*0Sstevel@tonic-gate goto result_pwd2ent; 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate pwd->pw_uid = strtol(attrptr->attrvalue[0], 152*0Sstevel@tonic-gate (char **)NULL, 10); 153*0Sstevel@tonic-gate have_uidn = 1; 154*0Sstevel@tonic-gate continue; 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate if (strcasecmp(attrptr->attrname, _PWD_GIDNUMBER) == 0) { 157*0Sstevel@tonic-gate if (attrptr->attrvalue[0] == '\0') { 158*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 159*0Sstevel@tonic-gate goto result_pwd2ent; 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate pwd->pw_gid = strtol(attrptr->attrvalue[0], 162*0Sstevel@tonic-gate (char **)NULL, 10); 163*0Sstevel@tonic-gate have_gidn = 1; 164*0Sstevel@tonic-gate continue; 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate if ((strcasecmp(attrptr->attrname, _PWD_GECOS) == 0) && 167*0Sstevel@tonic-gate (attrptr->value_count > 0)) { 168*0Sstevel@tonic-gate if ((attrptr->attrvalue[0] == NULL) || 169*0Sstevel@tonic-gate (len = strlen(attrptr->attrvalue[0])) < 1) { 170*0Sstevel@tonic-gate pwd->pw_gecos = nullstring; 171*0Sstevel@tonic-gate } else { 172*0Sstevel@tonic-gate pwd->pw_gecos = buffer; 173*0Sstevel@tonic-gate buffer += len + 1; 174*0Sstevel@tonic-gate if (buffer >= ceiling) { 175*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 176*0Sstevel@tonic-gate goto result_pwd2ent; 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate (void) strcpy(pwd->pw_gecos, 179*0Sstevel@tonic-gate attrptr->attrvalue[0]); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate continue; 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate if ((strcasecmp(attrptr->attrname, _PWD_HOMEDIRECTORY) == 0) && 184*0Sstevel@tonic-gate (attrptr->value_count > 0)) { 185*0Sstevel@tonic-gate if ((attrptr->attrvalue[0] == NULL) || 186*0Sstevel@tonic-gate (len = strlen(attrptr->attrvalue[0])) < 1) { 187*0Sstevel@tonic-gate pwd->pw_dir = nullstring; 188*0Sstevel@tonic-gate } else { 189*0Sstevel@tonic-gate pwd->pw_dir = buffer; 190*0Sstevel@tonic-gate buffer += len + 1; 191*0Sstevel@tonic-gate if (buffer >= ceiling) { 192*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 193*0Sstevel@tonic-gate goto result_pwd2ent; 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate (void) strcpy(pwd->pw_dir, 196*0Sstevel@tonic-gate attrptr->attrvalue[0]); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate continue; 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate if ((strcasecmp(attrptr->attrname, _PWD_LOGINSHELL) == 0) && 201*0Sstevel@tonic-gate (attrptr->value_count > 0)) { 202*0Sstevel@tonic-gate if ((attrptr->attrvalue[0] == NULL) || 203*0Sstevel@tonic-gate (len = strlen(attrptr->attrvalue[0])) < 1) { 204*0Sstevel@tonic-gate pwd->pw_shell = nullstring; 205*0Sstevel@tonic-gate } else { 206*0Sstevel@tonic-gate pwd->pw_shell = buffer; 207*0Sstevel@tonic-gate buffer += len + 1; 208*0Sstevel@tonic-gate if (buffer >= ceiling) { 209*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_ERANGE; 210*0Sstevel@tonic-gate goto result_pwd2ent; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate (void) strcpy(pwd->pw_shell, 213*0Sstevel@tonic-gate attrptr->attrvalue[0]); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate continue; 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* error if missing required attributes */ 220*0Sstevel@tonic-gate if (have_uid == 0 || have_uidn == 0 || have_gidn == 0) { 221*0Sstevel@tonic-gate nss_result = (int)NSS_STR_PARSE_PARSE; 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate pwd->pw_age = nullstring; 225*0Sstevel@tonic-gate pwd->pw_comment = nullstring; 226*0Sstevel@tonic-gate pwd->pw_passwd = ptr2x; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate #ifdef DEBUG 229*0Sstevel@tonic-gate (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd2ent]\n"); 230*0Sstevel@tonic-gate (void) fprintf(stdout, " pw_name: [%s]\n", pwd->pw_name); 231*0Sstevel@tonic-gate (void) fprintf(stdout, " pw_uid: [%ld]\n", pwd->pw_uid); 232*0Sstevel@tonic-gate (void) fprintf(stdout, " pw_gid: [%ld]\n", pwd->pw_gid); 233*0Sstevel@tonic-gate (void) fprintf(stdout, " pw_gecos: [%s]\n", pwd->pw_gecos); 234*0Sstevel@tonic-gate (void) fprintf(stdout, " pw_dir: [%s]\n", pwd->pw_dir); 235*0Sstevel@tonic-gate (void) fprintf(stdout, " pw_shell: [%s]\n", pwd->pw_shell); 236*0Sstevel@tonic-gate #endif /* DEBUG */ 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate result_pwd2ent: 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result); 241*0Sstevel@tonic-gate return ((int)nss_result); 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* 246*0Sstevel@tonic-gate * getbyname gets a passwd entry by uid name. This function constructs an ldap 247*0Sstevel@tonic-gate * search filter using the name invocation parameter and the getpwnam search 248*0Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching 249*0Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend 250*0Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling. 251*0Sstevel@tonic-gate */ 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate static nss_status_t 254*0Sstevel@tonic-gate getbyname(ldap_backend_ptr be, void *a) 255*0Sstevel@tonic-gate { 256*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 257*0Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN]; 258*0Sstevel@tonic-gate char userdata[SEARCHFILTERLEN]; 259*0Sstevel@tonic-gate char name[SEARCHFILTERLEN]; 260*0Sstevel@tonic-gate int ret; 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate #ifdef DEBUG 263*0Sstevel@tonic-gate (void) fprintf(stdout, "\n[getpwnam.c: getbyname]\n"); 264*0Sstevel@tonic-gate #endif /* DEBUG */ 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 267*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name); 270*0Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0) 271*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name); 274*0Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0) 275*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp, 278*0Sstevel@tonic-gate _PASSWD, searchfilter, NULL, 279*0Sstevel@tonic-gate _merge_SSD_filter, userdata)); 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* 284*0Sstevel@tonic-gate * getbyuid gets a passwd entry by uid number. This function constructs an ldap 285*0Sstevel@tonic-gate * search filter using the uid invocation parameter and the getpwuid search 286*0Sstevel@tonic-gate * filter defined. Once the filter is constructed, we search for a matching 287*0Sstevel@tonic-gate * entry and marshal the data results into struct passwd for the frontend 288*0Sstevel@tonic-gate * process. The function _nss_ldap_passwd2ent performs the data marshaling. 289*0Sstevel@tonic-gate */ 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate static nss_status_t 292*0Sstevel@tonic-gate getbyuid(ldap_backend_ptr be, void *a) 293*0Sstevel@tonic-gate { 294*0Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 295*0Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN]; 296*0Sstevel@tonic-gate char userdata[SEARCHFILTERLEN]; 297*0Sstevel@tonic-gate int ret; 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate #ifdef DEBUG 300*0Sstevel@tonic-gate (void) fprintf(stdout, "\n[getpwnam.c: getbyuid]\n"); 301*0Sstevel@tonic-gate #endif /* DEBUG */ 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), 304*0Sstevel@tonic-gate _F_GETPWUID, (long)argp->key.uid); 305*0Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0) 306*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), 309*0Sstevel@tonic-gate _F_GETPWUID_SSD, (long)argp->key.uid); 310*0Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0) 311*0Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate return ((nss_status_t)_nss_ldap_lookup(be, argp, 314*0Sstevel@tonic-gate _PASSWD, searchfilter, NULL, 315*0Sstevel@tonic-gate _merge_SSD_filter, userdata)); 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate static ldap_backend_op_t passwd_ops[] = { 319*0Sstevel@tonic-gate _nss_ldap_destr, 320*0Sstevel@tonic-gate _nss_ldap_endent, 321*0Sstevel@tonic-gate _nss_ldap_setent, 322*0Sstevel@tonic-gate _nss_ldap_getent, 323*0Sstevel@tonic-gate getbyname, 324*0Sstevel@tonic-gate getbyuid 325*0Sstevel@tonic-gate }; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate /* 329*0Sstevel@tonic-gate * _nss_ldap_passwd_constr is where life begins. This function calls the 330*0Sstevel@tonic-gate * generic ldap constructor function to define and build the abstract 331*0Sstevel@tonic-gate * data types required to support ldap operations. 332*0Sstevel@tonic-gate */ 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate /*ARGSUSED0*/ 335*0Sstevel@tonic-gate nss_backend_t * 336*0Sstevel@tonic-gate _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2, 337*0Sstevel@tonic-gate const char *dummy3) 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate #ifdef DEBUG 341*0Sstevel@tonic-gate (void) fprintf(stdout, "\n[getpwnam.c: _nss_ldap_passwd_constr]\n"); 342*0Sstevel@tonic-gate #endif /* DEBUG */ 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(passwd_ops, 345*0Sstevel@tonic-gate sizeof (passwd_ops)/sizeof (passwd_ops[0]), 346*0Sstevel@tonic-gate _PASSWD, pwd_attrs, _nss_ldap_passwd2ent)); 347*0Sstevel@tonic-gate } 348