/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugins.d/mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2015-07-05 21:38:01 UTC
  • mto: This revision was merged to the branch mainline in revision 759.
  • Revision ID: teddy@recompile.se-20150705213801-pi8vk0ovlumuj826
plugin-helpers/mandos-client-iprouteadddel.c: Fix #include lines.
(main): Fix minor typo in error message.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008-2014 Teddy Hogeborn
13
 
 * Copyright © 2008-2014 Björn Påhlsson
 
12
 * Copyright © 2008-2015 Teddy Hogeborn
 
13
 * Copyright © 2008-2015 Björn Påhlsson
14
14
 * 
15
15
 * This program is free software: you can redistribute it and/or
16
16
 * modify it under the terms of the GNU General Public License as
493
493
  return plaintext_length;
494
494
}
495
495
 
496
 
__attribute__((warn_unused_result, const))
497
 
static const char *safe_string(const char *str){
498
 
  if(str == NULL)
499
 
    return "(unknown)";
500
 
  return str;
501
 
}
502
 
 
503
496
__attribute__((warn_unused_result))
504
497
static const char *safer_gnutls_strerror(int value){
505
498
  const char *ret = gnutls_strerror(value);
506
 
  return safe_string(ret);
 
499
  if(ret == NULL)
 
500
    ret = "(unknown)";
 
501
  return ret;
507
502
}
508
503
 
509
504
/* GnuTLS log function callback */
518
513
                              const char *seckeyfilename,
519
514
                              mandos_context *mc){
520
515
  int ret;
521
 
  unsigned int uret;
522
516
  
523
517
  if(debug){
524
518
    fprintf_plus(stderr, "Initializing GnuTLS\n");
575
569
                 safer_gnutls_strerror(ret));
576
570
    goto globalfail;
577
571
  }
578
 
  if(mc->dh_bits == 0){
579
 
    /* Find out the optimal number of DH bits */
580
 
    /* Try to read the private key file */
581
 
    gnutls_datum_t buffer = { .data = NULL, .size = 0 };
582
 
    {
583
 
      int secfile = open(seckeyfilename, O_RDONLY);
584
 
      size_t buffer_capacity = 0;
585
 
      while(true){
586
 
        buffer_capacity = incbuffer((char **)&buffer.data,
587
 
                                    (size_t)buffer.size,
588
 
                                    (size_t)buffer_capacity);
589
 
        if(buffer_capacity == 0){
590
 
          perror_plus("incbuffer");
591
 
          free(buffer.data);
592
 
          buffer.data = NULL;
593
 
          break;
594
 
        }
595
 
        ssize_t bytes_read = read(secfile, buffer.data + buffer.size,
596
 
                                  BUFFER_SIZE);
597
 
        /* EOF */
598
 
        if(bytes_read == 0){
599
 
          break;
600
 
        }
601
 
        /* check bytes_read for failure */
602
 
        if(bytes_read < 0){
603
 
          perror_plus("read");
604
 
          free(buffer.data);
605
 
          buffer.data = NULL;
606
 
          break;
607
 
        }
608
 
        buffer.size += (unsigned int)bytes_read;
609
 
      }
610
 
      close(secfile);
611
 
    }
612
 
    /* If successful, use buffer to parse private key */
613
 
    gnutls_sec_param_t sec_param = GNUTLS_SEC_PARAM_ULTRA;
614
 
    if(buffer.data != NULL){
615
 
      {
616
 
        gnutls_openpgp_privkey_t privkey = NULL;
617
 
        ret = gnutls_openpgp_privkey_init(&privkey);
618
 
        if(ret != GNUTLS_E_SUCCESS){
619
 
          fprintf_plus(stderr, "Error initializing OpenPGP key"
620
 
                       " structure: %s", safer_gnutls_strerror(ret));
621
 
          free(buffer.data);
622
 
          buffer.data = NULL;
623
 
        } else {
624
 
          ret = gnutls_openpgp_privkey_import(privkey, &buffer,
625
 
                                            GNUTLS_OPENPGP_FMT_BASE64,
626
 
                                              "", 0);
627
 
          if(ret != GNUTLS_E_SUCCESS){
628
 
            fprintf_plus(stderr, "Error importing OpenPGP key : %s",
629
 
                         safer_gnutls_strerror(ret));
630
 
            privkey = NULL;
631
 
          }
632
 
          free(buffer.data);
633
 
          buffer.data = NULL;
634
 
          if(privkey != NULL){
635
 
            /* Use private key to suggest an appropriate sec_param */
636
 
            sec_param = gnutls_openpgp_privkey_sec_param(privkey);
637
 
            gnutls_openpgp_privkey_deinit(privkey);
638
 
            if(debug){
639
 
              fprintf_plus(stderr, "This OpenPGP key implies using a"
640
 
                           " GnuTLS security parameter \"%s\".\n",
641
 
                           safe_string(gnutls_sec_param_get_name
642
 
                                       (sec_param)));
643
 
            }
644
 
          }
645
 
        }
646
 
      }
647
 
      if(sec_param == GNUTLS_SEC_PARAM_UNKNOWN){
648
 
        /* Err on the side of caution */
649
 
        sec_param = GNUTLS_SEC_PARAM_ULTRA;
650
 
        if(debug){
651
 
          fprintf_plus(stderr, "Falling back to security parameter"
652
 
                       " \"%s\"\n",
653
 
                       safe_string(gnutls_sec_param_get_name
654
 
                                   (sec_param)));
655
 
        }
656
 
      }
657
 
    }
658
 
    uret = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, sec_param);
659
 
    if(uret != 0){
660
 
      mc->dh_bits = uret;
661
 
      if(debug){
662
 
        fprintf_plus(stderr, "A \"%s\" GnuTLS security parameter"
663
 
                     " implies %u DH bits; using that.\n",
664
 
                     safe_string(gnutls_sec_param_get_name
665
 
                                 (sec_param)),
666
 
                     mc->dh_bits);
667
 
      }
668
 
    } else {
669
 
      fprintf_plus(stderr, "Failed to get implied number of DH"
670
 
                   " bits for security parameter \"%s\"): %s\n",
671
 
                   safe_string(gnutls_sec_param_get_name(sec_param)),
672
 
                   safer_gnutls_strerror(ret));
673
 
      goto globalfail;
674
 
    }
675
 
  } else if(debug){
676
 
    fprintf_plus(stderr, "DH bits explicitly set to %u\n",
677
 
                 mc->dh_bits);
678
 
  }
679
572
  ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
680
573
  if(ret != GNUTLS_E_SUCCESS){
681
 
    fprintf_plus(stderr, "Error in GnuTLS prime generation (%u bits):"
682
 
                 " %s\n", mc->dh_bits, safer_gnutls_strerror(ret));
 
574
    fprintf_plus(stderr, "Error in GnuTLS prime generation: %s\n",
 
575
                 safer_gnutls_strerror(ret));
683
576
    goto globalfail;
684
577
  }
685
578
  
757
650
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
758
651
                      __attribute__((unused)) const char *txt){}
759
652
 
 
653
/* Set effective uid to 0, return errno */
 
654
__attribute__((warn_unused_result))
 
655
error_t raise_privileges(void){
 
656
  error_t old_errno = errno;
 
657
  error_t ret_errno = 0;
 
658
  if(seteuid(0) == -1){
 
659
    ret_errno = errno;
 
660
  }
 
661
  errno = old_errno;
 
662
  return ret_errno;
 
663
}
 
664
 
 
665
/* Set effective and real user ID to 0.  Return errno. */
 
666
__attribute__((warn_unused_result))
 
667
error_t raise_privileges_permanently(void){
 
668
  error_t old_errno = errno;
 
669
  error_t ret_errno = raise_privileges();
 
670
  if(ret_errno != 0){
 
671
    errno = old_errno;
 
672
    return ret_errno;
 
673
  }
 
674
  if(setuid(0) == -1){
 
675
    ret_errno = errno;
 
676
  }
 
677
  errno = old_errno;
 
678
  return ret_errno;
 
679
}
 
680
 
 
681
/* Set effective user ID to unprivileged saved user ID */
 
682
__attribute__((warn_unused_result))
 
683
error_t lower_privileges(void){
 
684
  error_t old_errno = errno;
 
685
  error_t ret_errno = 0;
 
686
  if(seteuid(uid) == -1){
 
687
    ret_errno = errno;
 
688
  }
 
689
  errno = old_errno;
 
690
  return ret_errno;
 
691
}
 
692
 
 
693
/* Lower privileges permanently */
 
694
__attribute__((warn_unused_result))
 
695
error_t lower_privileges_permanently(void){
 
696
  error_t old_errno = errno;
 
697
  error_t ret_errno = 0;
 
698
  if(setuid(uid) == -1){
 
699
    ret_errno = errno;
 
700
  }
 
701
  errno = old_errno;
 
702
  return ret_errno;
 
703
}
 
704
 
 
705
/* Helper function to add_local_route() and remove_local_route() */
 
706
__attribute__((nonnull, warn_unused_result))
 
707
static bool add_remove_local_route(const bool add,
 
708
                                   const char *address,
 
709
                                   AvahiIfIndex if_index){
 
710
  int ret;
 
711
  char helper[] = "mandos-client-iprouteadddel";
 
712
  char add_arg[] = "add";
 
713
  char delete_arg[] = "delete";
 
714
  char *pluginhelperdir = getenv("MANDOSPLUGINHELPERDIR");
 
715
  if(pluginhelperdir == NULL){
 
716
    if(debug){
 
717
      fprintf_plus(stderr, "MANDOSPLUGINHELPERDIR environment"
 
718
                   " variable not set; cannot run helper\n");
 
719
    }
 
720
    return false;
 
721
  }
 
722
  
 
723
  char interface[IF_NAMESIZE];
 
724
  if(if_indextoname((unsigned int)if_index, interface) == NULL){
 
725
    perror_plus("if_indextoname");
 
726
    return false;
 
727
  }
 
728
  
 
729
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
 
730
  if(devnull == -1){
 
731
    perror_plus("open(\"/dev/null\", O_RDONLY)");
 
732
    return false;
 
733
  }
 
734
  pid_t pid = fork();
 
735
  if(pid == 0){
 
736
    /* Child */
 
737
    /* Raise privileges */
 
738
    errno = raise_privileges_permanently();
 
739
    if(errno != 0){
 
740
      perror_plus("Failed to raise privileges");
 
741
      /* _exit(EX_NOPERM); */
 
742
    } else {
 
743
      /* Set group */
 
744
      errno = 0;
 
745
      ret = setgid(0);
 
746
      if(ret == -1){
 
747
        perror_plus("setgid");
 
748
        _exit(EX_NOPERM);
 
749
      }
 
750
      /* Reset supplementary groups */
 
751
      errno = 0;
 
752
      ret = setgroups(0, NULL);
 
753
      if(ret == -1){
 
754
        perror_plus("setgroups");
 
755
        _exit(EX_NOPERM);
 
756
      }
 
757
    }
 
758
    ret = dup2(devnull, STDIN_FILENO);
 
759
    if(ret == -1){
 
760
      perror_plus("dup2(devnull, STDIN_FILENO)");
 
761
      _exit(EX_OSERR);
 
762
    }
 
763
    ret = (int)TEMP_FAILURE_RETRY(close(devnull));
 
764
    if(ret == -1){
 
765
      perror_plus("close");
 
766
      _exit(EX_OSERR);
 
767
    }
 
768
    ret = dup2(STDERR_FILENO, STDOUT_FILENO);
 
769
    if(ret == -1){
 
770
      perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
 
771
      _exit(EX_OSERR);
 
772
    }
 
773
    int helperdir_fd = (int)TEMP_FAILURE_RETRY(open(pluginhelperdir,
 
774
                                                    O_RDONLY
 
775
                                                    | O_DIRECTORY
 
776
                                                    | O_PATH
 
777
                                                    | O_CLOEXEC));
 
778
    if(helperdir_fd == -1){
 
779
      perror_plus("open");
 
780
      _exit(EX_UNAVAILABLE);
 
781
    }
 
782
    int helper_fd = (int)TEMP_FAILURE_RETRY(openat(helperdir_fd,
 
783
                                                   helper, O_RDONLY));
 
784
    if(helper_fd == -1){
 
785
      perror_plus("openat");
 
786
      _exit(EX_UNAVAILABLE);
 
787
    }
 
788
    TEMP_FAILURE_RETRY(close(helperdir_fd));
 
789
#ifdef __GNUC__
 
790
#pragma GCC diagnostic push
 
791
#pragma GCC diagnostic ignored "-Wcast-qual"
 
792
#endif
 
793
    if(fexecve(helper_fd, (char *const [])
 
794
               { helper, add ? add_arg : delete_arg, (char *)address,
 
795
                   interface, NULL }, environ) == -1){
 
796
#ifdef __GNUC__
 
797
#pragma GCC diagnostic pop
 
798
#endif
 
799
      perror_plus("fexecve");
 
800
      _exit(EXIT_FAILURE);
 
801
    }
 
802
  }
 
803
  if(pid == -1){
 
804
    perror_plus("fork");
 
805
    return false;
 
806
  }
 
807
  int status;
 
808
  pid_t pret = -1;
 
809
  errno = 0;
 
810
  do {
 
811
    pret = waitpid(pid, &status, 0);
 
812
    if(pret == -1 and errno == EINTR and quit_now){
 
813
      int errno_raising = 0;
 
814
      if((errno = raise_privileges()) != 0){
 
815
        errno_raising = errno;
 
816
        perror_plus("Failed to raise privileges in order to"
 
817
                    " kill helper program");
 
818
      }
 
819
      if(kill(pid, SIGTERM) == -1){
 
820
        perror_plus("kill");
 
821
      }
 
822
      if((errno_raising == 0) and (errno = lower_privileges()) != 0){
 
823
        perror_plus("Failed to lower privileges after killing"
 
824
                    " helper program");
 
825
      }
 
826
      return false;
 
827
    }
 
828
  } while(pret == -1 and errno == EINTR);
 
829
  if(pret == -1){
 
830
    perror_plus("waitpid");
 
831
    return false;
 
832
  }
 
833
  if(WIFEXITED(status)){
 
834
    if(WEXITSTATUS(status) != 0){
 
835
      fprintf_plus(stderr, "Error: iprouteadddel exited"
 
836
                   " with status %d\n", WEXITSTATUS(status));
 
837
      return false;
 
838
    }
 
839
    return true;
 
840
  }
 
841
  if(WIFSIGNALED(status)){
 
842
    fprintf_plus(stderr, "Error: iprouteadddel died by"
 
843
                 " signal %d\n", WTERMSIG(status));
 
844
    return false;
 
845
  }
 
846
  fprintf_plus(stderr, "Error: iprouteadddel crashed\n");
 
847
  return false;
 
848
}
 
849
 
 
850
__attribute__((nonnull, warn_unused_result))
 
851
static bool add_local_route(const char *address,
 
852
                            AvahiIfIndex if_index){
 
853
  return add_remove_local_route(true, address, if_index);
 
854
}
 
855
 
 
856
__attribute__((nonnull, warn_unused_result))
 
857
static bool remove_local_route(const char *address,
 
858
                               AvahiIfIndex if_index){
 
859
  return add_remove_local_route(false, address, if_index);
 
860
}
 
861
 
760
862
/* Called when a Mandos server is found */
761
863
__attribute__((nonnull, warn_unused_result))
762
864
static int start_mandos_communication(const char *ip, in_port_t port,
773
875
  int retval = -1;
774
876
  gnutls_session_t session;
775
877
  int pf;                       /* Protocol family */
 
878
  bool route_added = false;
776
879
  
777
880
  errno = 0;
778
881
  
836
939
                 PRIuMAX "\n", ip, (uintmax_t)port);
837
940
  }
838
941
  
839
 
  tcp_sd = socket(pf, SOCK_STREAM, 0);
 
942
  tcp_sd = socket(pf, SOCK_STREAM | SOCK_CLOEXEC, 0);
840
943
  if(tcp_sd < 0){
841
944
    int e = errno;
842
945
    perror_plus("socket");
931
1034
    goto mandos_end;
932
1035
  }
933
1036
  
934
 
  if(af == AF_INET6){
935
 
    ret = connect(tcp_sd, (struct sockaddr *)&to,
936
 
                  sizeof(struct sockaddr_in6));
937
 
  } else {
938
 
    ret = connect(tcp_sd, (struct sockaddr *)&to, /* IPv4 */
939
 
                  sizeof(struct sockaddr_in));
940
 
  }
941
 
  if(ret < 0){
942
 
    if((errno != ECONNREFUSED and errno != ENETUNREACH) or debug){
943
 
      int e = errno;
944
 
      perror_plus("connect");
945
 
      errno = e;
946
 
    }
947
 
    goto mandos_end;
948
 
  }
949
 
  
950
 
  if(quit_now){
951
 
    errno = EINTR;
952
 
    goto mandos_end;
 
1037
  while(true){
 
1038
    if(af == AF_INET6){
 
1039
      ret = connect(tcp_sd, (struct sockaddr *)&to,
 
1040
                    sizeof(struct sockaddr_in6));
 
1041
    } else {
 
1042
      ret = connect(tcp_sd, (struct sockaddr *)&to, /* IPv4 */
 
1043
                    sizeof(struct sockaddr_in));
 
1044
    }
 
1045
    if(ret < 0){
 
1046
      if(errno == ENETUNREACH
 
1047
         and if_index != AVAHI_IF_UNSPEC
 
1048
         and connect_to == NULL
 
1049
         and not route_added and
 
1050
         ((af == AF_INET6 and not
 
1051
           IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6 *)
 
1052
                                    &to)->sin6_addr)))
 
1053
          or (af == AF_INET and
 
1054
              /* Not a a IPv4LL address */
 
1055
              (ntohl(((struct sockaddr_in *)&to)->sin_addr.s_addr)
 
1056
               & 0xFFFF0000L) != 0xA9FE0000L))){
 
1057
        /* Work around Avahi bug - Avahi does not announce link-local
 
1058
           addresses if it has a global address, so local hosts with
 
1059
           *only* a link-local address (e.g. Mandos clients) cannot
 
1060
           connect to a Mandos server announced by Avahi on a server
 
1061
           host with a global address.  Work around this by retrying
 
1062
           with an explicit route added with the server's address.
 
1063
           
 
1064
           Avahi bug reference:
 
1065
           http://lists.freedesktop.org/archives/avahi/2010-February/001833.html
 
1066
           https://bugs.debian.org/587961
 
1067
        */
 
1068
        int e = errno;
 
1069
        route_added = add_local_route(ip, if_index);
 
1070
        if(route_added){
 
1071
          continue;
 
1072
        }
 
1073
        errno = e;
 
1074
      }
 
1075
      if(errno != ECONNREFUSED or debug){
 
1076
        int e = errno;
 
1077
        perror_plus("connect");
 
1078
        errno = e;
 
1079
      }
 
1080
      goto mandos_end;
 
1081
    }
 
1082
    
 
1083
    if(quit_now){
 
1084
      errno = EINTR;
 
1085
      goto mandos_end;
 
1086
    }
 
1087
    break;
953
1088
  }
954
1089
  
955
1090
  const char *out = mandos_protocol_version;
1138
1273
  
1139
1274
 mandos_end:
1140
1275
  {
 
1276
    if(route_added){
 
1277
      if(not remove_local_route(ip, if_index)){
 
1278
        fprintf_plus(stderr, "Failed to remove local route to %s on"
 
1279
                     " interface %d", ip, if_index);
 
1280
      }
 
1281
    }
1141
1282
    int e = errno;
1142
1283
    free(decrypted_buffer);
1143
1284
    free(buffer);
1569
1710
  }
1570
1711
}
1571
1712
 
1572
 
/* Set effective uid to 0, return errno */
1573
 
__attribute__((warn_unused_result))
1574
 
error_t raise_privileges(void){
1575
 
  error_t old_errno = errno;
1576
 
  error_t ret_errno = 0;
1577
 
  if(seteuid(0) == -1){
1578
 
    ret_errno = errno;
1579
 
  }
1580
 
  errno = old_errno;
1581
 
  return ret_errno;
1582
 
}
1583
 
 
1584
 
/* Set effective and real user ID to 0.  Return errno. */
1585
 
__attribute__((warn_unused_result))
1586
 
error_t raise_privileges_permanently(void){
1587
 
  error_t old_errno = errno;
1588
 
  error_t ret_errno = raise_privileges();
1589
 
  if(ret_errno != 0){
1590
 
    errno = old_errno;
1591
 
    return ret_errno;
1592
 
  }
1593
 
  if(setuid(0) == -1){
1594
 
    ret_errno = errno;
1595
 
  }
1596
 
  errno = old_errno;
1597
 
  return ret_errno;
1598
 
}
1599
 
 
1600
 
/* Set effective user ID to unprivileged saved user ID */
1601
 
__attribute__((warn_unused_result))
1602
 
error_t lower_privileges(void){
1603
 
  error_t old_errno = errno;
1604
 
  error_t ret_errno = 0;
1605
 
  if(seteuid(uid) == -1){
1606
 
    ret_errno = errno;
1607
 
  }
1608
 
  errno = old_errno;
1609
 
  return ret_errno;
1610
 
}
1611
 
 
1612
 
/* Lower privileges permanently */
1613
 
__attribute__((warn_unused_result))
1614
 
error_t lower_privileges_permanently(void){
1615
 
  error_t old_errno = errno;
1616
 
  error_t ret_errno = 0;
1617
 
  if(setuid(uid) == -1){
1618
 
    ret_errno = errno;
1619
 
  }
1620
 
  errno = old_errno;
1621
 
  return ret_errno;
1622
 
}
1623
 
 
1624
1713
__attribute__((nonnull))
1625
1714
void run_network_hooks(const char *mode, const char *interface,
1626
1715
                       const float delay){
1627
1716
  struct dirent **direntries = NULL;
1628
1717
  if(hookdir_fd == -1){
1629
 
    hookdir_fd = open(hookdir, O_RDONLY);
 
1718
    hookdir_fd = open(hookdir, O_RDONLY | O_DIRECTORY | O_PATH
 
1719
                      | O_CLOEXEC);
1630
1720
    if(hookdir_fd == -1){
1631
1721
      if(errno == ENOENT){
1632
1722
        if(debug){
1657
1747
  }
1658
1748
  struct dirent *direntry;
1659
1749
  int ret;
1660
 
  int devnull = open("/dev/null", O_RDONLY);
 
1750
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
 
1751
  if(devnull == -1){
 
1752
    perror_plus("open(\"/dev/null\", O_RDONLY)");
 
1753
    return;
 
1754
  }
1661
1755
  for(int i = 0; i < numhooks; i++){
1662
1756
    direntry = direntries[i];
1663
1757
    if(debug){
1687
1781
        perror_plus("setgroups");
1688
1782
        _exit(EX_NOPERM);
1689
1783
      }
1690
 
      ret = dup2(devnull, STDIN_FILENO);
1691
 
      if(ret == -1){
1692
 
        perror_plus("dup2(devnull, STDIN_FILENO)");
1693
 
        _exit(EX_OSERR);
1694
 
      }
1695
 
      ret = close(devnull);
1696
 
      if(ret == -1){
1697
 
        perror_plus("close");
1698
 
        _exit(EX_OSERR);
1699
 
      }
1700
 
      ret = dup2(STDERR_FILENO, STDOUT_FILENO);
1701
 
      if(ret == -1){
1702
 
        perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
1703
 
        _exit(EX_OSERR);
1704
 
      }
1705
1784
      ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1706
1785
      if(ret == -1){
1707
1786
        perror_plus("setenv");
1742
1821
          _exit(EX_OSERR);
1743
1822
        }
1744
1823
      }
1745
 
      int hook_fd = openat(hookdir_fd, direntry->d_name, O_RDONLY);
 
1824
      int hook_fd = (int)TEMP_FAILURE_RETRY(openat(hookdir_fd,
 
1825
                                                   direntry->d_name,
 
1826
                                                   O_RDONLY));
1746
1827
      if(hook_fd == -1){
1747
1828
        perror_plus("openat");
1748
1829
        _exit(EXIT_FAILURE);
1751
1832
        perror_plus("close");
1752
1833
        _exit(EXIT_FAILURE);
1753
1834
      }
 
1835
      ret = dup2(devnull, STDIN_FILENO);
 
1836
      if(ret == -1){
 
1837
        perror_plus("dup2(devnull, STDIN_FILENO)");
 
1838
        _exit(EX_OSERR);
 
1839
      }
 
1840
      ret = (int)TEMP_FAILURE_RETRY(close(devnull));
 
1841
      if(ret == -1){
 
1842
        perror_plus("close");
 
1843
        _exit(EX_OSERR);
 
1844
      }
 
1845
      ret = dup2(STDERR_FILENO, STDOUT_FILENO);
 
1846
      if(ret == -1){
 
1847
        perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
 
1848
        _exit(EX_OSERR);
 
1849
      }
1754
1850
      if(fexecve(hook_fd, (char *const []){ direntry->d_name, NULL },
1755
1851
                 environ) == -1){
1756
1852
        perror_plus("fexecve");
2007
2103
}
2008
2104
 
2009
2105
int main(int argc, char *argv[]){
2010
 
  mandos_context mc = { .server = NULL, .dh_bits = 0,
 
2106
  mandos_context mc = { .server = NULL, .dh_bits = 1024,
2011
2107
                        .priority = "SECURE256:!CTYPE-X.509:"
2012
 
                        "+CTYPE-OPENPGP:!RSA", .current_server = NULL,
 
2108
                        "+CTYPE-OPENPGP", .current_server = NULL,
2013
2109
                        .interfaces = NULL, .interfaces_size = 0 };
2014
2110
  AvahiSServiceBrowser *sb = NULL;
2015
2111
  error_t ret_errno;
2204
2300
      goto end;
2205
2301
    }
2206
2302
  }
2207
 
    
 
2303
  
2208
2304
  {
2209
2305
    /* Work around Debian bug #633582:
2210
2306
       <http://bugs.debian.org/633582> */
2237
2333
          TEMP_FAILURE_RETRY(close(seckey_fd));
2238
2334
        }
2239
2335
      }
2240
 
    
 
2336
      
2241
2337
      if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){
2242
2338
        int pubkey_fd = open(pubkey, O_RDONLY);
2243
2339
        if(pubkey_fd == -1){
2258
2354
          TEMP_FAILURE_RETRY(close(pubkey_fd));
2259
2355
        }
2260
2356
      }
2261
 
    
 
2357
      
2262
2358
      /* Lower privileges */
2263
2359
      ret_errno = lower_privileges();
2264
2360
      if(ret_errno != 0){
2733
2829
  /* Removes the GPGME temp directory and all files inside */
2734
2830
  if(tempdir != NULL){
2735
2831
    struct dirent **direntries = NULL;
2736
 
    int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY |
2737
 
                                                  O_NOFOLLOW));
 
2832
    int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY
 
2833
                                                  | O_NOFOLLOW
 
2834
                                                  | O_DIRECTORY
 
2835
                                                  | O_PATH));
2738
2836
    if(tempdir_fd == -1){
2739
2837
      perror_plus("open");
2740
2838
    } else {