00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00107 #define SSU_EXTERNAL_VERSION 1
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
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
00143 dns_name_format(identity, b_identity, sizeof(b_identity));
00144
00145
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
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
00184 req_len = sizeof(isc_uint32_t) +
00185 sizeof(isc_uint32_t) +
00186 strlen(b_signer) + 1 +
00187 strlen(b_name) + 1 +
00188 strlen(b_addr) + 1 +
00189 strlen(b_type) + 1 +
00190 strlen(b_key) + 1 +
00191 sizeof(isc_uint32_t) +
00192 token_len;
00193
00194
00195
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
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
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
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 }