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 27 #include <shadow.h> 28 #include <stdlib.h> 29 #include "ldap_common.h" 30 31 /* shadow attributes filters */ 32 #define _S_UID "uid" 33 #define _S_USERPASSWORD "userpassword" 34 #define _S_FLAG "shadowflag" 35 36 #define _F_GETSPNAM "(&(objectClass=shadowAccount)(uid=%s))" 37 #define _F_GETSPNAM_SSD "(&(%%s)(uid=%s))" 38 39 static const char *sp_attrs[] = { 40 _S_UID, 41 _S_USERPASSWORD, 42 _S_FLAG, 43 (char *)NULL 44 }; 45 46 /* 47 * _nss_ldap_shadow2str is the data marshaling method for the shadow getXbyY 48 * (e.g., getspnam(), getspent()) backend processes. This method is called after 49 * a successful ldap search has been performed. This method will parse the 50 * ldap search values into the file format. 51 * e.g. 52 * 53 * myname:gaBXNJuz4JDmA:6445:::::: 54 * 55 */ 56 57 static int 58 _nss_ldap_shadow2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) 59 { 60 int nss_result; 61 int buflen = 0; 62 unsigned long len = 0L; 63 char *tmp, *buffer = NULL; 64 char *pw_passwd = NULL; 65 ns_ldap_result_t *result = be->result; 66 char **uid, **passwd, **flag, *flag_str; 67 68 if (result == NULL) 69 return (NSS_STR_PARSE_PARSE); 70 buflen = argp->buf.buflen; 71 72 nss_result = NSS_STR_PARSE_SUCCESS; 73 (void) memset(argp->buf.buffer, 0, buflen); 74 75 uid = __ns_ldap_getAttr(result->entry, _S_UID); 76 if (uid == NULL || uid[0] == NULL || (strlen(uid[0]) < 1)) { 77 nss_result = NSS_STR_PARSE_PARSE; 78 goto result_spd2str; 79 } 80 len += strlen(uid[0]); 81 82 passwd = __ns_ldap_getAttr(result->entry, _S_USERPASSWORD); 83 if (passwd == NULL || passwd[0] == NULL) { 84 /* 85 * ACL does not allow userpassword to return or 86 * userpassword is not defined 87 */ 88 pw_passwd = NOPWDRTR; 89 } else if (strcmp(passwd[0], "") == 0) { 90 /* 91 * An empty password is not supported 92 */ 93 nss_result = NSS_STR_PARSE_PARSE; 94 goto result_spd2str; 95 } else { 96 if ((tmp = strstr(passwd[0], "{crypt}")) != NULL || 97 (tmp = strstr(passwd[0], "{CRYPT}")) != NULL) { 98 if (tmp != passwd[0]) 99 pw_passwd = NOPWDRTR; 100 else 101 pw_passwd = tmp + strlen("{crypt}"); 102 } else { 103 /* mark password as not retrievable */ 104 pw_passwd = NOPWDRTR; 105 } 106 } 107 len += strlen(pw_passwd); 108 109 /* 110 * Ignore the following password aging related attributes: 111 * -- shadowlastchange 112 * -- shadowmin 113 * -- shadowmax 114 * -- shadowwarning 115 * -- shadowinactive 116 * -- shadowexpire 117 * This is because the LDAP naming service does not 118 * really support the password aging fields defined 119 * in the shadow structure. These fields, sp_lstchg, 120 * sp_min, sp_max, sp_warn, sp_inact, and sp_expire, 121 * will be set to -1 by the front end marshaller. 122 */ 123 flag = __ns_ldap_getAttr(result->entry, _S_FLAG); 124 if (flag == NULL || flag[0] == NULL) 125 flag_str = _NO_VALUE; 126 else 127 flag_str = flag[0]; 128 129 /* 9 = 8 ':' + 1 '\0' */ 130 len += strlen(flag_str) + 9; 131 132 if (len > buflen) { 133 nss_result = NSS_STR_PARSE_ERANGE; 134 goto result_spd2str; 135 } 136 137 if (argp->buf.result != NULL) { 138 be->buffer = calloc(1, len); 139 if (be->buffer == NULL) { 140 nss_result = NSS_STR_PARSE_PARSE; 141 goto result_spd2str; 142 } 143 buffer = be->buffer; 144 } else 145 buffer = argp->buf.buffer; 146 147 (void) snprintf(buffer, len, "%s:%s:::::::%s", 148 uid[0], pw_passwd, flag_str); 149 150 /* The front end marhsaller doesn't need the trailing null */ 151 if (argp->buf.result != NULL) 152 be->buflen = strlen(be->buffer); 153 result_spd2str: 154 155 (void) __ns_ldap_freeResult(&be->result); 156 return ((int)nss_result); 157 } 158 159 /* 160 * getbynam gets a passwd entry by uid name. This function constructs an ldap 161 * search filter using the name invocation parameter and the getspnam search 162 * filter defined. Once the filter is constructed we search for a matching 163 * entry and marshal the data results into struct shadow for the frontend 164 * process. The function _nss_ldap_shadow2ent performs the data marshaling. 165 */ 166 167 static nss_status_t 168 getbynam(ldap_backend_ptr be, void *a) 169 { 170 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 171 char searchfilter[SEARCHFILTERLEN]; 172 char userdata[SEARCHFILTERLEN]; 173 char name[SEARCHFILTERLEN + 1]; 174 int ret; 175 176 if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 177 return ((nss_status_t)NSS_NOTFOUND); 178 179 ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETSPNAM, name); 180 if (ret >= sizeof (searchfilter) || ret < 0) 181 return ((nss_status_t)NSS_NOTFOUND); 182 183 ret = snprintf(userdata, sizeof (userdata), _F_GETSPNAM_SSD, name); 184 if (ret >= sizeof (userdata) || ret < 0) 185 return ((nss_status_t)NSS_NOTFOUND); 186 187 return (_nss_ldap_lookup(be, argp, _SHADOW, searchfilter, NULL, 188 _merge_SSD_filter, userdata)); 189 } 190 191 static ldap_backend_op_t sp_ops[] = { 192 _nss_ldap_destr, 193 _nss_ldap_endent, 194 _nss_ldap_setent, 195 _nss_ldap_getent, 196 getbynam 197 }; 198 199 200 /* 201 * _nss_ldap_passwd_constr is where life begins. This function calls the 202 * generic ldap constructor function to define and build the abstract 203 * data types required to support ldap operations. 204 */ 205 206 /*ARGSUSED0*/ 207 nss_backend_t * 208 _nss_ldap_shadow_constr(const char *dummy1, const char *dummy2, 209 const char *dummy3) 210 { 211 212 return ((nss_backend_t *)_nss_ldap_constr(sp_ops, 213 sizeof (sp_ops)/sizeof (sp_ops[0]), 214 _SHADOW, sp_attrs, _nss_ldap_shadow2str)); 215 } 216