ssu_external.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011-2013  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 /*
00020  * This implements external update-policy rules.  This allows permission
00021  * to update a zone to be checked by consulting an external daemon (e.g.,
00022  * kerberos).
00023  */
00024 
00025 #include <config.h>
00026 #include <errno.h>
00027 #include <unistd.h>
00028 
00029 #ifdef ISC_PLATFORM_HAVESYSUNH
00030 #include <sys/socket.h>
00031 #include <sys/un.h>
00032 #endif
00033 
00034 #include <isc/magic.h>
00035 #include <isc/mem.h>
00036 #include <isc/netaddr.h>
00037 #include <isc/result.h>
00038 #include <isc/string.h>
00039 #include <isc/util.h>
00040 #include <isc/strerror.h>
00041 
00042 #include <dns/fixedname.h>
00043 #include <dns/name.h>
00044 #include <dns/ssu.h>
00045 #include <dns/log.h>
00046 #include <dns/rdatatype.h>
00047 
00048 #include <dst/dst.h>
00049 
00050 
00051 static void
00052 ssu_e_log(int level, const char *fmt, ...) {
00053         va_list ap;
00054 
00055         va_start(ap, fmt);
00056         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_SECURITY,
00057                        DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(level), fmt, ap);
00058         va_end(ap);
00059 }
00060 
00061 
00062 /*
00063  * Connect to a UNIX domain socket.
00064  */
00065 static int
00066 ux_socket_connect(const char *path) {
00067         int fd = -1;
00068 #ifdef ISC_PLATFORM_HAVESYSUNH
00069         struct sockaddr_un addr;
00070 
00071         REQUIRE(path != NULL);
00072 
00073         if (strlen(path) > sizeof(addr.sun_path)) {
00074                 ssu_e_log(3, "ssu_external: socket path '%s' "
00075                              "longer than system maximum %u",
00076                           path, sizeof(addr.sun_path));
00077                 return (-1);
00078         }
00079 
00080         memset(&addr, 0, sizeof(addr));
00081         addr.sun_family = AF_UNIX;
00082         strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
00083 
00084         fd = socket(AF_UNIX, SOCK_STREAM, 0);
00085         if (fd == -1) {
00086                 char strbuf[ISC_STRERRORSIZE];
00087                 isc__strerror(errno, strbuf, sizeof(strbuf));
00088                 ssu_e_log(3, "ssu_external: unable to create socket - %s",
00089                           strbuf);
00090                 return (-1);
00091         }
00092 
00093         if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
00094                 char strbuf[ISC_STRERRORSIZE];
00095                 isc__strerror(errno, strbuf, sizeof(strbuf));
00096                 ssu_e_log(3, "ssu_external: unable to connect to "
00097                              "socket '%s' - %s",
00098                           path, strbuf);
00099                 close(fd);
00100                 return (-1);
00101         }
00102 #endif
00103         return (fd);
00104 }
00105 
00106 /* Change this version if you update the format of the request */
00107 #define SSU_EXTERNAL_VERSION 1
00108 
00109 /*
00110  * Perform an update-policy rule check against an external application
00111  * over a socket.
00112  *
00113  * This currently only supports local: for unix domain datagram sockets.
00114  *
00115  * Note that by using a datagram socket and creating a new socket each
00116  * time we avoid the need for locking and allow for parallel access to
00117  * the authorization server.
00118  */
00119 isc_boolean_t
00120 dns_ssu_external_match(dns_name_t *identity,
00121                        dns_name_t *signer, dns_name_t *name,
00122                        isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
00123                        const dst_key_t *key, isc_mem_t *mctx)
00124 {
00125         char b_identity[DNS_NAME_FORMATSIZE];
00126         char b_signer[DNS_NAME_FORMATSIZE];
00127         char b_name[DNS_NAME_FORMATSIZE];
00128         char b_addr[ISC_NETADDR_FORMATSIZE];
00129         char b_type[DNS_RDATATYPE_FORMATSIZE];
00130         char b_key[DST_KEY_FORMATSIZE];
00131         isc_buffer_t *tkey_token = NULL;
00132         int fd;
00133         const char *sock_path;
00134         unsigned int req_len;
00135         isc_region_t token_region;
00136         unsigned char *data;
00137         isc_buffer_t buf;
00138         isc_uint32_t token_len = 0;
00139         isc_uint32_t reply;
00140         ssize_t ret;
00141 
00142         /* The identity contains local:/path/to/socket */
00143         dns_name_format(identity, b_identity, sizeof(b_identity));
00144 
00145         /* For now only local: is supported */
00146         if (strncmp(b_identity, "local:", 6) != 0) {
00147                 ssu_e_log(3, "ssu_external: invalid socket path '%s'",
00148                           b_identity);
00149                 return (ISC_FALSE);
00150         }
00151         sock_path = &b_identity[6];
00152 
00153         fd = ux_socket_connect(sock_path);
00154         if (fd == -1)
00155                 return (ISC_FALSE);
00156 
00157         if (key != NULL) {
00158                 dst_key_format(key, b_key, sizeof(b_key));
00159                 tkey_token = dst_key_tkeytoken(key);
00160         } else
00161                 b_key[0] = 0;
00162 
00163         if (tkey_token != NULL) {
00164                 isc_buffer_region(tkey_token, &token_region);
00165                 token_len = token_region.length;
00166         }
00167 
00168         /* Format the request elements */
00169         if (signer != NULL)
00170                 dns_name_format(signer, b_signer, sizeof(b_signer));
00171         else
00172                 b_signer[0] = 0;
00173 
00174         dns_name_format(name, b_name, sizeof(b_name));
00175 
00176         if (tcpaddr != NULL)
00177                 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
00178         else
00179                 b_addr[0] = 0;
00180 
00181         dns_rdatatype_format(type, b_type, sizeof(b_type));
00182 
00183         /* Work out how big the request will be */
00184         req_len = sizeof(isc_uint32_t)     + /* Format version */
00185                   sizeof(isc_uint32_t)     + /* Length */
00186                   strlen(b_signer) + 1 + /* Signer */
00187                   strlen(b_name) + 1   + /* Name */
00188                   strlen(b_addr) + 1   + /* Address */
00189                   strlen(b_type) + 1   + /* Type */
00190                   strlen(b_key) + 1    + /* Key */
00191                   sizeof(isc_uint32_t)     + /* tkey_token length */
00192                   token_len;             /* tkey_token */
00193 
00194 
00195         /* format the buffer */
00196         data = isc_mem_allocate(mctx, req_len);
00197         if (data == NULL) {
00198                 close(fd);
00199                 return (ISC_FALSE);
00200         }
00201 
00202         isc_buffer_init(&buf, data, req_len);
00203         isc_buffer_putuint32(&buf, SSU_EXTERNAL_VERSION);
00204         isc_buffer_putuint32(&buf, req_len);
00205 
00206         /* Strings must be null-terminated */
00207         isc_buffer_putstr(&buf, b_signer);
00208         isc_buffer_putuint8(&buf, 0);
00209         isc_buffer_putstr(&buf, b_name);
00210         isc_buffer_putuint8(&buf, 0);
00211         isc_buffer_putstr(&buf, b_addr);
00212         isc_buffer_putuint8(&buf, 0);
00213         isc_buffer_putstr(&buf, b_type);
00214         isc_buffer_putuint8(&buf, 0);
00215         isc_buffer_putstr(&buf, b_key);
00216         isc_buffer_putuint8(&buf, 0);
00217 
00218         isc_buffer_putuint32(&buf, token_len);
00219         if (tkey_token && token_len != 0)
00220                 isc_buffer_putmem(&buf, token_region.base, token_len);
00221 
00222         ENSURE(isc_buffer_availablelength(&buf) == 0);
00223 
00224         /* Send the request */
00225         ret = write(fd, data, req_len);
00226         isc_mem_free(mctx, data);
00227         if (ret != (ssize_t) req_len) {
00228                 char strbuf[ISC_STRERRORSIZE];
00229                 isc__strerror(errno, strbuf, sizeof(strbuf));
00230                 ssu_e_log(3, "ssu_external: unable to send request - %s",
00231                           strbuf);
00232                 close(fd);
00233                 return (ISC_FALSE);
00234         }
00235 
00236         /* Receive the reply */
00237         ret = read(fd, &reply, sizeof(isc_uint32_t));
00238         if (ret != (ssize_t) sizeof(isc_uint32_t)) {
00239                 char strbuf[ISC_STRERRORSIZE];
00240                 isc__strerror(errno, strbuf, sizeof(strbuf));
00241                 ssu_e_log(3, "ssu_external: unable to receive reply - %s",
00242                           strbuf);
00243                 close(fd);
00244                 return (ISC_FALSE);
00245         }
00246 
00247         close(fd);
00248 
00249         reply = ntohl(reply);
00250 
00251         if (reply == 0) {
00252                 ssu_e_log(3, "ssu_external: denied external auth for '%s'",
00253                           b_name);
00254                 return (ISC_FALSE);
00255         } else if (reply == 1) {
00256                 ssu_e_log(3, "ssu_external: allowed external auth for '%s'",
00257                           b_name);
00258                 return (ISC_TRUE);
00259         }
00260 
00261         ssu_e_log(3, "ssu_external: invalid reply 0x%08x", reply);
00262 
00263         return (ISC_FALSE);
00264 }

Generated on Tue Apr 28 17:41:01 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha