17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5cb5caa98Sdjl * Common Development and Distribution License (the "License").
6cb5caa98Sdjl * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*dd1104fbSMichen Chang * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <shadow.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include "ldap_common.h"
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /* shadow attributes filters */
317c478bd9Sstevel@tonic-gate #define _S_UID "uid"
327c478bd9Sstevel@tonic-gate #define _S_USERPASSWORD "userpassword"
33*dd1104fbSMichen Chang #define _S_LASTCHANGE "shadowlastchange"
34*dd1104fbSMichen Chang #define _S_MIN "shadowmin"
35*dd1104fbSMichen Chang #define _S_MAX "shadowmax"
36*dd1104fbSMichen Chang #define _S_WARNING "shadowwarning"
37*dd1104fbSMichen Chang #define _S_INACTIVE "shadowinactive"
38*dd1104fbSMichen Chang #define _S_EXPIRE "shadowexpire"
397c478bd9Sstevel@tonic-gate #define _S_FLAG "shadowflag"
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #define _F_GETSPNAM "(&(objectClass=shadowAccount)(uid=%s))"
427c478bd9Sstevel@tonic-gate #define _F_GETSPNAM_SSD "(&(%%s)(uid=%s))"
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate static const char *sp_attrs[] = {
457c478bd9Sstevel@tonic-gate _S_UID,
467c478bd9Sstevel@tonic-gate _S_USERPASSWORD,
47*dd1104fbSMichen Chang _S_LASTCHANGE,
48*dd1104fbSMichen Chang _S_MIN,
49*dd1104fbSMichen Chang _S_MAX,
50*dd1104fbSMichen Chang _S_WARNING,
51*dd1104fbSMichen Chang _S_INACTIVE,
52*dd1104fbSMichen Chang _S_EXPIRE,
537c478bd9Sstevel@tonic-gate _S_FLAG,
547c478bd9Sstevel@tonic-gate (char *)NULL
557c478bd9Sstevel@tonic-gate };
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate /*
58cb5caa98Sdjl * _nss_ldap_shadow2str is the data marshaling method for the shadow getXbyY
597c478bd9Sstevel@tonic-gate * (e.g., getspnam(), getspent()) backend processes. This method is called after
607c478bd9Sstevel@tonic-gate * a successful ldap search has been performed. This method will parse the
61cb5caa98Sdjl * ldap search values into the file format.
62cb5caa98Sdjl * e.g.
63cb5caa98Sdjl *
64cb5caa98Sdjl * myname:gaBXNJuz4JDmA:6445::::::
65cb5caa98Sdjl *
667c478bd9Sstevel@tonic-gate */
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate static int
_nss_ldap_shadow2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)69cb5caa98Sdjl _nss_ldap_shadow2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate int nss_result;
72cb5caa98Sdjl int buflen = 0;
73*dd1104fbSMichen Chang int shadow_update_enabled;
747c478bd9Sstevel@tonic-gate unsigned long len = 0L;
75cb5caa98Sdjl char *tmp, *buffer = NULL;
76cb5caa98Sdjl char *pw_passwd = NULL;
777c478bd9Sstevel@tonic-gate ns_ldap_result_t *result = be->result;
78*dd1104fbSMichen Chang char **uid, **passwd, **last, **smin, **smax;
79*dd1104fbSMichen Chang char **warning, **inactive, **expire, **flag;
80*dd1104fbSMichen Chang char *last_str, *min_str, *max_str, *warning_str;
81*dd1104fbSMichen Chang char *inactive_str, *expire_str, *flag_str;
827c478bd9Sstevel@tonic-gate
83cb5caa98Sdjl if (result == NULL)
84cb5caa98Sdjl return (NSS_STR_PARSE_PARSE);
85cb5caa98Sdjl buflen = argp->buf.buflen;
867c478bd9Sstevel@tonic-gate
87cb5caa98Sdjl nss_result = NSS_STR_PARSE_SUCCESS;
88cb5caa98Sdjl (void) memset(argp->buf.buffer, 0, buflen);
89cb5caa98Sdjl
90cb5caa98Sdjl uid = __ns_ldap_getAttr(result->entry, _S_UID);
91cb5caa98Sdjl if (uid == NULL || uid[0] == NULL || (strlen(uid[0]) < 1)) {
92cb5caa98Sdjl nss_result = NSS_STR_PARSE_PARSE;
93cb5caa98Sdjl goto result_spd2str;
947c478bd9Sstevel@tonic-gate }
95cb5caa98Sdjl len += strlen(uid[0]);
967c478bd9Sstevel@tonic-gate
97cb5caa98Sdjl passwd = __ns_ldap_getAttr(result->entry, _S_USERPASSWORD);
98a1e48794Schinlong if (passwd == NULL || passwd[0] == NULL) {
99a1e48794Schinlong /*
100a1e48794Schinlong * ACL does not allow userpassword to return or
101a1e48794Schinlong * userpassword is not defined
102a1e48794Schinlong */
10366e150d7SJohn Sonnenschein pw_passwd = NOPWDRTR;
104a1e48794Schinlong } else if (strcmp(passwd[0], "") == 0) {
105a1e48794Schinlong /*
106a1e48794Schinlong * An empty password is not supported
107a1e48794Schinlong */
108a1e48794Schinlong nss_result = NSS_STR_PARSE_PARSE;
109a1e48794Schinlong goto result_spd2str;
110cb5caa98Sdjl } else {
111cb5caa98Sdjl if ((tmp = strstr(passwd[0], "{crypt}")) != NULL ||
112cb5caa98Sdjl (tmp = strstr(passwd[0], "{CRYPT}")) != NULL) {
113cb5caa98Sdjl if (tmp != passwd[0])
11466e150d7SJohn Sonnenschein pw_passwd = NOPWDRTR;
115*dd1104fbSMichen Chang else {
116cb5caa98Sdjl pw_passwd = tmp + strlen("{crypt}");
117*dd1104fbSMichen Chang if (strcmp(pw_passwd,
118*dd1104fbSMichen Chang NS_LDAP_NO_UNIX_PASSWORD) == 0)
119*dd1104fbSMichen Chang *pw_passwd = '\0';
120*dd1104fbSMichen Chang }
1217c478bd9Sstevel@tonic-gate } else {
12266e150d7SJohn Sonnenschein /* mark password as not retrievable */
12366e150d7SJohn Sonnenschein pw_passwd = NOPWDRTR;
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate }
126cb5caa98Sdjl len += strlen(pw_passwd);
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate /*
129*dd1104fbSMichen Chang * If shadow update is not enabled, ignore the following
130*dd1104fbSMichen Chang * password aging related attributes:
1317c478bd9Sstevel@tonic-gate * -- shadowlastchange
1327c478bd9Sstevel@tonic-gate * -- shadowmin
1337c478bd9Sstevel@tonic-gate * -- shadowmax
1347c478bd9Sstevel@tonic-gate * -- shadowwarning
1357c478bd9Sstevel@tonic-gate * -- shadowinactive
1367c478bd9Sstevel@tonic-gate * -- shadowexpire
137*dd1104fbSMichen Chang * When shadow update is not enabled, the LDAP naming
138*dd1104fbSMichen Chang * service does not support the password aging fields
139*dd1104fbSMichen Chang * defined in the shadow structure. These fields, sp_lstchg,
1407c478bd9Sstevel@tonic-gate * sp_min, sp_max, sp_warn, sp_inact, and sp_expire,
141cb5caa98Sdjl * will be set to -1 by the front end marshaller.
1427c478bd9Sstevel@tonic-gate */
143*dd1104fbSMichen Chang
144*dd1104fbSMichen Chang shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
145*dd1104fbSMichen Chang if (shadow_update_enabled) {
146*dd1104fbSMichen Chang last = __ns_ldap_getAttr(result->entry, _S_LASTCHANGE);
147*dd1104fbSMichen Chang if (last == NULL || last[0] == NULL)
148*dd1104fbSMichen Chang last_str = _NO_VALUE;
149*dd1104fbSMichen Chang else
150*dd1104fbSMichen Chang last_str = last[0];
151*dd1104fbSMichen Chang len += strlen(last_str);
152*dd1104fbSMichen Chang
153*dd1104fbSMichen Chang smin = __ns_ldap_getAttr(result->entry, _S_MIN);
154*dd1104fbSMichen Chang if (smin == NULL || smin[0] == NULL)
155*dd1104fbSMichen Chang min_str = _NO_VALUE;
156*dd1104fbSMichen Chang else
157*dd1104fbSMichen Chang min_str = smin[0];
158*dd1104fbSMichen Chang len += strlen(min_str);
159*dd1104fbSMichen Chang
160*dd1104fbSMichen Chang smax = __ns_ldap_getAttr(result->entry, _S_MAX);
161*dd1104fbSMichen Chang if (smax == NULL || smax[0] == NULL)
162*dd1104fbSMichen Chang max_str = _NO_VALUE;
163*dd1104fbSMichen Chang else
164*dd1104fbSMichen Chang max_str = smax[0];
165*dd1104fbSMichen Chang len += strlen(max_str);
166*dd1104fbSMichen Chang
167*dd1104fbSMichen Chang warning = __ns_ldap_getAttr(result->entry, _S_WARNING);
168*dd1104fbSMichen Chang if (warning == NULL || warning[0] == NULL)
169*dd1104fbSMichen Chang warning_str = _NO_VALUE;
170*dd1104fbSMichen Chang else
171*dd1104fbSMichen Chang warning_str = warning[0];
172*dd1104fbSMichen Chang len += strlen(warning_str);
173*dd1104fbSMichen Chang
174*dd1104fbSMichen Chang inactive = __ns_ldap_getAttr(result->entry, _S_INACTIVE);
175*dd1104fbSMichen Chang if (inactive == NULL || inactive[0] == NULL)
176*dd1104fbSMichen Chang inactive_str = _NO_VALUE;
177*dd1104fbSMichen Chang else
178*dd1104fbSMichen Chang inactive_str = inactive[0];
179*dd1104fbSMichen Chang len += strlen(inactive_str);
180*dd1104fbSMichen Chang
181*dd1104fbSMichen Chang expire = __ns_ldap_getAttr(result->entry, _S_EXPIRE);
182*dd1104fbSMichen Chang if (expire == NULL || expire[0] == NULL)
183*dd1104fbSMichen Chang expire_str = _NO_VALUE;
184*dd1104fbSMichen Chang else
185*dd1104fbSMichen Chang expire_str = expire[0];
186*dd1104fbSMichen Chang len += strlen(expire_str);
187*dd1104fbSMichen Chang }
188*dd1104fbSMichen Chang
189cb5caa98Sdjl flag = __ns_ldap_getAttr(result->entry, _S_FLAG);
190cb5caa98Sdjl if (flag == NULL || flag[0] == NULL)
191cb5caa98Sdjl flag_str = _NO_VALUE;
192cb5caa98Sdjl else
193cb5caa98Sdjl flag_str = flag[0];
1947c478bd9Sstevel@tonic-gate
195cb5caa98Sdjl /* 9 = 8 ':' + 1 '\0' */
196cb5caa98Sdjl len += strlen(flag_str) + 9;
197cb5caa98Sdjl
198cb5caa98Sdjl if (len > buflen) {
199cb5caa98Sdjl nss_result = NSS_STR_PARSE_ERANGE;
200cb5caa98Sdjl goto result_spd2str;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate
203cb5caa98Sdjl if (argp->buf.result != NULL) {
204cb5caa98Sdjl be->buffer = calloc(1, len);
205cb5caa98Sdjl if (be->buffer == NULL) {
206cb5caa98Sdjl nss_result = NSS_STR_PARSE_PARSE;
207cb5caa98Sdjl goto result_spd2str;
2087c478bd9Sstevel@tonic-gate }
209cb5caa98Sdjl buffer = be->buffer;
210cb5caa98Sdjl } else
211cb5caa98Sdjl buffer = argp->buf.buffer;
2127c478bd9Sstevel@tonic-gate
213*dd1104fbSMichen Chang if (shadow_update_enabled) {
214*dd1104fbSMichen Chang (void) snprintf(buffer, len, "%s:%s:%s:%s:%s:%s:%s:%s:%s",
215*dd1104fbSMichen Chang uid[0], pw_passwd, last_str, min_str, max_str, warning_str,
216*dd1104fbSMichen Chang inactive_str, expire_str, flag_str);
217*dd1104fbSMichen Chang } else {
218cb5caa98Sdjl (void) snprintf(buffer, len, "%s:%s:::::::%s",
219cb5caa98Sdjl uid[0], pw_passwd, flag_str);
220*dd1104fbSMichen Chang }
2217c478bd9Sstevel@tonic-gate
222cb5caa98Sdjl /* The front end marhsaller doesn't need the trailing null */
223cb5caa98Sdjl if (argp->buf.result != NULL)
224cb5caa98Sdjl be->buflen = strlen(be->buffer);
225cb5caa98Sdjl result_spd2str:
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate (void) __ns_ldap_freeResult(&be->result);
2287c478bd9Sstevel@tonic-gate return ((int)nss_result);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate /*
2327c478bd9Sstevel@tonic-gate * getbynam gets a passwd entry by uid name. This function constructs an ldap
2337c478bd9Sstevel@tonic-gate * search filter using the name invocation parameter and the getspnam search
2347c478bd9Sstevel@tonic-gate * filter defined. Once the filter is constructed we search for a matching
2357c478bd9Sstevel@tonic-gate * entry and marshal the data results into struct shadow for the frontend
2367c478bd9Sstevel@tonic-gate * process. The function _nss_ldap_shadow2ent performs the data marshaling.
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate static nss_status_t
getbynam(ldap_backend_ptr be,void * a)2407c478bd9Sstevel@tonic-gate getbynam(ldap_backend_ptr be, void *a)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2437c478bd9Sstevel@tonic-gate char searchfilter[SEARCHFILTERLEN];
2447c478bd9Sstevel@tonic-gate char userdata[SEARCHFILTERLEN];
2457c478bd9Sstevel@tonic-gate char name[SEARCHFILTERLEN + 1];
2467c478bd9Sstevel@tonic-gate int ret;
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
2497c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETSPNAM, name);
2527c478bd9Sstevel@tonic-gate if (ret >= sizeof (searchfilter) || ret < 0)
2537c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate ret = snprintf(userdata, sizeof (userdata), _F_GETSPNAM_SSD, name);
2567c478bd9Sstevel@tonic-gate if (ret >= sizeof (userdata) || ret < 0)
2577c478bd9Sstevel@tonic-gate return ((nss_status_t)NSS_NOTFOUND);
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate return (_nss_ldap_lookup(be, argp, _SHADOW, searchfilter, NULL,
2607c478bd9Sstevel@tonic-gate _merge_SSD_filter, userdata));
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate static ldap_backend_op_t sp_ops[] = {
2647c478bd9Sstevel@tonic-gate _nss_ldap_destr,
2657c478bd9Sstevel@tonic-gate _nss_ldap_endent,
2667c478bd9Sstevel@tonic-gate _nss_ldap_setent,
2677c478bd9Sstevel@tonic-gate _nss_ldap_getent,
2687c478bd9Sstevel@tonic-gate getbynam
2697c478bd9Sstevel@tonic-gate };
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate * _nss_ldap_passwd_constr is where life begins. This function calls the
2747c478bd9Sstevel@tonic-gate * generic ldap constructor function to define and build the abstract
2757c478bd9Sstevel@tonic-gate * data types required to support ldap operations.
2767c478bd9Sstevel@tonic-gate */
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate /*ARGSUSED0*/
2797c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_ldap_shadow_constr(const char * dummy1,const char * dummy2,const char * dummy3)2807c478bd9Sstevel@tonic-gate _nss_ldap_shadow_constr(const char *dummy1, const char *dummy2,
2817c478bd9Sstevel@tonic-gate const char *dummy3)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate return ((nss_backend_t *)_nss_ldap_constr(sp_ops,
2857c478bd9Sstevel@tonic-gate sizeof (sp_ops)/sizeof (sp_ops[0]),
286cb5caa98Sdjl _SHADOW, sp_attrs, _nss_ldap_shadow2str));
2877c478bd9Sstevel@tonic-gate }
288