9
9
* "browse_callback", and parts of "main".
11
11
* Everything else is
12
* Copyright © 2008-2013 Teddy Hogeborn
13
* Copyright © 2008-2013 Björn Påhlsson
12
* Copyright © 2008-2012 Teddy Hogeborn
13
* Copyright © 2008-2012 Björn Påhlsson
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
188
186
TEMP_FAILURE_RETRY(fprintf(stream, "Mandos plugin %s: ",
189
187
program_invocation_short_name));
190
return (int)TEMP_FAILURE_RETRY(vfprintf(stream, format, ap));
188
return TEMP_FAILURE_RETRY(vfprintf(stream, format, ap));
198
196
size_t incbuffer(char **buffer, size_t buffer_length,
199
197
size_t buffer_capacity){
200
198
if(buffer_length + BUFFER_SIZE > buffer_capacity){
201
char *new_buf = realloc(*buffer, buffer_capacity + BUFFER_SIZE);
203
int old_errno = errno;
199
*buffer = realloc(*buffer, buffer_capacity + BUFFER_SIZE);
210
203
buffer_capacity += BUFFER_SIZE;
212
205
return buffer_capacity;
667
/* If the interface is specified and we have a list of interfaces */
668
if(if_index != AVAHI_IF_UNSPEC and mc->interfaces != NULL){
669
/* Check if the interface is one of the interfaces we are using */
672
char *interface = NULL;
673
while((interface=argz_next(mc->interfaces, mc->interfaces_size,
675
if(if_nametoindex(interface) == (unsigned int)if_index){
682
/* This interface does not match any in the list, so we don't
683
connect to the server */
685
char interface[IF_NAMESIZE];
686
if(if_indextoname((unsigned int)if_index, interface) == NULL){
687
perror_plus("if_indextoname");
689
fprintf_plus(stderr, "Skipping server on non-used interface"
691
if_indextoname((unsigned int)if_index,
699
660
ret = init_gnutls_session(&session, mc);
742
703
if(af == AF_INET6){
743
704
to.in6.sin6_port = htons(port);
745
#pragma GCC diagnostic push
746
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
748
705
if(IN6_IS_ADDR_LINKLOCAL /* Spurious warnings from */
749
(&to.in6.sin6_addr)){ /* -Wstrict-aliasing=2 or lower */
751
#pragma GCC diagnostic pop
706
(&to.in6.sin6_addr)){ /* -Wstrict-aliasing=2 or lower and
753
708
if(if_index == AVAHI_IF_UNSPEC){
754
709
fprintf_plus(stderr, "An IPv6 link-local address is"
755
710
" incomplete without a network interface\n");
1493
1450
bool run_network_hooks(const char *mode, const char *interface,
1494
1451
const float delay){
1495
1452
struct dirent **direntries;
1453
struct dirent *direntry;
1496
1455
int numhooks = scandir(hookdir, &direntries, runnable_hook,
1498
1457
if(numhooks == -1){
1751
1710
network.ifr_flags &= ~(short)IFF_UP; /* clear flag */
1753
int sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1712
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1755
1714
ret_errno = errno;
1756
1715
perror_plus("socket");
1766
1725
/* Raise priviliges */
1767
1726
raise_privileges();
1769
int ret_setflags = ioctl(sd, SIOCSIFFLAGS, &network);
1728
ret_setflags = ioctl(sd, SIOCSIFFLAGS, &network);
1770
1729
ret_errno = errno;
1772
1731
/* Lower privileges */
1773
1732
lower_privileges();
1775
1734
/* Close the socket */
1776
int ret = (int)TEMP_FAILURE_RETRY(close(sd));
1735
ret = (int)TEMP_FAILURE_RETRY(close(sd));
1778
1737
perror_plus("close");
1796
1755
int main(int argc, char *argv[]){
1797
1756
mandos_context mc = { .server = NULL, .dh_bits = 1024,
1798
1757
.priority = "SECURE256:!CTYPE-X.509:"
1799
"+CTYPE-OPENPGP", .current_server = NULL,
1800
.interfaces = NULL, .interfaces_size = 0 };
1758
"+CTYPE-OPENPGP", .current_server = NULL };
1801
1759
AvahiSServiceBrowser *sb = NULL;
1802
1760
error_t ret_errno;
1804
1762
intmax_t tmpmax;
1806
1764
int exitcode = EXIT_SUCCESS;
1765
char *interfaces = NULL;
1766
size_t interfaces_size = 0;
1807
1767
char *interfaces_to_take_down = NULL;
1808
1768
size_t interfaces_to_take_down_size = 0;
1809
1769
char tempdir[] = "/tmp/mandosXXXXXX";
1812
1772
const char *seckey = PATHDIR "/" SECKEY;
1813
1773
const char *pubkey = PATHDIR "/" PUBKEY;
1814
1774
char *interfaces_hooks = NULL;
1775
size_t interfaces_hooks_size = 0;
1816
1777
bool gnutls_initialized = false;
1817
1778
bool gpgme_initialized = false;
1908
1869
connect_to = arg;
1910
1871
case 'i': /* --interface */
1911
ret_errno = argz_add_sep(&mc.interfaces, &mc.interfaces_size,
1872
ret_errno = argz_add_sep(&interfaces, &interfaces_size, arg,
1913
1874
if(ret_errno != 0){
1914
1875
argp_error(state, "%s", strerror(ret_errno));
2044
2005
/* Lower privileges */
2009
perror_plus("seteuid");
2049
/* Remove invalid interface names (except "none") */
2014
/* Remove empty interface names */
2051
2016
char *interface = NULL;
2052
while((interface = argz_next(mc.interfaces, mc.interfaces_size,
2017
while((interface = argz_next(interfaces, interfaces_size,
2054
if(strcmp(interface, "none") != 0
2055
and if_nametoindex(interface) == 0){
2056
if(interface[0] != '\0'){
2019
if(if_nametoindex(interface) == 0){
2020
if(interface[0] != '\0' and strcmp(interface, "none") != 0){
2057
2021
fprintf_plus(stderr, "Not using nonexisting interface"
2058
2022
" \"%s\"\n", interface);
2060
argz_delete(&mc.interfaces, &mc.interfaces_size, interface);
2024
argz_delete(&interfaces, &interfaces_size, interface);
2061
2025
interface = NULL;
2066
2030
/* Run network hooks */
2068
if(mc.interfaces != NULL){
2069
interfaces_hooks = malloc(mc.interfaces_size);
2033
if(interfaces != NULL){
2034
interfaces_hooks = malloc(interfaces_size);
2070
2035
if(interfaces_hooks == NULL){
2071
2036
perror_plus("malloc");
2074
memcpy(interfaces_hooks, mc.interfaces, mc.interfaces_size);
2075
argz_stringify(interfaces_hooks, mc.interfaces_size, (int)',');
2039
memcpy(interfaces_hooks, interfaces, interfaces_size);
2040
interfaces_hooks_size = interfaces_size;
2041
argz_stringify(interfaces_hooks, interfaces_hooks_size,
2077
2044
if(not run_network_hooks("start", interfaces_hooks != NULL ?
2078
2045
interfaces_hooks : "", delay)){
2162
2129
/* If no interfaces were specified, make a list */
2163
if(mc.interfaces == NULL){
2130
if(interfaces == NULL){
2164
2131
struct dirent **direntries;
2165
2132
/* Look for any good interfaces */
2166
2133
ret = scandir(sys_class_net, &direntries, good_interface,
2169
2136
/* Add all found interfaces to interfaces list */
2170
2137
for(int i = 0; i < ret; ++i){
2171
ret_errno = argz_add(&mc.interfaces, &mc.interfaces_size,
2138
ret_errno = argz_add(&interfaces, &interfaces_size,
2172
2139
direntries[i]->d_name);
2173
2140
if(ret_errno != 0){
2175
2141
perror_plus("argz_add");
2192
/* Bring up interfaces which are down, and remove any "none"s */
2158
/* If we only got one interface, explicitly use only that one */
2159
if(argz_count(interfaces, interfaces_size) == 1){
2161
fprintf_plus(stderr, "Using only interface \"%s\"\n",
2164
if_index = (AvahiIfIndex)if_nametoindex(interfaces);
2167
/* Bring up interfaces which are down */
2168
if(not (argz_count(interfaces, interfaces_size) == 1
2169
and strcmp(interfaces, "none") == 0)){
2194
2170
char *interface = NULL;
2195
while((interface = argz_next(mc.interfaces, mc.interfaces_size,
2171
while((interface = argz_next(interfaces, interfaces_size,
2197
/* If interface name is "none", stop bringing up interfaces.
2198
Also remove all instances of "none" from the list */
2199
if(strcmp(interface, "none") == 0){
2200
argz_delete(&mc.interfaces, &mc.interfaces_size,
2203
while((interface = argz_next(mc.interfaces,
2204
mc.interfaces_size, interface))){
2205
if(strcmp(interface, "none") == 0){
2206
argz_delete(&mc.interfaces, &mc.interfaces_size,
2213
2173
bool interface_was_up = interface_is_up(interface);
2214
2174
ret = bring_up_interface(interface, delay);
2215
2175
if(not interface_was_up){
2220
2180
ret_errno = argz_add(&interfaces_to_take_down,
2221
2181
&interfaces_to_take_down_size,
2225
perror_plus("argz_add");
2188
interfaces_size = 0;
2230
2189
if(debug and (interfaces_to_take_down == NULL)){
2231
2190
fprintf_plus(stderr, "No interfaces were brought up\n");
2235
/* If we only got one interface, explicitly use only that one */
2236
if(argz_count(mc.interfaces, mc.interfaces_size) == 1){
2238
fprintf_plus(stderr, "Using only interface \"%s\"\n",
2241
if_index = (AvahiIfIndex)if_nametoindex(mc.interfaces);