00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00031 #include "nufw.h"
00032
00033 #include <linux/netfilter.h>
00034 #include <unistd.h>
00035 #include <pthread.h>
00036 #include <netdb.h>
00037 #include <signal.h>
00038 #include <syslog.h>
00039 #include <errno.h>
00040 #include <sys/types.h>
00041
00042 #include <nubase.h>
00043
00044 GCRY_THREAD_OPTION_PTHREAD_IMPL;
00045
00046 char *key_file = NULL;
00047 char *cert_file = NULL;
00048
00049
00050 struct nufw_threadtype thread;
00051
00052
00053 struct nufw_signals signals;
00054
00057 #define NUFW_PID_FILE LOCAL_STATE_DIR "/run/nufw.pid"
00058
00062 void nufw_stop_thread()
00063 {
00064
00065 pthread_mutex_lock(&tls.auth_server_mutex);
00066 pthread_mutex_lock(&thread.mutex);
00067
00068
00069 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_MESSAGE,
00070 "Wait threads end");
00071 if (tls.auth_server_running) {
00072 pthread_join(tls.auth_server, NULL);
00073 }
00074 pthread_mutex_unlock(&tls.auth_server_mutex);
00075 pthread_join(thread.thread, NULL);
00076 pthread_mutex_unlock(&thread.mutex);
00077 }
00078
00082 void nufw_prepare_quit()
00083 {
00084
00085
00086 clear_packet_list();
00087 pthread_mutex_destroy(&packets_list.mutex);
00088
00089
00090 close_tls_session();
00091 pthread_mutex_destroy(&tls.mutex);
00092
00093
00094 #ifdef HAVE_LIBCONNTRACK
00095 nfct_close(cth);
00096 #endif
00097
00098
00099 free(key_file);
00100 free(cert_file);
00101 free(ca_file);
00102 free(crl_file);
00103 freeaddrinfo(adr_srv);
00104
00105
00106 unlink(NUFW_PID_FILE);
00107 }
00108
00113 void nufw_hard_cleanup(int signal)
00114 {
00115
00116 (void) sigaction(SIGTERM, &signals.old_sigterm_hdl, NULL);
00117 (void) sigaction(SIGINT, &signals.old_sigint_hdl, NULL);
00118
00119 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00120 "[+] NuFW \"hard\" cleanup (catch double signal)");
00121 nufw_prepare_quit();
00122 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00123 "[+] Exit NuFW");
00124 exit(EXIT_SUCCESS);
00125 }
00126
00134 void nufw_cleanup(int signal)
00135 {
00136 struct sigaction action;
00137
00138
00139 memset(&action, 0, sizeof(action));
00140 action.sa_handler = nufw_hard_cleanup;
00141 sigemptyset(&(action.sa_mask));
00142 action.sa_flags = 0;
00143 sigaction(SIGTERM, &action, NULL);
00144
00145
00146 memset(&action, 0, sizeof(action));
00147 action.sa_handler = nufw_hard_cleanup;
00148 sigemptyset(&(action.sa_mask));
00149 action.sa_flags = 0;
00150 sigaction(SIGINT, &action, NULL);
00151
00152 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00153 "[+] Stop NuFW (catch signal)");
00154 nufw_stop_thread();
00155 nufw_prepare_quit();
00156 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00157 "[+] Exit NuFW");
00158 exit(EXIT_SUCCESS);
00159 }
00160
00166 void create_thread()
00167 {
00168
00169 static struct nufw_threadargument arg;
00170 arg.thread = &thread;
00171 arg.parent_pid = getpid();
00172
00173
00174 pthread_attr_t attr;
00175 pthread_attr_init(&attr);
00176 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00177
00178
00179 pthread_mutex_init(&thread.mutex, NULL);
00180
00181
00182 if (pthread_create(&thread.thread, &attr, packetsrv, &arg) != 0) {
00183 pthread_mutex_destroy(&thread.mutex);
00184 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00185 "Fail to create thread!");
00186 exit(EXIT_FAILURE);
00187 }
00188 #ifdef HAVE_LIBCONNTRACK
00189 if (handle_conntrack_event) {
00190 if (pthread_create
00191 (&(tls.conntrack_event_handler), NULL,
00192 conntrack_event_handler, NULL) == EAGAIN) {
00193 exit(EXIT_FAILURE);
00194 }
00195 }
00196 #endif
00197
00198 }
00199
00209 void install_signals()
00210 {
00211 struct sigaction action;
00212
00213
00214 memset(&action, 0, sizeof(action));
00215 action.sa_handler = nufw_cleanup;
00216 sigemptyset(&(action.sa_mask));
00217 action.sa_flags = 0;
00218 if (sigaction(SIGTERM, &action, &signals.old_sigterm_hdl) != 0) {
00219 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00220 "Fail to install SIGTERM handler: %d \n",
00221 errno);
00222 exit(EXIT_FAILURE);
00223 }
00224
00225
00226 memset(&action, 0, sizeof(action));
00227 action.sa_handler = nufw_cleanup;
00228 sigemptyset(&(action.sa_mask));
00229 action.sa_flags = 0;
00230 if (sigaction(SIGINT, &action, &signals.old_sigint_hdl) != 0) {
00231 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00232 "Fail to install SIGINT handler: %d \n",
00233 errno);
00234 exit(EXIT_FAILURE);
00235 }
00236
00237
00238 signal(SIGPIPE, SIG_IGN);
00239
00240
00241 memset(&action, 0, sizeof(action));
00242 action.sa_handler = &process_usr1;
00243 action.sa_flags = SIGUSR1;
00244 if (sigaction(SIGUSR1, &action, NULL) == -1) {
00245 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
00246 "Warning: Could not set signal USR1");
00247 }
00248
00249
00250 memset(&action, 0, sizeof(action));
00251 action.sa_handler = &process_usr2;
00252 action.sa_flags = SIGUSR2;
00253 if (sigaction(SIGUSR2, &action, NULL) == -1) {
00254 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
00255 "Warning: Could not set signal USR2");
00256 }
00257
00258
00259 memset(&action, 0, sizeof(action));
00260 action.sa_handler = &process_poll;
00261 action.sa_flags = SIGPOLL;
00262 if (sigaction(SIGPOLL, &action, NULL) == -1) {
00263 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
00264 "Warning: Could not set signal POLL");
00265 }
00266
00267
00268 memset(&action, 0, sizeof(action));
00269 action.sa_handler = &process_hup;
00270 action.sa_flags = SIGHUP;
00271 if (sigaction(SIGHUP, &action, NULL) == -1) {
00272 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_WARNING,
00273 "Warning: Could not set signal HUP");
00274 }
00275 }
00276
00280 void nufw_daemonize()
00281 {
00282 FILE *pf;
00283 pid_t pidf;
00284
00285 if (access(NUFW_PID_FILE, R_OK) == 0) {
00286
00287 pid_t pidv;
00288
00289 pf = fopen(NUFW_PID_FILE, "r");
00290 if (pf != NULL &&
00291 fscanf(pf, "%d", &pidv) == 1 && kill(pidv, 0) == 0) {
00292 fclose(pf);
00293 printf
00294 ("pid file exists. Is nufw already running? Aborting!\n");
00295 exit(EXIT_FAILURE);
00296 }
00297
00298 if (pf != NULL)
00299 fclose(pf);
00300 }
00301
00302 pidf = fork();
00303 if (pidf < 0) {
00304 log_printf(DEBUG_LEVEL_FATAL, "Unable to fork. Aborting!");
00305 exit(-1);
00306 } else {
00307
00308 if (pidf > 0) {
00309 if ((pf = fopen(NUFW_PID_FILE, "w")) != NULL) {
00310 fprintf(pf, "%d\n", (int) pidf);
00311 fclose(pf);
00312 } else {
00313 printf("Dying, can not create PID file : "
00314 NUFW_PID_FILE "\n");
00315 exit(EXIT_FAILURE);
00316 }
00317 exit(EXIT_SUCCESS);
00318 }
00319 }
00320
00321 chdir("/");
00322
00323 setsid();
00324
00325
00326 log_engine = LOG_TO_SYSLOG;
00327
00328
00329 (void) close(0);
00330 (void) close(1);
00331 (void) close(2);
00332 }
00333
00334
00339 int init_checks()
00340 {
00341 #if USE_X509
00342 if (!init_x509_filenames()) {
00343 printf("ERROR: Unable to allocate memory for "
00344 "key or cert filename!\n");
00345 return 0;
00346 }
00347 if (access(key_file, R_OK)) {
00348 printf("ERROR: Unable to read key file: %s\n", key_file);
00349 return 0;
00350 }
00351 if (access(cert_file, R_OK)) {
00352 printf("ERROR: Unable to read key file: %s\n", cert_file);
00353 return 0;
00354 }
00355 #endif
00356 return 1;
00357 }
00358
00359
00385 int main(int argc, char *argv[])
00386 {
00387
00388 #if USE_NFQUEUE
00389 char *options_list = "4sSDhVvmq:"
00390 #ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
00391 "L:"
00392 #endif
00393 "c:k:a:n:r:d:p:t:T:A:"
00394 #ifdef HAVE_LIBCONNTRACK
00395 "CM"
00396 #endif
00397 ;
00398 #else
00399 char *options_list = "4sSDhVvmc:k:a:n:r:d:p:t:T:A:";
00400 #endif
00401 int option, daemonize = 0;
00402 char *version = PACKAGE_VERSION;
00403 nufw_no_ipv6 = 0;
00404
00405
00406
00407 log_engine = LOG_TO_STD;
00408 authreq_port = AUTHREQ_PORT;
00409 packet_timeout = PACKET_TIMEOUT;
00410 track_size = TRACK_SIZE;
00411 cert_file = NULL;
00412 key_file = NULL;
00413 ca_file = NULL;
00414 crl_file = NULL;
00415 nuauth_cert_dn = NULL;
00416 SECURE_STRNCPY(authreq_addr, AUTHREQ_ADDR, sizeof authreq_addr);
00417 debug_level = DEFAULT_DEBUG_LEVEL;
00418 debug_areas = DEFAULT_DEBUG_AREAS;
00419 #if USE_NFQUEUE
00420 nfqueue_num = DEFAULT_NFQUEUE;
00421 #ifdef HAVE_LIBCONNTRACK
00422 handle_conntrack_event = CONNTRACK_HANDLE_DEFAULT;
00423 nufw_conntrack_uses_mark = 0;
00424 #endif
00425 #ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
00426
00427 queue_maxlen = QUEUE_MAXLEN;
00428 #endif
00429 #endif
00430 nufw_set_mark = 0;
00431 nufw_strict_tls = 1;
00432
00433
00434 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_VERBOSE_DEBUG,
00435 "[+] Start NuFW");
00436
00437
00438 while ((option = getopt(argc, argv, options_list)) != -1) {
00439 switch (option) {
00440 case 'k':
00441 key_file = strdup(optarg);
00442 if (key_file == NULL) {
00443 fprintf(stderr,
00444 "Couldn't malloc! Exiting");
00445 exit(EXIT_FAILURE);
00446 }
00447 break;
00448 case 'c':
00449 cert_file = strdup(optarg);
00450 if (cert_file == NULL) {
00451 fprintf(stderr,
00452 "Couldn't malloc! Exiting");
00453 exit(EXIT_FAILURE);
00454 }
00455 break;
00456 case 'a':
00457 ca_file = strdup(optarg);
00458 if (ca_file == NULL) {
00459 fprintf(stderr,
00460 "Couldn't malloc! Exiting");
00461 exit(EXIT_FAILURE);
00462 }
00463 break;
00464 case 'r':
00465 crl_file = strdup(optarg);
00466 if (crl_file == NULL) {
00467 fprintf(stderr,
00468 "Couldn't malloc! Exiting");
00469 exit(EXIT_FAILURE);
00470 }
00471 break;
00472 case 'n':
00473 nuauth_cert_dn = strdup(optarg);
00474 if (nuauth_cert_dn == NULL) {
00475 fprintf(stderr,
00476 "Couldn't malloc! Exiting");
00477 exit(EXIT_FAILURE);
00478 }
00479 break;
00480 case 'V':
00481 fprintf(stdout, "%s (version %s)\n", PACKAGE_NAME,
00482 version);
00483 return 1;
00484 case 'D':
00485 daemonize = 1;
00486 break;
00487 case 'v':
00488
00489 debug_level += 1;
00490 break;
00491 case 'p':
00492 authreq_port = atoi(optarg);
00493 break;
00494
00495 case 'd':
00496 SECURE_STRNCPY(authreq_addr, optarg,
00497 sizeof authreq_addr);
00498 printf("Sending Auth request to %s\n",
00499 authreq_addr);
00500 break;
00501
00502 case 't':
00503 sscanf(optarg, "%d", &packet_timeout);
00504 break;
00505
00506 case 'T':
00507 sscanf(optarg, "%d", &track_size);
00508 break;
00509 case 'A':
00510 sscanf(optarg, "%d", &debug_areas);
00511 break;
00512 case 'm':
00513 nufw_set_mark = 1;
00514 break;
00515 case 's':
00516 nufw_strict_tls = 0;
00517 break;
00518 case 'S':
00519 break;
00520 case '4':
00521 nufw_no_ipv6 = 1;
00522 break;
00523 #if USE_NFQUEUE
00524 case 'q':
00525 sscanf(optarg, "%hu", &nfqueue_num);
00526 break;
00527 case 'C':
00528 #if HAVE_LIBCONNTRACK
00529 handle_conntrack_event = 1;
00530 break;
00531 case 'M':
00532 nufw_conntrack_uses_mark = 1;
00533
00534 handle_conntrack_event = 1;
00535
00536 nufw_set_mark = 1;
00537 break;
00538 #endif
00539 #ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
00540 case 'L':
00541 sscanf(optarg, "%u", &queue_maxlen);
00542 break;
00543 #endif
00544 #endif
00545
00546 case 'h':
00547 fprintf(stdout, "%s [-hVc"
00548 #ifdef HAVE_LIBCONNTRACK
00549 "CM"
00550 #endif
00551 "v[v[v[v[v[v[v[v[v[v]]]]]]]]]] [-d remote_addr] [-p remote_port] [-t packet_timeout] [-T track_size]"
00552 #ifdef USE_NFQUEUE
00553 " [-q queue_num]"
00554 #ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
00555 " [-L queue_maxlen]"
00556 #endif
00557 #endif
00558 "\n\
00559 \t-h: display this help and exit\n\
00560 \t-V: display version and exit\n\
00561 \t-D: daemonize\n\
00562 \t-s: do not enforce strict checking of TLS certificates\n\
00563 \t-S: this option does nothing, it is here for backward compatibility\n\
00564 \t-k: use specified file as key file\n\
00565 \t-c: use specified file as cert file\n\
00566 \t-a: use specified file as ca file (strict checking is done if selected) (default: none)\n\
00567 \t-r: use specified file as crl file (default: none)\n\
00568 \t-n: use specified string as the needed DN of nuauth (enforce certificate checking) (default is to)\n\
00569 \t\tcheck the DN against nuauth FQDN specified using the -d option)\n\
00570 \t-v: increase debug level (+1 for each 'v') (max useful number: 10)\n\
00571 \t-A: debug areas (see man page for details)\n\
00572 \t-4: use this flag if your system does not have IPv6 support for nfnetlink\n\
00573 \t-m: mark packet with nuauth provided mark\n"
00574 #ifdef HAVE_LIBCONNTRACK
00575 "\t-C: listen to conntrack events (needed for connection expiration)\n\
00576 \t-M: only report event on marked connections to nuauth (implies -C and -m)\n"
00577 #endif
00578 "\t-d: remote address we send auth requests to (address of the nuauth server) (default: 127.0.0.1)\n\
00579 \t-p: remote port we send auth requests to (TCP port nuauth server listens on) (default: 4128)\n"
00580 #if USE_NFQUEUE
00581 "\t-q: use nfqueue number (default: 0)\n"
00582 #ifdef HAVE_NFQ_SET_QUEUE_MAXLEN
00583 "\t-L : set queue max len (default: 1024)\n"
00584 #endif
00585 #endif
00586 "\t-t : timeout to forget about packets when they don't match (default: 15 s)\n\
00587 \t-T : track size (default : 1000)\n",
00588 PACKAGE_TARNAME);
00589
00590 exit(EXIT_SUCCESS);
00591 }
00592 }
00593
00594 if (getuid()) {
00595 printf("nufw must be run as root! Sorry\n");
00596 exit(EXIT_FAILURE);
00597 }
00598
00599 if (!init_checks()) {
00600 exit(EXIT_FAILURE);
00601 }
00602
00603
00604 nice(-1);
00605
00606
00607 if (daemonize == 1) {
00608 nufw_daemonize();
00609 }
00610
00611 install_signals();
00612
00613 init_log_engine("nufw");
00614
00615
00616 raw_sock4 = socket(PF_INET, SOCK_RAW, 1);
00617 if (raw_sock4 == -1) {
00618 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
00619 "Fail to create socket for ICMP!");
00620 exit(EXIT_FAILURE);
00621 }
00622
00623 if (!nufw_no_ipv6) {
00624
00625 raw_sock6 = socket(PF_INET6, SOCK_RAW, 58);
00626 if (raw_sock6 == -1) {
00627 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
00628 "Fail to create socket for ICMPv6!");
00629 }
00630 }
00631
00632
00633 packets_list.start = NULL;
00634 packets_list.end = NULL;
00635 packets_list.length = 0;
00636 pthread_mutex_init(&packets_list.mutex, NULL);
00637
00638
00639 tls.session = NULL;
00640 tls.auth_server_running = 0;
00641 pthread_mutex_init(&tls.mutex, NULL);
00642
00643
00644 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
00645 if (nussl_init() != NUSSL_OK) {
00646 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00647 "Unable to initialize NuSSL library.");
00648
00649 }
00650
00651 #ifdef HAVE_LIBCONNTRACK
00652 cth = nfct_open(CONNTRACK, 0);
00653 #endif
00654
00655
00656
00657 create_thread();
00658
00659
00660 tls_connect();
00661 if (tls.session) {
00662 log_area_printf(DEBUG_AREA_GW,
00663 DEBUG_LEVEL_WARNING,
00664 "[+] TLS connection to nuauth established");
00665 } else {
00666 log_area_printf(DEBUG_AREA_GW,
00667 DEBUG_LEVEL_CRITICAL,
00668 "[!] TLS connection to nuauth can NOT be established");
00669 }
00670
00671 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_FATAL,
00672 "[+] NuFW " VERSION " started");
00673
00674 if (daemonize == 0) {
00675 log_area_printf(DEBUG_AREA_MAIN, DEBUG_LEVEL_CRITICAL,
00676 "NuFW launched in foreground (without -D option), "
00677 "logging to stdout and stderr only (no syslog).");
00678 }
00679
00680
00681 pckt_tx = pckt_rx = 0;
00682 while (1 == 1) {
00683 int stat = pckt_tx;
00684 const int seconds = 5;
00685
00686 sleep(seconds);
00687
00688 stat = pckt_tx - stat;
00689
00690
00691 pthread_mutex_lock(&packets_list.mutex);
00692 clean_old_packets();
00693 pthread_mutex_unlock(&packets_list.mutex);
00694 #ifdef DEBUG_ENABLE
00695
00696 process_poll(0);
00697 printf("Average: %u\n", stat / seconds);
00698 #endif
00699 }
00700
00701 nufw_stop_thread();
00702 nufw_prepare_quit();
00703 return EXIT_SUCCESS;
00704 }