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
escape_colon(char * in,char * out)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
_nss_ldap_tnrhdb2str(ldap_backend_ptr be,nss_XbyY_args_t * argp)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
getbyaddr(ldap_backend_ptr be,void * a)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 *
_nss_ldap_tnrhdb_constr(const char * dummy1,const char * dummy2,const char * dummy3,const char * dummy4,const char * dummy5)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