/mandos/release

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

« back to all changes in this revision

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

  • Committer: Teddy Hogeborn
  • Date: 2014-06-15 01:01:14 UTC
  • mto: (237.7.272 trunk)
  • mto: This revision was merged to the branch mainline in revision 317.
  • Revision ID: teddy@recompile.se-20140615010114-fzz32p5naoo8nket
mandos-client: Better error messages.

* Makefile (run-client): Update message to match current messages.
                         Also set GNOME_KEYRING_CONTROL to empty
                         string to block pam_gnome_keyring.
* plugins.d/mandos-client (raise_privileges): Do not print errors.
  (raise_privileges_permanently): - '' -
  (lower_privileges): - '' -
  (lower_privileges_permanently): - '' -
  (run_network_hooks): Print errors from above functions correctly.
  (bring_up_interface, take_down_interface, main): - '' -

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
234
234
                          .af = af };
235
235
  if(new_server->ip == NULL){
236
236
    perror_plus("strdup");
237
 
    free(new_server);
238
237
    return false;
239
238
  }
240
239
  ret = clock_gettime(CLOCK_MONOTONIC, &(new_server->last_seen));
241
240
  if(ret == -1){
242
241
    perror_plus("clock_gettime");
243
 
#ifdef __GNUC__
244
 
#pragma GCC diagnostic push
245
 
#pragma GCC diagnostic ignored "-Wcast-qual"
246
 
#endif
247
 
    free((char *)(new_server->ip));
248
 
#ifdef __GNUC__
249
 
#pragma GCC diagnostic pop
250
 
#endif
251
 
    free(new_server);
252
242
    return false;
253
243
  }
254
244
  /* Special case of first server */
650
640
static void empty_log(__attribute__((unused)) AvahiLogLevel level,
651
641
                      __attribute__((unused)) const char *txt){}
652
642
 
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 remove_arg[] = "remove";
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 : remove_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
643
/* Called when a Mandos server is found */
863
644
__attribute__((nonnull, warn_unused_result))
864
645
static int start_mandos_communication(const char *ip, in_port_t port,
875
656
  int retval = -1;
876
657
  gnutls_session_t session;
877
658
  int pf;                       /* Protocol family */
878
 
  bool route_added = false;
879
659
  
880
660
  errno = 0;
881
661
  
939
719
                 PRIuMAX "\n", ip, (uintmax_t)port);
940
720
  }
941
721
  
942
 
  tcp_sd = socket(pf, SOCK_STREAM | SOCK_CLOEXEC, 0);
 
722
  tcp_sd = socket(pf, SOCK_STREAM, 0);
943
723
  if(tcp_sd < 0){
944
724
    int e = errno;
945
725
    perror_plus("socket");
1034
814
    goto mandos_end;
1035
815
  }
1036
816
  
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;
 
817
  if(af == AF_INET6){
 
818
    ret = connect(tcp_sd, (struct sockaddr *)&to,
 
819
                  sizeof(struct sockaddr_in6));
 
820
  } else {
 
821
    ret = connect(tcp_sd, (struct sockaddr *)&to, /* IPv4 */
 
822
                  sizeof(struct sockaddr_in));
 
823
  }
 
824
  if(ret < 0){
 
825
    if((errno != ECONNREFUSED and errno != ENETUNREACH) or debug){
 
826
      int e = errno;
 
827
      perror_plus("connect");
 
828
      errno = e;
 
829
    }
 
830
    goto mandos_end;
 
831
  }
 
832
  
 
833
  if(quit_now){
 
834
    errno = EINTR;
 
835
    goto mandos_end;
1088
836
  }
1089
837
  
1090
838
  const char *out = mandos_protocol_version;
1273
1021
  
1274
1022
 mandos_end:
1275
1023
  {
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
1024
    int e = errno;
1283
1025
    free(decrypted_buffer);
1284
1026
    free(buffer);
1324
1066
     timed out */
1325
1067
  
1326
1068
  if(quit_now){
1327
 
    avahi_s_service_resolver_free(r);
1328
1069
    return;
1329
1070
  }
1330
1071
  
1710
1451
  }
1711
1452
}
1712
1453
 
 
1454
/* Set effective uid to 0, return errno */
 
1455
__attribute__((warn_unused_result))
 
1456
error_t raise_privileges(void){
 
1457
  error_t old_errno = errno;
 
1458
  error_t ret_errno = 0;
 
1459
  if(seteuid(0) == -1){
 
1460
    ret_errno = errno;
 
1461
  }
 
1462
  errno = old_errno;
 
1463
  return ret_errno;
 
1464
}
 
1465
 
 
1466
/* Set effective and real user ID to 0.  Return errno. */
 
1467
__attribute__((warn_unused_result))
 
1468
error_t raise_privileges_permanently(void){
 
1469
  error_t old_errno = errno;
 
1470
  error_t ret_errno = raise_privileges();
 
1471
  if(ret_errno != 0){
 
1472
    errno = old_errno;
 
1473
    return ret_errno;
 
1474
  }
 
1475
  if(setuid(0) == -1){
 
1476
    ret_errno = errno;
 
1477
  }
 
1478
  errno = old_errno;
 
1479
  return ret_errno;
 
1480
}
 
1481
 
 
1482
/* Set effective user ID to unprivileged saved user ID */
 
1483
__attribute__((warn_unused_result))
 
1484
error_t lower_privileges(void){
 
1485
  error_t old_errno = errno;
 
1486
  error_t ret_errno = 0;
 
1487
  if(seteuid(uid) == -1){
 
1488
    ret_errno = errno;
 
1489
  }
 
1490
  errno = old_errno;
 
1491
  return ret_errno;
 
1492
}
 
1493
 
 
1494
/* Lower privileges permanently */
 
1495
__attribute__((warn_unused_result))
 
1496
error_t lower_privileges_permanently(void){
 
1497
  error_t old_errno = errno;
 
1498
  error_t ret_errno = 0;
 
1499
  if(setuid(uid) == -1){
 
1500
    ret_errno = errno;
 
1501
  }
 
1502
  errno = old_errno;
 
1503
  return ret_errno;
 
1504
}
 
1505
 
1713
1506
__attribute__((nonnull))
1714
1507
void run_network_hooks(const char *mode, const char *interface,
1715
1508
                       const float delay){
1716
1509
  struct dirent **direntries = NULL;
1717
1510
  if(hookdir_fd == -1){
1718
 
    hookdir_fd = open(hookdir, O_RDONLY | O_DIRECTORY | O_PATH
1719
 
                      | O_CLOEXEC);
 
1511
    hookdir_fd = open(hookdir, O_RDONLY);
1720
1512
    if(hookdir_fd == -1){
1721
1513
      if(errno == ENOENT){
1722
1514
        if(debug){
1747
1539
  }
1748
1540
  struct dirent *direntry;
1749
1541
  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
 
  }
 
1542
  int devnull = open("/dev/null", O_RDONLY);
1755
1543
  for(int i = 0; i < numhooks; i++){
1756
1544
    direntry = direntries[i];
1757
1545
    if(debug){
1781
1569
        perror_plus("setgroups");
1782
1570
        _exit(EX_NOPERM);
1783
1571
      }
 
1572
      ret = dup2(devnull, STDIN_FILENO);
 
1573
      if(ret == -1){
 
1574
        perror_plus("dup2(devnull, STDIN_FILENO)");
 
1575
        _exit(EX_OSERR);
 
1576
      }
 
1577
      ret = close(devnull);
 
1578
      if(ret == -1){
 
1579
        perror_plus("close");
 
1580
        _exit(EX_OSERR);
 
1581
      }
 
1582
      ret = dup2(STDERR_FILENO, STDOUT_FILENO);
 
1583
      if(ret == -1){
 
1584
        perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
 
1585
        _exit(EX_OSERR);
 
1586
      }
1784
1587
      ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1785
1588
      if(ret == -1){
1786
1589
        perror_plus("setenv");
1821
1624
          _exit(EX_OSERR);
1822
1625
        }
1823
1626
      }
1824
 
      int hook_fd = (int)TEMP_FAILURE_RETRY(openat(hookdir_fd,
1825
 
                                                   direntry->d_name,
1826
 
                                                   O_RDONLY));
 
1627
      int hook_fd = openat(hookdir_fd, direntry->d_name, O_RDONLY);
1827
1628
      if(hook_fd == -1){
1828
1629
        perror_plus("openat");
1829
1630
        _exit(EXIT_FAILURE);
1832
1633
        perror_plus("close");
1833
1634
        _exit(EXIT_FAILURE);
1834
1635
      }
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
1636
      if(fexecve(hook_fd, (char *const []){ direntry->d_name, NULL },
1851
1637
                 environ) == -1){
1852
1638
        perror_plus("fexecve");
1853
1639
        _exit(EXIT_FAILURE);
1854
1640
      }
1855
1641
    } else {
1856
 
      if(hook_pid == -1){
1857
 
        perror_plus("fork");
1858
 
        free(direntry);
1859
 
        continue;
1860
 
      }
1861
1642
      int status;
1862
1643
      if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
1863
1644
        perror_plus("waitpid");
1864
 
        free(direntry);
1865
1645
        continue;
1866
1646
      }
1867
1647
      if(WIFEXITED(status)){
1869
1649
          fprintf_plus(stderr, "Warning: network hook \"%s\" exited"
1870
1650
                       " with status %d\n", direntry->d_name,
1871
1651
                       WEXITSTATUS(status));
1872
 
          free(direntry);
1873
1652
          continue;
1874
1653
        }
1875
1654
      } else if(WIFSIGNALED(status)){
1876
1655
        fprintf_plus(stderr, "Warning: network hook \"%s\" died by"
1877
1656
                     " signal %d\n", direntry->d_name,
1878
1657
                     WTERMSIG(status));
1879
 
        free(direntry);
1880
1658
        continue;
1881
1659
      } else {
1882
1660
        fprintf_plus(stderr, "Warning: network hook \"%s\""
1883
1661
                     " crashed\n", direntry->d_name);
1884
 
        free(direntry);
1885
1662
        continue;
1886
1663
      }
1887
1664
    }
1889
1666
      fprintf_plus(stderr, "Network hook \"%s\" ran successfully\n",
1890
1667
                   direntry->d_name);
1891
1668
    }
1892
 
    free(direntry);
1893
1669
  }
1894
1670
  free(direntries);
1895
1671
  if((int)TEMP_FAILURE_RETRY(close(hookdir_fd)) == -1){
2300
2076
      goto end;
2301
2077
    }
2302
2078
  }
2303
 
  
 
2079
    
2304
2080
  {
2305
2081
    /* Work around Debian bug #633582:
2306
2082
       <http://bugs.debian.org/633582> */
2333
2109
          TEMP_FAILURE_RETRY(close(seckey_fd));
2334
2110
        }
2335
2111
      }
2336
 
      
 
2112
    
2337
2113
      if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){
2338
2114
        int pubkey_fd = open(pubkey, O_RDONLY);
2339
2115
        if(pubkey_fd == -1){
2354
2130
          TEMP_FAILURE_RETRY(close(pubkey_fd));
2355
2131
        }
2356
2132
      }
2357
 
      
 
2133
    
2358
2134
      /* Lower privileges */
2359
2135
      ret_errno = lower_privileges();
2360
2136
      if(ret_errno != 0){
2489
2265
        if(ret_errno != 0){
2490
2266
          errno = ret_errno;
2491
2267
          perror_plus("argz_add");
2492
 
          free(direntries[i]);
2493
2268
          continue;
2494
2269
        }
2495
2270
        if(debug){
2496
2271
          fprintf_plus(stderr, "Will use interface \"%s\"\n",
2497
2272
                       direntries[i]->d_name);
2498
2273
        }
2499
 
        free(direntries[i]);
2500
2274
      }
2501
2275
      free(direntries);
2502
2276
    } else {
2772
2546
    mc.current_server->prev->next = NULL;
2773
2547
    while(mc.current_server != NULL){
2774
2548
      server *next = mc.current_server->next;
2775
 
#ifdef __GNUC__
2776
 
#pragma GCC diagnostic push
2777
 
#pragma GCC diagnostic ignored "-Wcast-qual"
2778
 
#endif
2779
 
      free((char *)(mc.current_server->ip));
2780
 
#ifdef __GNUC__
2781
 
#pragma GCC diagnostic pop
2782
 
#endif
2783
2549
      free(mc.current_server);
2784
2550
      mc.current_server = next;
2785
2551
    }
2829
2595
  /* Removes the GPGME temp directory and all files inside */
2830
2596
  if(tempdir != NULL){
2831
2597
    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));
 
2598
    int tempdir_fd = (int)TEMP_FAILURE_RETRY(open(tempdir, O_RDONLY |
 
2599
                                                  O_NOFOLLOW));
2836
2600
    if(tempdir_fd == -1){
2837
2601
      perror_plus("open");
2838
2602
    } else {
2856
2620
                         " \"%s\", 0): %s\n", tempdir,
2857
2621
                         direntries[i]->d_name, strerror(errno));
2858
2622
          }
2859
 
          free(direntries[i]);
2860
2623
        }
2861
2624
        
2862
2625
        /* need to clean even if 0 because man page doesn't specify */