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
_nss_ldap_hosts2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)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
getbyname(ldap_backend_ptr be,void * a)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
getbyaddr(ldap_backend_ptr be,void * a)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 *
_nss_ldap_ipnodes_constr(const char * dummy1,const char * dummy2,const char * dummy3)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