=== modified file 'Makefile' --- Makefile 2011-06-23 22:27:15 +0000 +++ Makefile 2011-07-13 02:24:39 +0000 @@ -53,7 +53,7 @@ # Do not change these two CFLAGS=$(WARN) $(DEBUG) $(FORTIFY) $(COVERAGE) $(OPTIMIZE) \ $(LANGUAGE) $(GNUTLS_CFLAGS) $(AVAHI_CFLAGS) $(GPGME_CFLAGS) \ - -lrt -DVERSION='"$(version)"' + -DVERSION='"$(version)"' LDFLAGS=$(COVERAGE) $(LINK_FORTIFY) $(foreach flag,$(LINK_FORTIFY_LD),-Xlinker $(flag)) # Commands to format a DocBook document into a manual page @@ -210,8 +210,8 @@ $@) plugins.d/mandos-client: plugins.d/mandos-client.c - $(LINK.c) $(GNUTLS_LIBS) $(AVAHI_LIBS) $(GPGME_LIBS) $(strip\ - ) $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@ + $(LINK.c) $^ -lrt $(GNUTLS_LIBS) $(AVAHI_LIBS) $(strip\ + ) $(GPGME_LIBS) $(LOADLIBES) $(LDLIBS) -o $@ .PHONY : all doc html clean distclean run-client run-server install \ install-server install-client uninstall uninstall-server \ === modified file 'TODO' --- TODO 2011-06-23 22:27:15 +0000 +++ TODO 2011-07-13 02:24:39 +0000 @@ -4,8 +4,14 @@ * mandos-applet +* Convert README into intro(8mandos) man page + * mandos-client ** TODO [#B] Use capabilities instead of seteuid(). +** TODO [#B] Use struct sockaddr_storage instead of a union +** TODO [#B] Use getaddrinfo(hints=AI_NUMERICHOST) instead of inet_pton() +** TODO [#B] Use getnameinfo(serv=NULL, NI_NUMERICHOST) instead of inet_ntop() +** TODO [#B] Accept [] around IPv6 address in --connect option; see [[http://tools.ietf.org/html/rfc5952][RFC 5952 - A Recommendation for IPv6 Address Text Representation]] * splashy ** TODO [#B] use scandir(3) instead of readdir(3) @@ -20,6 +26,10 @@ * password-prompt ** TODO [#B] lock stdin (with flock()?) +** TODO [#A] Free direntries after scandir() + +* plymouth +** TODO [#A] Free direntries after scandir() * TODO [#B] passdev @@ -77,6 +87,7 @@ ** TODO [#B] break the wait on approval_delay if connection dies ** TODO Generate Client.runtime_expansions from client options + extra ** TODO Allow %%(checker)s as a runtime expansion +** TODO Use python-tlslite? * mandos.xml ** Add mandos contact info in manual pages === modified file 'initramfs-tools-script' --- initramfs-tools-script 2009-09-16 23:28:39 +0000 +++ initramfs-tools-script 2011-07-16 00:29:19 +0000 @@ -108,6 +108,7 @@ # Our keyscript mandos=/lib/mandos/plugin-runner +test -x "$mandos" # parse /conf/conf.d/cryptroot. Format: # target=sda2_crypt,source=/dev/sda2,key=none,keyscript=/foo/bar/baz === modified file 'plugin-runner.c' --- plugin-runner.c 2010-09-26 21:27:28 +0000 +++ plugin-runner.c 2011-07-16 00:29:19 +0000 @@ -742,7 +742,29 @@ } } - /* Strip permissions down to nobody */ + { + /* Work around Debian bug #633582: + */ + int plugindir_fd = open(/* plugindir or */ PDIR, O_RDONLY); + if(plugindir_fd == -1){ + error(0, errno, "open"); + } else { + ret = (int)TEMP_FAILURE_RETRY(fstat(plugindir_fd, &st)); + if(ret == -1){ + error(0, errno, "fstat"); + } else { + if(S_ISDIR(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ + ret = fchown(plugindir_fd, uid, gid); + if(ret == -1){ + error(0, errno, "fchown"); + } + } + } + TEMP_FAILURE_RETRY(close(plugindir_fd)); + } + } + + /* Lower permissions */ setgid(gid); if(ret == -1){ error(0, errno, "setgid"); === modified file 'plugins.d/askpass-fifo.c' --- plugins.d/askpass-fifo.c 2011-06-23 22:27:15 +0000 +++ plugins.d/askpass-fifo.c 2011-07-13 02:24:39 +0000 @@ -32,7 +32,8 @@ ENFILE, ENOMEM, EBADF, EINVAL, EIO, EISDIR, EFBIG */ #include /* error() */ -#include /* fprintf(), vfprintf(), vasprintf() */ +#include /* fprintf(), vfprintf(), + vasprintf() */ #include /* EXIT_FAILURE, NULL, size_t, free(), realloc(), EXIT_SUCCESS */ #include /* open(), O_RDONLY */ @@ -45,7 +46,8 @@ /* Function to use when printing errors */ -void error_plus(int status, int errnum, const char *formatstring, ...){ +void error_plus(int status, int errnum, const char *formatstring, + ...){ va_list ap; char *text; int ret; @@ -53,7 +55,8 @@ va_start(ap, formatstring); ret = vasprintf(&text, formatstring, ap); if (ret == -1){ - fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name); + fprintf(stderr, "Mandos plugin %s: ", + program_invocation_short_name); vfprintf(stderr, formatstring, ap); fprintf(stderr, ": "); fprintf(stderr, "%s\n", strerror(errnum)); === modified file 'plugins.d/mandos-client.c' --- plugins.d/mandos-client.c 2011-06-23 22:27:15 +0000 +++ plugins.d/mandos-client.c 2011-07-16 00:29:19 +0000 @@ -62,7 +62,8 @@ #include /* PRIu16, PRIdMAX, intmax_t, strtoimax() */ #include /* assert() */ -#include /* perror(), errno, program_invocation_short_name */ +#include /* perror(), errno, + program_invocation_short_name */ #include /* nanosleep(), time(), sleep() */ #include /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP, SIOCSIFFLAGS, if_indextoname(), @@ -73,7 +74,7 @@ #include /* close(), SEEK_SET, off_t, write(), getuid(), getgid(), seteuid(), setgid(), pause() */ -#include /* inet_pton(), htons */ +#include /* inet_pton(), htons, inet_ntop() */ #include /* not, or, and */ #include /* struct argp_option, error_t, struct argp_state, struct argp, @@ -130,7 +131,7 @@ static const char sys_class_net[] = "/sys/class/net"; char *connect_to = NULL; -/* Doubly linked list that need to be circular linked when ever used */ +/* Doubly linked list that need to be circularly linked when used */ typedef struct server{ const char *ip; uint16_t port; @@ -156,14 +157,16 @@ /* global context so signal handler can reach it*/ mandos_context mc = { .simple_poll = NULL, .server = NULL, .dh_bits = 1024, .priority = "SECURE256" - ":!CTYPE-X.509:+CTYPE-OPENPGP", .current_server = NULL }; + ":!CTYPE-X.509:+CTYPE-OPENPGP", + .current_server = NULL }; sig_atomic_t quit_now = 0; int signal_received = 0; /* Function to use when printing errors */ void perror_plus(const char *print_text){ - fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name); + fprintf(stderr, "Mandos plugin %s: ", + program_invocation_short_name); perror(print_text); } @@ -199,9 +202,9 @@ .af = af }; if(new_server->ip == NULL){ perror_plus("strdup"); - return -1; + return -1; } - /* uniqe case of first server */ + /* unique case of first server */ if (mc.current_server == NULL){ new_server->next = new_server; new_server->prev = new_server; @@ -478,12 +481,9 @@ } /* OpenPGP credentials */ - gnutls_certificate_allocate_credentials(&mc.cred); + ret = gnutls_certificate_allocate_credentials(&mc.cred); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "GnuTLS memory error: %s\n", /* Spurious warning - from - -Wunreachable-code - */ + fprintf(stderr, "GnuTLS memory error: %s\n", safer_gnutls_strerror(ret)); gnutls_global_deinit(); return -1; @@ -796,8 +796,8 @@ errno = EINTR; goto mandos_end; } - - /* Spurious warnings from -Wint-to-pointer-cast */ + + /* Spurious warning from -Wint-to-pointer-cast */ gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd); if(quit_now){ @@ -1069,7 +1069,7 @@ } } -/* Signal handler that stops main loop after sigterm has been called */ +/* Signal handler that stops main loop after SIGTERM */ static void handle_sigterm(int sig){ if(quit_now){ return; @@ -1110,7 +1110,7 @@ free(flagname); typedef short ifreq_flags; /* ifreq.ifr_flags in netdevice(7) */ /* read line from flags_fd */ - ssize_t to_read = (sizeof(ifreq_flags)*2)+3; /* "0x1003\n" */ + ssize_t to_read = 2+(sizeof(ifreq_flags)*2)+1; /* "0x1003\n" */ char *flagstring = malloc((size_t)to_read+1); /* +1 for final \0 */ flagstring[(size_t)to_read] = '\0'; if(flagstring == NULL){ @@ -1209,12 +1209,14 @@ while(true){ if(mc.current_server == NULL){ if (debug){ - fprintf(stderr, "Wait until first server is found. No timeout!\n"); + fprintf(stderr, + "Wait until first server is found. No timeout!\n"); } ret = avahi_simple_poll_iterate(s, -1); } else { if (debug){ - fprintf(stderr, "Check current_server if we should run it, or wait\n"); + fprintf(stderr, "Check current_server if we should run it," + " or wait\n"); } /* the current time */ ret = clock_gettime(CLOCK_MONOTONIC, &now); @@ -1224,31 +1226,39 @@ } /* Calculating in ms how long time between now and server who we visted longest time ago. Now - last seen. */ - waited_time.tv_sec = now.tv_sec - mc.current_server->last_seen.tv_sec; - waited_time.tv_nsec = now.tv_nsec - mc.current_server->last_seen.tv_nsec; - /* total time is 10s/10000ms. Converting to s to ms by 1000/s, and ns to ms by divind by 1000000. */ - block_time = (retry_interval - ((intmax_t)waited_time.tv_sec * 1000)) - ((intmax_t)waited_time.tv_nsec / 1000000); + waited_time.tv_sec = (now.tv_sec + - mc.current_server->last_seen.tv_sec); + waited_time.tv_nsec = (now.tv_nsec + - mc.current_server->last_seen.tv_nsec); + /* total time is 10s/10,000ms. + Converting to s from ms by dividing by 1,000, + and ns to ms by dividing by 1,000,000. */ + block_time = ((retry_interval + - ((intmax_t)waited_time.tv_sec * 1000)) + - ((intmax_t)waited_time.tv_nsec / 1000000)); if (debug){ - fprintf(stderr, "Blocking for %ld ms\n", block_time); + fprintf(stderr, "Blocking for %ld ms\n", block_time); } if(block_time <= 0){ ret = start_mandos_communication(mc.current_server->ip, - mc.current_server->port, - mc.current_server->if_index, - mc.current_server->af); + mc.current_server->port, + mc.current_server->if_index, + mc.current_server->af); if(ret == 0){ avahi_simple_poll_quit(mc.simple_poll); return 0; } - ret = clock_gettime(CLOCK_MONOTONIC, &mc.current_server->last_seen); + ret = clock_gettime(CLOCK_MONOTONIC, + &mc.current_server->last_seen); if(ret == -1){ perror_plus("clock_gettime"); return -1; } mc.current_server = mc.current_server->next; - block_time = 0; /* call avahi to find new mandos servers, but dont block */ + block_time = 0; /* Call avahi to find new Mandos + servers, but don't block */ } ret = avahi_simple_poll_iterate(s, (int)block_time); @@ -1283,7 +1293,8 @@ bool gnutls_initialized = false; bool gpgme_initialized = false; float delay = 2.5f; - double retry_interval = 10; /* 10s between retrying a server and checking again*/ + double retry_interval = 10; /* 10s between trying a server and + retrying the same server again */ struct sigaction old_sigterm_action = { .sa_handler = SIG_DFL }; struct sigaction sigterm_action = { .sa_handler = handle_sigterm }; @@ -1444,6 +1455,62 @@ goto end; } } + + { + /* Work around Debian bug #633582: + */ + struct stat st; + + /* Re-raise priviliges */ + errno = 0; + ret = seteuid(0); + if(ret == -1){ + perror_plus("seteuid"); + } + + int seckey_fd = open(PATHDIR "/" SECKEY, O_RDONLY); + if(seckey_fd == -1){ + perror_plus("open"); + } else { + ret = (int)TEMP_FAILURE_RETRY(fstat(seckey_fd, &st)); + if(ret == -1){ + perror_plus("fstat"); + } else { + if(S_ISREG(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ + ret = fchown(seckey_fd, uid, gid); + if(ret == -1){ + perror_plus("fchown"); + } + } + } + TEMP_FAILURE_RETRY(close(seckey_fd)); + } + + int pubkey_fd = open(PATHDIR "/" PUBKEY, O_RDONLY); + if(pubkey_fd == -1){ + perror_plus("open"); + } else { + ret = (int)TEMP_FAILURE_RETRY(fstat(pubkey_fd, &st)); + if(ret == -1){ + perror_plus("fstat"); + } else { + if(S_ISREG(st.st_mode) and st.st_uid == 0 and st.st_gid == 0){ + ret = fchown(pubkey_fd, uid, gid); + if(ret == -1){ + perror_plus("fchown"); + } + } + } + TEMP_FAILURE_RETRY(close(pubkey_fd)); + } + + /* Lower privileges */ + errno = 0; + ret = seteuid(uid); + if(ret == -1){ + perror_plus("seteuid"); + } + } if(not debug){ avahi_set_log_function(empty_log); @@ -1645,7 +1712,8 @@ goto end; } } - /* sleep checking until interface is running. Check every 0.25s, up to total time of delay */ + /* Sleep checking until interface is running. + Check every 0.25s, up to total time of delay */ for(int i=0; i < delay * 4; i++){ ret = ioctl(sd, SIOCGIFFLAGS, &network); if(ret == -1){ @@ -1844,7 +1912,8 @@ fprintf(stderr, "Starting Avahi loop search\n"); } - ret = avahi_loop_with_timeout(mc.simple_poll, (int)(retry_interval * 1000)); + ret = avahi_loop_with_timeout(mc.simple_poll, + (int)(retry_interval * 1000)); if(debug){ fprintf(stderr, "avahi_loop_with_timeout exited %s\n", (ret == 0) ? "successfully" : "with error"); @@ -1876,7 +1945,8 @@ gpgme_release(mc.ctx); } - /* cleans up the circular linked list of mandos servers the client has seen */ + /* Cleans up the circular linked list of Mandos servers the client + has seen */ if(mc.current_server != NULL){ mc.current_server->prev->next = NULL; while(mc.current_server != NULL){ @@ -1942,7 +2012,8 @@ } } - /* need to be cleaned even if ret == 0 because man page dont specify */ + /* need to be cleaned even if ret == 0 because man page doesn't + specify */ free(direntries); if (ret == -1){ perror_plus("scandir"); === modified file 'plugins.d/password-prompt.c' --- plugins.d/password-prompt.c 2011-06-19 20:25:38 +0000 +++ plugins.d/password-prompt.c 2011-07-13 02:24:39 +0000 @@ -41,8 +41,8 @@ getenv(), free() */ #include /* scandir(), alphasort() */ #include /* fprintf(), stderr, getline(), - stdin, feof(), fputc(), vfprintf(), vasprintf() - */ + stdin, feof(), fputc(), vfprintf(), + vasprintf() */ #include /* errno, EBADF, ENOTTY, EINVAL, EFAULT, EFBIG, EIO, ENOSPC, EINTR */ @@ -51,7 +51,8 @@ #include /* bool, false, true */ #include /* strtoumax() */ #include /* struct stat, lstat(), open() */ -#include /* strlen, rindex, memcmp, strerror() */ +#include /* strlen, rindex, memcmp, strerror() + */ #include /* struct argp_option, struct argp_state, struct argp, argp_parse(), error_t, @@ -72,7 +73,8 @@ const char plymouth_name[] = "plymouthd"; /* Function to use when printing errors */ -void error_plus(int status, int errnum, const char *formatstring, ...){ +void error_plus(int status, int errnum, const char *formatstring, + ...){ va_list ap; char *text; int ret; @@ -80,7 +82,8 @@ va_start(ap, formatstring); ret = vasprintf(&text, formatstring, ap); if (ret == -1){ - fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name); + fprintf(stderr, "Mandos plugin %s: ", + program_invocation_short_name); vfprintf(stderr, formatstring, ap); fprintf(stderr, ": "); fprintf(stderr, "%s\n", strerror(errnum)); === modified file 'plugins.d/plymouth.c' --- plugins.d/plymouth.c 2011-06-23 22:27:15 +0000 +++ plugins.d/plymouth.c 2011-07-13 02:24:39 +0000 @@ -36,7 +36,8 @@ #include /* NULL */ #include /* strchr(), memcmp() */ #include /* asprintf(), perror(), fopen(), - fscanf(), vasprintf(), fprintf(), vfprintf() */ + fscanf(), vasprintf(), fprintf(), + vfprintf() */ #include /* close(), readlink(), read(), fork(), setsid(), chdir(), dup2(), STDERR_FILENO, execv(), access() */ @@ -72,7 +73,8 @@ } /* Function to use when printing errors */ -void error_plus(int status, int errnum, const char *formatstring, ...){ +void error_plus(int status, int errnum, const char *formatstring, + ...){ va_list ap; char *text; int ret; @@ -80,7 +82,8 @@ va_start(ap, formatstring); ret = vasprintf(&text, formatstring, ap); if (ret == -1){ - fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name); + fprintf(stderr, "Mandos plugin %s: ", + program_invocation_short_name); vfprintf(stderr, formatstring, ap); fprintf(stderr, ": "); fprintf(stderr, "%s\n", strerror(errnum)); @@ -279,7 +282,7 @@ } } /* scandir might preallocate for this variable (man page unclear). - even if ret == 0, we need to free it. */ + even if ret == 0, therefore we need to free it. */ free(direntries); } pid_t pid; === modified file 'plugins.d/splashy.c' --- plugins.d/splashy.c 2011-06-23 22:27:15 +0000 +++ plugins.d/splashy.c 2011-07-13 02:24:39 +0000 @@ -29,7 +29,8 @@ SIG_IGN, kill(), SIGKILL */ #include /* NULL */ #include /* getenv() */ -#include /* asprintf(), vasprintf(), vprintf(), fprintf() */ +#include /* asprintf(), vasprintf(), vprintf(), + fprintf() */ #include /* EXIT_FAILURE, free(), EXIT_SUCCESS */ #include /* pid_t, DIR, struct dirent, @@ -60,7 +61,8 @@ int signal_received; /* Function to use when printing errors */ -void error_plus(int status, int errnum, const char *formatstring, ...){ +void error_plus(int status, int errnum, const char *formatstring, + ...){ va_list ap; char *text; int ret; @@ -68,7 +70,8 @@ va_start(ap, formatstring); ret = vasprintf(&text, formatstring, ap); if (ret == -1){ - fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name); + fprintf(stderr, "Mandos plugin %s: ", + program_invocation_short_name); vfprintf(stderr, formatstring, ap); fprintf(stderr, ": "); fprintf(stderr, "%s\n", strerror(errnum)); === modified file 'plugins.d/usplash.c' --- plugins.d/usplash.c 2011-06-23 22:27:15 +0000 +++ plugins.d/usplash.c 2011-07-13 02:24:39 +0000 @@ -36,7 +36,8 @@ dirent */ #include /* NULL */ #include /* strlen(), memcmp(), strerror() */ -#include /* asprintf(), vasprintf(), vprintf(), fprintf() */ +#include /* asprintf(), vasprintf(), vprintf(), + fprintf() */ #include /* close(), write(), readlink(), read(), STDOUT_FILENO, sleep(), fork(), setuid(), geteuid(), @@ -57,7 +58,8 @@ const char usplash_name[] = "/sbin/usplash"; /* Function to use when printing errors */ -void error_plus(int status, int errnum, const char *formatstring, ...){ +void error_plus(int status, int errnum, const char *formatstring, + ...){ va_list ap; char *text; int ret; @@ -65,7 +67,8 @@ va_start(ap, formatstring); ret = vasprintf(&text, formatstring, ap); if (ret == -1){ - fprintf(stderr, "Mandos plugin %s: ", program_invocation_short_name); + fprintf(stderr, "Mandos plugin %s: ", + program_invocation_short_name); vfprintf(stderr, formatstring, ap); fprintf(stderr, ": "); fprintf(stderr, "%s\n", strerror(errnum));