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 <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 || strlen(passwd[0]) < 1) { 86 pw_passwd = _NO_VALUE; 87 } else { 88 if ((tmp = strstr(passwd[0], "{crypt}")) != NULL || 89 (tmp = strstr(passwd[0], "{CRYPT}")) != NULL) { 90 if (tmp != passwd[0]) 91 pw_passwd = np; 92 else 93 pw_passwd = tmp + strlen("{crypt}"); 94 } else { 95 /* Replace it with *NP* */ 96 pw_passwd = np; 97 } 98 } 99 len += strlen(pw_passwd); 100 101 /* 102 * Ignore the following password aging related attributes: 103 * -- shadowlastchange 104 * -- shadowmin 105 * -- shadowmax 106 * -- shadowwarning 107 * -- shadowinactive 108 * -- shadowexpire 109 * This is because the LDAP naming service does not 110 * really support the password aging fields defined 111 * in the shadow structure. These fields, sp_lstchg, 112 * sp_min, sp_max, sp_warn, sp_inact, and sp_expire, 113 * will be set to -1 by the front end marshaller. 114 */ 115 flag = __ns_ldap_getAttr(result->entry, _S_FLAG); 116 if (flag == NULL || flag[0] == NULL) 117 flag_str = _NO_VALUE; 118 else 119 flag_str = flag[0]; 120 121 /* 9 = 8 ':' + 1 '\0' */ 122 len += strlen(flag_str) + 9; 123 124 if (len > buflen) { 125 nss_result = NSS_STR_PARSE_ERANGE; 126 goto result_spd2str; 127 } 128 129 if (argp->buf.result != NULL) { 130 be->buffer = calloc(1, len); 131 if (be->buffer == NULL) { 132 nss_result = NSS_STR_PARSE_PARSE; 133 goto result_spd2str; 134 } 135 buffer = be->buffer; 136 } else 137 buffer = argp->buf.buffer; 138 139 (void) snprintf(buffer, len, "%s:%s:::::::%s", 140 uid[0], pw_passwd, flag_str); 141 142 /* The front end marhsaller doesn't need the trailing null */ 143 if (argp->buf.result != NULL) 144 be->buflen = strlen(be->buffer); 145 result_spd2str: 146 147 (void) __ns_ldap_freeResult(&be->result); 148 return ((int)nss_result); 149 } 150 151 /* 152 * getbynam gets a passwd entry by uid name. This function constructs an ldap 153 * search filter using the name invocation parameter and the getspnam search 154 * filter defined. Once the filter is constructed we search for a matching 155 * entry and marshal the data results into struct shadow for the frontend 156 * process. The function _nss_ldap_shadow2ent performs the data marshaling. 157 */ 158 159 static nss_status_t 160 getbynam(ldap_backend_ptr be, void *a) 161 { 162 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a; 163 char searchfilter[SEARCHFILTERLEN]; 164 char userdata[SEARCHFILTERLEN]; 165 char name[SEARCHFILTERLEN + 1]; 166 int ret; 167 168 if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0) 169 return ((nss_status_t)NSS_NOTFOUND); 170 171 ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETSPNAM, name); 172 if (ret >= sizeof (searchfilter) || ret < 0) 173 return ((nss_status_t)NSS_NOTFOUND); 174 175 ret = snprintf(userdata, sizeof (userdata), _F_GETSPNAM_SSD, name); 176 if (ret >= sizeof (userdata) || ret < 0) 177 return ((nss_status_t)NSS_NOTFOUND); 178 179 return (_nss_ldap_lookup(be, argp, _SHADOW, searchfilter, NULL, 180 _merge_SSD_filter, userdata)); 181 } 182 183 static ldap_backend_op_t sp_ops[] = { 184 _nss_ldap_destr, 185 _nss_ldap_endent, 186 _nss_ldap_setent, 187 _nss_ldap_getent, 188 getbynam 189 }; 190 191 192 /* 193 * _nss_ldap_passwd_constr is where life begins. This function calls the 194 * generic ldap constructor function to define and build the abstract 195 * data types required to support ldap operations. 196 */ 197 198 /*ARGSUSED0*/ 199 nss_backend_t * 200 _nss_ldap_shadow_constr(const char *dummy1, const char *dummy2, 201 const char *dummy3) 202 { 203 204 return ((nss_backend_t *)_nss_ldap_constr(sp_ops, 205 sizeof (sp_ops)/sizeof (sp_ops[0]), 206 _SHADOW, sp_attrs, _nss_ldap_shadow2str)); 207 } 208