1 /* $NetBSD: ssu_external.c,v 1.7 2014/12/10 04:37:58 christos Exp $ */
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.
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.,
31 #ifdef ISC_PLATFORM_HAVESYSUNH
32 #include <sys/socket.h>
36 #include <isc/magic.h>
38 #include <isc/netaddr.h>
39 #include <isc/result.h>
40 #include <isc/string.h>
42 #include <isc/strerror.h>
44 #include <dns/fixedname.h>
48 #include <dns/rdatatype.h>
54 ssu_e_log(int level
, const char *fmt
, ...) {
58 isc_log_vwrite(dns_lctx
, DNS_LOGCATEGORY_SECURITY
,
59 DNS_LOGMODULE_ZONE
, ISC_LOG_DEBUG(level
), fmt
, ap
);
65 * Connect to a UNIX domain socket.
68 ux_socket_connect(const char *path
) {
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
));
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);
88 char strbuf
[ISC_STRERRORSIZE
];
89 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
90 ssu_e_log(3, "ssu_external: unable to create socket - %s",
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 "
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
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.
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
;
135 const char *sock_path
;
136 unsigned int req_len
;
137 isc_region_t token_region
;
140 isc_uint32_t token_len
= 0;
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'",
153 sock_path
= &b_identity
[6];
155 fd
= ux_socket_connect(sock_path
);
160 dst_key_format(key
, b_key
, sizeof(b_key
));
161 tkey_token
= dst_key_tkeytoken(key
);
165 if (tkey_token
!= NULL
) {
166 isc_buffer_region(tkey_token
, &token_region
);
167 token_len
= token_region
.length
;
170 /* Format the request elements */
172 dns_name_format(signer
, b_signer
, sizeof(b_signer
));
176 dns_name_format(name
, b_name
, sizeof(b_name
));
179 isc_netaddr_format(tcpaddr
, b_addr
, sizeof(b_addr
));
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
);
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",
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",
251 reply
= ntohl(reply
);
254 ssu_e_log(3, "ssu_external: denied external auth for '%s'",
257 } else if (reply
== 1) {
258 ssu_e_log(3, "ssu_external: allowed external auth for '%s'",
263 ssu_e_log(3, "ssu_external: invalid reply 0x%08x", reply
);