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