=== modified file 'Makefile' --- Makefile 2008-08-31 15:06:39 +0000 +++ Makefile 2008-09-03 18:47:50 +0000 @@ -96,7 +96,7 @@ run-client: all keydir/seckey.txt keydir/pubkey.txt \ keydir/secring.gpg keydir/pubring.gpg ./plugin-runner --plugin-dir=plugins.d \ - --options-for=password-request:--keydir=keydir + --options-for=password-request:--seckey=keydir/seckey.txt,--pubkey=keydir/pubkey.txt # Used by run-client keydir/secring.gpg: keydir/seckey.txt === modified file 'plugins.d/password-request.c' --- plugins.d/password-request.c 2008-08-24 10:49:09 +0000 +++ plugins.d/password-request.c 2008-09-03 18:47:50 +0000 @@ -47,21 +47,24 @@ #include /* socket(), inet_pton(), sockaddr, sockaddr_in6, PF_INET6, SOCK_STREAM, INET6_ADDRSTRLEN, - uid_t, gid_t */ -#include /* PRIu16 */ + uid_t, gid_t, open(), opendir(), DIR */ +#include /* open() */ #include /* socket(), struct sockaddr_in6, struct in6_addr, inet_pton(), connect() */ +#include /* open() */ +#include /* opendir(), struct dirent, readdir() */ +#include /* PRIu16 */ #include /* assert() */ #include /* perror(), errno */ #include /* time() */ #include /* ioctl, ifreq, SIOCGIFFLAGS, IFF_UP, SIOCSIFFLAGS, if_indextoname(), if_nametoindex(), IF_NAMESIZE */ +#include #include /* close(), SEEK_SET, off_t, write(), getuid(), getgid(), setuid(), setgid() */ -#include #include /* inet_pton(), htons */ #include /* not, and */ #include /* struct argp_option, error_t, struct @@ -98,8 +101,15 @@ #define BUFFER_SIZE 256 +/* + #define PATHDIR "/conf/conf.d/mandos" +*/ + +#define PATHDIR "/conf/conf.d/mandos" +#define SECKEY "seckey.txt" +#define PUBKEY "pupkey.txt" + bool debug = false; -static const char *keydir = "/conf/conf.d/mandos"; static const char mandos_protocol_version[] = "1"; const char *argp_program_version = "password-request 1.0"; const char *argp_program_bug_address = ""; @@ -112,6 +122,7 @@ unsigned int dh_bits; gnutls_dh_params_t dh_params; const char *priority; + gpgme_ctx_t ctx; } mandos_context; /* @@ -132,52 +143,114 @@ } /* - * Decrypt OpenPGP data using keyrings in HOMEDIR. - * Returns -1 on error + * Initialize GPGME. */ -static ssize_t pgp_packet_decrypt (const char *cryptotext, - size_t crypto_size, - char **plaintext, - const char *homedir){ - gpgme_data_t dh_crypto, dh_plain; - gpgme_ctx_t ctx; +static bool init_gpgme(mandos_context *mc, const char *seckey, + const char *pubkey, const char *tempdir){ + int ret; gpgme_error_t rc; - ssize_t ret; - size_t plaintext_capacity = 0; - ssize_t plaintext_length = 0; gpgme_engine_info_t engine_info; + + + /* + * Helper function to insert pub and seckey to the enigne keyring. + */ + bool import_key(const char *filename){ + int fd; + gpgme_data_t pgp_data; + + fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY)); + if(fd == -1){ + perror("open"); + return false; + } + + 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", + 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", + gpgme_strsource(rc), gpgme_strerror(rc)); + return false; + } + + ret = TEMP_FAILURE_RETRY(close(fd)); + if(ret == -1){ + perror("close"); + } + gpgme_data_release(pgp_data); + return true; + } if (debug){ - fprintf(stderr, "Trying to decrypt OpenPGP data\n"); + fprintf(stderr, "Initialize 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", gpgme_strsource(rc), gpgme_strerror(rc)); - return -1; + return false; } - - /* Set GPGME home directory for the OpenPGP engine only */ + + /* 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", gpgme_strsource(rc), gpgme_strerror(rc)); - return -1; + return false; } while(engine_info != NULL){ if(engine_info->protocol == GPGME_PROTOCOL_OpenPGP){ gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, - engine_info->file_name, homedir); + engine_info->file_name, tempdir); break; } engine_info = engine_info->next; } if(engine_info == NULL){ - fprintf(stderr, "Could not set GPGME home dir to %s\n", homedir); - return -1; + fprintf(stderr, "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)); + return false; + } + + if (not import_key(pubkey) or not import_key(seckey)){ + return false; + } + + return true; +} + +/* + * Decrypt OpenPGP data. + * Returns -1 on error + */ +static ssize_t pgp_packet_decrypt (const mandos_context *mc, + const char *cryptotext, + size_t crypto_size, + char **plaintext){ + gpgme_data_t dh_crypto, dh_plain; + gpgme_error_t rc; + ssize_t ret; + size_t plaintext_capacity = 0; + ssize_t plaintext_length = 0; + + if (debug){ + fprintf(stderr, "Trying to decrypt OpenPGP data\n"); } /* Create new GPGME data buffer from memory cryptotext */ @@ -198,25 +271,16 @@ return -1; } - /* Create new GPGME "context" */ - rc = gpgme_new(&ctx); - if (rc != GPG_ERR_NO_ERROR){ - fprintf(stderr, "bad gpgme_new: %s: %s\n", - gpgme_strsource(rc), gpgme_strerror(rc)); - plaintext_length = -1; - goto decrypt_end; - } - /* Decrypt data from the cryptotext data buffer to the plaintext data buffer */ - rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain); + 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", gpgme_strsource(rc), gpgme_strerror(rc)); plaintext_length = -1; if (debug){ gpgme_decrypt_result_t result; - result = gpgme_op_decrypt_result(ctx); + result = gpgme_op_decrypt_result(mc->ctx); if (result == NULL){ fprintf(stderr, "gpgme_op_decrypt_result failed\n"); } else { @@ -360,7 +424,7 @@ fprintf(stderr, "Error[%d] while reading the OpenPGP key pair ('%s'," " '%s')\n", ret, pubkeyfilename, seckeyfilename); - fprintf(stdout, "The GnuTLS error is: %s\n", + fprintf(stderr, "The GnuTLS error is: %s\n", safer_gnutls_strerror(ret)); goto globalfail; } @@ -611,10 +675,9 @@ gnutls_bye (session, GNUTLS_SHUT_RDWR); if (buffer_length > 0){ - decrypted_buffer_size = pgp_packet_decrypt(buffer, + decrypted_buffer_size = pgp_packet_decrypt(mc, buffer, buffer_length, - &decrypted_buffer, - keydir); + &decrypted_buffer); if (decrypted_buffer_size >= 0){ written = 0; while(written < (size_t) decrypted_buffer_size){ @@ -643,7 +706,10 @@ mandos_end: free(buffer); - close(tcp_sd); + ret = TEMP_FAILURE_RETRY(close(tcp_sd)); + if(ret == -1){ + perror("close"); + } gnutls_deinit (session); return retval; } @@ -745,18 +811,6 @@ } } -/* Combines file name and path and returns the malloced new - string. some sane checks could/should be added */ -static char *combinepath(const char *first, const char *second){ - char *tmp; - int ret = asprintf(&tmp, "%s/%s", first, second); - if(ret < 0){ - return NULL; - } - return tmp; -} - - int main(int argc, char *argv[]){ AvahiSServiceBrowser *sb = NULL; int error; @@ -768,14 +822,15 @@ uid_t uid; gid_t gid; char *connect_to = NULL; + char tempdir[] = "/tmp/mandosXXXXXX"; AvahiIfIndex if_index = AVAHI_IF_UNSPEC; - char *pubkeyfilename = NULL; - char *seckeyfilename = NULL; - const char *pubkeyname = "pubkey.txt"; - const char *seckeyname = "seckey.txt"; + const char *seckey = PATHDIR "/" SECKEY; + const char *pubkey = PATHDIR "/" PUBKEY; + mandos_context mc = { .simple_poll = NULL, .server = NULL, .dh_bits = 1024, .priority = "SECURE256"}; bool gnutls_initalized = false; + bool pgpme_initalized = false; { struct argp_option options[] = { @@ -789,10 +844,6 @@ .arg = "INTERFACE", .doc = "Interface that Avahi will conntect through", .group = 1 }, - { .name = "keydir", .key = 'd', - .arg = "KEYDIR", - .doc = "Directory where the openpgp keyring is", - .group = 1 }, { .name = "seckey", .key = 's', .arg = "SECKEY", .doc = "Secret openpgp key for gnutls authentication", @@ -826,14 +877,11 @@ case 'i': interface = arg; break; - case 'd': - keydir = arg; - break; case 's': - seckeyname = arg; + seckey = arg; break; case 'p': - pubkeyname = arg; + pubkey = arg; break; case 129: errno = 0; @@ -867,22 +915,8 @@ goto end; } } - - pubkeyfilename = combinepath(keydir, pubkeyname); - if (pubkeyfilename == NULL){ - perror("combinepath"); - exitcode = EXIT_FAILURE; - goto end; - } - - seckeyfilename = combinepath(keydir, seckeyname); - if (seckeyfilename == NULL){ - perror("combinepath"); - exitcode = EXIT_FAILURE; - goto end; - } - ret = init_gnutls_global(&mc, pubkeyfilename, seckeyfilename); + ret = init_gnutls_global(&mc, pubkey, seckey); if (ret == -1){ fprintf(stderr, "init_gnutls_global failed\n"); exitcode = EXIT_FAILURE; @@ -890,6 +924,20 @@ } else { gnutls_initalized = true; } + + if(mkdtemp(tempdir) == NULL){ + perror("mkdtemp"); + tempdir[0] = '\0'; + goto end; + } + + if(not init_gpgme(&mc, pubkey, seckey, tempdir)){ + fprintf(stderr, "pgpme_initalized failed\n"); + exitcode = EXIT_FAILURE; + goto end; + } else { + pgpme_initalized = true; + } /* If the interface is down, bring it up */ { @@ -915,7 +963,10 @@ goto end; } } - close(sd); + ret = TEMP_FAILURE_RETRY(close(sd)); + if(ret == -1){ + perror("close"); + } } uid = getuid(); @@ -1041,13 +1092,51 @@ if (mc.simple_poll != NULL) avahi_simple_poll_free(mc.simple_poll); - free(pubkeyfilename); - free(seckeyfilename); if (gnutls_initalized){ gnutls_certificate_free_credentials(mc.cred); gnutls_global_deinit (); } - + + if(pgpme_initalized){ + gpgme_release(mc.ctx); + } + + /* Removes the temp directory used by GPGME */ + if(tempdir[0] != '\0'){ + DIR *d; + struct dirent *direntry; + d = opendir(tempdir); + if(d == NULL){ + perror("opendir"); + } else { + while(true){ + direntry = readdir(d); + if(direntry == NULL){ + break; + } + if (direntry->d_type == DT_REG){ + char *fullname = NULL; + ret = asprintf(&fullname, "%s/%s", tempdir, + direntry->d_name); + if(ret < 0){ + perror("asprintf"); + continue; + } + ret = unlink(fullname); + if(ret == -1){ + fprintf(stderr, "unlink(\"%s\"): %s", + fullname, strerror(errno)); + } + free(fullname); + } + } + } + ret = rmdir(tempdir); + if(ret == -1){ + perror("rmdir"); + } + } + return exitcode; }