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 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 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 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 * 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