=== modified file 'Makefile' --- Makefile 2009-10-30 16:27:17 +0000 +++ Makefile 2009-11-01 00:10:28 +0000 @@ -13,6 +13,8 @@ FORTIFY=-D_FORTIFY_SOURCE=2 -fstack-protector-all -fPIC LINK_FORTIFY_LD=-z relro -z now LINK_FORTIFY= + +# If BROKEN_PIE is set, do not build with -pie ifndef BROKEN_PIE FORTIFY += -fPIE LINK_FORTIFY_LD += -fPIE === modified file 'TODO' --- TODO 2009-10-18 17:29:55 +0000 +++ TODO 2009-11-01 00:10:28 +0000 @@ -8,7 +8,6 @@ *** A closed connection during the TLS handshake *** A TCP timeout ** TODO [#B] Use capabilities instead of seteuid(). -** TODO use EX_* from * splashy ** TODO [#B] use scandir(3) instead of readdir(3) @@ -19,7 +18,6 @@ ** TODO [#B] use scandir(3) instead of readdir(3) ** TODO [#B] Prefix all debug output with "Mandos plugin " + program_invocation_short_name ** TODO use error() instead of perror() -** TODO use EX_* from * askpass-fifo ** TODO [#B] Prefix all debug output with "Mandos plugin " + program_invocation_short_name @@ -36,7 +34,6 @@ * plugin-runner ** TODO [#B] use scandir(3) instead of readdir(3) ** TODO [#C] use same file name rules as run-parts(8) -** TODO use EX_* from ** TODO use error() instead of perror() * mandos (server) === modified file 'debian/rules' --- debian/rules 2009-10-26 21:16:16 +0000 +++ debian/rules 2009-11-01 00:10:28 +0000 @@ -15,6 +15,8 @@ # This has to be exported to make some magic below work. export DH_OPTIONS +# -pie is broken on the mips and mipsel architectures, see +# ifneq (,$(findstring :$(DEB_HOST_ARCH):,:mips:mipsel:)) BROKEN_PIE := yes export BROKEN_PIE === modified file 'plugin-runner.c' --- plugin-runner.c 2009-10-24 19:17:52 +0000 +++ plugin-runner.c 2009-11-01 00:10:28 +0000 @@ -25,8 +25,8 @@ #define _GNU_SOURCE /* TEMP_FAILURE_RETRY(), getline(), asprintf(), O_CLOEXEC */ #include /* size_t, NULL */ -#include /* malloc(), exit(), EXIT_FAILURE, - EXIT_SUCCESS, realloc() */ +#include /* malloc(), exit(), EXIT_SUCCESS, + realloc() */ #include /* bool, true, false */ #include /* perror, fileno(), fprintf(), stderr, STDOUT_FILENO */ @@ -68,7 +68,8 @@ */ #include /* errno, EBADF */ #include /* intmax_t, PRIdMAX, strtoimax() */ -#include /* EX_OSERR, EX_USAGE */ +#include /* EX_OSERR, EX_USAGE, EX_IOERR, + EX_CONFIG, EX_UNAVAILABLE, EX_OK */ #define BUFFER_SIZE 256 @@ -357,13 +358,13 @@ ret = sigaddset(&sigchld_action.sa_mask, SIGCHLD); if(ret == -1){ perror("sigaddset"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } ret = sigaction(SIGCHLD, &sigchld_action, &old_sigchld_action); if(ret == -1){ perror("sigaction"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } @@ -626,7 +627,7 @@ custom_argv = malloc(sizeof(char*) * 2); if(custom_argv == NULL){ perror("malloc"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } custom_argv[0] = argv[0]; @@ -649,7 +650,7 @@ new_arg = strdup(p); if(new_arg == NULL){ perror("strdup"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; free(org_line); goto fallback; } @@ -659,7 +660,7 @@ * ((unsigned int) custom_argc + 1)); if(custom_argv == NULL){ perror("realloc"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; free(org_line); goto fallback; } @@ -672,7 +673,7 @@ } while(ret == EOF and errno == EINTR); if(ret == EOF){ perror("fclose"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_IOERR; goto fallback; } free(org_line); @@ -681,7 +682,7 @@ not affect opening plugins */ if(errno == EMFILE or errno == ENFILE or errno == ENOMEM){ perror("fopen"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_IOERR; goto fallback; } } @@ -771,7 +772,7 @@ } if(dir_fd == -1){ perror("Could not open plugin dir"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_UNAVAILABLE; goto fallback; } @@ -781,7 +782,7 @@ if(ret < 0){ perror("set_cloexec_flag"); TEMP_FAILURE_RETRY(close(dir_fd)); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } #endif /* O_CLOEXEC */ @@ -790,7 +791,7 @@ if(dir == NULL){ perror("Could not open plugin dir"); TEMP_FAILURE_RETRY(close(dir_fd)); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } } @@ -807,7 +808,7 @@ if(dirst == NULL){ if(errno == EBADF){ perror("readdir"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_IOERR; goto fallback; } break; @@ -937,20 +938,20 @@ ret = (int)TEMP_FAILURE_RETRY(pipe(pipefd)); if(ret == -1){ perror("pipe"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } /* Ask OS to automatic close the pipe on exec */ ret = set_cloexec_flag(pipefd[0]); if(ret < 0){ perror("set_cloexec_flag"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } ret = set_cloexec_flag(pipefd[1]); if(ret < 0){ perror("set_cloexec_flag"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } /* Block SIGCHLD until process is safely in process list */ @@ -959,7 +960,7 @@ NULL)); if(ret < 0){ perror("sigprocmask"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } /* Starting a new process to be watched */ @@ -969,7 +970,7 @@ } while(pid == -1 and errno == EINTR); if(pid == -1){ perror("fork"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } if(pid == 0){ @@ -977,18 +978,18 @@ ret = sigaction(SIGCHLD, &old_sigchld_action, NULL); if(ret < 0){ perror("sigaction"); - _exit(EXIT_FAILURE); + _exit(EX_OSERR); } ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL); if(ret < 0){ perror("sigprocmask"); - _exit(EXIT_FAILURE); + _exit(EX_OSERR); } ret = dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */ if(ret == -1){ perror("dup2"); - _exit(EXIT_FAILURE); + _exit(EX_OSERR); } if(dirfd(dir) < 0){ @@ -999,12 +1000,12 @@ if(p->environ[0] == NULL){ if(execv(filename, p->argv) < 0){ perror("execv"); - _exit(EXIT_FAILURE); + _exit(EX_OSERR); } } else { if(execve(filename, p->argv, p->environ) < 0){ perror("execve"); - _exit(EXIT_FAILURE); + _exit(EX_OSERR); } } /* no return */ @@ -1022,7 +1023,7 @@ if(ret < 0){ perror("sigprocmask"); } - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } @@ -1036,7 +1037,7 @@ NULL)); if(ret < 0){ perror("sigprocmask"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } @@ -1069,7 +1070,7 @@ int select_ret = select(maxfd+1, &rfds, NULL, NULL, NULL); if(select_ret == -1 and errno != EINTR){ perror("select"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } /* OK, now either a process completed, or something can be read @@ -1111,7 +1112,7 @@ NULL)); if(ret < 0){ perror("sigprocmask"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } @@ -1125,7 +1126,7 @@ &sigchld_action.sa_mask, NULL))); if(ret < 0){ perror("sigprocmask"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } @@ -1142,7 +1143,7 @@ proc->buffer_length); if(not bret){ perror("print_out_password"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_IOERR; } goto fallback; } @@ -1161,7 +1162,7 @@ + (size_t) BUFFER_SIZE); if(proc->buffer == NULL){ perror("malloc"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; goto fallback; } proc->buffer_size += BUFFER_SIZE; @@ -1188,7 +1189,8 @@ fallback: - if(plugin_list == NULL or exitstatus != EXIT_SUCCESS){ + if(plugin_list == NULL or (exitstatus != EXIT_SUCCESS + and exitstatus != EX_OK)){ /* Fallback if all plugins failed, none are found or an error occured */ bool bret; @@ -1203,7 +1205,7 @@ bret = print_out_password(passwordbuffer, len); if(not bret){ perror("print_out_password"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_IOERR; } } @@ -1211,7 +1213,7 @@ ret = sigaction(SIGCHLD, &old_sigchld_action, NULL); if(ret == -1){ perror("sigaction"); - exitstatus = EXIT_FAILURE; + exitstatus = EX_OSERR; } if(custom_argv != NULL){ === modified file 'plugins.d/mandos-client.c' --- plugins.d/mandos-client.c 2009-10-24 19:17:52 +0000 +++ plugins.d/mandos-client.c 2009-11-01 00:10:28 +0000 @@ -43,8 +43,8 @@ stdout, ferror(), remove() */ #include /* uint16_t, uint32_t */ #include /* NULL, size_t, ssize_t */ -#include /* free(), EXIT_SUCCESS, EXIT_FAILURE, - srand(), strtof(), abort() */ +#include /* free(), EXIT_SUCCESS, srand(), + strtof(), abort() */ #include /* bool, false, true */ #include /* memset(), strcmp(), strlen(), strerror(), asprintf(), strcpy() */ @@ -82,7 +82,8 @@ #include /* sigemptyset(), sigaddset(), sigaction(), SIGTERM, sig_atomic_t, raise() */ -#include /* EX_OSERR, EX_USAGE */ +#include /* EX_OSERR, EX_USAGE, EX_UNAVAILABLE, + EX_NOHOST, EX_IOERR, EX_PROTOCOL */ #ifdef __linux__ #include /* klogctl() */ @@ -553,7 +554,10 @@ gnutls_session_t session; int pf; /* Protocol family */ + errno = 0; + if(quit_now){ + errno = EINTR; return -1; } @@ -566,6 +570,7 @@ break; default: fprintf(stderr, "Bad address family: %d\n", af); + errno = EINVAL; return -1; } @@ -581,11 +586,14 @@ tcp_sd = socket(pf, SOCK_STREAM, 0); if(tcp_sd < 0){ + int e = errno; perror("socket"); + errno = e; goto mandos_end; } if(quit_now){ + errno = EINTR; goto mandos_end; } @@ -598,11 +606,15 @@ ret = inet_pton(af, ip, &to.in.sin_addr); } if(ret < 0 ){ + int e = errno; perror("inet_pton"); + errno = e; goto mandos_end; } if(ret == 0){ + int e = errno; fprintf(stderr, "Bad address: %s\n", ip); + errno = e; goto mandos_end; } if(af == AF_INET6){ @@ -616,6 +628,7 @@ if(if_index == AVAHI_IF_UNSPEC){ fprintf(stderr, "An IPv6 link-local address is incomplete" " without a network interface\n"); + errno = EINVAL; goto mandos_end; } /* Set the network interface number as scope */ @@ -628,6 +641,7 @@ } if(quit_now){ + errno = EINTR; goto mandos_end; } @@ -664,6 +678,7 @@ } if(quit_now){ + errno = EINTR; goto mandos_end; } @@ -673,11 +688,14 @@ ret = connect(tcp_sd, &to.in, sizeof(to)); /* IPv4 */ } if(ret < 0){ + int e = errno; perror("connect"); + errno = e; goto mandos_end; } if(quit_now){ + errno = EINTR; goto mandos_end; } @@ -688,7 +706,9 @@ ret = (int)TEMP_FAILURE_RETRY(write(tcp_sd, out + written, out_size - written)); if(ret == -1){ + int e = errno; perror("write"); + errno = e; goto mandos_end; } written += (size_t)ret; @@ -704,6 +724,7 @@ } if(quit_now){ + errno = EINTR; goto mandos_end; } } @@ -713,18 +734,21 @@ } if(quit_now){ + errno = EINTR; goto mandos_end; } gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd); if(quit_now){ + errno = EINTR; goto mandos_end; } do { ret = gnutls_handshake(session); if(quit_now){ + errno = EINTR; goto mandos_end; } } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED); @@ -734,6 +758,7 @@ fprintf(stderr, "*** GnuTLS Handshake failed ***\n"); gnutls_perror(ret); } + errno = EPROTO; goto mandos_end; } @@ -747,17 +772,21 @@ while(true){ if(quit_now){ + errno = EINTR; goto mandos_end; } buffer_capacity = incbuffer(&buffer, buffer_length, buffer_capacity); if(buffer_capacity == 0){ + int e = errno; perror("incbuffer"); + errno = e; goto mandos_end; } if(quit_now){ + errno = EINTR; goto mandos_end; } @@ -776,12 +805,14 @@ ret = gnutls_handshake(session); if(quit_now){ + errno = EINTR; goto mandos_end; } } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED); if(ret < 0){ fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n"); gnutls_perror(ret); + errno = EPROTO; goto mandos_end; } break; @@ -789,6 +820,7 @@ fprintf(stderr, "Unknown error while reading data from" " encrypted session with Mandos server\n"); gnutls_bye(session, GNUTLS_SHUT_RDWR); + errno = EIO; goto mandos_end; } } else { @@ -801,12 +833,14 @@ } if(quit_now){ + errno = EINTR; goto mandos_end; } do { ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); if(quit_now){ + errno = EINTR; goto mandos_end; } } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED); @@ -821,6 +855,7 @@ written = 0; while(written < (size_t) decrypted_buffer_size){ if(quit_now){ + errno = EINTR; goto mandos_end; } @@ -828,10 +863,12 @@ (size_t)decrypted_buffer_size - written, stdout); if(ret == 0 and ferror(stdout)){ + int e = errno; if(debug){ fprintf(stderr, "Error writing encrypted data: %s\n", strerror(errno)); } + errno = e; goto mandos_end; } written += (size_t)ret; @@ -843,17 +880,25 @@ /* Shutdown procedure */ mandos_end: - free(decrypted_buffer); - free(buffer); - if(tcp_sd >= 0){ - ret = (int)TEMP_FAILURE_RETRY(close(tcp_sd)); - } - if(ret == -1){ - perror("close"); - } - gnutls_deinit(session); - if(quit_now){ - retval = -1; + { + int e = errno; + free(decrypted_buffer); + free(buffer); + if(tcp_sd >= 0){ + ret = (int)TEMP_FAILURE_RETRY(close(tcp_sd)); + } + if(ret == -1){ + if(e == 0){ + e = errno; + } + perror("close"); + } + gnutls_deinit(session); + if(quit_now){ + e = EINTR; + retval = -1; + } + errno = e; } return retval; } @@ -1159,7 +1204,7 @@ mc.simple_poll = avahi_simple_poll_new(); if(mc.simple_poll == NULL){ fprintf(stderr, "Avahi: Failed to create simple poll object.\n"); - exitcode = EXIT_FAILURE; + exitcode = EX_UNAVAILABLE; goto end; } @@ -1167,19 +1212,19 @@ ret = sigaddset(&sigterm_action.sa_mask, SIGINT); if(ret == -1){ perror("sigaddset"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; goto end; } ret = sigaddset(&sigterm_action.sa_mask, SIGHUP); if(ret == -1){ perror("sigaddset"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; goto end; } ret = sigaddset(&sigterm_action.sa_mask, SIGTERM); if(ret == -1){ perror("sigaddset"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; goto end; } /* Need to check if the handler is SIG_IGN before handling: @@ -1189,39 +1234,39 @@ ret = sigaction(SIGINT, NULL, &old_sigterm_action); if(ret == -1){ perror("sigaction"); - return EXIT_FAILURE; + return EX_OSERR; } if(old_sigterm_action.sa_handler != SIG_IGN){ ret = sigaction(SIGINT, &sigterm_action, NULL); if(ret == -1){ perror("sigaction"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; goto end; } } ret = sigaction(SIGHUP, NULL, &old_sigterm_action); if(ret == -1){ perror("sigaction"); - return EXIT_FAILURE; + return EX_OSERR; } if(old_sigterm_action.sa_handler != SIG_IGN){ ret = sigaction(SIGHUP, &sigterm_action, NULL); if(ret == -1){ perror("sigaction"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; goto end; } } ret = sigaction(SIGTERM, NULL, &old_sigterm_action); if(ret == -1){ perror("sigaction"); - return EXIT_FAILURE; + return EX_OSERR; } if(old_sigterm_action.sa_handler != SIG_IGN){ ret = sigaction(SIGTERM, &sigterm_action, NULL); if(ret == -1){ perror("sigaction"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; goto end; } } @@ -1231,7 +1276,7 @@ if_index = (AvahiIfIndex) if_nametoindex(interface); if(if_index == 0){ fprintf(stderr, "No such interface: \"%s\"\n", interface); - exitcode = EXIT_FAILURE; + exitcode = EX_UNAVAILABLE; goto end; } @@ -1260,7 +1305,7 @@ sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP); if(sd < 0){ perror("socket"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; #ifdef __linux__ if(restore_loglevel){ ret = klogctl(7, NULL, 0); @@ -1289,7 +1334,7 @@ } } #endif /* __linux__ */ - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; /* Lower privileges */ errno = 0; ret = seteuid(uid); @@ -1305,7 +1350,7 @@ if(ret == -1){ take_down_interface = false; perror("ioctl SIOCSIFFLAGS"); - exitcode = EXIT_FAILURE; + exitcode = EX_OSERR; #ifdef __linux__ if(restore_loglevel){ ret = klogctl(7, NULL, 0); @@ -1377,7 +1422,7 @@ ret = init_gnutls_global(pubkey, seckey); if(ret == -1){ fprintf(stderr, "init_gnutls_global failed\n"); - exitcode = EXIT_FAILURE; + exitcode = EX_UNAVAILABLE; goto end; } else { gnutls_initialized = true; @@ -1400,7 +1445,7 @@ if(not init_gpgme(pubkey, seckey, tempdir)){ fprintf(stderr, "init_gpgme failed\n"); - exitcode = EXIT_FAILURE; + exitcode = EX_UNAVAILABLE; goto end; } else { gpgme_initialized = true; @@ -1416,7 +1461,7 @@ char *address = strrchr(connect_to, ':'); if(address == NULL){ fprintf(stderr, "No colon in address\n"); - exitcode = EXIT_FAILURE; + exitcode = EX_USAGE; goto end; } @@ -1430,7 +1475,7 @@ if(errno != 0 or tmp == address+1 or *tmp != '\0' or tmpmax != (uint16_t)tmpmax){ fprintf(stderr, "Bad port number\n"); - exitcode = EXIT_FAILURE; + exitcode = EX_USAGE; goto end; } @@ -1455,7 +1500,25 @@ ret = start_mandos_communication(address, port, if_index, af); if(ret < 0){ - exitcode = EXIT_FAILURE; + switch(errno){ + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: + exitcode = EX_NOHOST; + break; + case EINVAL: + exitcode = EX_USAGE; + break; + case EIO: + exitcode = EX_IOERR; + break; + case EPROTO: + exitcode = EX_PROTOCOL; + break; + default: + exitcode = EX_OSERR; + break; + } } else { exitcode = EXIT_SUCCESS; } @@ -1488,7 +1551,7 @@ if(mc.server == NULL){ fprintf(stderr, "Failed to create Avahi server: %s\n", avahi_strerror(error)); - exitcode = EXIT_FAILURE; + exitcode = EX_UNAVAILABLE; goto end; } @@ -1503,7 +1566,7 @@ if(sb == NULL){ fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(mc.server))); - exitcode = EXIT_FAILURE; + exitcode = EX_UNAVAILABLE; goto end; }