Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / ssu_external.c
blob60ccb9892fec167259d90dc2d1979b63ab0d083b
1 /* $NetBSD: ssu_external.c,v 1.7 2014/12/10 04:37:58 christos Exp $ */
3 /*
4 * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id */
22 * This implements external update-policy rules. This allows permission
23 * to update a zone to be checked by consulting an external daemon (e.g.,
24 * kerberos).
27 #include <config.h>
28 #include <errno.h>
29 #include <unistd.h>
31 #ifdef ISC_PLATFORM_HAVESYSUNH
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #endif
36 #include <isc/magic.h>
37 #include <isc/mem.h>
38 #include <isc/netaddr.h>
39 #include <isc/result.h>
40 #include <isc/string.h>
41 #include <isc/util.h>
42 #include <isc/strerror.h>
44 #include <dns/fixedname.h>
45 #include <dns/name.h>
46 #include <dns/ssu.h>
47 #include <dns/log.h>
48 #include <dns/rdatatype.h>
50 #include <dst/dst.h>
53 static void
54 ssu_e_log(int level, const char *fmt, ...) {
55 va_list ap;
57 va_start(ap, fmt);
58 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_SECURITY,
59 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(level), fmt, ap);
60 va_end(ap);
65 * Connect to a UNIX domain socket.
67 static int
68 ux_socket_connect(const char *path) {
69 int fd = -1;
70 #ifdef ISC_PLATFORM_HAVESYSUNH
71 struct sockaddr_un addr;
73 REQUIRE(path != NULL);
75 if (strlen(path) > sizeof(addr.sun_path)) {
76 ssu_e_log(3, "ssu_external: socket path '%s' "
77 "longer than system maximum %u",
78 path, sizeof(addr.sun_path));
79 return (-1);
82 memset(&addr, 0, sizeof(addr));
83 addr.sun_family = AF_UNIX;
84 strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
86 fd = socket(AF_UNIX, SOCK_STREAM, 0);
87 if (fd == -1) {
88 char strbuf[ISC_STRERRORSIZE];
89 isc__strerror(errno, strbuf, sizeof(strbuf));
90 ssu_e_log(3, "ssu_external: unable to create socket - %s",
91 strbuf);
92 return (-1);
95 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
96 char strbuf[ISC_STRERRORSIZE];
97 isc__strerror(errno, strbuf, sizeof(strbuf));
98 ssu_e_log(3, "ssu_external: unable to connect to "
99 "socket '%s' - %s",
100 path, strbuf);
101 close(fd);
102 return (-1);
104 #endif
105 return (fd);
108 /* Change this version if you update the format of the request */
109 #define SSU_EXTERNAL_VERSION 1
112 * Perform an update-policy rule check against an external application
113 * over a socket.
115 * This currently only supports local: for unix domain datagram sockets.
117 * Note that by using a datagram socket and creating a new socket each
118 * time we avoid the need for locking and allow for parallel access to
119 * the authorization server.
121 isc_boolean_t
122 dns_ssu_external_match(dns_name_t *identity,
123 dns_name_t *signer, dns_name_t *name,
124 isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
125 const dst_key_t *key, isc_mem_t *mctx)
127 char b_identity[DNS_NAME_FORMATSIZE];
128 char b_signer[DNS_NAME_FORMATSIZE];
129 char b_name[DNS_NAME_FORMATSIZE];
130 char b_addr[ISC_NETADDR_FORMATSIZE];
131 char b_type[DNS_RDATATYPE_FORMATSIZE];
132 char b_key[DST_KEY_FORMATSIZE];
133 isc_buffer_t *tkey_token = NULL;
134 int fd;
135 const char *sock_path;
136 unsigned int req_len;
137 isc_region_t token_region;
138 unsigned char *data;
139 isc_buffer_t buf;
140 isc_uint32_t token_len = 0;
141 isc_uint32_t reply;
142 ssize_t ret;
144 /* The identity contains local:/path/to/socket */
145 dns_name_format(identity, b_identity, sizeof(b_identity));
147 /* For now only local: is supported */
148 if (strncmp(b_identity, "local:", 6) != 0) {
149 ssu_e_log(3, "ssu_external: invalid socket path '%s'",
150 b_identity);
151 return (ISC_FALSE);
153 sock_path = &b_identity[6];
155 fd = ux_socket_connect(sock_path);
156 if (fd == -1)
157 return (ISC_FALSE);
159 if (key != NULL) {
160 dst_key_format(key, b_key, sizeof(b_key));
161 tkey_token = dst_key_tkeytoken(key);
162 } else
163 b_key[0] = 0;
165 if (tkey_token != NULL) {
166 isc_buffer_region(tkey_token, &token_region);
167 token_len = token_region.length;
170 /* Format the request elements */
171 if (signer != NULL)
172 dns_name_format(signer, b_signer, sizeof(b_signer));
173 else
174 b_signer[0] = 0;
176 dns_name_format(name, b_name, sizeof(b_name));
178 if (tcpaddr != NULL)
179 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
180 else
181 b_addr[0] = 0;
183 dns_rdatatype_format(type, b_type, sizeof(b_type));
185 /* Work out how big the request will be */
186 req_len = sizeof(isc_uint32_t) + /* Format version */
187 sizeof(isc_uint32_t) + /* Length */
188 strlen(b_signer) + 1 + /* Signer */
189 strlen(b_name) + 1 + /* Name */
190 strlen(b_addr) + 1 + /* Address */
191 strlen(b_type) + 1 + /* Type */
192 strlen(b_key) + 1 + /* Key */
193 sizeof(isc_uint32_t) + /* tkey_token length */
194 token_len; /* tkey_token */
197 /* format the buffer */
198 data = isc_mem_allocate(mctx, req_len);
199 if (data == NULL) {
200 close(fd);
201 return (ISC_FALSE);
204 isc_buffer_init(&buf, data, req_len);
205 isc_buffer_putuint32(&buf, SSU_EXTERNAL_VERSION);
206 isc_buffer_putuint32(&buf, req_len);
208 /* Strings must be null-terminated */
209 isc_buffer_putstr(&buf, b_signer);
210 isc_buffer_putuint8(&buf, 0);
211 isc_buffer_putstr(&buf, b_name);
212 isc_buffer_putuint8(&buf, 0);
213 isc_buffer_putstr(&buf, b_addr);
214 isc_buffer_putuint8(&buf, 0);
215 isc_buffer_putstr(&buf, b_type);
216 isc_buffer_putuint8(&buf, 0);
217 isc_buffer_putstr(&buf, b_key);
218 isc_buffer_putuint8(&buf, 0);
220 isc_buffer_putuint32(&buf, token_len);
221 if (tkey_token && token_len != 0)
222 isc_buffer_putmem(&buf, token_region.base, token_len);
224 ENSURE(isc_buffer_availablelength(&buf) == 0);
226 /* Send the request */
227 ret = write(fd, data, req_len);
228 isc_mem_free(mctx, data);
229 if (ret != (ssize_t) req_len) {
230 char strbuf[ISC_STRERRORSIZE];
231 isc__strerror(errno, strbuf, sizeof(strbuf));
232 ssu_e_log(3, "ssu_external: unable to send request - %s",
233 strbuf);
234 close(fd);
235 return (ISC_FALSE);
238 /* Receive the reply */
239 ret = read(fd, &reply, sizeof(isc_uint32_t));
240 if (ret != (ssize_t) sizeof(isc_uint32_t)) {
241 char strbuf[ISC_STRERRORSIZE];
242 isc__strerror(errno, strbuf, sizeof(strbuf));
243 ssu_e_log(3, "ssu_external: unable to receive reply - %s",
244 strbuf);
245 close(fd);
246 return (ISC_FALSE);
249 close(fd);
251 reply = ntohl(reply);
253 if (reply == 0) {
254 ssu_e_log(3, "ssu_external: denied external auth for '%s'",
255 b_name);
256 return (ISC_FALSE);
257 } else if (reply == 1) {
258 ssu_e_log(3, "ssu_external: allowed external auth for '%s'",
259 b_name);
260 return (ISC_TRUE);
263 ssu_e_log(3, "ssu_external: invalid reply 0x%08x", reply);
265 return (ISC_FALSE);