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