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#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <project.h>
29#include "ldap_common.h"
30
31/* Project attributes filters */
32#define	_PROJ_NAME	"SolarisProjectName"
33#define	_PROJ_PROJID	"SolarisProjectID"
34#define	_PROJ_DESCR	"description"
35#define	_PROJ_USERS	"memberUid"
36#define	_PROJ_GROUPS	"memberGid"
37#define	_PROJ_ATTR	"SolarisProjectAttr"
38
39#define	_F_GETPROJNAME	"(&(objectClass=SolarisProject)(SolarisProjectName=%s))"
40#define	_F_GETPROJID	"(&(objectClass=SolarisProject)(SolarisProjectID=%ld))"
41
42static const char *project_attrs[] = {
43	_PROJ_NAME,
44	_PROJ_PROJID,
45	_PROJ_DESCR,
46	_PROJ_USERS,
47	_PROJ_GROUPS,
48	_PROJ_ATTR,
49	(char *)NULL
50};
51
52/*
53 * _nss_ldap_proj2str is the data marshalling method for the project getXbyY
54 * (getprojbyname, getprojbyid, getprojent) backend processes. This method
55 * is called after a successful ldap search has been performed. This method
56 * will parse the ldap search values into the file format.
57 * e.g.
58 *
59 * system:0:System:::
60 *
61 * beatles:100:The Beatles:john,paul,george,ringo::task.max-lwps=
62 * 	(privileged,100,signal=SIGTERM),(privileged,110,deny)
63 *
64 * (All in one line)
65 */
66static int
67_nss_ldap_proj2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
68{
69	int			i;
70	int			nss_result;
71	int			buflen = 0, len;
72	int			firsttime;
73	char			*buffer, *comment, *attr_str;
74	ns_ldap_result_t	*result = be->result;
75	char			**name, **id, **descr, **attr;
76	ns_ldap_attr_t		*users, *groups;
77
78	if (result == NULL)
79		return (NSS_STR_PARSE_PARSE);
80	buflen = argp->buf.buflen;
81
82	if (argp->buf.result != NULL) {
83		/* In all cases it must be deallocated by caller */
84		if ((be->buffer = calloc(1, buflen)) == NULL) {
85			nss_result = NSS_STR_PARSE_PARSE;
86			goto result_proj2str;
87		}
88		buffer = be->buffer;
89	} else
90		buffer = argp->buf.buffer;
91
92	nss_result = NSS_STR_PARSE_SUCCESS;
93	(void) memset(buffer, 0, buflen);
94
95	name = __ns_ldap_getAttr(result->entry, _PROJ_NAME);
96	if (name == NULL || name[0] == NULL || (strlen(name[0]) < 1)) {
97		nss_result = NSS_STR_PARSE_PARSE;
98		goto result_proj2str;
99	}
100	id = __ns_ldap_getAttr(result->entry, _PROJ_PROJID);
101	if (id == NULL || id[0] == NULL || (strlen(id[0]) < 1)) {
102		nss_result = NSS_STR_PARSE_PARSE;
103		goto result_proj2str;
104	}
105	descr = __ns_ldap_getAttr(result->entry, _PROJ_DESCR);
106	if (descr == NULL || descr[0] == NULL || (strlen(descr[0]) < 1))
107		comment = _NO_VALUE;
108	else
109		comment = descr[0];
110	len = snprintf(buffer, buflen, "%s:%s:%s:", name[0], id[0],
111	    comment);
112	TEST_AND_ADJUST(len, buffer, buflen, result_proj2str);
113
114	users = __ns_ldap_getAttrStruct(result->entry, _PROJ_USERS);
115	if (!(users == NULL || users->attrvalue == NULL)) {
116		firsttime = 1;
117		for (i = 0; i < users->value_count; i++) {
118			if (users->attrvalue[i] == NULL) {
119				nss_result = NSS_STR_PARSE_PARSE;
120				goto result_proj2str;
121			}
122			if (firsttime) {
123				len = snprintf(buffer, buflen, "%s",
124				    users->attrvalue[i]);
125				firsttime = 0;
126			} else {
127				len = snprintf(buffer, buflen, ",%s",
128				    users->attrvalue[i]);
129			}
130			TEST_AND_ADJUST(len, buffer, buflen, result_proj2str);
131		}
132	}
133	len = snprintf(buffer, buflen, ":");
134	TEST_AND_ADJUST(len, buffer, buflen, result_proj2str);
135
136	groups = __ns_ldap_getAttrStruct(result->entry, _PROJ_GROUPS);
137	if (!(groups == NULL || groups->attrvalue == NULL)) {
138		firsttime = 1;
139		for (i = 0; i < groups->value_count; i++) {
140			if (groups->attrvalue[i] == NULL) {
141				nss_result = NSS_STR_PARSE_PARSE;
142				goto result_proj2str;
143			}
144			if (firsttime) {
145				len = snprintf(buffer, buflen, "%s",
146				    groups->attrvalue[i]);
147				firsttime = 0;
148			} else {
149				len = snprintf(buffer, buflen, ",%s",
150				    groups->attrvalue[i]);
151			}
152			TEST_AND_ADJUST(len, buffer, buflen, result_proj2str);
153		}
154	}
155
156	attr = __ns_ldap_getAttr(result->entry, _PROJ_ATTR);
157	if (attr == NULL || attr[0] == NULL || (strlen(attr[0]) < 1))
158		attr_str = _NO_VALUE;
159
160	else
161		attr_str = attr[0];
162	len = snprintf(buffer, buflen, ":%s", attr_str);
163	TEST_AND_ADJUST(len, buffer, buflen, result_proj2str);
164
165	/* The front end marshaller doesn't need the trailing nulls */
166	if (argp->buf.result != NULL)
167		be->buflen = strlen(be->buffer);
168result_proj2str:
169	(void) __ns_ldap_freeResult(&be->result);
170	return ((int)nss_result);
171}
172
173
174/*
175 * getbyname gets a project entry by name. This function constructs an ldap
176 * search filter using the name invocation parameter and the getprojname search
177 * filter defined. Once the filter is constructed, we search for a matching
178 * entry and marshal the data results into struct project for the frontend
179 * process. The function _nss_ldap_proj2ent performs the data marshaling.
180 */
181static nss_status_t
182getbyname(ldap_backend_ptr be, void *a)
183{
184	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
185	char searchfilter[SEARCHFILTERLEN];
186
187	if (snprintf(searchfilter, SEARCHFILTERLEN,
188	    _F_GETPROJNAME, argp->key.name) < 0)
189		return (NSS_NOTFOUND);
190	return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL, NULL,
191	    NULL));
192}
193
194
195/*
196 * getbyprojid gets a project entry by number. This function constructs an ldap
197 * search filter using the name invocation parameter and the getprojid search
198 * filter defined. Once the filter is constructed, we search for a matching
199 * entry and marshal the data results into struct project for the frontend
200 * process. The function _nss_ldap_proj2ent performs the data marshaling.
201 */
202static nss_status_t
203getbyprojid(ldap_backend_ptr be, void *a)
204{
205	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
206	char searchfilter[SEARCHFILTERLEN];
207
208	if (snprintf(searchfilter, SEARCHFILTERLEN, _F_GETPROJID,
209	    (long)argp->key.projid) < 0)
210		return (NSS_NOTFOUND);
211	return (_nss_ldap_lookup(be, argp, _PROJECT, searchfilter, NULL, NULL,
212	    NULL));
213}
214
215static ldap_backend_op_t project_ops[] = {
216	_nss_ldap_destr,
217	_nss_ldap_endent,
218	_nss_ldap_setent,
219	_nss_ldap_getent,
220	getbyname,
221	getbyprojid
222};
223
224
225/*ARGSUSED0*/
226nss_backend_t *
227_nss_ldap_project_constr(const char *dummy1, const char *dummy2,
228    const char *dummy3)
229{
230	return (_nss_ldap_constr(project_ops,
231	    sizeof (project_ops) / sizeof (project_ops[0]),
232	    _PROJECT, project_attrs, _nss_ldap_proj2str));
233}
234