235
224
perror_plus("strdup");
238
ret = clock_gettime(CLOCK_MONOTONIC, &(new_server->last_seen));
240
perror_plus("clock_gettime");
243
227
/* Special case of first server */
244
228
if(*current_server == NULL){
245
229
new_server->next = new_server;
246
230
new_server->prev = new_server;
247
231
*current_server = new_server;
232
/* Place the new server last in the list */
249
/* Place the new server last in the list */
250
234
new_server->next = *current_server;
251
235
new_server->prev = (*current_server)->prev;
252
236
new_server->prev->next = new_server;
253
237
(*current_server)->prev = new_server;
239
ret = clock_gettime(CLOCK_MONOTONIC, &(*current_server)->last_seen);
241
perror_plus("clock_gettime");
259
248
* Initialize GPGME.
261
__attribute__((nonnull, warn_unused_result))
262
static bool init_gpgme(const char * const seckey,
263
const char * const pubkey,
264
const char * const tempdir,
250
static bool init_gpgme(const char *seckey, const char *pubkey,
251
const char *tempdir, mandos_context *mc){
266
252
gpgme_error_t rc;
267
253
gpgme_engine_info_t engine_info;
270
256
* Helper function to insert pub and seckey to the engine keyring.
272
bool import_key(const char * const filename){
258
bool import_key(const char *filename){
275
261
gpgme_data_t pgp_data;
789
779
char addrstr[(INET_ADDRSTRLEN > INET6_ADDRSTRLEN) ?
790
780
INET_ADDRSTRLEN : INET6_ADDRSTRLEN] = "";
791
782
if(af == AF_INET6){
792
ret = getnameinfo((struct sockaddr *)&to,
793
sizeof(struct sockaddr_in6),
794
addrstr, sizeof(addrstr), NULL, 0,
783
pcret = inet_ntop(af, &(to.in6.sin6_addr), addrstr,
797
ret = getnameinfo((struct sockaddr *)&to,
798
sizeof(struct sockaddr_in),
799
addrstr, sizeof(addrstr), NULL, 0,
786
pcret = inet_ntop(af, &(to.in.sin_addr), addrstr,
802
if(ret == EAI_SYSTEM){
803
perror_plus("getnameinfo");
804
} else if(ret != 0) {
805
fprintf_plus(stderr, "getnameinfo: %s", gai_strerror(ret));
806
} else if(strcmp(addrstr, ip) != 0){
807
fprintf_plus(stderr, "Canonical address form: %s\n", addrstr);
790
perror_plus("inet_ntop");
792
if(strcmp(addrstr, ip) != 0){
793
fprintf_plus(stderr, "Canonical address form: %s\n", addrstr);
1506
1485
return ret_errno;
1511
* Based on the example in the GNU LibC manual chapter 13.13 "File
1512
* Descriptor Flags".
1513
| [[info:libc:Descriptor%20Flags][File Descriptor Flags]] |
1515
__attribute__((warn_unused_result))
1516
static int set_cloexec_flag(int fd){
1517
int ret = (int)TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD, 0));
1518
/* If reading the flags failed, return error indication now. */
1522
/* Store modified flag word in the descriptor. */
1523
return (int)TEMP_FAILURE_RETRY(fcntl(fd, F_SETFD,
1526
#endif /* not O_CLOEXEC */
1528
__attribute__((nonnull))
1529
void run_network_hooks(const char *mode, const char *interface,
1488
bool run_network_hooks(const char *mode, const char *interface,
1530
1489
const float delay){
1531
1490
struct dirent **direntries;
1532
if(hookdir_fd == -1){
1533
hookdir_fd = open(hookdir, O_RDONLY |
1536
#else /* not O_CLOEXEC */
1538
#endif /* not O_CLOEXEC */
1540
if(hookdir_fd == -1){
1541
if(errno == ENOENT){
1543
fprintf_plus(stderr, "Network hook directory \"%s\" not"
1544
" found\n", hookdir);
1547
perror_plus("open");
1552
if(set_cloexec_flag(hookdir_fd) < 0){
1553
perror_plus("set_cloexec_flag");
1554
if((int)TEMP_FAILURE_RETRY(close(hookdir_fd)) == -1){
1555
perror_plus("close");
1561
#endif /* not O_CLOEXEC */
1564
#if __GLIBC_PREREQ(2, 15)
1565
int numhooks = scandirat(hookdir_fd, ".", &direntries,
1566
runnable_hook, alphasort);
1567
#else /* not __GLIBC_PREREQ(2, 15) */
1568
int numhooks = scandir(hookdir, &direntries, runnable_hook,
1570
#endif /* not __GLIBC_PREREQ(2, 15) */
1571
#else /* not __GLIBC__ */
1572
int numhooks = scandir(hookdir, &direntries, runnable_hook,
1574
#endif /* not __GLIBC__ */
1491
struct dirent *direntry;
1493
int numhooks = scandir(hookdir, &direntries, runnable_hook,
1575
1495
if(numhooks == -1){
1576
perror_plus("scandir");
1579
struct dirent *direntry;
1581
int devnull = open("/dev/null", O_RDONLY);
1582
for(int i = 0; i < numhooks; i++){
1583
direntry = direntries[i];
1585
fprintf_plus(stderr, "Running network hook \"%s\"\n",
1496
if(errno == ENOENT){
1498
fprintf_plus(stderr, "Network hook directory \"%s\" not"
1499
" found\n", hookdir);
1502
perror_plus("scandir");
1588
pid_t hook_pid = fork();
1591
/* Raise privileges */
1592
if(raise_privileges_permanently() != 0){
1593
perror_plus("Failed to raise privileges");
1600
perror_plus("setgid");
1603
/* Reset supplementary groups */
1605
ret = setgroups(0, NULL);
1607
perror_plus("setgroups");
1610
ret = dup2(devnull, STDIN_FILENO);
1612
perror_plus("dup2(devnull, STDIN_FILENO)");
1615
ret = close(devnull);
1617
perror_plus("close");
1620
ret = dup2(STDERR_FILENO, STDOUT_FILENO);
1622
perror_plus("dup2(STDERR_FILENO, STDOUT_FILENO)");
1625
ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1627
perror_plus("setenv");
1630
ret = setenv("DEVICE", interface, 1);
1632
perror_plus("setenv");
1635
ret = setenv("VERBOSITY", debug ? "1" : "0", 1);
1637
perror_plus("setenv");
1640
ret = setenv("MODE", mode, 1);
1642
perror_plus("setenv");
1646
ret = asprintf(&delaystring, "%f", (double)delay);
1505
int devnull = open("/dev/null", O_RDONLY);
1506
for(int i = 0; i < numhooks; i++){
1507
direntry = direntries[i];
1508
char *fullname = NULL;
1509
ret = asprintf(&fullname, "%s/%s", hookdir, direntry->d_name);
1648
1511
perror_plus("asprintf");
1651
ret = setenv("DELAY", delaystring, 1);
1515
fprintf_plus(stderr, "Running network hook \"%s\"\n",
1518
pid_t hook_pid = fork();
1521
/* Raise privileges */
1522
raise_privileges_permanently();
1527
perror_plus("setgid");
1529
/* Reset supplementary groups */
1531
ret = setgroups(0, NULL);
1533
perror_plus("setgroups");
1535
dup2(devnull, STDIN_FILENO);
1537
dup2(STDERR_FILENO, STDOUT_FILENO);
1538
ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1540
perror_plus("setenv");
1543
ret = setenv("DEVICE", interface, 1);
1545
perror_plus("setenv");
1548
ret = setenv("VERBOSITY", debug ? "1" : "0", 1);
1550
perror_plus("setenv");
1553
ret = setenv("MODE", mode, 1);
1555
perror_plus("setenv");
1559
ret = asprintf(&delaystring, "%f", delay);
1561
perror_plus("asprintf");
1564
ret = setenv("DELAY", delaystring, 1);
1567
perror_plus("setenv");
1653
1570
free(delaystring);
1654
perror_plus("setenv");
1658
if(connect_to != NULL){
1659
ret = setenv("CONNECT", connect_to, 1);
1661
perror_plus("setenv");
1665
if(fexecve(hookdir_fd, (char *const [])
1666
{ direntry->d_name, NULL }, environ) == -1){
1667
perror_plus("fexecve");
1668
_exit(EXIT_FAILURE);
1672
if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
1673
perror_plus("waitpid");
1676
if(WIFEXITED(status)){
1677
if(WEXITSTATUS(status) != 0){
1678
fprintf_plus(stderr, "Warning: network hook \"%s\" exited"
1679
" with status %d\n", direntry->d_name,
1680
WEXITSTATUS(status));
1683
} else if(WIFSIGNALED(status)){
1684
fprintf_plus(stderr, "Warning: network hook \"%s\" died by"
1685
" signal %d\n", direntry->d_name,
1571
if(connect_to != NULL){
1572
ret = setenv("CONNECT", connect_to, 1);
1574
perror_plus("setenv");
1578
if(execl(fullname, direntry->d_name, mode, NULL) == -1){
1579
perror_plus("execl");
1580
_exit(EXIT_FAILURE);
1689
fprintf_plus(stderr, "Warning: network hook \"%s\""
1690
" crashed\n", direntry->d_name);
1695
fprintf_plus(stderr, "Network hook \"%s\" ran successfully\n",
1699
if((int)TEMP_FAILURE_RETRY(close(hookdir_fd)) == -1){
1700
perror_plus("close");
1584
if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
1585
perror_plus("waitpid");
1589
if(WIFEXITED(status)){
1590
if(WEXITSTATUS(status) != 0){
1591
fprintf_plus(stderr, "Warning: network hook \"%s\" exited"
1592
" with status %d\n", direntry->d_name,
1593
WEXITSTATUS(status));
1597
} else if(WIFSIGNALED(status)){
1598
fprintf_plus(stderr, "Warning: network hook \"%s\" died by"
1599
" signal %d\n", direntry->d_name,
1604
fprintf_plus(stderr, "Warning: network hook \"%s\""
1605
" crashed\n", direntry->d_name);
1612
fprintf_plus(stderr, "Network hook \"%s\" ran successfully\n",
1707
__attribute__((nonnull, warn_unused_result))
1708
1621
error_t bring_up_interface(const char *const interface,
1709
1622
const float delay){
1710
1624
error_t old_errno = errno;
1625
error_t ret_errno = 0;
1626
int ret, ret_setflags;
1712
1627
struct ifreq network;
1713
1628
unsigned int if_index = if_nametoindex(interface);
1714
1629
if(if_index == 0){
2578
/* Re-raise privileges */
2449
/* Re-raise priviliges */
2580
ret_errno = raise_privileges();
2582
perror_plus("Failed to raise privileges");
2585
/* Run network hooks */
2586
run_network_hooks("stop", interfaces_hooks != NULL ?
2587
interfaces_hooks : "", delay);
2589
/* Take down the network interfaces which were brought up */
2591
char *interface = NULL;
2592
while((interface=argz_next(interfaces_to_take_down,
2593
interfaces_to_take_down_size,
2595
ret_errno = take_down_interface(interface);
2598
perror_plus("Failed to take down interface");
2601
if(debug and (interfaces_to_take_down == NULL)){
2602
fprintf_plus(stderr, "No interfaces needed to be taken"
2608
ret_errno = lower_privileges_permanently();
2610
perror_plus("Failed to lower privileges permanently");
2453
/* Run network hooks */
2454
run_network_hooks("stop", interfaces_hooks != NULL ?
2455
interfaces_hooks : "", delay);
2457
/* Take down the network interfaces which were brought up */
2459
char *interface = NULL;
2460
while((interface=argz_next(interfaces_to_take_down,
2461
interfaces_to_take_down_size,
2463
ret_errno = take_down_interface(interface);
2466
perror_plus("Failed to take down interface");
2469
if(debug and (interfaces_to_take_down == NULL)){
2470
fprintf_plus(stderr, "No interfaces needed to be taken"
2475
lower_privileges_permanently();
2614
2478
free(interfaces_to_take_down);
2615
2479
free(interfaces_hooks);
2617
2481
/* Removes the GPGME temp directory and all files inside */
2618
if(tempdir != NULL){
2482
if(tempdir_created){
2619
2483
struct dirent **direntries = NULL;
2620
2484
struct dirent *direntry = NULL;
2621
2485
int numentries = scandir(tempdir, &direntries, notdotentries,
2487
if (numentries > 0){
2624
2488
for(int i = 0; i < numentries; i++){
2625
2489
direntry = direntries[i];
2626
2490
char *fullname = NULL;