1 /* 2 * checkconf/unbound-control.c - remote control utility for unbound. 3 * 4 * Copyright (c) 2008, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /** 37 * \file 38 * 39 * The remote control utility contacts the unbound server over ssl and 40 * sends the command, receives the answer, and displays the result 41 * from the commandline. 42 */ 43 44 #include "config.h" 45 #ifdef HAVE_GETOPT_H 46 #include <getopt.h> 47 #endif 48 #ifdef HAVE_OPENSSL_SSL_H 49 #include <openssl/ssl.h> 50 #endif 51 #ifdef HAVE_OPENSSL_ERR_H 52 #include <openssl/err.h> 53 #endif 54 #ifdef HAVE_OPENSSL_RAND_H 55 #include <openssl/rand.h> 56 #endif 57 #include "util/log.h" 58 #include "util/config_file.h" 59 #include "util/locks.h" 60 #include "util/net_help.h" 61 62 #ifdef HAVE_SYS_UN_H 63 #include <sys/un.h> 64 #endif 65 66 /** Give unbound-control usage, and exit (1). */ 67 static void 68 usage() 69 { 70 printf("Usage: unbound-control [options] command\n"); 71 printf(" Remote control utility for unbound server.\n"); 72 printf("Options:\n"); 73 printf(" -c file config file, default is %s\n", CONFIGFILE); 74 printf(" -s ip[@port] server address, if omitted config is used.\n"); 75 printf(" -q quiet (don't print anything if it works ok).\n"); 76 printf(" -h show this usage help.\n"); 77 printf("Commands:\n"); 78 printf(" start start server; runs unbound(8)\n"); 79 printf(" stop stops the server\n"); 80 printf(" reload reloads the server\n"); 81 printf(" (this flushes data, stats, requestlist)\n"); 82 printf(" stats print statistics\n"); 83 printf(" stats_noreset peek at statistics\n"); 84 printf(" status display status of server\n"); 85 printf(" verbosity <number> change logging detail\n"); 86 printf(" log_reopen close and open the logfile\n"); 87 printf(" local_zone <name> <type> add new local zone\n"); 88 printf(" local_zone_remove <name> remove local zone and its contents\n"); 89 printf(" local_data <RR data...> add local data, for example\n"); 90 printf(" local_data www.example.com A 192.0.2.1\n"); 91 printf(" local_data_remove <name> remove local RR data from name\n"); 92 printf(" dump_cache print cache to stdout\n"); 93 printf(" load_cache load cache from stdin\n"); 94 printf(" lookup <name> print nameservers for name\n"); 95 printf(" flush <name> flushes common types for name from cache\n"); 96 printf(" types: A, AAAA, MX, PTR, NS,\n"); 97 printf(" SOA, CNAME, DNAME, SRV, NAPTR\n"); 98 printf(" flush_type <name> <type> flush name, type from cache\n"); 99 printf(" flush_zone <name> flush everything at or under name\n"); 100 printf(" from rr and dnssec caches\n"); 101 printf(" flush_bogus flush all bogus data\n"); 102 printf(" flush_negative flush all negative data\n"); 103 printf(" flush_stats flush statistics, make zero\n"); 104 printf(" flush_requestlist drop queries that are worked on\n"); 105 printf(" dump_requestlist show what is worked on\n"); 106 printf(" flush_infra [all | ip] remove ping, edns for one IP or all\n"); 107 printf(" dump_infra show ping and edns entries\n"); 108 printf(" set_option opt: val set option to value, no reload\n"); 109 printf(" get_option opt get option value\n"); 110 printf(" list_stubs list stub-zones and root hints in use\n"); 111 printf(" list_forwards list forward-zones in use\n"); 112 printf(" list_local_zones list local-zones in use\n"); 113 printf(" list_local_data list local-data RRs in use\n"); 114 printf(" insecure_add zone add domain-insecure zone\n"); 115 printf(" insecure_remove zone remove domain-insecure zone\n"); 116 printf(" forward_add [+i] zone addr.. add forward-zone with servers\n"); 117 printf(" forward_remove [+i] zone remove forward zone\n"); 118 printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n"); 119 printf(" stub_remove [+i] zone remove stub zone\n"); 120 printf(" +i also do dnssec insecure point\n"); 121 printf(" +p set stub to use priming\n"); 122 printf(" forward [off | addr ...] without arg show forward setup\n"); 123 printf(" or off to turn off root forwarding\n"); 124 printf(" or give list of ip addresses\n"); 125 printf("Version %s\n", PACKAGE_VERSION); 126 printf("BSD licensed, see LICENSE in source package for details.\n"); 127 printf("Report bugs to %s\n", PACKAGE_BUGREPORT); 128 exit(1); 129 } 130 131 /** exit with ssl error */ 132 static void ssl_err(const char* s) 133 { 134 fprintf(stderr, "error: %s\n", s); 135 ERR_print_errors_fp(stderr); 136 exit(1); 137 } 138 139 /** setup SSL context */ 140 static SSL_CTX* 141 setup_ctx(struct config_file* cfg) 142 { 143 char* s_cert=NULL, *c_key=NULL, *c_cert=NULL; 144 SSL_CTX* ctx; 145 146 if(cfg->remote_control_use_cert) { 147 s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1); 148 c_key = fname_after_chroot(cfg->control_key_file, cfg, 1); 149 c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1); 150 if(!s_cert || !c_key || !c_cert) 151 fatal_exit("out of memory"); 152 } 153 ctx = SSL_CTX_new(SSLv23_client_method()); 154 if(!ctx) 155 ssl_err("could not allocate SSL_CTX pointer"); 156 if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) 157 ssl_err("could not set SSL_OP_NO_SSLv2"); 158 if(cfg->remote_control_use_cert) { 159 if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)) 160 ssl_err("could not set SSL_OP_NO_SSLv3"); 161 if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) || 162 !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM) 163 || !SSL_CTX_check_private_key(ctx)) 164 ssl_err("Error setting up SSL_CTX client key and cert"); 165 if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1) 166 ssl_err("Error setting up SSL_CTX verify, server cert"); 167 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 168 169 free(s_cert); 170 free(c_key); 171 free(c_cert); 172 } else { 173 /* Use ciphers that don't require authentication */ 174 if(!SSL_CTX_set_cipher_list(ctx, "aNULL")) 175 ssl_err("Error setting NULL cipher!"); 176 } 177 return ctx; 178 } 179 180 /** contact the server with TCP connect */ 181 static int 182 contact_server(const char* svr, struct config_file* cfg, int statuscmd) 183 { 184 struct sockaddr_storage addr; 185 socklen_t addrlen; 186 int addrfamily = 0; 187 int fd; 188 /* use svr or the first config entry */ 189 if(!svr) { 190 if(cfg->control_ifs) 191 svr = cfg->control_ifs->str; 192 else svr = "127.0.0.1"; 193 /* config 0 addr (everything), means ask localhost */ 194 if(strcmp(svr, "0.0.0.0") == 0) 195 svr = "127.0.0.1"; 196 else if(strcmp(svr, "::0") == 0 || 197 strcmp(svr, "0::0") == 0 || 198 strcmp(svr, "0::") == 0 || 199 strcmp(svr, "::") == 0) 200 svr = "::1"; 201 } 202 if(strchr(svr, '@')) { 203 if(!extstrtoaddr(svr, &addr, &addrlen)) 204 fatal_exit("could not parse IP@port: %s", svr); 205 #ifdef HAVE_SYS_UN_H 206 } else if(svr[0] == '/') { 207 struct sockaddr_un* usock = (struct sockaddr_un *) &addr; 208 usock->sun_family = AF_LOCAL; 209 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 210 usock->sun_len = (socklen_t)sizeof(usock); 211 #endif 212 (void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path)); 213 addrlen = (socklen_t)sizeof(struct sockaddr_un); 214 addrfamily = AF_LOCAL; 215 #endif 216 } else { 217 if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen)) 218 fatal_exit("could not parse IP: %s", svr); 219 } 220 221 if(addrfamily == 0) 222 addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET; 223 fd = socket(addrfamily, SOCK_STREAM, 0); 224 if(fd == -1) { 225 #ifndef USE_WINSOCK 226 fatal_exit("socket: %s", strerror(errno)); 227 #else 228 fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); 229 #endif 230 } 231 if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { 232 #ifndef USE_WINSOCK 233 log_err_addr("connect", strerror(errno), &addr, addrlen); 234 if(errno == ECONNREFUSED && statuscmd) { 235 printf("unbound is stopped\n"); 236 exit(3); 237 } 238 #else 239 log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen); 240 if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) { 241 printf("unbound is stopped\n"); 242 exit(3); 243 } 244 #endif 245 exit(1); 246 } 247 return fd; 248 } 249 250 /** setup SSL on the connection */ 251 static SSL* 252 setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg) 253 { 254 SSL* ssl; 255 X509* x; 256 int r; 257 258 ssl = SSL_new(ctx); 259 if(!ssl) 260 ssl_err("could not SSL_new"); 261 SSL_set_connect_state(ssl); 262 (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 263 if(!SSL_set_fd(ssl, fd)) 264 ssl_err("could not SSL_set_fd"); 265 while(1) { 266 ERR_clear_error(); 267 if( (r=SSL_do_handshake(ssl)) == 1) 268 break; 269 r = SSL_get_error(ssl, r); 270 if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) 271 ssl_err("SSL handshake failed"); 272 /* wants to be called again */ 273 } 274 275 /* check authenticity of server */ 276 if(SSL_get_verify_result(ssl) != X509_V_OK) 277 ssl_err("SSL verification failed"); 278 if(cfg->remote_control_use_cert) { 279 x = SSL_get_peer_certificate(ssl); 280 if(!x) 281 ssl_err("Server presented no peer certificate"); 282 X509_free(x); 283 } 284 285 return ssl; 286 } 287 288 /** send stdin to server */ 289 static void 290 send_file(SSL* ssl, FILE* in, char* buf, size_t sz) 291 { 292 while(fgets(buf, (int)sz, in)) { 293 if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0) 294 ssl_err("could not SSL_write contents"); 295 } 296 } 297 298 /** send command and display result */ 299 static int 300 go_cmd(SSL* ssl, int quiet, int argc, char* argv[]) 301 { 302 char pre[10]; 303 const char* space=" "; 304 const char* newline="\n"; 305 int was_error = 0, first_line = 1; 306 int r, i; 307 char buf[1024]; 308 snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION); 309 if(SSL_write(ssl, pre, (int)strlen(pre)) <= 0) 310 ssl_err("could not SSL_write"); 311 for(i=0; i<argc; i++) { 312 if(SSL_write(ssl, space, (int)strlen(space)) <= 0) 313 ssl_err("could not SSL_write"); 314 if(SSL_write(ssl, argv[i], (int)strlen(argv[i])) <= 0) 315 ssl_err("could not SSL_write"); 316 } 317 if(SSL_write(ssl, newline, (int)strlen(newline)) <= 0) 318 ssl_err("could not SSL_write"); 319 320 if(argc == 1 && strcmp(argv[0], "load_cache") == 0) { 321 send_file(ssl, stdin, buf, sizeof(buf)); 322 } 323 324 while(1) { 325 ERR_clear_error(); 326 if((r = SSL_read(ssl, buf, (int)sizeof(buf)-1)) <= 0) { 327 if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { 328 /* EOF */ 329 break; 330 } 331 ssl_err("could not SSL_read"); 332 } 333 buf[r] = 0; 334 if(first_line && strncmp(buf, "error", 5) == 0) { 335 printf("%s", buf); 336 was_error = 1; 337 } else if (!quiet) 338 printf("%s", buf); 339 340 first_line = 0; 341 } 342 return was_error; 343 } 344 345 /** go ahead and read config, contact server and perform command and display */ 346 static int 347 go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[]) 348 { 349 struct config_file* cfg; 350 int fd, ret; 351 SSL_CTX* ctx; 352 SSL* ssl; 353 354 /* read config */ 355 if(!(cfg = config_create())) 356 fatal_exit("out of memory"); 357 if(!config_read(cfg, cfgfile, NULL)) 358 fatal_exit("could not read config file"); 359 if(!cfg->remote_control_enable) 360 log_warn("control-enable is 'no' in the config file."); 361 ctx = setup_ctx(cfg); 362 363 /* contact server */ 364 fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0); 365 ssl = setup_ssl(ctx, fd, cfg); 366 367 /* send command */ 368 ret = go_cmd(ssl, quiet, argc, argv); 369 370 SSL_free(ssl); 371 #ifndef USE_WINSOCK 372 close(fd); 373 #else 374 closesocket(fd); 375 #endif 376 SSL_CTX_free(ctx); 377 config_delete(cfg); 378 return ret; 379 } 380 381 /** getopt global, in case header files fail to declare it. */ 382 extern int optind; 383 /** getopt global, in case header files fail to declare it. */ 384 extern char* optarg; 385 386 /** Main routine for unbound-control */ 387 int main(int argc, char* argv[]) 388 { 389 int c, ret; 390 int quiet = 0; 391 const char* cfgfile = CONFIGFILE; 392 char* svr = NULL; 393 #ifdef USE_WINSOCK 394 int r; 395 WSADATA wsa_data; 396 #endif 397 #ifdef USE_THREAD_DEBUG 398 /* stop the file output from unbound-control, overwites the servers */ 399 extern int check_locking_order; 400 check_locking_order = 0; 401 #endif /* USE_THREAD_DEBUG */ 402 log_ident_set("unbound-control"); 403 log_init(NULL, 0, NULL); 404 checklock_start(); 405 #ifdef USE_WINSOCK 406 if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) 407 fatal_exit("WSAStartup failed: %s", wsa_strerror(r)); 408 /* use registry config file in preference to compiletime location */ 409 if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile"))) 410 cfgfile = CONFIGFILE; 411 #endif 412 413 ERR_load_crypto_strings(); 414 ERR_load_SSL_strings(); 415 OpenSSL_add_all_algorithms(); 416 (void)SSL_library_init(); 417 418 if(!RAND_status()) { 419 /* try to seed it */ 420 unsigned char buf[256]; 421 unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid(); 422 unsigned int v = seed; 423 size_t i; 424 for(i=0; i<256/sizeof(v); i++) { 425 memmove(buf+i*sizeof(v), &v, sizeof(v)); 426 v = v*seed + (unsigned int)i; 427 } 428 RAND_seed(buf, 256); 429 log_warn("no entropy, seeding openssl PRNG with time\n"); 430 } 431 432 /* parse the options */ 433 while( (c=getopt(argc, argv, "c:s:qh")) != -1) { 434 switch(c) { 435 case 'c': 436 cfgfile = optarg; 437 break; 438 case 's': 439 svr = optarg; 440 break; 441 case 'q': 442 quiet = 1; 443 break; 444 case '?': 445 case 'h': 446 default: 447 usage(); 448 } 449 } 450 argc -= optind; 451 argv += optind; 452 if(argc == 0) 453 usage(); 454 if(argc >= 1 && strcmp(argv[0], "start")==0) { 455 if(execlp("unbound", "unbound", "-c", cfgfile, 456 (char*)NULL) < 0) { 457 fatal_exit("could not exec unbound: %s", 458 strerror(errno)); 459 } 460 } 461 462 ret = go(cfgfile, svr, quiet, argc, argv); 463 464 #ifdef USE_WINSOCK 465 WSACleanup(); 466 #endif 467 checklock_stop(); 468 return ret; 469 } 470