/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

* plugin-runner.c (add_to_char_array): Added "nonnull" attribute.
  (add_argument): Added "nonnull" attribute on the "arg" argument.
  (add_environment): Added "nonnull" attribute on the "def" argument.
  (print_out_password, free_plugin): Added "nonnull" attribute.
  (main/parse_opt): Added "nonnull" attribute on the "state" argument.
* plugins.d/mandos-client.c (perror_plus): Bug fix; restore errno
                                           after fprintf().
* plugins.d/password-prompt.c (fprintf_plus): New.
 (conflict_detection/is_plymouth, main/parse_opt): Added "nonnull"
                                                   attribute.
 (conflict_detection/is_plymouth, conflict_detection, main): Bug fix;
                                                             Call
                                                             error_plus()
                                                             instead
                                                             of
                                                             error().
  (main/parse_opt): Added "nonnull" attribute on the "state" argument.
* plugins.d/plymouth.c (exec_and_wait): Added "nonnull" attribute on
                                        the "path" and "argv"
                                        arguments.
  (is_plymouth): Added "nonnull" attribute.

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-2012 Teddy Hogeborn
13
 
 * Copyright © 2008-2012 Björn Påhlsson
 
12
 * Copyright © 2008-2011 Teddy Hogeborn
 
13
 * Copyright © 2008-2011 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
41
41
 
42
42
#include <stdio.h>              /* fprintf(), stderr, fwrite(),
43
43
                                   stdout, ferror(), remove() */
44
 
#include <stdint.h>             /* uint16_t, uint32_t, intptr_t */
 
44
#include <stdint.h>             /* uint16_t, uint32_t */
45
45
#include <stddef.h>             /* NULL, size_t, ssize_t */
46
46
#include <stdlib.h>             /* free(), EXIT_SUCCESS, srand(),
47
47
                                   strtof(), abort() */
135
135
static const char sys_class_net[] = "/sys/class/net";
136
136
char *connect_to = NULL;
137
137
const char *hookdir = HOOKDIR;
138
 
uid_t uid = 65534;
139
 
gid_t gid = 65534;
140
138
 
141
139
/* Doubly linked list that need to be circularly linked when used */
142
140
typedef struct server{
823
821
    goto mandos_end;
824
822
  }
825
823
  
826
 
  /* This casting via intptr_t is to eliminate warning about casting
827
 
     an int to a pointer type.  This is exactly how the GnuTLS Guile
828
 
     function "set-session-transport-fd!" does it. */
829
 
  gnutls_transport_set_ptr(session,
830
 
                           (gnutls_transport_ptr_t)(intptr_t)tcp_sd);
 
824
  /* Spurious warning from -Wint-to-pointer-cast */
 
825
  gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd);
831
826
  
832
827
  if(quit_now){
833
828
    errno = EINTR;
1392
1387
  }
1393
1388
}
1394
1389
 
1395
 
/* Set effective uid to 0, return errno */
1396
 
int raise_privileges(void){
1397
 
  int old_errno = errno;
1398
 
  int ret_errno = 0;
1399
 
  errno = 0;
1400
 
  if(seteuid(0) == -1){
1401
 
    perror_plus("seteuid");
1402
 
  }
1403
 
  ret_errno = errno;
1404
 
  errno = old_errno;
1405
 
  return ret_errno;
1406
 
}
1407
 
 
1408
 
/* Set effective and real user ID to 0.  Return errno. */
1409
 
int raise_privileges_permanently(void){
1410
 
  int old_errno = errno;
1411
 
  int ret_errno = raise_privileges();
1412
 
  if(ret_errno != 0){
1413
 
    errno = old_errno;
1414
 
    return ret_errno;
1415
 
  }
1416
 
  errno = 0;
1417
 
  if(setuid(0) == -1){
1418
 
    perror_plus("seteuid");
1419
 
  }
1420
 
  ret_errno = errno;
1421
 
  errno = old_errno;
1422
 
  return ret_errno;
1423
 
}
1424
 
 
1425
 
/* Set effective user ID to unprivileged saved user ID */
1426
 
int lower_privileges(void){
1427
 
  int old_errno = errno;
1428
 
  int ret_errno = 0;
1429
 
  errno = 0;
1430
 
  if(seteuid(uid) == -1){
1431
 
    perror_plus("seteuid");
1432
 
  }
1433
 
  ret_errno = errno;
1434
 
  errno = old_errno;
1435
 
  return ret_errno;
1436
 
}
1437
 
 
1438
1390
bool run_network_hooks(const char *mode, const char *interface,
1439
1391
                       const float delay){
1440
1392
  struct dirent **direntries;
1462
1414
      if(hook_pid == 0){
1463
1415
        /* Child */
1464
1416
        /* Raise privileges */
1465
 
        raise_privileges_permanently();
 
1417
        errno = 0;
 
1418
        ret = seteuid(0);
 
1419
        if(ret == -1){
 
1420
          perror_plus("seteuid");
 
1421
        }
 
1422
        /* Raise privileges even more */
 
1423
        errno = 0;
 
1424
        ret = setuid(0);
 
1425
        if(ret == -1){
 
1426
          perror_plus("setuid");
 
1427
        }
1466
1428
        /* Set group */
1467
1429
        errno = 0;
1468
1430
        ret = setgid(0);
1488
1450
          perror_plus("setenv");
1489
1451
          _exit(EX_OSERR);
1490
1452
        }
1491
 
        ret = setenv("VERBOSITY", debug ? "1" : "0", 1);
 
1453
        ret = setenv("VERBOSE", debug ? "1" : "0", 1);
1492
1454
        if(ret == -1){
1493
1455
          perror_plus("setenv");
1494
1456
          _exit(EX_OSERR);
1511
1473
          _exit(EX_OSERR);
1512
1474
        }
1513
1475
        free(delaystring);
1514
 
        if(connect_to != NULL){
1515
 
          ret = setenv("CONNECT", connect_to, 1);
1516
 
          if(ret == -1){
1517
 
            perror_plus("setenv");
1518
 
            _exit(EX_OSERR);
1519
 
          }
1520
 
        }
1521
1476
        if(execl(fullname, direntry->d_name, mode, NULL) == -1){
1522
1477
          perror_plus("execl");
1523
1478
          _exit(EXIT_FAILURE);
1561
1516
  return true;
1562
1517
}
1563
1518
 
1564
 
int bring_up_interface(const char * const interface, const float delay){
1565
 
  int sd = -1;
1566
 
  int old_errno = errno;
1567
 
  int ret_errno = 0;
1568
 
  int ret;
1569
 
  struct ifreq network;
1570
 
  AvahiIfIndex if_index = (AvahiIfIndex)if_nametoindex(interface);
1571
 
  if(if_index == 0){
1572
 
    fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
1573
 
    errno = old_errno;
1574
 
    return ENXIO;
1575
 
  }
1576
 
  
1577
 
  if(quit_now){
1578
 
    errno = old_errno;
1579
 
    return EINTR;
1580
 
  }
1581
 
  
1582
 
  /* Re-raise priviliges */
1583
 
  raise_privileges();
1584
 
  
1585
 
#ifdef __linux__
1586
 
  /* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
1587
 
     messages about the network interface to mess up the prompt */
1588
 
  ret = klogctl(8, NULL, 5);
1589
 
  bool restore_loglevel = true;
1590
 
  if(ret == -1){
1591
 
    restore_loglevel = false;
1592
 
    perror_plus("klogctl");
1593
 
  }
1594
 
#endif  /* __linux__ */
1595
 
    
1596
 
  sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1597
 
  if(sd < 0){
1598
 
    ret_errno = errno;
1599
 
    perror_plus("socket");
1600
 
#ifdef __linux__
1601
 
    if(restore_loglevel){
1602
 
      ret = klogctl(7, NULL, 0);
1603
 
      if(ret == -1){
1604
 
        perror_plus("klogctl");
1605
 
      }
1606
 
    }
1607
 
#endif  /* __linux__ */
1608
 
    /* Lower privileges */
1609
 
    lower_privileges();
1610
 
    errno = old_errno;
1611
 
    return ret_errno;
1612
 
  }
1613
 
  strcpy(network.ifr_name, interface);
1614
 
  ret = ioctl(sd, SIOCGIFFLAGS, &network);
1615
 
  if(ret == -1){
1616
 
    ret_errno = errno;
1617
 
    perror_plus("ioctl SIOCGIFFLAGS");
1618
 
#ifdef __linux__
1619
 
    if(restore_loglevel){
1620
 
      ret = klogctl(7, NULL, 0);
1621
 
      if(ret == -1){
1622
 
        perror_plus("klogctl");
1623
 
      }
1624
 
    }
1625
 
#endif  /* __linux__ */
1626
 
    /* Lower privileges */
1627
 
    lower_privileges();
1628
 
    errno = old_errno;
1629
 
    return ret_errno;
1630
 
  }
1631
 
  if((network.ifr_flags & IFF_UP) == 0){
1632
 
    network.ifr_flags |= IFF_UP;
1633
 
    ret = ioctl(sd, SIOCSIFFLAGS, &network);
1634
 
    if(ret == -1){
1635
 
      ret_errno = errno;
1636
 
      perror_plus("ioctl SIOCSIFFLAGS +IFF_UP");
1637
 
#ifdef __linux__
1638
 
      if(restore_loglevel){
1639
 
        ret = klogctl(7, NULL, 0);
1640
 
        if(ret == -1){
1641
 
          perror_plus("klogctl");
1642
 
        }
1643
 
      }
1644
 
#endif  /* __linux__ */
1645
 
        /* Lower privileges */
1646
 
      lower_privileges();
1647
 
      errno = old_errno;
1648
 
      return ret_errno;
1649
 
    }
1650
 
  }
1651
 
  /* Sleep checking until interface is running.
1652
 
     Check every 0.25s, up to total time of delay */
1653
 
  for(int i=0; i < delay * 4; i++){
1654
 
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
1655
 
    if(ret == -1){
1656
 
      perror_plus("ioctl SIOCGIFFLAGS");
1657
 
    } else if(network.ifr_flags & IFF_RUNNING){
1658
 
      break;
1659
 
    }
1660
 
    struct timespec sleeptime = { .tv_nsec = 250000000 };
1661
 
    ret = nanosleep(&sleeptime, NULL);
1662
 
    if(ret == -1 and errno != EINTR){
1663
 
      perror_plus("nanosleep");
1664
 
    }
1665
 
  }
1666
 
  /* Close the socket */
1667
 
  ret = (int)TEMP_FAILURE_RETRY(close(sd));
1668
 
  if(ret == -1){
1669
 
    perror_plus("close");
1670
 
  }
1671
 
#ifdef __linux__
1672
 
  if(restore_loglevel){
1673
 
    /* Restores kernel loglevel to default */
1674
 
    ret = klogctl(7, NULL, 0);
1675
 
    if(ret == -1){
1676
 
      perror_plus("klogctl");
1677
 
    }
1678
 
  }
1679
 
#endif  /* __linux__ */
1680
 
  /* Lower privileges */
1681
 
  lower_privileges();
1682
 
  errno = old_errno;
1683
 
  return 0;
1684
 
}
1685
 
 
1686
1519
int main(int argc, char *argv[]){
1687
1520
  AvahiSServiceBrowser *sb = NULL;
1688
1521
  int error;
1694
1527
  struct ifreq network;
1695
1528
  int sd = -1;
1696
1529
  bool take_down_interface = false;
 
1530
  uid_t uid;
 
1531
  gid_t gid;
1697
1532
  char tempdir[] = "/tmp/mandosXXXXXX";
1698
1533
  bool tempdir_created = false;
1699
1534
  AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
1766
1601
        .group = 2 },
1767
1602
      { .name = "retry", .key = 132,
1768
1603
        .arg = "SECONDS",
1769
 
        .doc = "Retry interval used when denied by the Mandos server",
 
1604
        .doc = "Retry interval used when denied by the mandos server",
1770
1605
        .group = 2 },
1771
1606
      { .name = "network-hook-dir", .key = 133,
1772
1607
        .arg = "DIR",
1879
1714
       <http://bugs.debian.org/633582> */
1880
1715
    
1881
1716
    /* Re-raise priviliges */
1882
 
    if(raise_privileges() == 0){
 
1717
    errno = 0;
 
1718
    ret = seteuid(0);
 
1719
    if(ret == -1){
 
1720
      perror_plus("seteuid");
 
1721
    } else {
1883
1722
      struct stat st;
1884
1723
      
1885
1724
      if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){
2050
1889
  }
2051
1890
  
2052
1891
  /* If the interface is down, bring it up */
2053
 
  if((interface[0] != '\0') and (strcmp(interface, "none") != 0)){
2054
 
    ret = bring_up_interface(interface, delay);
2055
 
    if(ret != 0){
2056
 
      errno = ret;
2057
 
      perror_plus("Failed to bring up interface");
 
1892
  if(strcmp(interface, "none") != 0){
 
1893
    if_index = (AvahiIfIndex) if_nametoindex(interface);
 
1894
    if(if_index == 0){
 
1895
      fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
 
1896
      exitcode = EX_UNAVAILABLE;
 
1897
      goto end;
 
1898
    }
 
1899
    
 
1900
    if(quit_now){
 
1901
      goto end;
 
1902
    }
 
1903
    
 
1904
    /* Re-raise priviliges */
 
1905
    errno = 0;
 
1906
    ret = seteuid(0);
 
1907
    if(ret == -1){
 
1908
      perror_plus("seteuid");
 
1909
    }
 
1910
    
 
1911
#ifdef __linux__
 
1912
    /* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
 
1913
       messages about the network interface to mess up the prompt */
 
1914
    ret = klogctl(8, NULL, 5);
 
1915
    bool restore_loglevel = true;
 
1916
    if(ret == -1){
 
1917
      restore_loglevel = false;
 
1918
      perror_plus("klogctl");
 
1919
    }
 
1920
#endif  /* __linux__ */
 
1921
    
 
1922
    sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
 
1923
    if(sd < 0){
 
1924
      perror_plus("socket");
 
1925
      exitcode = EX_OSERR;
 
1926
#ifdef __linux__
 
1927
      if(restore_loglevel){
 
1928
        ret = klogctl(7, NULL, 0);
 
1929
        if(ret == -1){
 
1930
          perror_plus("klogctl");
 
1931
        }
 
1932
      }
 
1933
#endif  /* __linux__ */
 
1934
      /* Lower privileges */
 
1935
      errno = 0;
 
1936
      ret = seteuid(uid);
 
1937
      if(ret == -1){
 
1938
        perror_plus("seteuid");
 
1939
      }
 
1940
      goto end;
 
1941
    }
 
1942
    strcpy(network.ifr_name, interface);
 
1943
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
1944
    if(ret == -1){
 
1945
      perror_plus("ioctl SIOCGIFFLAGS");
 
1946
#ifdef __linux__
 
1947
      if(restore_loglevel){
 
1948
        ret = klogctl(7, NULL, 0);
 
1949
        if(ret == -1){
 
1950
          perror_plus("klogctl");
 
1951
        }
 
1952
      }
 
1953
#endif  /* __linux__ */
 
1954
      exitcode = EX_OSERR;
 
1955
      /* Lower privileges */
 
1956
      errno = 0;
 
1957
      ret = seteuid(uid);
 
1958
      if(ret == -1){
 
1959
        perror_plus("seteuid");
 
1960
      }
 
1961
      goto end;
 
1962
    }
 
1963
    if((network.ifr_flags & IFF_UP) == 0){
 
1964
      network.ifr_flags |= IFF_UP;
 
1965
      take_down_interface = true;
 
1966
      ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
1967
      if(ret == -1){
 
1968
        take_down_interface = false;
 
1969
        perror_plus("ioctl SIOCSIFFLAGS +IFF_UP");
 
1970
        exitcode = EX_OSERR;
 
1971
#ifdef __linux__
 
1972
        if(restore_loglevel){
 
1973
          ret = klogctl(7, NULL, 0);
 
1974
          if(ret == -1){
 
1975
            perror_plus("klogctl");
 
1976
          }
 
1977
        }
 
1978
#endif  /* __linux__ */
 
1979
        /* Lower privileges */
 
1980
        errno = 0;
 
1981
        ret = seteuid(uid);
 
1982
        if(ret == -1){
 
1983
          perror_plus("seteuid");
 
1984
        }
 
1985
        goto end;
 
1986
      }
 
1987
    }
 
1988
    /* Sleep checking until interface is running.
 
1989
       Check every 0.25s, up to total time of delay */
 
1990
    for(int i=0; i < delay * 4; i++){
 
1991
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
1992
      if(ret == -1){
 
1993
        perror_plus("ioctl SIOCGIFFLAGS");
 
1994
      } else if(network.ifr_flags & IFF_RUNNING){
 
1995
        break;
 
1996
      }
 
1997
      struct timespec sleeptime = { .tv_nsec = 250000000 };
 
1998
      ret = nanosleep(&sleeptime, NULL);
 
1999
      if(ret == -1 and errno != EINTR){
 
2000
        perror_plus("nanosleep");
 
2001
      }
 
2002
    }
 
2003
    if(not take_down_interface){
 
2004
      /* We won't need the socket anymore */
 
2005
      ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
2006
      if(ret == -1){
 
2007
        perror_plus("close");
 
2008
      }
 
2009
    }
 
2010
#ifdef __linux__
 
2011
    if(restore_loglevel){
 
2012
      /* Restores kernel loglevel to default */
 
2013
      ret = klogctl(7, NULL, 0);
 
2014
      if(ret == -1){
 
2015
        perror_plus("klogctl");
 
2016
      }
 
2017
    }
 
2018
#endif  /* __linux__ */
 
2019
    /* Lower privileges */
 
2020
    errno = 0;
 
2021
    /* Lower privileges */
 
2022
    ret = seteuid(uid);
 
2023
    if(ret == -1){
 
2024
      perror_plus("seteuid");
2058
2025
    }
2059
2026
  }
2060
2027
  
2101
2068
    /* Connect directly, do not use Zeroconf */
2102
2069
    /* (Mainly meant for debugging) */
2103
2070
    char *address = strrchr(connect_to, ':');
2104
 
    
2105
2071
    if(address == NULL){
2106
2072
      fprintf_plus(stderr, "No colon in address\n");
2107
2073
      exitcode = EX_USAGE;
2270
2236
  
2271
2237
  /* Re-raise priviliges */
2272
2238
  {
2273
 
    raise_privileges();
 
2239
    errno = 0;
 
2240
    ret = seteuid(0);
 
2241
    if(ret == -1){
 
2242
      perror_plus("seteuid");
 
2243
    }
2274
2244
    
2275
2245
    /* Take down the network interface */
2276
2246
    if(take_down_interface and geteuid() == 0){