=== modified file 'plugins.d/mandos-client.c' --- plugins.d/mandos-client.c 2011-11-11 20:19:01 +0000 +++ plugins.d/mandos-client.c 2011-11-12 16:24:19 +0000 @@ -85,6 +85,8 @@ raise() */ #include /* EX_OSERR, EX_USAGE, EX_UNAVAILABLE, EX_NOHOST, EX_IOERR, EX_PROTOCOL */ +#include /* waitpid(), WIFEXITED(), + WEXITSTATUS(), WTERMSIG() */ #ifdef __linux__ #include /* klogctl() */ @@ -251,14 +253,16 @@ rc = gpgme_data_new_from_fd(&pgp_data, fd); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_data_new_from_fd: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_data_new_from_fd: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } rc = gpgme_op_import(mc.ctx, pgp_data); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_op_import: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_op_import: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } @@ -272,14 +276,16 @@ } if(debug){ - fprintf(stderr, "Initializing GPGME\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Initializing GPGME\n"); } /* Init GPGME */ gpgme_check_version(NULL); rc = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_engine_check_version: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_engine_check_version: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } @@ -287,7 +293,8 @@ /* Set GPGME home directory for the OpenPGP engine only */ rc = gpgme_get_engine_info(&engine_info); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_get_engine_info: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_get_engine_info: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return false; } @@ -300,15 +307,17 @@ engine_info = engine_info->next; } if(engine_info == NULL){ - fprintf(stderr, "Could not set GPGME home dir to %s\n", tempdir); + fprintf(stderr, "Mandos plugin mandos-client: " + "Could not set GPGME home dir to %s\n", tempdir); return false; } /* Create new GPGME "context" */ rc = gpgme_new(&(mc.ctx)); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_new: %s: %s\n", - gpgme_strsource(rc), gpgme_strerror(rc)); + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_new: %s: %s\n", gpgme_strsource(rc), + gpgme_strerror(rc)); return false; } @@ -333,14 +342,16 @@ ssize_t plaintext_length = 0; if(debug){ - fprintf(stderr, "Trying to decrypt OpenPGP data\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Trying to decrypt OpenPGP data\n"); } /* Create new GPGME data buffer from memory cryptotext */ rc = gpgme_data_new_from_mem(&dh_crypto, cryptotext, crypto_size, 0); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_data_new_from_mem: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_data_new_from_mem: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); return -1; } @@ -348,7 +359,8 @@ /* Create new empty GPGME data buffer for the plaintext */ rc = gpgme_data_new(&dh_plain); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_data_new: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_data_new: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); gpgme_data_release(dh_crypto); return -1; @@ -358,29 +370,37 @@ data buffer */ rc = gpgme_op_decrypt(mc.ctx, dh_crypto, dh_plain); if(rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "bad gpgme_op_decrypt: %s: %s\n", gpgme_strsource(rc), gpgme_strerror(rc)); plaintext_length = -1; if(debug){ gpgme_decrypt_result_t result; result = gpgme_op_decrypt_result(mc.ctx); if(result == NULL){ - fprintf(stderr, "gpgme_op_decrypt_result failed\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "gpgme_op_decrypt_result failed\n"); } else { - fprintf(stderr, "Unsupported algorithm: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Unsupported algorithm: %s\n", result->unsupported_algorithm); - fprintf(stderr, "Wrong key usage: %u\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Wrong key usage: %u\n", result->wrong_key_usage); if(result->file_name != NULL){ - fprintf(stderr, "File name: %s\n", result->file_name); + fprintf(stderr, "Mandos plugin mandos-client: " + "File name: %s\n", result->file_name); } gpgme_recipient_t recipient; recipient = result->recipients; while(recipient != NULL){ - fprintf(stderr, "Public key algorithm: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Public key algorithm: %s\n", gpgme_pubkey_algo_name(recipient->pubkey_algo)); - fprintf(stderr, "Key ID: %s\n", recipient->keyid); - fprintf(stderr, "Secret key available: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Key ID: %s\n", recipient->keyid); + fprintf(stderr, "Mandos plugin mandos-client: " + "Secret key available: %s\n", recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes"); recipient = recipient->next; @@ -391,7 +411,8 @@ } if(debug){ - fprintf(stderr, "Decryption of OpenPGP data succeeded\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Decryption of OpenPGP data succeeded\n"); } /* Seek back to the beginning of the GPGME plaintext data buffer */ @@ -428,7 +449,8 @@ } if(debug){ - fprintf(stderr, "Decrypted password is: "); + fprintf(stderr, "Mandos plugin mandos-client: " + "Decrypted password is: "); for(ssize_t i = 0; i < plaintext_length; i++){ fprintf(stderr, "%02hhX ", (*plaintext)[i]); } @@ -456,7 +478,7 @@ /* GnuTLS log function callback */ static void debuggnutls(__attribute__((unused)) int level, const char* string){ - fprintf(stderr, "GnuTLS: %s", string); + fprintf(stderr, "Mandos plugin mandos-client: GnuTLS: %s", string); } static int init_gnutls_global(const char *pubkeyfilename, @@ -464,13 +486,14 @@ int ret; if(debug){ - fprintf(stderr, "Initializing GnuTLS\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Initializing GnuTLS\n"); } ret = gnutls_global_init(); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "GnuTLS global_init: %s\n", - safer_gnutls_strerror(ret)); + fprintf(stderr, "Mandos plugin mandos-client: " + "GnuTLS global_init: %s\n", safer_gnutls_strerror(ret)); return -1; } @@ -485,14 +508,15 @@ /* OpenPGP credentials */ ret = gnutls_certificate_allocate_credentials(&mc.cred); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "GnuTLS memory error: %s\n", - safer_gnutls_strerror(ret)); + fprintf(stderr, "Mandos plugin mandos-client: " + "GnuTLS memory error: %s\n", safer_gnutls_strerror(ret)); gnutls_global_deinit(); return -1; } if(debug){ - fprintf(stderr, "Attempting to use OpenPGP public key %s and" + fprintf(stderr, "Mandos plugin mandos-client: " + "Attempting to use OpenPGP public key %s and" " secret key %s as GnuTLS credentials\n", pubkeyfilename, seckeyfilename); } @@ -502,23 +526,26 @@ GNUTLS_OPENPGP_FMT_BASE64); if(ret != GNUTLS_E_SUCCESS){ fprintf(stderr, + "Mandos plugin mandos-client: " "Error[%d] while reading the OpenPGP key pair ('%s'," " '%s')\n", ret, pubkeyfilename, seckeyfilename); - fprintf(stderr, "The GnuTLS error is: %s\n", - safer_gnutls_strerror(ret)); + fprintf(stderr, "Mandos plugin mandos-client: " + "The GnuTLS error is: %s\n", safer_gnutls_strerror(ret)); goto globalfail; } /* GnuTLS server initialization */ ret = gnutls_dh_params_init(&mc.dh_params); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "Error in GnuTLS DH parameter initialization:" + fprintf(stderr, "Mandos plugin mandos-client: " + "Error in GnuTLS DH parameter initialization:" " %s\n", safer_gnutls_strerror(ret)); goto globalfail; } ret = gnutls_dh_params_generate2(mc.dh_params, mc.dh_bits); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "Error in GnuTLS prime generation: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Error in GnuTLS prime generation: %s\n", safer_gnutls_strerror(ret)); goto globalfail; } @@ -545,7 +572,8 @@ } } while(ret == GNUTLS_E_INTERRUPTED or ret == GNUTLS_E_AGAIN); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "Error in GnuTLS session initialization: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Error in GnuTLS session initialization: %s\n", safer_gnutls_strerror(ret)); } @@ -559,9 +587,10 @@ } } while(ret == GNUTLS_E_INTERRUPTED or ret == GNUTLS_E_AGAIN); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "Syntax error at: %s\n", err); - fprintf(stderr, "GnuTLS error: %s\n", - safer_gnutls_strerror(ret)); + fprintf(stderr, "Mandos plugin mandos-client: " + "Syntax error at: %s\n", err); + fprintf(stderr, "Mandos plugin mandos-client: " + "GnuTLS error: %s\n", safer_gnutls_strerror(ret)); gnutls_deinit(*session); return -1; } @@ -576,7 +605,8 @@ } } while(ret == GNUTLS_E_INTERRUPTED or ret == GNUTLS_E_AGAIN); if(ret != GNUTLS_E_SUCCESS){ - fprintf(stderr, "Error setting GnuTLS credentials: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Error setting GnuTLS credentials: %s\n", safer_gnutls_strerror(ret)); gnutls_deinit(*session); return -1; @@ -628,7 +658,8 @@ pf = PF_INET; break; default: - fprintf(stderr, "Bad address family: %d\n", af); + fprintf(stderr, "Mandos plugin mandos-client: " + "Bad address family: %d\n", af); errno = EINVAL; return -1; } @@ -639,7 +670,8 @@ } if(debug){ - fprintf(stderr, "Setting up a TCP connection to %s, port %" PRIu16 + fprintf(stderr, "Mandos plugin mandos-client: " + "Setting up a TCP connection to %s, port %" PRIu16 "\n", ip, port); } @@ -672,7 +704,8 @@ } if(ret == 0){ int e = errno; - fprintf(stderr, "Bad address: %s\n", ip); + fprintf(stderr, "Mandos plugin mandos-client: " + "Bad address: %s\n", ip); errno = e; goto mandos_end; } @@ -685,7 +718,8 @@ (&to.in6.sin6_addr)){ /* -Wstrict-aliasing=2 or lower and -Wunreachable-code*/ if(if_index == AVAHI_IF_UNSPEC){ - fprintf(stderr, "An IPv6 link-local address is incomplete" + fprintf(stderr, "Mandos plugin mandos-client: " + "An IPv6 link-local address is incomplete" " without a network interface\n"); errno = EINVAL; goto mandos_end; @@ -710,12 +744,13 @@ if(if_indextoname((unsigned int)if_index, interface) == NULL){ perror_plus("if_indextoname"); } else { - fprintf(stderr, "Connection to: %s%%%s, port %" PRIu16 "\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Connection to: %s%%%s, port %" PRIu16 "\n", ip, interface, port); } } else { - fprintf(stderr, "Connection to: %s, port %" PRIu16 "\n", ip, - port); + fprintf(stderr, "Mandos plugin mandos-client: " + "Connection to: %s, port %" PRIu16 "\n", ip, port); } char addrstr[(INET_ADDRSTRLEN > INET6_ADDRSTRLEN) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN] = ""; @@ -731,7 +766,8 @@ perror_plus("inet_ntop"); } else { if(strcmp(addrstr, ip) != 0){ - fprintf(stderr, "Canonical address form: %s\n", addrstr); + fprintf(stderr, "Mandos plugin mandos-client: " + "Canonical address form: %s\n", addrstr); } } } @@ -791,7 +827,8 @@ } if(debug){ - fprintf(stderr, "Establishing TLS session with %s\n", ip); + fprintf(stderr, "Mandos plugin mandos-client: " + "Establishing TLS session with %s\n", ip); } if(quit_now){ @@ -817,7 +854,8 @@ if(ret != GNUTLS_E_SUCCESS){ if(debug){ - fprintf(stderr, "*** GnuTLS Handshake failed ***\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "*** GnuTLS Handshake failed ***\n"); gnutls_perror(ret); } errno = EPROTO; @@ -827,8 +865,8 @@ /* Read OpenPGP packet that contains the wanted password */ if(debug){ - fprintf(stderr, "Retrieving OpenPGP encrypted password from %s\n", - ip); + fprintf(stderr, "Mandos plugin mandos-client: " + "Retrieving OpenPGP encrypted password from %s\n", ip); } while(true){ @@ -872,14 +910,16 @@ } } while(ret == GNUTLS_E_AGAIN or ret == GNUTLS_E_INTERRUPTED); if(ret < 0){ - fprintf(stderr, "*** GnuTLS Re-handshake failed ***\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "*** GnuTLS Re-handshake failed ***\n"); gnutls_perror(ret); errno = EPROTO; goto mandos_end; } break; default: - fprintf(stderr, "Unknown error while reading data from" + fprintf(stderr, "Mandos plugin mandos-client: " + "Unknown error while reading data from" " encrypted session with Mandos server\n"); gnutls_bye(session, GNUTLS_SHUT_RDWR); errno = EIO; @@ -891,7 +931,8 @@ } if(debug){ - fprintf(stderr, "Closing TLS session\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Closing TLS session\n"); } if(quit_now){ @@ -927,7 +968,8 @@ if(ret == 0 and ferror(stdout)){ int e = errno; if(debug){ - fprintf(stderr, "Error writing encrypted data: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Error writing encrypted data: %s\n", strerror(errno)); } errno = e; @@ -991,7 +1033,8 @@ switch(event){ default: case AVAHI_RESOLVER_FAILURE: - fprintf(stderr, "(Avahi Resolver) Failed to resolve service '%s'" + fprintf(stderr, "Mandos plugin mandos-client: " + "(Avahi Resolver) Failed to resolve service '%s'" " of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_server_errno(mc.server))); break; @@ -1001,7 +1044,8 @@ char ip[AVAHI_ADDRESS_STR_MAX]; avahi_address_snprint(ip, sizeof(ip), address); if(debug){ - fprintf(stderr, "Mandos server \"%s\" found on %s (%s, %" + fprintf(stderr, "Mandos plugin mandos-client: " + "Mandos server \"%s\" found on %s (%s, %" PRIdMAX ") on port %" PRIu16 "\n", name, host_name, ip, (intmax_t)interface, port); } @@ -1041,7 +1085,8 @@ default: case AVAHI_BROWSER_FAILURE: - fprintf(stderr, "(Avahi browser) %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "(Avahi browser) %s\n", avahi_strerror(avahi_server_errno(mc.server))); avahi_simple_poll_quit(mc.simple_poll); return; @@ -1055,7 +1100,8 @@ if(avahi_s_service_resolver_new(mc.server, interface, protocol, name, type, domain, protocol, 0, resolve_callback, NULL) == NULL) - fprintf(stderr, "Avahi: Failed to resolve service '%s': %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Avahi: Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(mc.server))); break; @@ -1065,7 +1111,8 @@ case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: if(debug){ - fprintf(stderr, "No Mandos server found, still searching...\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "No Mandos server found, still searching...\n"); } break; } @@ -1110,38 +1157,40 @@ /* Reject the loopback device */ if(ifr->ifr_flags & IFF_LOOPBACK){ if(debug){ - fprintf(stderr, "Rejecting loopback interface \"%s\"\n", - ifname); + fprintf(stderr, "Mandos plugin mandos-client: " + "Rejecting loopback interface \"%s\"\n", ifname); } return false; } /* Accept point-to-point devices only if connect_to is specified */ if(connect_to != NULL and (ifr->ifr_flags & IFF_POINTOPOINT)){ if(debug){ - fprintf(stderr, "Accepting point-to-point interface \"%s\"\n", - ifname); + fprintf(stderr, "Mandos plugin mandos-client: " + "Accepting point-to-point interface \"%s\"\n", ifname); } return true; } /* Otherwise, reject non-broadcast-capable devices */ if(not (ifr->ifr_flags & IFF_BROADCAST)){ if(debug){ - fprintf(stderr, "Rejecting non-broadcast interface \"%s\"\n", - ifname); + fprintf(stderr, "Mandos plugin mandos-client: " + "Rejecting non-broadcast interface \"%s\"\n", ifname); } return false; } /* Reject non-ARP interfaces (including dummy interfaces) */ if(ifr->ifr_flags & IFF_NOARP){ if(debug){ - fprintf(stderr, "Rejecting non-ARP interface \"%s\"\n", ifname); + fprintf(stderr, "Mandos plugin mandos-client: " + "Rejecting non-ARP interface \"%s\"\n", ifname); } return false; } /* Accept this device */ if(debug){ - fprintf(stderr, "Interface \"%s\" is good\n", ifname); + fprintf(stderr, "Mandos plugin mandos-client: " + "Interface \"%s\" is good\n", ifname); } return true; } @@ -1159,7 +1208,8 @@ struct ifreq ifr; if(not get_flags(if_entry->d_name, &ifr)){ if(debug){ - fprintf(stderr, "Failed to get flags for interface \"%s\"\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Failed to get flags for interface \"%s\"\n", if_entry->d_name); } return 0; @@ -1184,7 +1234,8 @@ struct ifreq ifr; if(not get_flags(if_entry->d_name, &ifr)){ if(debug){ - fprintf(stderr, "Failed to get flags for interface \"%s\"\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Failed to get flags for interface \"%s\"\n", if_entry->d_name); } return 0; @@ -1193,7 +1244,8 @@ /* Reject down interfaces */ if(not (ifr.ifr_flags & IFF_UP)){ if(debug){ - fprintf(stderr, "Rejecting down interface \"%s\"\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Rejecting down interface \"%s\"\n", if_entry->d_name); } return 0; @@ -1202,7 +1254,8 @@ /* Reject non-running interfaces */ if(not (ifr.ifr_flags & IFF_RUNNING)){ if(debug){ - fprintf(stderr, "Rejecting non-running interface \"%s\"\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Rejecting non-running interface \"%s\"\n", if_entry->d_name); } return 0; @@ -1278,13 +1331,14 @@ while(true){ if(mc.current_server == NULL){ if (debug){ - fprintf(stderr, + fprintf(stderr, "Mandos plugin mandos-client: " "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," + fprintf(stderr, "Mandos plugin mandos-client: " + "Check current_server if we should run it," " or wait\n"); } /* the current time */ @@ -1307,7 +1361,8 @@ - ((intmax_t)waited_time.tv_nsec / 1000000)); if (debug){ - fprintf(stderr, "Blocking for %" PRIdMAX " ms\n", block_time); + fprintf(stderr, "Mandos plugin mandos-client: " + "Blocking for %" PRIdMAX " ms\n", block_time); } if(block_time <= 0){ @@ -1333,7 +1388,7 @@ ret = avahi_simple_poll_iterate(s, (int)block_time); } if(ret != 0){ - if (ret > 0 or errno != EINTR) { + if (ret > 0 or errno != EINTR){ return (ret != 1) ? ret : 0; } } @@ -1496,6 +1551,7 @@ argp_state_help(state, state->out_stream, ARGP_HELP_USAGE | ARGP_HELP_EXIT_ERR); case 'V': /* --version */ + fprintf(state->out_stream, "Mandos plugin mandos-client: "); fprintf(state->out_stream, "%s\n", argp_program_version); exit(argp_err_exit_status); break; @@ -1592,59 +1648,93 @@ struct dirent *direntry; int numhooks = scandir(HOOKDIR, &direntries, runnable_hook, alphasort); - int devnull = open("/dev/null", O_RDONLY); - for(int i = 0; i < numhooks; i++){ - direntry = direntries[0]; - char *fullname = NULL; - ret = asprintf(&fullname, "%s/%s", tempdir, - direntry->d_name); - if(ret < 0){ - perror_plus("asprintf"); - continue; - } - pid_t hook_pid = fork(); - if(hook_pid == 0){ - /* Child */ - dup2(devnull, STDIN_FILENO); - close(devnull); - dup2(STDERR_FILENO, STDOUT_FILENO); - ret = setenv("DEVICE", interface, 1); - if(ret == -1){ - perror_plus("setenv"); - exit(1); - } - ret = setenv("VERBOSE", debug ? "1" : "0", 1); - if(ret == -1){ - perror_plus("setenv"); - exit(1); - } - ret = setenv("MODE", "start", 1); - if(ret == -1){ - perror_plus("setenv"); - exit(1); - } - char *delaystring; - ret = asprintf(&delaystring, "%f", delay); - if(ret == -1){ + if(numhooks == -1){ + perror_plus("scandir"); + } else { + int devnull = open("/dev/null", O_RDONLY); + for(int i = 0; i < numhooks; i++){ + direntry = direntries[0]; + char *fullname = NULL; + ret = asprintf(&fullname, "%s/%s", tempdir, + direntry->d_name); + if(ret < 0){ perror_plus("asprintf"); - exit(1); + continue; } - ret = setenv("DELAY", delaystring, 1); - if(ret == -1){ + pid_t hook_pid = fork(); + if(hook_pid == 0){ + /* Child */ + dup2(devnull, STDIN_FILENO); + close(devnull); + dup2(STDERR_FILENO, STDOUT_FILENO); + ret = setenv("DEVICE", interface, 1); + if(ret == -1){ + perror_plus("setenv"); + exit(1); + } + ret = setenv("VERBOSE", debug ? "1" : "0", 1); + if(ret == -1){ + perror_plus("setenv"); + exit(1); + } + ret = setenv("MODE", "start", 1); + if(ret == -1){ + perror_plus("setenv"); + exit(1); + } + char *delaystring; + ret = asprintf(&delaystring, "%f", delay); + if(ret == -1){ + perror_plus("asprintf"); + exit(1); + } + ret = setenv("DELAY", delaystring, 1); + if(ret == -1){ + free(delaystring); + perror_plus("setenv"); + exit(1); + } free(delaystring); - perror_plus("setenv"); - exit(1); - } - free(delaystring); - ret = execl(fullname, direntry->d_name, "start", NULL); - perror_plus("execl"); - } - free(fullname); - if(quit_now){ - goto end; - } + ret = execl(fullname, direntry->d_name, "start", NULL); + perror_plus("execl"); + } else { + int status; + if(TEMP_FAILURE_RETRY(waitpid(hook_pid, &status, 0)) == -1){ + perror_plus("waitpid"); + free(fullname); + continue; + } + if(WIFEXITED(status)){ + if(WEXITSTATUS(status) != 0){ + fprintf(stderr, "Mandos plugin mandos-client: " + "Warning: network hook \"%s\" exited" + " with status %d\n", direntry->d_name, + WEXITSTATUS(status)); + free(fullname); + continue; + } + } else if(WIFSIGNALED(status)){ + fprintf(stderr, "Mandos plugin mandos-client: " + "Warning: network hook \"%s\" died by" + " signal %d\n", direntry->d_name, + WTERMSIG(status)); + free(fullname); + continue; + } else { + fprintf(stderr, "Mandos plugin mandos-client: " + "Warning: network hook \"%s\" crashed\n", + direntry->d_name); + free(fullname); + continue; + } + } + free(fullname); + if(quit_now){ + goto end; + } + } + close(devnull); } - close(devnull); } if(not debug){ @@ -1666,7 +1756,8 @@ /* Pick the first interface returned */ interface = strdup(direntries[0]->d_name); if(debug){ - fprintf(stderr, "Using interface \"%s\"\n", interface); + fprintf(stderr, "Mandos plugin mandos-client: " + "Using interface \"%s\"\n", interface); } if(interface == NULL){ perror_plus("malloc"); @@ -1677,7 +1768,8 @@ free(direntries); } else { free(direntries); - fprintf(stderr, "Could not find a network interface\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Could not find a network interface\n"); exitcode = EXIT_FAILURE; goto end; } @@ -1689,7 +1781,8 @@ srand((unsigned int) time(NULL)); mc.simple_poll = avahi_simple_poll_new(); if(mc.simple_poll == NULL){ - fprintf(stderr, "Avahi: Failed to create simple poll object.\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Avahi: Failed to create simple poll object.\n"); exitcode = EX_UNAVAILABLE; goto end; } @@ -1761,7 +1854,8 @@ if(strcmp(interface, "none") != 0){ if_index = (AvahiIfIndex) if_nametoindex(interface); if(if_index == 0){ - fprintf(stderr, "No such interface: \"%s\"\n", interface); + fprintf(stderr, "Mandos plugin mandos-client: " + "No such interface: \"%s\"\n", interface); exitcode = EX_UNAVAILABLE; goto end; } @@ -1908,7 +2002,8 @@ ret = init_gnutls_global(pubkey, seckey); if(ret == -1){ - fprintf(stderr, "init_gnutls_global failed\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "init_gnutls_global failed\n"); exitcode = EX_UNAVAILABLE; goto end; } else { @@ -1930,7 +2025,8 @@ } if(not init_gpgme(pubkey, seckey, tempdir)){ - fprintf(stderr, "init_gpgme failed\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "init_gpgme failed\n"); exitcode = EX_UNAVAILABLE; goto end; } else { @@ -1946,7 +2042,8 @@ /* (Mainly meant for debugging) */ char *address = strrchr(connect_to, ':'); if(address == NULL){ - fprintf(stderr, "No colon in address\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "No colon in address\n"); exitcode = EX_USAGE; goto end; } @@ -1960,7 +2057,8 @@ tmpmax = strtoimax(address+1, &tmp, 10); if(errno != 0 or tmp == address+1 or *tmp != '\0' or tmpmax != (uint16_t)tmpmax){ - fprintf(stderr, "Bad port number\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Bad port number\n"); exitcode = EX_USAGE; goto end; } @@ -1996,8 +2094,8 @@ break; } if(debug){ - fprintf(stderr, "Retrying in %d seconds\n", - (int)retry_interval); + fprintf(stderr, "Mandos plugin mandos-client: " + "Retrying in %d seconds\n", (int)retry_interval); } sleep((int)retry_interval); } @@ -2033,7 +2131,8 @@ /* Check if creating the Avahi server object succeeded */ if(mc.server == NULL){ - fprintf(stderr, "Failed to create Avahi server: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Failed to create Avahi server: %s\n", avahi_strerror(error)); exitcode = EX_UNAVAILABLE; goto end; @@ -2048,7 +2147,8 @@ AVAHI_PROTO_UNSPEC, "_mandos._tcp", NULL, 0, browse_callback, NULL); if(sb == NULL){ - fprintf(stderr, "Failed to create service browser: %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(mc.server))); exitcode = EX_UNAVAILABLE; goto end; @@ -2061,20 +2161,23 @@ /* Run the main loop */ if(debug){ - fprintf(stderr, "Starting Avahi loop search\n"); + fprintf(stderr, "Mandos plugin mandos-client: " + "Starting Avahi loop search\n"); } ret = avahi_loop_with_timeout(mc.simple_poll, (int)(retry_interval * 1000)); if(debug){ - fprintf(stderr, "avahi_loop_with_timeout exited %s\n", + fprintf(stderr, "Mandos plugin mandos-client: " + "avahi_loop_with_timeout exited %s\n", (ret == 0) ? "successfully" : "with error"); } end: if(debug){ - fprintf(stderr, "%s exiting\n", argv[0]); + fprintf(stderr, "Mandos plugin mandos-client: " + "%s exiting\n", argv[0]); } /* Cleanup things */ @@ -2122,7 +2225,7 @@ ret = ioctl(sd, SIOCGIFFLAGS, &network); if(ret == -1){ perror_plus("ioctl SIOCGIFFLAGS"); - } else if(network.ifr_flags & IFF_UP) { + } else if(network.ifr_flags & IFF_UP){ network.ifr_flags &= ~(short)IFF_UP; /* clear flag */ ret = ioctl(sd, SIOCSIFFLAGS, &network); if(ret == -1){ @@ -2160,8 +2263,8 @@ } ret = remove(fullname); if(ret == -1){ - fprintf(stderr, "remove(\"%s\"): %s\n", fullname, - strerror(errno)); + fprintf(stderr, "Mandos plugin mandos-client: " + "remove(\"%s\"): %s\n", fullname, strerror(errno)); } free(fullname); }