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