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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <pwd.h> 27 #include "ldap_common.h" 28 29 /* passwd attributes filters */ 30 #define _PWD_CN "cn" 31 #define _PWD_UID "uid" 32 #define _PWD_USERPASSWORD "userpassword" 33 #define _PWD_UIDNUMBER "uidnumber" 34 #define _PWD_GIDNUMBER "gidnumber" 35 #define _PWD_GECOS "gecos" 36 #define _PWD_DESCRIPTION "description" 37 #define _PWD_HOMEDIRECTORY "homedirectory" 38 #define _PWD_LOGINSHELL "loginshell" 39 40 41 #define _F_GETPWNAM "(&(objectClass=posixAccount)(uid=%s))" 42 #define _F_GETPWNAM_SSD "(&(%%s)(uid=%s))" 43 #define _F_GETPWUID "(&(objectClass=posixAccount)(uidNumber=%ld))" 44 #define _F_GETPWUID_SSD "(&(%%s)(uidNumber=%ld))" 45 46 static const char *pwd_attrs[] = { 47 _PWD_CN, 48 _PWD_UID, 49 _PWD_UIDNUMBER, 50 _PWD_GIDNUMBER, 51 _PWD_GECOS, 52 _PWD_DESCRIPTION, 53 _PWD_HOMEDIRECTORY, 54 _PWD_LOGINSHELL, 55 (char *)NULL 56 }; 57 58 /* 59 * _nss_ldap_passwd2str is the data marshaling method for the passwd getXbyY 60 * (e.g., getbyuid(), getbyname(), getpwent()) backend processes. This method is 61 * called after a successful ldap search has been performed. This method will 62 * parse the ldap search values into the file format. 63 * e.g. 64 * 65 * nobody:x:60001:60001:Nobody:/: 66 * 67 */ 68 static int 69 _nss_ldap_passwd2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) 70 { 71 int nss_result; 72 int buflen = 0; 73 unsigned long str_len = 0L; 74 char *buffer = NULL; 75 ns_ldap_result_t *result = be->result; 76 ns_ldap_entry_t *entry; 77 char **uid_v, **uidn_v, **gidn_v; 78 char **gecos_v, **homedir_v, **shell_v; 79 char *NULL_STR = ""; 80 char uid_nobody[NOBODY_STR_LEN]; 81 char gid_nobody[NOBODY_STR_LEN], *end; 82 char *uid_nobody_v[1], *gid_nobody_v[1]; 83 84 (void) snprintf(uid_nobody, sizeof (uid_nobody), "%u", UID_NOBODY); 85 uid_nobody_v[0] = uid_nobody; 86 (void) snprintf(gid_nobody, sizeof (gid_nobody), "%u", GID_NOBODY); 87 gid_nobody_v[0] = gid_nobody; 88 89 if (result == NULL) 90 return (NSS_STR_PARSE_PARSE); 91 92 entry = result->entry; 93 94 buflen = argp->buf.buflen; 95 buffer = argp->buf.buffer; 96 97 nss_result = NSS_STR_PARSE_SUCCESS; 98 (void) memset(buffer, 0, buflen); 99 100 /* 8 = 6 ':' + 1 '\0' + 1 'x' */ 101 buflen -= 8; 102 103 uid_v = __ns_ldap_getAttr(entry, _PWD_UID); 104 uidn_v = __ns_ldap_getAttr(entry, _PWD_UIDNUMBER); 105 gidn_v = __ns_ldap_getAttr(entry, _PWD_GIDNUMBER); 106 if (uid_v == NULL || uidn_v == NULL || gidn_v == NULL || 107 uid_v[0] == NULL || uidn_v[0] == NULL || gidn_v[0] == NULL) { 108 nss_result = NSS_STR_PARSE_PARSE; 109 goto result_pwd2str; 110 } 111 /* Validate UID and GID */ 112 if (strtoul(uidn_v[0], &end, 10) > MAXUID) 113 uidn_v = uid_nobody_v; 114 if (strtoul(gidn_v[0], &end, 10) > MAXUID) 115 gidn_v = gid_nobody_v; 116 str_len = strlen(uid_v[0]) + strlen(uidn_v[0]) + strlen(gidn_v[0]); 117 if (str_len > buflen) { 118 nss_result = NSS_STR_PARSE_ERANGE; 119 goto result_pwd2str; 120 } 121 122 gecos_v = __ns_ldap_getAttr(entry, _PWD_GECOS); 123 if (gecos_v == NULL || gecos_v[0] == NULL || *gecos_v[0] == '\0') 124 gecos_v = &NULL_STR; 125 else 126 str_len += strlen(gecos_v[0]); 127 128 homedir_v = __ns_ldap_getAttr(entry, _PWD_HOMEDIRECTORY); 129 if (homedir_v == NULL || homedir_v[0] == NULL || *homedir_v[0] == '\0') 130 homedir_v = &NULL_STR; 131 else 132 str_len += strlen(homedir_v[0]); 133 134 shell_v = __ns_ldap_getAttr(entry, _PWD_LOGINSHELL); 135 if (shell_v == NULL || shell_v[0] == NULL || *shell_v[0] == '\0') 136 shell_v = &NULL_STR; 137 else 138 str_len += strlen(shell_v[0]); 139 140 if (str_len > buflen) { 141 nss_result = NSS_STR_PARSE_ERANGE; 142 goto result_pwd2str; 143 } 144 145 if (argp->buf.result != NULL) { 146 be->buflen = str_len + 8; 147 be->buffer = malloc(be->buflen); 148 if (be->buffer == NULL) { 149 nss_result = (int)NSS_STR_PARSE_ERANGE; 150 goto result_pwd2str; 151 } 152 153 (void) snprintf(be->buffer, be->buflen, 154 "%s:%s:%s:%s:%s:%s:%s", 155 uid_v[0], "x", uidn_v[0], gidn_v[0], 156 gecos_v[0], homedir_v[0], shell_v[0]); 157 } else { 158 (void) snprintf(argp->buf.buffer, (str_len + 8), 159 "%s:%s:%s:%s:%s:%s:%s", 160 uid_v[0], "x", uidn_v[0], gidn_v[0], 161 gecos_v[0], homedir_v[0], shell_v[0]); 162 } 163 164 result_pwd2str: 165 166 (void) __ns_ldap_freeResult(&be->result); 167 return ((int)nss_result); 168 } 169 170 /* 171 * getbyname gets a passwd entry by uid name. This function constructs an ldap 172 * search filter using the name invocation parameter and the getpwnam search 173 * filter defined. Once the filter is constructed, we search for a matching 174 * entry and marshal the data results into struct passwd for the frontend 175 * process. The function _nss_ldap_passwd2ent performs the data marshaling. 176 */ 177 178 static nss_status_t 179 getbyname(ldap_backend_ptr be, void *a) 180 { 181 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 182 char searchfilter[SEARCHFILTERLEN]; 183 char userdata[SEARCHFILTERLEN]; 184 char name[SEARCHFILTERLEN]; 185 int ret; 186 187 if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 188 return ((nss_status_t)NSS_NOTFOUND); 189 190 ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETPWNAM, name); 191 if (ret >= sizeof (searchfilter) || ret < 0) 192 return ((nss_status_t)NSS_NOTFOUND); 193 194 ret = snprintf(userdata, sizeof (userdata), _F_GETPWNAM_SSD, name); 195 if (ret >= sizeof (userdata) || ret < 0) 196 return ((nss_status_t)NSS_NOTFOUND); 197 198 return ((nss_status_t)_nss_ldap_lookup(be, argp, 199 _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata)); 200 } 201 202 203 /* 204 * getbyuid gets a passwd entry by uid number. This function constructs an ldap 205 * search filter using the uid invocation parameter and the getpwuid search 206 * filter defined. Once the filter is constructed, we search for a matching 207 * entry and marshal the data results into struct passwd for the frontend 208 * process. The function _nss_ldap_passwd2ent performs the data marshaling. 209 */ 210 211 static nss_status_t 212 getbyuid(ldap_backend_ptr be, void *a) 213 { 214 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 215 char searchfilter[SEARCHFILTERLEN]; 216 char userdata[SEARCHFILTERLEN]; 217 int ret; 218 219 if (argp->key.uid > MAXUID) 220 return ((nss_status_t)NSS_NOTFOUND); 221 222 ret = snprintf(searchfilter, sizeof (searchfilter), 223 _F_GETPWUID, (long)argp->key.uid); 224 if (ret >= sizeof (searchfilter) || ret < 0) 225 return ((nss_status_t)NSS_NOTFOUND); 226 227 ret = snprintf(userdata, sizeof (userdata), 228 _F_GETPWUID_SSD, (long)argp->key.uid); 229 if (ret >= sizeof (userdata) || ret < 0) 230 return ((nss_status_t)NSS_NOTFOUND); 231 232 return ((nss_status_t)_nss_ldap_lookup(be, argp, 233 _PASSWD, searchfilter, NULL, _merge_SSD_filter, userdata)); 234 } 235 236 static ldap_backend_op_t passwd_ops[] = { 237 _nss_ldap_destr, 238 _nss_ldap_endent, 239 _nss_ldap_setent, 240 _nss_ldap_getent, 241 getbyname, 242 getbyuid 243 }; 244 245 246 /* 247 * _nss_ldap_passwd_constr is where life begins. This function calls the 248 * generic ldap constructor function to define and build the abstract 249 * data types required to support ldap operations. 250 */ 251 252 /*ARGSUSED0*/ 253 nss_backend_t * 254 _nss_ldap_passwd_constr(const char *dummy1, const char *dummy2, 255 const char *dummy3) 256 { 257 258 return ((nss_backend_t *)_nss_ldap_constr(passwd_ops, 259 sizeof (passwd_ops)/sizeof (passwd_ops[0]), 260 _PASSWD, pwd_attrs, _nss_ldap_passwd2str)); 261 } 262