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