xref: /illumos-gate/usr/src/lib/nsswitch/ldap/common/gethostent6.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2006 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 <netdb.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <sys/systeminfo.h>
34 #include "ns_internal.h"
35 #include "ldap_common.h"
36 
37 /* host attributes filters */
38 
39 /* probably some change in the ipHostNumber field */
40 
41 #define	_H_DN			"dn"
42 #define	_H_NAME			"cn"
43 #define	_H_ADDR			"iphostnumber"
44 #define	_F_GETHOSTS6BYNAME	"(&(objectClass=ipHost)(cn=%s))"
45 #define	_F_GETHOSTS6BYNAME_SSD	"(&(%%s)(cn=%s))"
46 #define	_F_GETHOSTS6DOTTEDBYNAME \
47 				"(&(objectClass=ipHost)(|(cn=%s)(cn=%s)))"
48 #define	_F_GETHOSTS6DOTTEDBYNAME_SSD \
49 				"(&(%%s)(|(cn=%s)(cn=%s)))"
50 #define	_F_GETHOSTS6BYADDR	"(&(objectClass=ipHost)(ipHostNumber=%s))"
51 #define	_F_GETHOSTS6BYADDR_SSD	"(&(%%s)(ipHostNumber=%s))"
52 
53 static const char *ipnodes_attrs[] = {
54 	_H_NAME,
55 	_H_ADDR,
56 	(char *)NULL
57 };
58 
59 extern int
60 _nss_ldap_hosts2str_int(int af, ldap_backend_ptr be, nss_XbyY_args_t *argp);
61 
62 /*
63  * _nss_ldap_hosts2str is the data marshaling method for the ipnodes getXbyY
64  * system call gethostbyname() and gethostbyaddr.
65  * This method is called after a successful search has been performed.
66  * This method will parse the search results into the file format.
67  * e.g.
68  *
69  * fe80::a00:20ff:fec4:f2b6 ipnodes_1
70  *
71  */
72 static int
73 _nss_ldap_hosts2str(ldap_backend_ptr be, nss_XbyY_args_t *argp) {
74 	return (_nss_ldap_hosts2str_int(AF_INET6, be, argp));
75 }
76 
77 /*
78  * getbyname gets a struct hostent by hostname. This function constructs
79  * an ldap search filter using the name invocation parameter and the
80  * gethostbyname search filter defined. Once the filter is constructed,
81  * we search for a matching entry and marshal the data results into
82  * struct hostent for the frontend process.  Host name searches will be
83  * on fully qualified host names (foo.bar.sun.com)
84  */
85 
86 static nss_status_t
87 getbyname(ldap_backend_ptr be, void *a)
88 {
89 	char		hostname[3 * MAXHOSTNAMELEN];
90 	char		realdomain[BUFSIZ];
91 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
92 	nss_status_t	lstat;
93 	char		searchfilter[SEARCHFILTERLEN];
94 	char		userdata[SEARCHFILTERLEN];
95 	int		rc;
96 
97 	if (_ldap_filter_name(hostname, argp->key.ipnode.name,
98 			sizeof (hostname)) != 0)
99 		return ((nss_status_t)NSS_NOTFOUND);
100 
101 	rc = snprintf(searchfilter, sizeof (searchfilter),
102 	    _F_GETHOSTS6BYNAME, hostname);
103 	if (rc >= sizeof (searchfilter) || rc < 0)
104 		return ((nss_status_t)NSS_NOTFOUND);
105 	rc = snprintf(userdata, sizeof (userdata),
106 	    _F_GETHOSTS6BYNAME_SSD, hostname);
107 	if (rc >= sizeof (userdata) || rc < 0)
108 		return ((nss_status_t)NSS_NOTFOUND);
109 
110 	/* get the domain we are in */
111 	rc = sysinfo(SI_SRPC_DOMAIN, realdomain, BUFSIZ);
112 	if (rc <= 0)
113 		return ((nss_status_t)NSS_NOTFOUND);
114 
115 	/* Is this a request for a host.domain */
116 	if (DOTTEDSUBDOMAIN(hostname)) {
117 		char	host[MAXHOSTNAMELEN];
118 		char	domain[MAXHOSTNAMELEN];
119 		char	hname[3 * MAXHOSTNAMELEN];
120 
121 		/* separate host and domain.  this function */
122 		/* will munge hname, so use argp->keyname */
123 		/* from here on for original string */
124 
125 		(void) strcpy(hname, hostname);
126 		if (chophostdomain(hname, host, domain) == -1) {
127 			return ((nss_status_t)NSS_NOTFOUND);
128 		}
129 
130 		/* if domain is a proper subset of realdomain */
131 		/* ie. domain = "foo" and realdomain */
132 		/* = "foor.bar.sun.com", we try to lookup both" */
133 		/* host.domain and host */
134 
135 		if (propersubdomain(realdomain, domain) == 1) {
136 			/* yes, it is a proper domain */
137 			rc = snprintf(searchfilter, sizeof (searchfilter),
138 			    _F_GETHOSTS6DOTTEDBYNAME, hostname, host);
139 			if (rc >= sizeof (searchfilter) || rc < 0)
140 				return ((nss_status_t)NSS_NOTFOUND);
141 
142 			rc = snprintf(userdata, sizeof (userdata),
143 			    _F_GETHOSTS6DOTTEDBYNAME_SSD, hostname, host);
144 			if (rc >= sizeof (userdata) || rc < 0)
145 				return ((nss_status_t)NSS_NOTFOUND);
146 		} else {
147 			/* it is not a proper domain, so only try to look up */
148 			/* host.domain */
149 			rc = snprintf(searchfilter, sizeof (searchfilter),
150 			    _F_GETHOSTS6BYNAME, hostname);
151 			if (rc >= sizeof (searchfilter) || rc < 0)
152 				return ((nss_status_t)NSS_NOTFOUND);
153 
154 			rc = snprintf(userdata, sizeof (userdata),
155 			    _F_GETHOSTS6BYNAME_SSD, hostname);
156 			if (rc >= sizeof (userdata) || rc < 0)
157 				return ((nss_status_t)NSS_NOTFOUND);
158 		}
159 	} else {
160 		rc = snprintf(searchfilter, sizeof (searchfilter),
161 		    _F_GETHOSTS6BYNAME, hostname);
162 		if (rc >= sizeof (searchfilter) || rc < 0)
163 			return ((nss_status_t)NSS_NOTFOUND);
164 
165 		rc = snprintf(userdata, sizeof (userdata),
166 		    _F_GETHOSTS6BYNAME_SSD, hostname);
167 		if (rc >= sizeof (userdata) || rc < 0)
168 			return ((nss_status_t)NSS_NOTFOUND);
169 	}
170 	lstat = (nss_status_t)_nss_ldap_lookup(be, argp, _HOSTS,
171 		searchfilter, NULL,
172 		_merge_SSD_filter, userdata);
173 	if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
174 		return ((nss_status_t)NSS_SUCCESS);
175 
176 	argp->h_errno = __nss2herrno(lstat);
177 	return ((nss_status_t)lstat);
178 }
179 
180 
181 /*
182  * getbyaddr gets a struct hostent by host address. This function
183  * constructs an ldap search filter using the host address invocation
184  * parameter and the gethostbyaddr search filter defined. Once the
185  * filter is constructed, we search for a matching entry and marshal
186  * the data results into struct hostent for the frontend process.
187  */
188 
189 static nss_status_t
190 getbyaddr(ldap_backend_ptr be, void *a)
191 {
192 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
193 	struct in6_addr	addr;
194 	char		addrbuf[INET6_ADDRSTRLEN + 1];
195 	nss_status_t	lstat;
196 	char		searchfilter[SEARCHFILTERLEN];
197 	char		userdata[SEARCHFILTERLEN];
198 	int		ret;
199 
200 	argp->h_errno = 0;
201 	if ((argp->key.hostaddr.type != AF_INET6) ||
202 	    (argp->key.hostaddr.len != sizeof (addr)))
203 		return (NSS_NOTFOUND);
204 
205 	(void) memcpy(&addr, argp->key.hostaddr.addr, sizeof (addr));
206 	if (IN6_IS_ADDR_V4MAPPED(&addr)) {
207 		if (inet_ntop(AF_INET, (void *) &addr.s6_addr[12],
208 				(void *)addrbuf, INET_ADDRSTRLEN) == NULL) {
209 			return (NSS_NOTFOUND);
210 		}
211 	} else {
212 		if (inet_ntop(AF_INET6, (void *)&addr, (void *)addrbuf,
213 				INET6_ADDRSTRLEN) == NULL)
214 			return (NSS_NOTFOUND);
215 	}
216 	ret = snprintf(searchfilter, sizeof (searchfilter),
217 	    _F_GETHOSTS6BYADDR, addrbuf);
218 	if (ret >= sizeof (searchfilter) || ret < 0)
219 		return ((nss_status_t)NSS_NOTFOUND);
220 
221 	ret = snprintf(userdata, sizeof (userdata),
222 	    _F_GETHOSTS6BYADDR_SSD, addrbuf);
223 	if (ret >= sizeof (userdata) || ret < 0)
224 		return ((nss_status_t)NSS_NOTFOUND);
225 
226 	lstat = (nss_status_t)_nss_ldap_lookup(be, argp,
227 		_HOSTS6, searchfilter, NULL,
228 		_merge_SSD_filter, userdata);
229 	if (lstat == (nss_status_t)NS_LDAP_SUCCESS)
230 		return ((nss_status_t)NSS_SUCCESS);
231 
232 	argp->h_errno = __nss2herrno(lstat);
233 	return ((nss_status_t)lstat);
234 }
235 
236 static ldap_backend_op_t ipnodes_ops[] = {
237 	_nss_ldap_destr,
238 	0,
239 	0,
240 	0,
241 	getbyname,
242 	getbyaddr
243 };
244 
245 
246 /*
247  * _nss_ldap_hosts_constr is where life begins. This function calls the generic
248  * ldap constructor function to define and build the abstract data types
249  * required to support ldap operations.
250  */
251 
252 /*ARGSUSED0*/
253 nss_backend_t *
254 _nss_ldap_ipnodes_constr(const char *dummy1, const char *dummy2,
255 			const char *dummy3)
256 {
257 
258 	return ((nss_backend_t *)_nss_ldap_constr(ipnodes_ops,
259 		sizeof (ipnodes_ops)/sizeof (ipnodes_ops[0]), _HOSTS6,
260 		ipnodes_attrs, _nss_ldap_hosts2str));
261 }
262