71
71
                                   INET_ADDRSTRLEN, INET6_ADDRSTRLEN
 
73
73
#include <unistd.h>             /* close(), SEEK_SET, off_t, write(),
 
74
 
                                   getuid(), getgid(), setuid(),
 
 
74
                                   getuid(), getgid(), seteuid(),
 
76
76
#include <arpa/inet.h>          /* inet_pton(), htons */
 
77
77
#include <iso646.h>             /* not, or, and */
 
 
80
80
                                   argp_parse(), ARGP_KEY_ARG,
 
81
81
                                   ARGP_KEY_END, ARGP_ERR_UNKNOWN */
 
82
82
#include <signal.h>             /* sigemptyset(), sigaddset(),
 
83
 
                                   sigaction(), SIGTERM, sigaction,
 
 
83
                                   sigaction(), SIGTERM, sig_atomic_t,
 
87
87
#include <sys/klog.h>           /* klogctl() */
 
 
310
310
        gpgme_recipient_t recipient;
 
311
311
        recipient = result->recipients;
 
313
 
          while(recipient != NULL){
 
314
 
            fprintf(stderr, "Public key algorithm: %s\n",
 
315
 
                    gpgme_pubkey_algo_name(recipient->pubkey_algo));
 
316
 
            fprintf(stderr, "Key ID: %s\n", recipient->keyid);
 
317
 
            fprintf(stderr, "Secret key available: %s\n",
 
318
 
                    recipient->status == GPG_ERR_NO_SECKEY
 
320
 
            recipient = recipient->next;
 
 
312
        while(recipient != NULL){
 
 
313
          fprintf(stderr, "Public key algorithm: %s\n",
 
 
314
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
 
 
315
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
 
 
316
          fprintf(stderr, "Secret key available: %s\n",
 
 
317
                  recipient->status == GPG_ERR_NO_SECKEY
 
 
319
          recipient = recipient->next;
 
 
516
514
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
 
517
515
                      __attribute__((unused)) const char *txt){}
 
 
517
sig_atomic_t quit_now = 0;
 
 
518
int signal_received = 0;
 
519
520
/* Called when a Mandos server is found */
 
520
521
static int start_mandos_communication(const char *ip, uint16_t port,
 
521
522
                                      AvahiIfIndex if_index,
 
 
524
  int ret, tcp_sd = -1;
 
526
527
    struct sockaddr_in in;
 
 
530
531
  char *decrypted_buffer;
 
531
532
  size_t buffer_length = 0;
 
532
533
  size_t buffer_capacity = 0;
 
533
 
  ssize_t decrypted_buffer_size;
 
536
536
  gnutls_session_t session;
 
537
537
  int pf;                       /* Protocol family */
 
 
561
565
  tcp_sd = socket(pf, SOCK_STREAM, 0);
 
563
567
    perror("socket");
 
567
576
  memset(&to, 0, sizeof(to));
 
568
577
  if(af == AF_INET6){
 
569
 
    to.in6.sin6_family = (uint16_t)af;
 
 
578
    to.in6.sin6_family = (sa_family_t)af;
 
570
579
    ret = inet_pton(af, ip, &to.in6.sin6_addr);
 
571
580
  } else {                      /* IPv4 */
 
572
581
    to.in.sin_family = (sa_family_t)af;
 
 
591
602
      if(if_index == AVAHI_IF_UNSPEC){
 
592
603
        fprintf(stderr, "An IPv6 link-local address is incomplete"
 
593
604
                " without a network interface\n");
 
596
608
      /* Set the network interface number as scope */
 
597
609
      to.in6.sin6_scope_id = (uint32_t)if_index;
 
 
672
701
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
 
675
708
  gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd);
 
678
715
    ret = gnutls_handshake(session);
 
679
719
  } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
 
681
721
  if(ret != GNUTLS_E_SUCCESS){
 
 
714
763
      case GNUTLS_E_AGAIN:
 
716
765
      case GNUTLS_E_REHANDSHAKE:
 
718
767
          ret = gnutls_handshake(session);
 
719
772
        } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED);
 
721
774
          fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n");
 
 
740
793
    fprintf(stderr, "Closing TLS session\n");
 
743
800
  gnutls_bye(session, GNUTLS_SHUT_RDWR);
 
745
806
  if(buffer_length > 0){
 
 
807
    ssize_t decrypted_buffer_size;
 
746
808
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
 
748
810
                                               &decrypted_buffer);
 
749
811
    if(decrypted_buffer_size >= 0){
 
751
814
      while(written < (size_t) decrypted_buffer_size){
 
752
819
        ret = (int)fwrite(decrypted_buffer + written, 1,
 
753
820
                          (size_t)decrypted_buffer_size - written,
 
 
880
 
sig_atomic_t quit_now = 0;
 
882
960
/* stop main loop after sigterm has been called */
 
883
 
static void handle_sigterm(__attribute__((unused)) int sig){
 
 
961
static void handle_sigterm(int sig){
 
 
966
  signal_received = sig;
 
888
967
  int old_errno = errno;
 
889
968
  if(mc.simple_poll != NULL){
 
890
969
    avahi_simple_poll_quit(mc.simple_poll);
 
 
1050
1130
    exitcode = EXIT_FAILURE;
 
1053
 
  ret = sigaction(SIGTERM, &sigterm_action, &old_sigterm_action);
 
1055
 
    perror("sigaction");
 
1056
 
    exitcode = EXIT_FAILURE;
 
 
1133
  /* Need to check if the handler is SIG_IGN before handling:
 
 
1134
     | [[info:libc:Initial Signal Actions]] |
 
 
1135
     | [[info:libc:Basic Signal Handling]]  |
 
 
1137
  ret = sigaction(SIGINT, NULL, &old_sigterm_action);
 
 
1139
    perror("sigaction");
 
 
1140
    return EXIT_FAILURE;
 
 
1142
  if(old_sigterm_action.sa_handler != SIG_IGN){
 
 
1143
    ret = sigaction(SIGINT, &sigterm_action, NULL);
 
 
1145
      perror("sigaction");
 
 
1146
      exitcode = EXIT_FAILURE;
 
 
1150
  ret = sigaction(SIGHUP, NULL, &old_sigterm_action);
 
 
1152
    perror("sigaction");
 
 
1153
    return EXIT_FAILURE;
 
 
1155
  if(old_sigterm_action.sa_handler != SIG_IGN){
 
 
1156
    ret = sigaction(SIGHUP, &sigterm_action, NULL);
 
 
1158
      perror("sigaction");
 
 
1159
      exitcode = EXIT_FAILURE;
 
 
1163
  ret = sigaction(SIGTERM, NULL, &old_sigterm_action);
 
 
1165
    perror("sigaction");
 
 
1166
    return EXIT_FAILURE;
 
 
1168
  if(old_sigterm_action.sa_handler != SIG_IGN){
 
 
1169
    ret = sigaction(SIGTERM, &sigterm_action, NULL);
 
 
1171
      perror("sigaction");
 
 
1172
      exitcode = EXIT_FAILURE;
 
1060
1177
  /* If the interface is down, bring it up */
 
1061
1178
  if(interface[0] != '\0'){
 
 
1179
    if_index = (AvahiIfIndex) if_nametoindex(interface);
 
 
1181
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
 
 
1182
      exitcode = EXIT_FAILURE;
 
1062
1190
#ifdef __linux__
 
1063
1191
    /* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
 
1064
1192
       messages to mess up the prompt */
 
 
1102
1230
    if((network.ifr_flags & IFF_UP) == 0){
 
1103
1231
      network.ifr_flags |= IFF_UP;
 
 
1232
      take_down_interface = true;
 
1104
1233
      ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
 
1235
        take_down_interface = false;
 
1106
1236
        perror("ioctl SIOCSIFFLAGS");
 
1107
1237
        exitcode = EXIT_FAILURE;
 
1108
1238
#ifdef __linux__
 
 
1145
1278
#endif  /* __linux__ */
 
1148
1285
  uid = getuid();
 
1149
1286
  gid = getgid();
 
 
1288
  /* Drop any group privileges we might have, just to be safe */
 
1154
1292
    perror("setgid");
 
 
1295
  /* Drop user privileges */
 
 
1297
  /* Will we need privileges later? */
 
 
1298
  if(take_down_interface){
 
 
1299
    /* Drop user privileges temporarily */
 
 
1305
    /* Drop user privileges permanently */
 
1162
1316
  ret = init_gnutls_global(pubkey, seckey);
 
 
1168
1322
    gnutls_initialized = true;
 
 
1329
  tempdir_created = true;
 
1171
1330
  if(mkdtemp(tempdir) == NULL){
 
 
1331
    tempdir_created = false;
 
1172
1332
    perror("mkdtemp");
 
1175
 
  tempdir_created = true;
 
1177
1340
  if(not init_gpgme(pubkey, seckey, tempdir)){
 
1178
1341
    fprintf(stderr, "init_gpgme failed\n");
 
 
1182
1345
    gpgme_initialized = true;
 
1185
 
  if(interface[0] != '\0'){
 
1186
 
    if_index = (AvahiIfIndex) if_nametoindex(interface);
 
1188
 
      fprintf(stderr, "No such interface: \"%s\"\n", interface);
 
1189
 
      exitcode = EXIT_FAILURE;
 
1194
1352
  if(connect_to != NULL){
 
 
1257
1438
  /* Create the Avahi service browser */
 
1258
1439
  sb = avahi_s_service_browser_new(mc.server, if_index,
 
1259
1440
                                   AVAHI_PROTO_UNSPEC, "_mandos._tcp",
 
 
1299
1484
    gpgme_release(mc.ctx);
 
 
1487
  /* Take down the network interface */
 
 
1488
  if(take_down_interface){
 
 
1489
    /* Re-raise priviliges */
 
 
1496
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
 
1498
        perror("ioctl SIOCGIFFLAGS");
 
 
1499
      } else if(network.ifr_flags & IFF_UP) {
 
 
1500
        network.ifr_flags &= ~IFF_UP; /* clear flag */
 
 
1501
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
 
1503
          perror("ioctl SIOCSIFFLAGS");
 
 
1506
      ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
 
1510
      /* Lower privileges, permanently this time */
 
1302
1519
  /* Removes the temp directory used by GPGME */
 
1303
1520
  if(tempdir_created){