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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <project.h>
30 #include "ldap_common.h"
31 
32 /* Project attributes filters */
33 #define	_PROJ_NAME	"SolarisProjectName"
34 #define	_PROJ_PROJID	"SolarisProjectID"
35 #define	_PROJ_DESCR	"description"
36 #define	_PROJ_USERS	"memberUid"
37 #define	_PROJ_GROUPS	"memberGid"
38 #define	_PROJ_ATTR	"SolarisProjectAttr"
39 
40 #define	_F_GETPROJNAME	"(&(objectClass=SolarisProject)(SolarisProjectName=%s))"
41 #define	_F_GETPROJID	"(&(objectClass=SolarisProject)(SolarisProjectID=%ld))"
42 
43 static const char *project_attrs[] = {
44 	_PROJ_NAME,
45 	_PROJ_PROJID,
46 	_PROJ_DESCR,
47 	_PROJ_USERS,
48 	_PROJ_GROUPS,
49 	_PROJ_ATTR,
50 	(char *)NULL
51 };
52 
53 static char *
54 gettok(char **nextpp, char sep)
55 {
56 	char *p = *nextpp;
57 	char *q = p;
58 	char c;
59 
60 	if (p == NULL)
61 		return (NULL);
62 	while ((c = *q) != '\0' && c != sep)
63 		q++;
64 	if (c == '\0')
65 		*nextpp = 0;
66 	else {
67 		*q++ = '\0';
68 		*nextpp = q;
69 	}
70 	return (p);
71 }
72 
73 /*
74  * _nss_ldap_proj2ent is the data marshalling method for the project getXbyY
75  * (getprojbyname, getprojbyid, getprojent) backend processes. This method
76  * is called after a successful ldap search has been performed. This method
77  * will parse the ldap search values into struct project = argp->buf.buffer
78  * which the frontend routine expects. Three error conditions are expected
79  * and returned to nsswitch.
80  */
81 static int
82 _nss_ldap_proj2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
83 {
84 	int i, nss_result;
85 	unsigned long len = 0;
86 	char **uglist;
87 	char *buffer, *ceiling;
88 	char *users, *groups, *p;
89 	struct project *proj;
90 	ns_ldap_result_t *result = be->result;
91 	ns_ldap_attr_t *attrptr;
92 
93 	buffer = argp->buf.buffer;
94 	if (!argp->buf.result) {
95 		nss_result = NSS_STR_PARSE_ERANGE;
96 		goto result_proj2ent;
97 	}
98 	attrptr = getattr(result, 0);
99 	if (attrptr == NULL) {
100 		nss_result = NSS_STR_PARSE_PARSE;
101 		goto result_proj2ent;
102 	}
103 	nss_result = NSS_STR_PARSE_SUCCESS;
104 	proj = argp->buf.result;
105 	proj->pj_users = proj->pj_groups = NULL;
106 	proj->pj_attr = proj->pj_comment = NULL;
107 	ceiling = (char *)ROUND_DOWN(buffer + argp->buf.buflen,
108 	    sizeof (char *));
109 	(void) memset(argp->buf.buffer, 0, argp->buf.buflen);
110 	for (i = 0; i < result->entry->attr_count; i++) {
111 		attrptr = getattr(result, i);
112 		if (attrptr == NULL) {
113 			nss_result = NSS_STR_PARSE_PARSE;
114 			goto result_proj2ent;
115 		}
116 		len = strlen(attrptr->attrvalue[0]);
117 		if (strcasecmp(attrptr->attrname, _PROJ_NAME) == 0) {
118 			if (len == 0) {
119 				nss_result = NSS_STR_PARSE_PARSE;
120 				goto result_proj2ent;
121 			}
122 			proj->pj_name = buffer;
123 			buffer += len + 1;
124 			if (buffer >= ceiling) {
125 				nss_result = NSS_STR_PARSE_ERANGE;
126 				goto result_proj2ent;
127 			}
128 			(void) strcpy(proj->pj_name, attrptr->attrvalue[0]);
129 			continue;
130 		}
131 		if (strcasecmp(attrptr->attrname, _PROJ_PROJID) == 0) {
132 			if (len == 0) {
133 				nss_result = NSS_STR_PARSE_PARSE;
134 				goto result_proj2ent;
135 			}
136 			errno = 0;
137 			proj->pj_projid =
138 			    (projid_t)strtol(attrptr->attrvalue[0],
139 			    NULL, 10);
140 			if (errno != 0) {
141 				nss_result = NSS_STR_PARSE_PARSE;
142 				goto result_proj2ent;
143 			}
144 			continue;
145 		}
146 		if (strcasecmp(attrptr->attrname, _PROJ_DESCR) == 0) {
147 			proj->pj_comment = buffer;
148 			buffer += len + 1;
149 			if (buffer >= ceiling) {
150 				nss_result = NSS_STR_PARSE_ERANGE;
151 				goto result_proj2ent;
152 			}
153 			(void) strcpy(proj->pj_comment, attrptr->attrvalue[0]);
154 			continue;
155 		}
156 		if (strcasecmp(attrptr->attrname, _PROJ_ATTR) == 0) {
157 			proj->pj_attr = buffer;
158 			buffer += len + 1;
159 			if (buffer >= ceiling) {
160 				nss_result = NSS_STR_PARSE_ERANGE;
161 				goto result_proj2ent;
162 			}
163 			(void) strcpy(proj->pj_attr, attrptr->attrvalue[0]);
164 			continue;
165 		}
166 		if (strcasecmp(attrptr->attrname, _PROJ_USERS) == 0) {
167 			buffer = (char *)ROUND_UP(buffer, sizeof (char *));
168 			users = buffer;
169 			buffer += len + 1;
170 			if (buffer >= ceiling) {
171 				nss_result = NSS_STR_PARSE_ERANGE;
172 				goto result_proj2ent;
173 			}
174 			(void) strcpy(users, attrptr->attrvalue[0]);
175 			buffer = (char *)ROUND_UP(buffer, sizeof (char *));
176 			if (buffer >= ceiling) {
177 				nss_result = NSS_STR_PARSE_ERANGE;
178 				goto result_proj2ent;
179 			}
180 			proj->pj_users = uglist = (char **)buffer;
181 			*uglist = NULL;
182 			while (uglist < (char **)ceiling) {
183 				p = gettok(&users, ',');
184 				if (p == NULL || *p == '\0') {
185 					*uglist++ = 0;
186 					break;
187 				}
188 				*uglist++ = p;
189 			}
190 			buffer = (char *)uglist;
191 			if (buffer >= ceiling)
192 				return (NSS_STR_PARSE_ERANGE);
193 			continue;
194 		}
195 		if (strcasecmp(attrptr->attrname, _PROJ_GROUPS) == 0) {
196 			buffer = (char *)ROUND_UP(buffer, sizeof (char *));
197 			groups = buffer;
198 			buffer += len + 1;
199 			if (buffer >= ceiling) {
200 				nss_result = NSS_STR_PARSE_ERANGE;
201 				goto result_proj2ent;
202 			}
203 			(void) strcpy(groups, attrptr->attrvalue[0]);
204 			buffer = (char *)ROUND_UP(buffer, sizeof (char *));
205 			if (buffer >= ceiling) {
206 				nss_result = NSS_STR_PARSE_ERANGE;
207 				goto result_proj2ent;
208 			}
209 			proj->pj_groups = uglist = (char **)buffer;
210 			*uglist = NULL;
211 			while (uglist < (char **)ceiling) {
212 				p = gettok(&groups, ',');
213 				if (p == NULL || *p == '\0') {
214 					*uglist++ = 0;
215 					break;
216 				}
217 				*uglist++ = p;
218 			}
219 			buffer = (char *)uglist;
220 			if (buffer >= ceiling)
221 				return (NSS_STR_PARSE_ERANGE);
222 			continue;
223 		}
224 	}
225 	if (proj->pj_comment == NULL) {
226 		buffer = (char *)ROUND_UP(buffer, sizeof (char *));
227 		if (buffer >= ceiling) {
228 			nss_result = NSS_STR_PARSE_ERANGE;
229 			goto result_proj2ent;
230 		}
231 		proj->pj_comment = buffer;
232 		*buffer = '\0';
233 		buffer++;
234 	}
235 	if (proj->pj_users == NULL) {
236 		buffer = (char *)ROUND_UP(buffer, sizeof (char *));
237 		if (buffer >= ceiling) {
238 			nss_result = NSS_STR_PARSE_ERANGE;
239 			goto result_proj2ent;
240 		}
241 		proj->pj_users = (char **)buffer;
242 		*buffer = '\0';
243 		buffer++;
244 	}
245 	if (proj->pj_groups == NULL) {
246 		buffer = (char *)ROUND_UP(buffer, sizeof (char *));
247 		if (buffer >= ceiling) {
248 			nss_result = NSS_STR_PARSE_ERANGE;
249 			goto result_proj2ent;
250 		}
251 		proj->pj_groups = (char **)buffer;
252 		*buffer = '\0';
253 		buffer++;
254 	}
255 	if (proj->pj_attr == NULL) {
256 		buffer = (char *)ROUND_UP(buffer, sizeof (char *));
257 		if (buffer >= ceiling) {
258 			nss_result = NSS_STR_PARSE_ERANGE;
259 			goto result_proj2ent;
260 		}
261 		proj->pj_attr = buffer;
262 		*buffer = '\0';
263 		buffer++;
264 	}
265 
266 result_proj2ent:
267 	(void) __ns_ldap_freeResult(&be->result);
268 	return ((int)nss_result);
269 }
270 
271 
272 /*
273  * getbyname gets a project entry by name. This function constructs an ldap
274  * search filter using the name invocation parameter and the getprojname search
275  * filter defined. Once the filter is constructed, we search for a matching
276  * entry and marshal the data results into struct project for the frontend
277  * process. The function _nss_ldap_proj2ent performs the data marshaling.
278  */
279 static nss_status_t
280 getbyname(ldap_backend_ptr be, void *a)
281 {
282 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
283 	char searchfilter[SEARCHFILTERLEN];
284 
285 	if (snprintf(searchfilter, SEARCHFILTERLEN,
286 		_F_GETPROJNAME, argp->key.name) < 0)
287 		return (NSS_NOTFOUND);
288 	return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL,
289 			NULL, NULL));
290 }
291 
292 
293 /*
294  * getbyprojid gets a project entry by number. This function constructs an ldap
295  * search filter using the name invocation parameter and the getprojid search
296  * filter defined. Once the filter is constructed, we search for a matching
297  * entry and marshal the data results into struct project for the frontend
298  * process. The function _nss_ldap_proj2ent performs the data marshaling.
299  */
300 static nss_status_t
301 getbyprojid(ldap_backend_ptr be, void *a)
302 {
303 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
304 	char searchfilter[SEARCHFILTERLEN];
305 
306 	if (snprintf(searchfilter, SEARCHFILTERLEN,
307 		_F_GETPROJID, (long)argp->key.projid) < 0)
308 		return (NSS_NOTFOUND);
309 	return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL,
310 			NULL, NULL));
311 }
312 
313 static ldap_backend_op_t project_ops[] = {
314 	_nss_ldap_destr,
315 	_nss_ldap_endent,
316 	_nss_ldap_setent,
317 	_nss_ldap_getent,
318 	getbyname,
319 	getbyprojid
320 };
321 
322 
323 /*ARGSUSED0*/
324 nss_backend_t *
325 _nss_ldap_project_constr(const char *dummy1, const char *dummy2,
326     const char *dummy3)
327 {
328 	return (_nss_ldap_constr(project_ops,
329 	    sizeof (project_ops) / sizeof (project_ops[0]),
330 	    _PROJECT, project_attrs, _nss_ldap_proj2ent));
331 }
332