9
9
* "browse_callback", and parts of "main".
11
11
* Everything else is
12
* Copyright © 2008-2011 Teddy Hogeborn
13
* Copyright © 2008-2011 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
42
42
#include <stdio.h> /* fprintf(), stderr, fwrite(),
43
43
stdout, ferror(), remove() */
44
#include <stdint.h> /* uint16_t, uint32_t */
44
#include <stdint.h> /* uint16_t, uint32_t, intptr_t */
45
45
#include <stddef.h> /* NULL, size_t, ssize_t */
46
46
#include <stdlib.h> /* free(), EXIT_SUCCESS, srand(),
47
47
strtof(), abort() */
74
74
#include <unistd.h> /* close(), SEEK_SET, off_t, write(),
75
75
getuid(), getgid(), seteuid(),
76
setgid(), pause(), _exit() */
77
77
#include <arpa/inet.h> /* inet_pton(), htons, inet_ntop() */
78
78
#include <iso646.h> /* not, or, and */
79
79
#include <argp.h> /* struct argp_option, error_t, struct
87
87
EX_NOHOST, EX_IOERR, EX_PROTOCOL */
88
88
#include <sys/wait.h> /* waitpid(), WIFEXITED(),
89
89
WEXITSTATUS(), WTERMSIG() */
90
#include <grp.h> /* setgroups() */
92
93
#include <sys/klog.h> /* klogctl() */
170
171
/* Function to use when printing errors */
171
172
void perror_plus(const char *print_text){
172
174
fprintf(stderr, "Mandos plugin %s: ",
173
175
program_invocation_short_name);
174
177
perror(print_text);
180
__attribute__((format (gnu_printf, 2, 3)))
177
181
int fprintf_plus(FILE *stream, const char *format, ...){
179
183
va_start (ap, format);
203
207
/* Add server to set of servers to retry periodically */
204
int add_server(const char *ip, uint16_t port, AvahiIfIndex if_index,
208
bool add_server(const char *ip, uint16_t port, AvahiIfIndex if_index,
207
211
server *new_server = malloc(sizeof(server));
208
212
if(new_server == NULL){
209
213
perror_plus("malloc");
212
216
*new_server = (server){ .ip = strdup(ip),
820
/* Spurious warning from -Wint-to-pointer-cast */
821
gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd);
824
/* This casting via intptr_t is to eliminate warning about casting
825
an int to a pointer type. This is exactly how the GnuTLS Guile
826
function "set-session-transport-fd!" does it. */
827
gnutls_transport_set_ptr(session,
828
(gnutls_transport_ptr_t)(intptr_t)tcp_sd);
1030
1037
avahi_simple_poll_quit(mc.simple_poll);
1032
ret = add_server(ip, port, interface,
1033
avahi_proto_to_af(proto));
1039
if(not add_server(ip, port, interface,
1040
avahi_proto_to_af(proto))){
1041
fprintf_plus(stderr, "Failed to add server \"%s\" to server"
1389
1403
int devnull = open("/dev/null", O_RDONLY);
1390
1404
for(int i = 0; i < numhooks; i++){
1391
direntry = direntries[0];
1405
direntry = direntries[i];
1392
1406
char *fullname = NULL;
1393
1407
ret = asprintf(&fullname, "%s/%s", hookdir, direntry->d_name);
1395
1409
perror_plus("asprintf");
1413
fprintf_plus(stderr, "Running network hook \"%s\"\n",
1398
1416
pid_t hook_pid = fork();
1399
1417
if(hook_pid == 0){
1419
/* Raise privileges */
1423
perror_plus("seteuid");
1425
/* Raise privileges even more */
1429
perror_plus("setuid");
1435
perror_plus("setgid");
1437
/* Reset supplementary groups */
1439
ret = setgroups(0, NULL);
1441
perror_plus("setgroups");
1401
1443
dup2(devnull, STDIN_FILENO);
1402
1444
close(devnull);
1403
1445
dup2(STDERR_FILENO, STDOUT_FILENO);
1404
1446
ret = setenv("MANDOSNETHOOKDIR", hookdir, 1);
1406
1448
perror_plus("setenv");
1409
1451
ret = setenv("DEVICE", interface, 1);
1411
1453
perror_plus("setenv");
1414
ret = setenv("VERBOSE", debug ? "1" : "0", 1);
1456
ret = setenv("VERBOSITY", debug ? "1" : "0", 1);
1416
1458
perror_plus("setenv");
1419
1461
ret = setenv("MODE", mode, 1);
1421
1463
perror_plus("setenv");
1424
1466
char *delaystring;
1425
1467
ret = asprintf(&delaystring, "%f", delay);
1427
1469
perror_plus("asprintf");
1430
1472
ret = setenv("DELAY", delaystring, 1);
1432
1474
free(delaystring);
1433
1475
perror_plus("setenv");
1436
1478
free(delaystring);
1437
ret = execl(fullname, direntry->d_name, mode, NULL);
1438
perror_plus("execl");
1479
if(connect_to != NULL){
1480
ret = setenv("CONNECT", connect_to, 1);
1482
perror_plus("setenv");
1486
if(execl(fullname, direntry->d_name, mode, NULL) == -1){
1487
perror_plus("execl");
1488
_exit(EXIT_FAILURE);
1441
1492
if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){
1560
1612
{ .name = "retry", .key = 132,
1561
1613
.arg = "SECONDS",
1562
.doc = "Retry interval used when denied by the mandos server",
1614
.doc = "Retry interval used when denied by the Mandos server",
1564
1616
{ .name = "network-hook-dir", .key = 133,
1637
1689
argp_state_help(state, state->out_stream,
1638
1690
ARGP_HELP_USAGE | ARGP_HELP_EXIT_ERR);
1639
1691
case 'V': /* --version */
1640
fprintf_plus(state->out_stream,
1641
"Mandos plugin mandos-client: ");
1642
1692
fprintf_plus(state->out_stream, "%s\n", argp_program_version);
1643
1693
exit(argp_err_exit_status);
1673
1723
/* Work around Debian bug #633582:
1674
1724
<http://bugs.debian.org/633582> */
1677
1726
/* Re-raise priviliges */
1679
1728
ret = seteuid(0);
1681
1730
perror_plus("seteuid");
1684
if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){
1685
int seckey_fd = open(seckey, O_RDONLY);
1686
if(seckey_fd == -1){
1687
perror_plus("open");
1689
ret = (int)TEMP_FAILURE_RETRY(fstat(seckey_fd, &st));
1691
perror_plus("fstat");
1693
if(S_ISREG(st.st_mode)
1694
and st.st_uid == 0 and st.st_gid == 0){
1695
ret = fchown(seckey_fd, uid, gid);
1697
perror_plus("fchown");
1701
TEMP_FAILURE_RETRY(close(seckey_fd));
1705
if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){
1706
int pubkey_fd = open(pubkey, O_RDONLY);
1707
if(pubkey_fd == -1){
1708
perror_plus("open");
1710
ret = (int)TEMP_FAILURE_RETRY(fstat(pubkey_fd, &st));
1712
perror_plus("fstat");
1714
if(S_ISREG(st.st_mode)
1715
and st.st_uid == 0 and st.st_gid == 0){
1716
ret = fchown(pubkey_fd, uid, gid);
1718
perror_plus("fchown");
1722
TEMP_FAILURE_RETRY(close(pubkey_fd));
1726
/* Lower privileges */
1730
perror_plus("seteuid");
1734
if(strcmp(seckey, PATHDIR "/" SECKEY) == 0){
1735
int seckey_fd = open(seckey, O_RDONLY);
1736
if(seckey_fd == -1){
1737
perror_plus("open");
1739
ret = (int)TEMP_FAILURE_RETRY(fstat(seckey_fd, &st));
1741
perror_plus("fstat");
1743
if(S_ISREG(st.st_mode)
1744
and st.st_uid == 0 and st.st_gid == 0){
1745
ret = fchown(seckey_fd, uid, gid);
1747
perror_plus("fchown");
1751
TEMP_FAILURE_RETRY(close(seckey_fd));
1755
if(strcmp(pubkey, PATHDIR "/" PUBKEY) == 0){
1756
int pubkey_fd = open(pubkey, O_RDONLY);
1757
if(pubkey_fd == -1){
1758
perror_plus("open");
1760
ret = (int)TEMP_FAILURE_RETRY(fstat(pubkey_fd, &st));
1762
perror_plus("fstat");
1764
if(S_ISREG(st.st_mode)
1765
and st.st_uid == 0 and st.st_gid == 0){
1766
ret = fchown(pubkey_fd, uid, gid);
1768
perror_plus("fchown");
1772
TEMP_FAILURE_RETRY(close(pubkey_fd));
1776
/* Lower privileges */
1780
perror_plus("seteuid");
1734
1785
/* Run network hooks */
1736
/* Re-raise priviliges */
1740
perror_plus("seteuid");
1742
if(not run_network_hooks("start", interface, delay)){
1745
/* Lower privileges */
1749
perror_plus("seteuid");
1786
if(not run_network_hooks("start", interface, delay)){