xref: /illumos-gate/usr/src/lib/nsswitch/ldap/common/tsol_getrhent.c (revision 5d9d9091f564c198a760790b0bfa72c44e17912b)
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 "ldap_common.h"
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <sys/tsol/tndb.h>
33 
34 /* tnrhdb attributes filters */
35 #define	_TNRHDB_ADDR		"ipTnetNumber"
36 #define	_TNRHDB_TNAME		"ipTnetTemplateName"
37 #define	_F_GETTNDBBYADDR	"(&(objectClass=ipTnetHost)(ipTnetNumber=%s))"
38 #define	_F_GETTNDBBYADDR_SSD	"(&(%%s)(ipTnetNumber=%s))"
39 
40 static const char *tnrhdb_attrs[] = {
41 	_TNRHDB_ADDR,
42 	_TNRHDB_TNAME,
43 	NULL
44 };
45 
46 static void
47 escape_colon(char *in, char *out) {
48 	int i, j;
49 	for (i = 0, j = 0; in[i] != '\0'; i++) {
50 		if (in[i] == ':') {
51 			out[j++] = '\\';
52 			out[j++] = in[i];
53 		} else
54 			out[j++] = in[i];
55 	}
56 	out[j] = '\0';
57 }
58 
59 /*
60  * _nss_ldap_tnrhdb2str is the data marshaling method for the tnrhdb
61  * (tsol_getrhbyaddr()/tsol_getrhent()) backend processes.
62  * This method is called after a successful ldap search has been performed.
63  * This method will parse the ldap search values into the file format.
64  *
65  * e.g.
66  *
67  * 192.168.120.6:public
68  * fec0\:\:a00\:20ff\:fea0\:21f7:cipso
69  *
70  */
71 static int
72 _nss_ldap_tnrhdb2str(ldap_backend_ptr be, nss_XbyY_args_t *argp)
73 {
74 	int			nss_result = NSS_STR_PARSE_SUCCESS;
75 	int			len = 0;
76 	char			*buffer = NULL;
77 	char			**addr, **template, *addr_out;
78 	ns_ldap_result_t	*result = be->result;
79 	char addr6[INET6_ADDRSTRLEN + 5]; /* 5 '\' for ':' at most */
80 
81 	if (result == NULL)
82 		return (NSS_STR_PARSE_PARSE);
83 
84 	addr = __ns_ldap_getAttr(result->entry, _TNRHDB_ADDR);
85 	if (addr == NULL || addr[0] == NULL || (strlen(addr[0]) < 1)) {
86 		nss_result = NSS_STR_PARSE_PARSE;
87 		goto result_tnrhdb2str;
88 	}
89 
90 	/*
91 	 * Escape ':' in IPV6.
92 	 * The value is stored in LDAP directory without escape charaters.
93 	 */
94 	if (strchr(addr[0], ':') != NULL) {
95 		escape_colon(addr[0], addr6);
96 		addr_out = addr6;
97 	} else
98 		addr_out = addr[0];
99 
100 	template = __ns_ldap_getAttr(result->entry, _TNRHDB_TNAME);
101 	if (template == NULL || template[0] == NULL ||
102 			(strlen(template[0]) < 1)) {
103 		nss_result = NSS_STR_PARSE_PARSE;
104 		goto result_tnrhdb2str;
105 	}
106 	/* "addr:template" */
107 	len = strlen(addr_out) + strlen(template[0]) + 2;
108 
109 	if (argp->buf.result != NULL) {
110 		if ((be->buffer = calloc(1, len)) == NULL) {
111 			nss_result = NSS_STR_PARSE_PARSE;
112 			goto result_tnrhdb2str;
113 		}
114 		be->buflen = len - 1;
115 		buffer = be->buffer;
116 	} else
117 		buffer = argp->buf.buffer;
118 
119 	(void) snprintf(buffer, len, "%s:%s", addr_out, template[0]);
120 
121 result_tnrhdb2str:
122 	(void) __ns_ldap_freeResult(&be->result);
123 	return (nss_result);
124 }
125 
126 
127 static nss_status_t
128 getbyaddr(ldap_backend_ptr be, void *a)
129 {
130 	char		searchfilter[SEARCHFILTERLEN];
131 	char		userdata[SEARCHFILTERLEN];
132 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)a;
133 
134 	if (argp->key.hostaddr.addr == NULL ||
135 		(argp->key.hostaddr.type != AF_INET &&
136 		argp->key.hostaddr.type != AF_INET6))
137 			return (NSS_NOTFOUND);
138 	if (strchr(argp->key.hostaddr.addr, ':') != NULL) {
139 		/* IPV6 */
140 		if (argp->key.hostaddr.type == AF_INET)
141 			return (NSS_NOTFOUND);
142 	} else {
143 		/* IPV4 */
144 		if (argp->key.hostaddr.type == AF_INET6)
145 			return (NSS_NOTFOUND);
146 	}
147 
148 	/*
149 	 * The IPV6 addresses are saved in the directory without '\'s.
150 	 * So don't need to escape colons in IPV6 addresses.
151 	 */
152 	if (snprintf(searchfilter, sizeof (searchfilter), _F_GETTNDBBYADDR,
153 	    argp->key.hostaddr.addr) < 0)
154 		return ((nss_status_t)NSS_NOTFOUND);
155 
156 	if (snprintf(userdata, sizeof (userdata), _F_GETTNDBBYADDR_SSD,
157 	    argp->key.hostaddr.addr) < 0)
158 		return ((nss_status_t)NSS_NOTFOUND);
159 
160 	return (_nss_ldap_lookup(be, argp, _TNRHDB, searchfilter, NULL,
161 	    _merge_SSD_filter, userdata));
162 }
163 
164 
165 static ldap_backend_op_t tnrhdb_ops[] = {
166 	_nss_ldap_destr,
167 	_nss_ldap_endent,
168 	_nss_ldap_setent,
169 	_nss_ldap_getent,
170 	getbyaddr
171 };
172 
173 
174 /* ARGSUSED */
175 nss_backend_t *
176 _nss_ldap_tnrhdb_constr(const char *dummy1,
177     const char *dummy2,
178     const char *dummy3,
179     const char *dummy4,
180     const char *dummy5)
181 {
182 	return ((nss_backend_t *)_nss_ldap_constr(tnrhdb_ops,
183 		sizeof (tnrhdb_ops)/sizeof (tnrhdb_ops[0]), _TNRHDB,
184 		tnrhdb_attrs, _nss_ldap_tnrhdb2str));
185 }
186