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