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 2003 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 <rpc/rpcent.h>
30 #include "ns_internal.h"
31 #include "ldap_common.h"
32 
33 /* rpc attributes filters */
34 #define	_R_NAME			"cn"
35 #define	_R_NUMBER		"oncrpcnumber"
36 
37 
38 #define	_F_GETRPCBYNAME		"(&(objectClass=oncRpc)(cn=%s))"
39 #define	_F_GETRPCBYNAME_SSD	"(&(%%s)(cn=%s))"
40 #define	_F_GETRPCBYNUMBER	"(&(objectClass=oncRpc)(oncRpcNumber=%d))"
41 #define	_F_GETRPCBYNUMBER_SSD	"(&(%%s)(oncRpcNumber=%d))"
42 
43 static const char *rpc_attrs[] = {
44 	_R_NAME,
45 	_R_NUMBER,
46 	(char *)NULL
47 };
48 
49 /*
50  * _nss_ldap_rpc2ent is the data marshaling method for the rpc getXbyY
51  * (e.g., getbyname(), getbynumber(), getrpcent()) backend processes.
52  * This method is called after a successful ldap search has been performed.
53  * This method will parse the ldap search values into *rpc = (struct
54  * rpcent *)argp->buf.result which the frontend process expects. Three
55  * error conditions are expected and returned to nsswitch.
56  */
57 
58 static int
59 _nss_ldap_rpc2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
60 {
61 	int		i, j;
62 	int		nss_result;
63 	int		buflen = (int)0;
64 	int		firstime = (int)1;
65 	unsigned long	len = 0L;
66 	char		**mp, *cname = NULL;
67 	char		*buffer = (char *)NULL;
68 	char		*ceiling = (char *)NULL;
69 	struct rpcent	*rpc = (struct rpcent *)NULL;
70 	ns_ldap_result_t	*result = be->result;
71 	ns_ldap_attr_t	*attrptr;
72 
73 	buffer = (char *)argp->buf.buffer;
74 	buflen = (size_t)argp->buf.buflen;
75 	if (!argp->buf.result) {
76 		nss_result = (int)NSS_STR_PARSE_ERANGE;
77 		goto result_rpc2ent;
78 	}
79 	rpc = (struct rpcent *)argp->buf.result;
80 	ceiling = buffer + buflen;
81 
82 	nss_result = (int)NSS_STR_PARSE_SUCCESS;
83 	(void) memset(argp->buf.buffer, 0, buflen);
84 
85 	attrptr = getattr(result, 0);
86 	if (attrptr == NULL) {
87 		nss_result = (int)NSS_STR_PARSE_PARSE;
88 		goto result_rpc2ent;
89 	}
90 	for (i = 0; i < result->entry->attr_count; i++) {
91 		attrptr = getattr(result, i);
92 		if (attrptr == NULL) {
93 			nss_result = (int)NSS_STR_PARSE_PARSE;
94 			goto result_rpc2ent;
95 		}
96 		if (strcasecmp(attrptr->attrname, _R_NAME) == 0) {
97 			for (j = 0; j < attrptr->value_count; j++) {
98 			/* traverse for all multivalued values */
99 				if (firstime) {
100 					/* rpc name */
101 					cname = __s_api_get_canonical_name(
102 						result->entry, attrptr, 1);
103 					if (cname == NULL ||
104 						(len = strlen(cname)) < 1) {
105 						nss_result =
106 							NSS_STR_PARSE_PARSE;
107 						goto result_rpc2ent;
108 					}
109 					rpc->r_name = buffer;
110 					buffer += len + 1;
111 					if (buffer >= ceiling) {
112 						nss_result =
113 						    (int)NSS_STR_PARSE_ERANGE;
114 						goto result_rpc2ent;
115 					}
116 					(void) strcpy(rpc->r_name, cname);
117 					/* alias list */
118 					mp = rpc->r_aliases =
119 						    (char **)ROUND_UP(buffer,
120 						    sizeof (char **));
121 					buffer = (char *)rpc->r_aliases +
122 						    sizeof (char *) *
123 						    (attrptr->value_count + 1);
124 					buffer = (char *)ROUND_UP(buffer,
125 						    sizeof (char **));
126 					if (buffer >= ceiling) {
127 						nss_result =
128 						    (int)NSS_STR_PARSE_ERANGE;
129 						goto result_rpc2ent;
130 					}
131 					firstime = (int)0;
132 				}
133 				/* alias list */
134 				if ((attrptr->attrvalue[j] == NULL) ||
135 				    (len = strlen(attrptr->attrvalue[j])) < 1) {
136 					nss_result = (int)NSS_STR_PARSE_PARSE;
137 					goto result_rpc2ent;
138 				}
139 				/* skip canonical name */
140 				if (strcmp(attrptr->attrvalue[j], cname) == 0)
141 					continue;
142 				*mp = buffer;
143 				buffer += len + 1;
144 				if (buffer >= ceiling) {
145 					nss_result = (int)NSS_STR_PARSE_ERANGE;
146 					goto result_rpc2ent;
147 				}
148 				(void) strcpy(*mp++, attrptr->attrvalue[j]);
149 				continue;
150 			}
151 		}
152 		if (strcasecmp(attrptr->attrname, _R_NUMBER) == 0) {
153 			if ((attrptr->attrvalue[0] == NULL) ||
154 			    (len = strlen(attrptr->attrvalue[0])) < 1) {
155 				nss_result = (int)NSS_STR_PARSE_PARSE;
156 				goto result_rpc2ent;
157 			}
158 			errno = 0;
159 			rpc->r_number = (int)strtol(attrptr->attrvalue[0],
160 						    (char **)NULL, 10);
161 			if (errno != 0) {
162 				nss_result = (int)NSS_STR_PARSE_PARSE;
163 				goto result_rpc2ent;
164 			}
165 			continue;
166 		}
167 	}
168 	if (mp != NULL)
169 		*mp = NULL;
170 
171 #ifdef DEBUG
172 	(void) fprintf(stdout, "\n[getrpcent.c: _nss_ldap_rpc2ent]\n");
173 	(void) fprintf(stdout, "        r_name: [%s]\n", rpc->r_name);
174 	if (mp != NULL) {
175 		for (mp = rpc->r_aliases; *mp != NULL; mp++)
176 			(void) fprintf(stdout, "     r_aliases: [%s]\n", *mp);
177 	}
178 	(void) fprintf(stdout, "      r_number: [%d]\n", rpc->r_number);
179 #endif /* DEBUG */
180 
181 result_rpc2ent:
182 
183 	(void) __ns_ldap_freeResult(&be->result);
184 	return ((int)nss_result);
185 }
186 
187 
188 /*
189  * getbyname gets struct rpcent values by rpc name. This function
190  * constructs an ldap search filter using the rpc name invocation
191  * parameter and the getrpcbyname search filter defined. Once the
192  * filter is constructed, we search for a matching entry and marshal
193  * the data results into *rpc = (struct rpcent *)argp->buf.result.
194  * The function _nss_ldap_rpc2ent performs the data marshaling.
195  */
196 
197 static nss_status_t
198 getbyname(ldap_backend_ptr be, void *a)
199 {
200 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
201 	char		searchfilter[SEARCHFILTERLEN];
202 	char		userdata[SEARCHFILTERLEN];
203 	char		name[SEARCHFILTERLEN];
204 	int		ret;
205 
206 	if (_ldap_filter_name(name, argp->key.name, sizeof (name)) != 0)
207 		return ((nss_status_t)NSS_NOTFOUND);
208 
209 	ret = snprintf(searchfilter, sizeof (searchfilter), _F_GETRPCBYNAME,
210 	    name);
211 	if (ret >= sizeof (searchfilter) || ret < 0)
212 		return ((nss_status_t)NSS_NOTFOUND);
213 
214 	ret = snprintf(userdata, sizeof (userdata), _F_GETRPCBYNAME_SSD, name);
215 	if (ret >= sizeof (userdata) || ret < 0)
216 		return ((nss_status_t)NSS_NOTFOUND);
217 
218 	return ((nss_status_t)_nss_ldap_lookup(be, argp, _RPC, searchfilter,
219 		NULL, _merge_SSD_filter, userdata));
220 }
221 
222 
223 /*
224  * getbynumber gets struct rpcent values by rpc number. This function
225  * constructs an ldap search filter using the rpc number invocation
226  * parameter and the getrpcbynumber search filter defined. Once the
227  * filter is constructed, we search for a matching entry and marshal
228  * the data results into *rpc = (struct rpcent *)argp->buf.result.
229  * The function _nss_ldap_rpc2ent performs the data marshaling.
230  */
231 
232 static nss_status_t
233 getbynumber(ldap_backend_ptr be, void *a)
234 {
235 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
236 	char		searchfilter[SEARCHFILTERLEN];
237 	char		userdata[SEARCHFILTERLEN];
238 	int		ret;
239 
240 	ret = snprintf(searchfilter, sizeof (searchfilter),
241 	    _F_GETRPCBYNUMBER, argp->key.number);
242 	if (ret >= sizeof (searchfilter) || ret < 0)
243 		return ((nss_status_t)NSS_NOTFOUND);
244 
245 	ret = snprintf(userdata, sizeof (userdata),
246 	    _F_GETRPCBYNUMBER_SSD, argp->key.number);
247 	if (ret >= sizeof (userdata) || ret < 0)
248 		return ((nss_status_t)NSS_NOTFOUND);
249 
250 	return ((nss_status_t)_nss_ldap_lookup(be, argp, _RPC, searchfilter,
251 		NULL, _merge_SSD_filter, userdata));
252 }
253 
254 
255 static ldap_backend_op_t rpc_ops[] = {
256 	_nss_ldap_destr,
257 	_nss_ldap_endent,
258 	_nss_ldap_setent,
259 	_nss_ldap_getent,
260 	getbyname,
261 	getbynumber
262 };
263 
264 
265 /*
266  * _nss_ldap_rpc_constr is where life begins. This function calls the generic
267  * ldap constructor function to define and build the abstract data types
268  * required to support ldap operations.
269  */
270 
271 /*ARGSUSED0*/
272 nss_backend_t *
273 _nss_ldap_rpc_constr(const char *dummy1, const char *dummy2,
274 			const char *dummy3)
275 {
276 
277 	return ((nss_backend_t *)_nss_ldap_constr(rpc_ops,
278 		sizeof (rpc_ops)/sizeof (rpc_ops[0]),
279 		_RPC, rpc_attrs, _nss_ldap_rpc2ent));
280 }
281