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