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 <netdb.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <sys/socket.h>
33 #include "ldap_common.h"
34 
35 /* netmasks attributes filters */
36 #define	_N_NETWORK	"ipnetworknumber"
37 #define	_N_NETMASK	"ipnetmasknumber"
38 
39 #define	_F_GETMASKBYNET	"(&(objectClass=ipNetwork)(ipNetworkNumber=%s))"
40 #define	_F_GETMASKBYNET_SSD	"(&(%%s)(ipNetworkNumber=%s))"
41 
42 static const char *netmasks_attrs[] = {
43 	_N_NETWORK,
44 	_N_NETMASK,
45 	(char *)NULL
46 };
47 
48 
49 /*
50  * _nss_ldap_netmasks2ent is the data marshaling method for the netmasks
51  * getXbyY * (e.g., getbynet()) backend processes. This method is called
52  * after a successful ldap search has been performed. This method will
53  * parse the ldap search values into struct in_addr *mask = argp->buf.result
54  * only if argp->buf.result is initialized (not NULL). Three error
55  * conditions are expected and returned to nsswitch.
56  */
57 
58 static int
59 _nss_ldap_netmasks2ent(ldap_backend_ptr be, nss_XbyY_args_t *argp)
60 {
61 	int		i, j;
62 	int		nss_result;
63 	unsigned long	len = 0L;
64 #ifdef DEBUG
65 	char		maskstr[16];
66 #endif /* DEBUG */
67 	struct in_addr	addr;
68 	struct in_addr	*mask = (struct in_addr *)NULL;
69 	ns_ldap_result_t	*result = be->result;
70 	ns_ldap_attr_t	*attrptr;
71 
72 	mask = (struct in_addr *)argp->buf.result;
73 	nss_result = (int)NSS_STR_PARSE_SUCCESS;
74 
75 	attrptr = getattr(result, 0);
76 	if (attrptr == NULL) {
77 		nss_result = (int)NSS_STR_PARSE_PARSE;
78 		goto result_nmks2ent;
79 	}
80 
81 	for (i = 0; i < result->entry->attr_count; i++) {
82 		attrptr = getattr(result, i);
83 		if (attrptr == NULL) {
84 			nss_result = (int)NSS_STR_PARSE_PARSE;
85 			goto result_nmks2ent;
86 		}
87 		if (strcasecmp(attrptr->attrname, _N_NETMASK) == 0) {
88 			for (j = 0;  j < attrptr->value_count; j++) {
89 				if (mask == NULL)
90 					continue;
91 				if ((attrptr->attrvalue[j] == NULL) ||
92 				    (len = strlen(attrptr->attrvalue[j])) < 1) {
93 					nss_result = (int)NSS_STR_PARSE_PARSE;
94 					goto result_nmks2ent;
95 				}
96 				/* addr a IPv4 address and 32 bits */
97 				addr.s_addr = inet_addr(attrptr->attrvalue[j]);
98 				if (addr.s_addr == 0xffffffffUL) {
99 					nss_result = (int)NSS_STR_PARSE_PARSE;
100 					goto result_nmks2ent;
101 				}
102 				mask->s_addr = addr.s_addr;
103 #ifdef DEBUG
104 				strlcpy(maskstr, attrptr->attrvalue[j],
105 							sizeof (maskstr));
106 #endif /* DEBUG */
107 				continue;
108 			}
109 		}
110 	}
111 
112 #ifdef DEBUG
113 	(void) fprintf(stdout, "\n[netmasks.c: _nss_ldap_netmasks2ent]\n");
114 	(void) fprintf(stdout, "       netmask: [%s]\n", maskstr);
115 #endif /* DEBUG */
116 
117 result_nmks2ent:
118 
119 	(void) __ns_ldap_freeResult(&be->result);
120 	return ((int)nss_result);
121 }
122 
123 
124 /*
125  * getbynet gets a network mask by address. This function constructs an
126  * ldap search filter using the netmask name invocation parameter and the
127  * getmaskbynet search filter defined. Once the filter is constructed, we
128  * search for a matching entry and marshal the data results into struct
129  * in_addr for the frontend process. The function _nss_ldap_netmasks2ent
130  * performs the data marshaling.
131  */
132 
133 static nss_status_t
134 getbynet(ldap_backend_ptr be, void *a)
135 {
136 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
137 	char		searchfilter[SEARCHFILTERLEN];
138 	char		userdata[SEARCHFILTERLEN];
139 	char		netnumber[SEARCHFILTERLEN];
140 	int		ret;
141 
142 	if (_ldap_filter_name(netnumber, argp->key.name, sizeof (netnumber))
143 			!= 0)
144 		return ((nss_status_t)NSS_NOTFOUND);
145 
146 	ret = snprintf(searchfilter, sizeof (searchfilter),
147 	    _F_GETMASKBYNET, netnumber);
148 	if (ret >= sizeof (searchfilter) || ret < 0)
149 		return ((nss_status_t)NSS_NOTFOUND);
150 
151 	ret = snprintf(userdata, sizeof (userdata),
152 	    _F_GETMASKBYNET_SSD, netnumber);
153 	if (ret >= sizeof (userdata) || ret < 0)
154 		return ((nss_status_t)NSS_NOTFOUND);
155 
156 	return ((nss_status_t)_nss_ldap_lookup(be, argp,
157 		_NETMASKS, searchfilter, NULL,
158 		_merge_SSD_filter, userdata));
159 }
160 
161 
162 static ldap_backend_op_t netmasks_ops[] = {
163 	_nss_ldap_destr,
164 	getbynet
165 };
166 
167 
168 /*
169  * _nss_ldap_netmasks_constr is where life begins. This function calls
170  * the generic ldap constructor function to define and build the abstract
171  * data types required to support ldap operations.
172  */
173 
174 /*ARGSUSED0*/
175 nss_backend_t *
176 _nss_ldap_netmasks_constr(const char *dummy1, const char *dummy2,
177 			const char *dummy3)
178 {
179 
180 	return ((nss_backend_t *)_nss_ldap_constr(netmasks_ops,
181 		sizeof (netmasks_ops)/sizeof (netmasks_ops[0]), _NETMASKS,
182 		netmasks_attrs, _nss_ldap_netmasks2ent));
183 }
184