/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-05-31 16:13:39 UTC
  • Revision ID: teddy@recompile.se-20150531161339-igb3l0ip3c10ejpz
mandos-ctl: Generate better messages in exceptions.

mandos (rfc3339_duration_to_delta): Remove dead code.  Adjust white
                                    space.
mandos-ctl (rfc3339_duration_to_delta): Do minor formatting and
                                        whitespace adjustments, and
                                        Generate better message in
                                        exception.
(string_to_delta): Adjust quote character in doc string.

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-2015 Teddy Hogeborn
13
 
 * Copyright © 2008-2015 Björn Påhlsson
 
12
 * Copyright © 2008-2014 Teddy Hogeborn
 
13
 * Copyright © 2008-2014 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
 
496
503
__attribute__((warn_unused_result))
497
504
static const char *safer_gnutls_strerror(int value){
498
505
  const char *ret = gnutls_strerror(value);
499
 
  if(ret == NULL)
500
 
    ret = "(unknown)";
501
 
  return ret;
 
506
  return safe_string(ret);
502
507
}
503
508
 
504
509
/* GnuTLS log function callback */
513
518
                              const char *seckeyfilename,
514
519
                              mandos_context *mc){
515
520
  int ret;
 
521
  unsigned int uret;
516
522
  
517
523
  if(debug){
518
524
    fprintf_plus(stderr, "Initializing GnuTLS\n");
569
575
                 safer_gnutls_strerror(ret));
570
576
    goto globalfail;
571
577
  }
 
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
  }
572
679
  ret = gnutls_dh_params_generate2(mc->dh_params, mc->dh_bits);
573
680
  if(ret != GNUTLS_E_SUCCESS){
574
 
    fprintf_plus(stderr, "Error in GnuTLS prime generation: %s\n",
575
 
                 safer_gnutls_strerror(ret));
 
681
    fprintf_plus(stderr, "Error in GnuTLS prime generation (%u bits):"
 
682
                 " %s\n", mc->dh_bits, safer_gnutls_strerror(ret));
576
683
    goto globalfail;
577
684
  }
578
685
  
650
757
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
651
758
                      __attribute__((unused)) const char *txt){}
652
759
 
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
 
 
862
760
/* Called when a Mandos server is found */
863
761
__attribute__((nonnull, warn_unused_result))
864
762
static int start_mandos_communication(const char *ip, in_port_t port,
875
773
  int retval = -1;
876
774
  gnutls_session_t session;
877
775
  int pf;                       /* Protocol family */
878
 
  bool route_added = false;
879
776
  
880
777
  errno = 0;
881
778
  
939
836
                 PRIuMAX "\n", ip, (uintmax_t)port);
940
837
  }
941
838
  
942
 
  tcp_sd = socket(pf, SOCK_STREAM | SOCK_CLOEXEC, 0);
 
839
  tcp_sd = socket(pf, SOCK_STREAM, 0);
943
840
  if(tcp_sd < 0){
944
841
    int e = errno;
945
842
    perror_plus("socket");
1034
931
    goto mandos_end;
1035
932
  }
1036
933
  
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;
 
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;
1088
953
  }
1089
954
  
1090
955
  const char *out = mandos_protocol_version;
1273
1138
  
1274
1139
 mandos_end:
1275
1140
  {
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
 
    }
1282
1141
    int e = errno;
1283
1142
    free(decrypted_buffer);
1284
1143
    free(buffer);
1710
1569
  }
1711
1570
}
1712
1571
 
 
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
 
1713
1624
__attribute__((nonnull))
1714
1625
void run_network_hooks(const char *mode, const char *interface,
1715
1626
                       const float delay){
1716
1627
  struct dirent **direntries = NULL;
1717
1628
  if(hookdir_fd == -1){
1718
 
    hookdir_fd = open(hookdir, O_RDONLY | O_DIRECTORY | O_PATH
1719
 
                      | O_CLOEXEC);
 
1629
    hookdir_fd = open(hookdir, O_RDONLY);
1720
1630
    if(hookdir_fd == -1){
1721
1631
      if(errno == ENOENT){
1722
1632
        if(debug){
1747
1657
  }
1748
1658
  struct dirent *direntry;
1749
1659
  int ret;
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
 
  }
 
1660
  int devnull = open("/dev/null", O_RDONLY);
1755
1661
  for(int i = 0; i < numhooks; i++){
1756
1662
    direntry = direntries[i];
1757
1663
    if(debug){
1781
1687
        perror_plus("setgroups");
1782
1688
        _exit(EX_NOPERM);
1783
1689
      }
 
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
      }
1784
1705
      ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1785
1706
      if(ret == -1){
1786
1707
        perror_plus("setenv");
1821
1742
          _exit(EX_OSERR);
1822
1743
        }
1823
1744
      }
1824
 
      int hook_fd = (int)TEMP_FAILURE_RETRY(openat(hookdir_fd,
1825
 
                                                   direntry->d_name,
1826
 
                                                   O_RDONLY));
 
1745
      int hook_fd = openat(hookdir_fd, direntry->d_name, O_RDONLY);
1827
1746
      if(hook_fd == -1){
1828
1747
        perror_plus("openat");
1829
1748
        _exit(EXIT_FAILURE);
1832
1751
        perror_plus("close");
1833
1752
        _exit(EXIT_FAILURE);
1834
1753
      }
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
 
      }
1850
1754
      if(fexecve(hook_fd, (char *const []){ direntry->d_name, NULL },
1851
1755
                 environ) == -1){
1852
1756
        perror_plus("fexecve");
2103
2007
}
2104
2008
 
2105
2009
int main(int argc, char *argv[]){
2106
 
  mandos_context mc = { .server = NULL, .dh_bits = 1024,
 
2010
  mandos_context mc = { .server = NULL, .dh_bits = 0,
2107
2011
                        .priority = "SECURE256:!CTYPE-X.509:"
2108
 
                        "+CTYPE-OPENPGP", .current_server = NULL,
 
2012
                        "+CTYPE-OPENPGP:!RSA", .current_server = NULL,
2109
2013
                        .interfaces = NULL, .interfaces_size = 0 };
2110
2014
  AvahiSServiceBrowser *sb = NULL;
2111
2015
  error_t ret_errno;
2300
2204
      goto end;
2301
2205
    }
2302
2206
  }
2303
 
  
 
2207
    
2304
2208
  {
2305
2209
    /* Work around Debian bug #633582:
2306
2210
       <http://bugs.debian.org/633582> */
2333
2237
          TEMP_FAILURE_RETRY(close(seckey_fd));
2334
2238
        }
2335
2239
      }
2336
 
      
 
2240
    
2337
2241
      if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){
2338
2242
        int pubkey_fd = open(pubkey, O_RDONLY);
2339
2243
        if(pubkey_fd == -1){
2354
2258
          TEMP_FAILURE_RETRY(close(pubkey_fd));
2355
2259
        }
2356
2260
      }
2357
 
      
 
2261
    
2358
2262
      /* Lower privileges */
2359
2263
      ret_errno = lower_privileges();
2360
2264
      if(ret_errno != 0){
2829
2733
  /* Removes the GPGME temp directory and all files inside */
2830
2734
  if(tempdir != NULL){
2831
2735
    struct dirent **direntries = NULL;
2832
 
    int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY
2833
 
                                                  | O_NOFOLLOW
2834
 
                                                  | O_DIRECTORY
2835
 
                                                  | O_PATH));
 
2736
    int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY |
 
2737
                                                  O_NOFOLLOW));
2836
2738
    if(tempdir_fd == -1){
2837
2739
      perror_plus("open");
2838
2740
    } else {