1 1.1 christos /* 2 1.1 christos * nsd-control.c - remote control utility for nsd. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2011, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * This software is open source. 7 1.1 christos * 8 1.1 christos * Redistribution and use in source and binary forms, with or without 9 1.1 christos * modification, are permitted provided that the following conditions 10 1.1 christos * are met: 11 1.1 christos * 12 1.1 christos * Redistributions of source code must retain the above copyright notice, 13 1.1 christos * this list of conditions and the following disclaimer. 14 1.1 christos * 15 1.1 christos * Redistributions in binary form must reproduce the above copyright notice, 16 1.1 christos * this list of conditions and the following disclaimer in the documentation 17 1.1 christos * and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * Neither the name of the NLNET LABS nor the names of its contributors may 20 1.1 christos * be used to endorse or promote products derived from this software without 21 1.1 christos * specific prior written permission. 22 1.1 christos * 23 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 1.1 christos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 1.1 christos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 1.1 christos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 1.1 christos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 1.1 christos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 1.1 christos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 christos */ 35 1.1 christos 36 1.1 christos /** 37 1.1 christos * \file 38 1.1 christos * 39 1.1 christos * The remote control utility contacts the nsd server over ssl and 40 1.1 christos * sends the command, receives the answer, and displays the result 41 1.1 christos * from the commandline. 42 1.1 christos */ 43 1.1 christos 44 1.1 christos #include "config.h" 45 1.1.1.6 christos #include <stdio.h> 46 1.1.1.8 christos #include <stdlib.h> 47 1.1.1.9 christos 48 1.1.1.9 christos struct region; 49 1.1.1.9 christos struct domain_table; 50 1.1.1.9 christos struct zone; 51 1.1.1.9 christos struct domain; 52 1.1.1.9 christos int zonec_parse_string(struct region* ATTR_UNUSED(region), 53 1.1.1.9 christos struct domain_table* ATTR_UNUSED(domains), 54 1.1.1.9 christos struct zone* ATTR_UNUSED(zone), char* ATTR_UNUSED(str), 55 1.1.1.9 christos struct domain** ATTR_UNUSED(parsed), int* ATTR_UNUSED(num_rrs)) 56 1.1.1.9 christos { 57 1.1.1.9 christos return 0; 58 1.1.1.9 christos } 59 1.1.1.9 christos 60 1.1 christos #include <sys/types.h> 61 1.1 christos #include <unistd.h> 62 1.1 christos #include <string.h> 63 1.1.1.9 christos #include <errno.h> 64 1.1.1.9 christos #ifdef HAVE_SSL 65 1.1 christos #ifdef HAVE_OPENSSL_SSL_H 66 1.1 christos #include <openssl/ssl.h> 67 1.1 christos #endif 68 1.1 christos #ifdef HAVE_OPENSSL_ERR_H 69 1.1 christos #include <openssl/err.h> 70 1.1 christos #endif 71 1.1 christos #ifdef HAVE_OPENSSL_RAND_H 72 1.1 christos #include <openssl/rand.h> 73 1.1 christos #endif 74 1.1.1.9 christos #endif /* HAVE_SSL */ 75 1.1.1.3 christos #ifdef HAVE_SYS_UN_H 76 1.1.1.3 christos #include <sys/un.h> 77 1.1.1.3 christos #endif 78 1.1.1.7 christos #include <fcntl.h> 79 1.1.1.8 christos #ifndef AF_LOCAL 80 1.1.1.8 christos #define AF_LOCAL AF_UNIX 81 1.1.1.8 christos #endif 82 1.1 christos #include "util.h" 83 1.1 christos #include "tsig.h" 84 1.1 christos #include "options.h" 85 1.1.1.8 christos #include "zonec.h" 86 1.1 christos 87 1.1.1.7 christos static void usage(void) ATTR_NORETURN; 88 1.1.1.9 christos #ifdef HAVE_SSL 89 1.1.1.4 prlw1 static void ssl_err(const char* s) ATTR_NORETURN; 90 1.1.1.4 prlw1 static void ssl_path_err(const char* s, const char *path) ATTR_NORETURN; 91 1.1.1.9 christos #else 92 1.1.1.9 christos /* define SSL to use as a boolean to turn it off in function calls. */ 93 1.1.1.9 christos #define SSL int 94 1.1.1.9 christos #endif 95 1.1.1.4 prlw1 96 1.1.1.7 christos /** timeout to wait for connection over stream, in msec */ 97 1.1.1.7 christos #define NSD_CONTROL_CONNECT_TIMEOUT 5000 98 1.1.1.7 christos 99 1.1 christos /** Give nsd-control usage, and exit (1). */ 100 1.1 christos static void 101 1.1 christos usage() 102 1.1 christos { 103 1.1 christos printf("Usage: nsd-control [options] command\n"); 104 1.1 christos printf(" Remote control utility for nsd server.\n"); 105 1.1 christos printf("Version %s. Report bugs to <%s>.\n", 106 1.1 christos PACKAGE_VERSION, PACKAGE_BUGREPORT); 107 1.1 christos printf("Options:\n"); 108 1.1 christos printf(" -c file config file, default is %s\n", CONFIGFILE); 109 1.1 christos printf(" -s ip[@port] server address, if omitted config is used.\n"); 110 1.1 christos printf(" -h show this usage help.\n"); 111 1.1 christos printf("Commands:\n"); 112 1.1 christos printf(" start start server; runs nsd(8)\n"); 113 1.1 christos printf(" stop stops the server\n"); 114 1.1 christos printf(" reload [<zone>] reload modified zonefiles from disk\n"); 115 1.1 christos printf(" reconfig reload the config file\n"); 116 1.1 christos printf(" repattern the same as reconfig\n"); 117 1.1 christos printf(" log_reopen reopen logfile (for log rotate)\n"); 118 1.1 christos printf(" status display status of server\n"); 119 1.1 christos printf(" stats print statistics\n"); 120 1.1 christos printf(" stats_noreset peek at statistics\n"); 121 1.1 christos printf(" addzone <name> <pattern> add a new zone\n"); 122 1.1 christos printf(" delzone <name> remove a zone\n"); 123 1.1.1.4 prlw1 printf(" changezone <name> <pattern> change zone to use pattern\n"); 124 1.1 christos printf(" addzones add zone list on stdin {name space pattern newline}\n"); 125 1.1 christos printf(" delzones remove zone list on stdin {name newline}\n"); 126 1.1 christos printf(" write [<zone>] write changed zonefiles to disk\n"); 127 1.1.1.10 christos printf(" notify [<zone>] send NOTIFY messages to secondary servers\n"); 128 1.1.1.10 christos printf(" transfer [<zone>] try to update secondary zones to newer serial\n"); 129 1.1.1.10 christos printf(" force_transfer [<zone>] update secondary zones with AXFR, no serial check\n"); 130 1.1 christos printf(" zonestatus [<zone>] print state, serial, activity\n"); 131 1.1 christos printf(" serverpid get pid of server process\n"); 132 1.1 christos printf(" verbosity <number> change logging detail\n"); 133 1.1.1.5 christos printf(" print_tsig [<key_name>] print tsig with <name> the secret and algo\n"); 134 1.1.1.5 christos printf(" update_tsig <name> <secret> change existing tsig with <name> to a new <secret>\n"); 135 1.1.1.5 christos printf(" add_tsig <name> <secret> [algo] add new key with the given parameters\n"); 136 1.1.1.5 christos printf(" assoc_tsig <zone> <key_name> associate <zone> with given tsig <key_name> name\n"); 137 1.1.1.5 christos printf(" del_tsig <key_name> delete tsig <key_name> from configuration\n"); 138 1.1.1.8 christos printf(" add_cookie_secret <secret> add (or replace) a new cookie secret <secret>\n"); 139 1.1.1.8 christos printf(" drop_cookie_secret drop a staging cookie secret\n"); 140 1.1.1.8 christos printf(" activate_cookie_secret make a staging cookie secret active\n"); 141 1.1.1.8 christos printf(" print_cookie_secrets show all cookie secrets with their status\n"); 142 1.1 christos exit(1); 143 1.1 christos } 144 1.1 christos 145 1.1.1.9 christos #ifdef HAVE_SSL 146 1.1 christos /** exit with ssl error */ 147 1.1 christos static void ssl_err(const char* s) 148 1.1 christos { 149 1.1 christos fprintf(stderr, "error: %s\n", s); 150 1.1 christos ERR_print_errors_fp(stderr); 151 1.1 christos exit(1); 152 1.1 christos } 153 1.1 christos 154 1.1.1.4 prlw1 /** exit with ssl error related to a file path */ 155 1.1.1.4 prlw1 static void ssl_path_err(const char* s, const char *path) 156 1.1.1.4 prlw1 { 157 1.1.1.4 prlw1 unsigned long err; 158 1.1.1.4 prlw1 err = ERR_peek_error(); 159 1.1.1.8 christos if (ERR_GET_LIB(err) == ERR_LIB_SYS) { 160 1.1.1.4 prlw1 fprintf(stderr, "error: %s\n%s: %s\n", 161 1.1.1.4 prlw1 s, path, ERR_reason_error_string(err)); 162 1.1.1.4 prlw1 exit(1); 163 1.1.1.4 prlw1 } else { 164 1.1.1.4 prlw1 ssl_err(s); 165 1.1.1.4 prlw1 } 166 1.1.1.4 prlw1 } 167 1.1.1.4 prlw1 168 1.1 christos /** setup SSL context */ 169 1.1 christos static SSL_CTX* 170 1.1.1.2 christos setup_ctx(struct nsd_options* cfg) 171 1.1 christos { 172 1.1 christos char* s_cert, *c_key, *c_cert; 173 1.1 christos SSL_CTX* ctx; 174 1.1 christos 175 1.1.1.3 christos if(!options_remote_is_address(cfg)) 176 1.1.1.3 christos return NULL; 177 1.1 christos s_cert = cfg->server_cert_file; 178 1.1 christos c_key = cfg->control_key_file; 179 1.1 christos c_cert = cfg->control_cert_file; 180 1.1 christos 181 1.1 christos /* filenames may be relative to zonesdir */ 182 1.1 christos if (cfg->zonesdir && cfg->zonesdir[0] && 183 1.1 christos (s_cert[0] != '/' || c_key[0] != '/' || c_cert[0] != '/')) { 184 1.1 christos if(chdir(cfg->zonesdir)) 185 1.1.1.4 prlw1 error("could not chdir to zonesdir: %s %s", 186 1.1.1.4 prlw1 cfg->zonesdir, strerror(errno)); 187 1.1 christos } 188 1.1 christos 189 1.1 christos ctx = SSL_CTX_new(SSLv23_client_method()); 190 1.1 christos if(!ctx) 191 1.1 christos ssl_err("could not allocate SSL_CTX pointer"); 192 1.1.1.7 christos #if SSL_OP_NO_SSLv2 != 0 193 1.1 christos if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) 194 1.1 christos != SSL_OP_NO_SSLv2) 195 1.1 christos ssl_err("could not set SSL_OP_NO_SSLv2"); 196 1.1.1.7 christos #endif 197 1.1 christos if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) 198 1.1 christos != SSL_OP_NO_SSLv3) 199 1.1 christos ssl_err("could not set SSL_OP_NO_SSLv3"); 200 1.1.1.6 christos #if defined(SSL_OP_NO_RENEGOTIATION) 201 1.1.1.6 christos /* disable client renegotiation */ 202 1.1.1.6 christos if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & 203 1.1.1.6 christos SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) 204 1.1.1.6 christos ssl_err("could not set SSL_OP_NO_RENEGOTIATION"); 205 1.1.1.6 christos #endif 206 1.1.1.4 prlw1 if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM)) 207 1.1.1.4 prlw1 ssl_path_err("Error setting up SSL_CTX client cert", c_cert); 208 1.1.1.4 prlw1 if(!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)) 209 1.1.1.4 prlw1 ssl_path_err("Error setting up SSL_CTX client key", c_key); 210 1.1.1.4 prlw1 if(!SSL_CTX_check_private_key(ctx)) 211 1.1.1.4 prlw1 ssl_err("Error setting up SSL_CTX client key"); 212 1.1 christos if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1) 213 1.1.1.4 prlw1 ssl_path_err("Error setting up SSL_CTX verify, server cert", 214 1.1.1.4 prlw1 s_cert); 215 1.1 christos SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 216 1.1 christos 217 1.1 christos return ctx; 218 1.1 christos } 219 1.1.1.9 christos #endif /* HAVE_SSL */ 220 1.1 christos 221 1.1.1.7 christos /** check connect error */ 222 1.1.1.7 christos static void 223 1.1.1.7 christos checkconnecterr(int err, const char* svr, int port, int statuscmd) 224 1.1.1.7 christos { 225 1.1.1.7 christos if(!port) fprintf(stderr, "error: connect (%s): %s\n", svr, 226 1.1.1.7 christos strerror(err)); 227 1.1.1.7 christos else fprintf(stderr, "error: connect (%s@%d): %s\n", svr, port, 228 1.1.1.7 christos strerror(err)); 229 1.1.1.7 christos if(err == ECONNREFUSED && statuscmd) { 230 1.1.1.7 christos printf("nsd is stopped\n"); 231 1.1.1.7 christos exit(3); 232 1.1.1.7 christos } 233 1.1.1.7 christos exit(1); 234 1.1.1.7 christos } 235 1.1.1.7 christos 236 1.1 christos /** contact the server with TCP connect */ 237 1.1 christos static int 238 1.1.1.2 christos contact_server(const char* svr, struct nsd_options* cfg, int statuscmd) 239 1.1 christos { 240 1.1 christos #ifdef INET6 241 1.1 christos struct sockaddr_storage addr; 242 1.1 christos #else 243 1.1 christos struct sockaddr_in addr; 244 1.1 christos #endif 245 1.1 christos socklen_t addrlen; 246 1.1 christos int fd; 247 1.1 christos int port = cfg->control_port; 248 1.1.1.3 christos int addrfamily = 0; 249 1.1 christos /* use svr or a config entry */ 250 1.1 christos if(!svr) { 251 1.1.1.2 christos if(cfg->control_interface) { 252 1.1 christos svr = cfg->control_interface->address; 253 1.1.1.2 christos } else if(cfg->do_ip4) { 254 1.1.1.2 christos svr = "127.0.0.1"; 255 1.1.1.2 christos } else { 256 1.1.1.2 christos svr = "::1"; 257 1.1.1.2 christos } 258 1.1 christos /* config 0 addr (everything), means ask localhost */ 259 1.1 christos if(strcmp(svr, "0.0.0.0") == 0) 260 1.1 christos svr = "127.0.0.1"; 261 1.1 christos else if(strcmp(svr, "::0") == 0 || 262 1.1 christos strcmp(svr, "0::0") == 0 || 263 1.1 christos strcmp(svr, "0::") == 0 || 264 1.1 christos strcmp(svr, "::") == 0) 265 1.1 christos svr = "::1"; 266 1.1 christos } 267 1.1 christos if(strchr(svr, '@')) { 268 1.1 christos char* ps = strchr(svr, '@'); 269 1.1 christos *ps++ = 0; 270 1.1 christos port = atoi(ps); 271 1.1 christos if(!port) { 272 1.1 christos fprintf(stderr, "could not parse port %s\n", ps); 273 1.1 christos exit(1); 274 1.1 christos } 275 1.1 christos } 276 1.1.1.3 christos if(svr[0] == '/') { 277 1.1.1.3 christos #ifdef HAVE_SYS_UN_H 278 1.1.1.3 christos struct sockaddr_un* usock = (struct sockaddr_un *) &addr; 279 1.1.1.3 christos usock->sun_family = AF_LOCAL; 280 1.1.1.3 christos #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 281 1.1.1.3 christos usock->sun_len = (unsigned)sizeof(usock); 282 1.1.1.3 christos #endif 283 1.1.1.3 christos (void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path)); 284 1.1.1.3 christos addrlen = (socklen_t)sizeof(struct sockaddr_un); 285 1.1.1.3 christos addrfamily = AF_LOCAL; 286 1.1.1.3 christos port = 0; 287 1.1.1.3 christos #endif 288 1.1.1.6 christos #ifdef INET6 289 1.1.1.3 christos } else if(strchr(svr, ':')) { 290 1.1 christos struct sockaddr_in6 sa; 291 1.1 christos addrlen = (socklen_t)sizeof(struct sockaddr_in6); 292 1.1 christos memset(&sa, 0, addrlen); 293 1.1 christos sa.sin6_family = AF_INET6; 294 1.1 christos sa.sin6_port = (in_port_t)htons((uint16_t)port); 295 1.1 christos if(inet_pton((int)sa.sin6_family, svr, &sa.sin6_addr) <= 0) { 296 1.1 christos fprintf(stderr, "could not parse IP: %s\n", svr); 297 1.1 christos exit(1); 298 1.1 christos } 299 1.1 christos memcpy(&addr, &sa, addrlen); 300 1.1.1.3 christos addrfamily = AF_INET6; 301 1.1.1.6 christos #endif 302 1.1 christos } else { /* ip4 */ 303 1.1 christos struct sockaddr_in sa; 304 1.1 christos addrlen = (socklen_t)sizeof(struct sockaddr_in); 305 1.1 christos memset(&sa, 0, addrlen); 306 1.1 christos sa.sin_family = AF_INET; 307 1.1 christos sa.sin_port = (in_port_t)htons((uint16_t)port); 308 1.1 christos if(inet_pton((int)sa.sin_family, svr, &sa.sin_addr) <= 0) { 309 1.1 christos fprintf(stderr, "could not parse IP: %s\n", svr); 310 1.1 christos exit(1); 311 1.1 christos } 312 1.1 christos memcpy(&addr, &sa, addrlen); 313 1.1.1.3 christos addrfamily = AF_INET; 314 1.1 christos } 315 1.1 christos 316 1.1.1.3 christos fd = socket(addrfamily, SOCK_STREAM, 0); 317 1.1 christos if(fd == -1) { 318 1.1 christos fprintf(stderr, "socket: %s\n", strerror(errno)); 319 1.1 christos exit(1); 320 1.1 christos } 321 1.1.1.7 christos if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 322 1.1.1.7 christos fprintf(stderr, "error: set nonblocking: fcntl: %s", 323 1.1.1.7 christos strerror(errno)); 324 1.1.1.7 christos } 325 1.1 christos if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { 326 1.1.1.7 christos if(errno != EINPROGRESS) { 327 1.1.1.7 christos checkconnecterr(errno, svr, port, statuscmd); 328 1.1 christos } 329 1.1.1.7 christos } 330 1.1.1.7 christos while(1) { 331 1.1.1.7 christos fd_set rset, wset, eset; 332 1.1.1.7 christos struct timeval tv; 333 1.1.1.7 christos FD_ZERO(&rset); 334 1.1.1.7 christos FD_SET(fd, &rset); 335 1.1.1.7 christos FD_ZERO(&wset); 336 1.1.1.7 christos FD_SET(fd, &wset); 337 1.1.1.7 christos FD_ZERO(&eset); 338 1.1.1.7 christos FD_SET(fd, &eset); 339 1.1.1.7 christos tv.tv_sec = NSD_CONTROL_CONNECT_TIMEOUT/1000; 340 1.1.1.7 christos tv.tv_usec= (NSD_CONTROL_CONNECT_TIMEOUT%1000)*1000; 341 1.1.1.7 christos if(select(fd+1, &rset, &wset, &eset, &tv) == -1) { 342 1.1.1.7 christos fprintf(stderr, "select: %s\n", strerror(errno)); 343 1.1.1.7 christos exit(1); 344 1.1.1.7 christos } 345 1.1.1.7 christos if(!FD_ISSET(fd, &rset) && !FD_ISSET(fd, &wset) && 346 1.1.1.7 christos !FD_ISSET(fd, &eset)) { 347 1.1.1.7 christos fprintf(stderr, "timeout: could not connect to server\n"); 348 1.1.1.7 christos exit(1); 349 1.1.1.7 christos } else { 350 1.1.1.7 christos /* check nonblocking connect error */ 351 1.1.1.7 christos int error = 0; 352 1.1.1.7 christos socklen_t len = (socklen_t)sizeof(error); 353 1.1.1.7 christos if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, 354 1.1.1.7 christos &len) < 0) { 355 1.1.1.7 christos error = errno; /* on solaris errno is error */ 356 1.1.1.7 christos } 357 1.1.1.7 christos if(error != 0) { 358 1.1.1.7 christos if(error == EINPROGRESS || error == EWOULDBLOCK) 359 1.1.1.7 christos continue; /* try again later */ 360 1.1.1.7 christos checkconnecterr(error, svr, port, statuscmd); 361 1.1.1.7 christos } 362 1.1.1.7 christos } 363 1.1.1.7 christos break; 364 1.1.1.7 christos } 365 1.1.1.7 christos if(fcntl(fd, F_SETFL, 0) == -1) { 366 1.1.1.7 christos fprintf(stderr, "error: set blocking: fcntl: %s", 367 1.1.1.7 christos strerror(errno)); 368 1.1 christos } 369 1.1 christos return fd; 370 1.1 christos } 371 1.1 christos 372 1.1.1.9 christos #ifdef HAVE_SSL 373 1.1 christos /** setup SSL on the connection */ 374 1.1 christos static SSL* 375 1.1 christos setup_ssl(SSL_CTX* ctx, int fd) 376 1.1 christos { 377 1.1 christos SSL* ssl; 378 1.1 christos X509* x; 379 1.1 christos int r; 380 1.1 christos 381 1.1.1.3 christos if(!ctx) return NULL; 382 1.1 christos ssl = SSL_new(ctx); 383 1.1 christos if(!ssl) 384 1.1 christos ssl_err("could not SSL_new"); 385 1.1 christos SSL_set_connect_state(ssl); 386 1.1 christos (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 387 1.1 christos if(!SSL_set_fd(ssl, fd)) 388 1.1 christos ssl_err("could not SSL_set_fd"); 389 1.1 christos while(1) { 390 1.1 christos ERR_clear_error(); 391 1.1 christos if( (r=SSL_do_handshake(ssl)) == 1) 392 1.1 christos break; 393 1.1 christos r = SSL_get_error(ssl, r); 394 1.1 christos if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) 395 1.1 christos ssl_err("SSL handshake failed"); 396 1.1 christos /* wants to be called again */ 397 1.1 christos } 398 1.1 christos 399 1.1 christos /* check authenticity of server */ 400 1.1 christos if(SSL_get_verify_result(ssl) != X509_V_OK) 401 1.1 christos ssl_err("SSL verification failed"); 402 1.1.1.10 christos #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE 403 1.1.1.10 christos x = SSL_get1_peer_certificate(ssl); 404 1.1.1.10 christos #else 405 1.1 christos x = SSL_get_peer_certificate(ssl); 406 1.1.1.10 christos #endif 407 1.1 christos if(!x) 408 1.1 christos ssl_err("Server presented no peer certificate"); 409 1.1 christos X509_free(x); 410 1.1 christos return ssl; 411 1.1 christos } 412 1.1.1.9 christos #endif /* HAVE_SSL */ 413 1.1 christos 414 1.1.1.3 christos /** read from ssl or fd, fatalexit on error, 0 EOF, 1 success */ 415 1.1.1.3 christos static int 416 1.1.1.3 christos remote_read(SSL* ssl, int fd, char* buf, size_t len) 417 1.1.1.3 christos { 418 1.1.1.3 christos if(ssl) { 419 1.1.1.9 christos #ifdef HAVE_SSL 420 1.1.1.3 christos int r; 421 1.1.1.3 christos ERR_clear_error(); 422 1.1.1.3 christos if((r = SSL_read(ssl, buf, (int)len-1)) <= 0) { 423 1.1.1.3 christos if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { 424 1.1.1.3 christos /* EOF */ 425 1.1.1.3 christos return 0; 426 1.1.1.3 christos } 427 1.1.1.3 christos ssl_err("could not SSL_read"); 428 1.1.1.3 christos } 429 1.1.1.3 christos buf[r] = 0; 430 1.1.1.9 christos #endif /* HAVE_SSL */ 431 1.1.1.3 christos } else { 432 1.1.1.3 christos ssize_t rr = read(fd, buf, len-1); 433 1.1.1.3 christos if(rr <= 0) { 434 1.1.1.3 christos if(rr == 0) { 435 1.1.1.3 christos /* EOF */ 436 1.1.1.3 christos return 0; 437 1.1.1.3 christos } 438 1.1.1.3 christos fprintf(stderr, "could not read: %s\n", 439 1.1.1.3 christos strerror(errno)); 440 1.1.1.3 christos exit(1); 441 1.1.1.3 christos } 442 1.1.1.3 christos buf[rr] = 0; 443 1.1.1.3 christos } 444 1.1.1.3 christos return 1; 445 1.1.1.3 christos } 446 1.1.1.3 christos 447 1.1.1.3 christos /** write to ssl or fd, fatalexit on error */ 448 1.1.1.3 christos static void 449 1.1.1.3 christos remote_write(SSL* ssl, int fd, const char* buf, size_t len) 450 1.1.1.3 christos { 451 1.1.1.3 christos if(ssl) { 452 1.1.1.9 christos #ifdef HAVE_SSL 453 1.1.1.3 christos if(SSL_write(ssl, buf, (int)len) <= 0) 454 1.1.1.3 christos ssl_err("could not SSL_write"); 455 1.1.1.9 christos #endif /* HAVE_SSL */ 456 1.1.1.3 christos } else { 457 1.1.1.3 christos if(write(fd, buf, len) < (ssize_t)len) { 458 1.1.1.3 christos fprintf(stderr, "could not write: %s\n", 459 1.1.1.3 christos strerror(errno)); 460 1.1.1.3 christos exit(1); 461 1.1.1.3 christos } 462 1.1.1.3 christos } 463 1.1.1.3 christos } 464 1.1.1.3 christos 465 1.1 christos /** send stdin to server */ 466 1.1 christos static void 467 1.1.1.3 christos send_file(SSL* ssl, int fd, FILE* in, char* buf, size_t sz) 468 1.1 christos { 469 1.1 christos char e[] = {0x04, 0x0a}; 470 1.1 christos while(fgets(buf, (int)sz, in)) { 471 1.1.1.3 christos remote_write(ssl, fd, buf, strlen(buf)); 472 1.1 christos } 473 1.1 christos /* send end-of-file marker */ 474 1.1.1.3 christos remote_write(ssl, fd, e, sizeof(e)); 475 1.1 christos } 476 1.1 christos 477 1.1 christos /** send command and display result */ 478 1.1 christos static int 479 1.1.1.3 christos go_cmd(SSL* ssl, int fd, int argc, char* argv[]) 480 1.1 christos { 481 1.1 christos char pre[10]; 482 1.1 christos const char* space=" "; 483 1.1 christos const char* newline="\n"; 484 1.1 christos int was_error = 0, first_line = 1; 485 1.1.1.3 christos int i; 486 1.1 christos char buf[1024]; 487 1.1 christos snprintf(pre, sizeof(pre), "NSDCT%d ", NSD_CONTROL_VERSION); 488 1.1.1.3 christos remote_write(ssl, fd, pre, strlen(pre)); 489 1.1 christos for(i=0; i<argc; i++) { 490 1.1.1.3 christos remote_write(ssl, fd, space, strlen(space)); 491 1.1.1.3 christos remote_write(ssl, fd, argv[i], strlen(argv[i])); 492 1.1 christos } 493 1.1.1.3 christos remote_write(ssl, fd, newline, strlen(newline)); 494 1.1 christos 495 1.1 christos /* send contents to server */ 496 1.1 christos if(argc == 1 && (strcmp(argv[0], "addzones") == 0 || 497 1.1 christos strcmp(argv[0], "delzones") == 0)) { 498 1.1.1.3 christos send_file(ssl, fd, stdin, buf, sizeof(buf)); 499 1.1 christos } 500 1.1 christos 501 1.1 christos while(1) { 502 1.1.1.3 christos if(remote_read(ssl, fd, buf, sizeof(buf)) == 0) { 503 1.1.1.3 christos break; /* EOF */ 504 1.1 christos } 505 1.1 christos printf("%s", buf); 506 1.1 christos if(first_line && strncmp(buf, "error", 5) == 0) 507 1.1 christos was_error = 1; 508 1.1 christos first_line = 0; 509 1.1 christos } 510 1.1 christos return was_error; 511 1.1 christos } 512 1.1 christos 513 1.1 christos /** go ahead and read config, contact server and perform command and display */ 514 1.1 christos static int 515 1.1 christos go(const char* cfgfile, char* svr, int argc, char* argv[]) 516 1.1 christos { 517 1.1.1.2 christos struct nsd_options* opt; 518 1.1 christos int fd, ret; 519 1.1.1.9 christos #ifdef HAVE_SSL 520 1.1.1.9 christos SSL_CTX* ctx = NULL; 521 1.1.1.9 christos #endif 522 1.1.1.9 christos SSL* ssl = NULL; 523 1.1 christos 524 1.1 christos /* read config */ 525 1.1 christos if(!(opt = nsd_options_create(region_create(xalloc, free)))) { 526 1.1 christos fprintf(stderr, "out of memory\n"); 527 1.1 christos exit(1); 528 1.1 christos } 529 1.1 christos tsig_init(opt->region); 530 1.1.1.10 christos if(!parse_options_file(opt, cfgfile, NULL, NULL, NULL)) { 531 1.1 christos fprintf(stderr, "could not read config file\n"); 532 1.1 christos exit(1); 533 1.1 christos } 534 1.1 christos if(!opt->control_enable) 535 1.1 christos fprintf(stderr, "warning: control-enable is 'no' in the config file.\n"); 536 1.1.1.8 christos resolve_interface_names(opt); 537 1.1.1.9 christos #ifdef HAVE_SSL 538 1.1 christos ctx = setup_ctx(opt); 539 1.1.1.9 christos #else 540 1.1.1.9 christos if(options_remote_is_address(opt)) { 541 1.1.1.9 christos fprintf(stderr, "error: NSD was compiled without SSL.\n"); 542 1.1.1.9 christos exit(1); 543 1.1.1.9 christos } 544 1.1.1.9 christos #endif /* HAVE_SSL */ 545 1.1 christos 546 1.1 christos /* contact server */ 547 1.1 christos fd = contact_server(svr, opt, argc>0&&strcmp(argv[0],"status")==0); 548 1.1.1.9 christos #ifdef HAVE_SSL 549 1.1 christos ssl = setup_ssl(ctx, fd); 550 1.1.1.9 christos #endif 551 1.1 christos 552 1.1 christos /* send command */ 553 1.1.1.3 christos ret = go_cmd(ssl, fd, argc, argv); 554 1.1 christos 555 1.1.1.9 christos #ifdef HAVE_SSL 556 1.1.1.3 christos if(ssl) SSL_free(ssl); 557 1.1.1.9 christos #endif 558 1.1 christos close(fd); 559 1.1.1.9 christos #ifdef HAVE_SSL 560 1.1.1.3 christos if(ctx) SSL_CTX_free(ctx); 561 1.1.1.9 christos #endif 562 1.1 christos region_destroy(opt->region); 563 1.1 christos return ret; 564 1.1 christos } 565 1.1 christos 566 1.1 christos /** getopt global, in case header files fail to declare it. */ 567 1.1 christos extern int optind; 568 1.1 christos /** getopt global, in case header files fail to declare it. */ 569 1.1 christos extern char* optarg; 570 1.1 christos 571 1.1 christos /** Main routine for nsd-control */ 572 1.1 christos int main(int argc, char* argv[]) 573 1.1 christos { 574 1.1 christos int c; 575 1.1 christos const char* cfgfile = CONFIGFILE; 576 1.1 christos char* svr = NULL; 577 1.1 christos log_init("nsd-control"); 578 1.1 christos 579 1.1.1.9 christos #ifdef HAVE_SSL 580 1.1 christos #ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS 581 1.1 christos ERR_load_crypto_strings(); 582 1.1 christos #endif 583 1.1.1.8 christos #if defined(HAVE_ERR_LOAD_SSL_STRINGS) && !defined(DEPRECATED_ERR_LOAD_SSL_STRINGS) 584 1.1 christos ERR_load_SSL_strings(); 585 1.1.1.8 christos #endif 586 1.1 christos #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) 587 1.1 christos OpenSSL_add_all_algorithms(); 588 1.1 christos #else 589 1.1 christos OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS 590 1.1 christos | OPENSSL_INIT_ADD_ALL_DIGESTS 591 1.1 christos | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); 592 1.1 christos #endif 593 1.1 christos #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) 594 1.1 christos (void)SSL_library_init(); 595 1.1 christos #else 596 1.1 christos OPENSSL_init_ssl(0, NULL); 597 1.1 christos #endif 598 1.1 christos 599 1.1 christos if(!RAND_status()) { 600 1.1 christos /* try to seed it */ 601 1.1 christos unsigned char buf[256]; 602 1.1 christos unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid(); 603 1.1 christos size_t i; 604 1.1 christos v = seed; 605 1.1 christos for(i=0; i<256/sizeof(v); i++) { 606 1.1 christos memmove(buf+i*sizeof(v), &v, sizeof(v)); 607 1.1 christos v = v*seed + (unsigned int)i; 608 1.1 christos } 609 1.1 christos RAND_seed(buf, 256); 610 1.1 christos fprintf(stderr, "warning: no entropy, seeding openssl PRNG with time\n"); 611 1.1 christos } 612 1.1.1.9 christos #endif /* HAVE_SSL */ 613 1.1 christos 614 1.1 christos /* parse the options */ 615 1.1 christos while( (c=getopt(argc, argv, "c:s:h")) != -1) { 616 1.1 christos switch(c) { 617 1.1 christos case 'c': 618 1.1 christos cfgfile = optarg; 619 1.1 christos break; 620 1.1 christos case 's': 621 1.1 christos svr = optarg; 622 1.1 christos break; 623 1.1 christos case '?': 624 1.1 christos case 'h': 625 1.1 christos default: 626 1.1 christos usage(); 627 1.1 christos } 628 1.1 christos } 629 1.1 christos argc -= optind; 630 1.1 christos argv += optind; 631 1.1 christos if(argc == 0) 632 1.1 christos usage(); 633 1.1 christos if(argc >= 1 && strcmp(argv[0], "start")==0) { 634 1.1.1.8 christos const char *path; 635 1.1.1.8 christos if((path = getenv("NSD_PATH")) == NULL) { 636 1.1.1.8 christos path = NSD_START_PATH; 637 1.1.1.8 christos } 638 1.1.1.8 christos if(execl(path, "nsd", "-c", cfgfile, (char*)NULL) < 0) { 639 1.1 christos fprintf(stderr, "could not exec %s: %s\n", 640 1.1 christos NSD_START_PATH, strerror(errno)); 641 1.1 christos exit(1); 642 1.1 christos } 643 1.1 christos } 644 1.1 christos 645 1.1 christos return go(cfgfile, svr, argc, argv); 646 1.1 christos } 647