diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-01-01 13:25:55 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-01-01 13:33:04 +0200 |
commit | 24e6dfa7cffceea0cac0f3cc349192788f040939 (patch) | |
tree | c2bd53e9bc58873c8187e6bd622ae152b35d1d51 /src/gpg.c | |
parent | 2bdd70d698c63d32f25b4f1142e09f5eaef4812a (diff) | |
download | wydawca-24e6dfa7cffceea0cac0f3cc349192788f040939.tar.gz wydawca-24e6dfa7cffceea0cac0f3cc349192788f040939.tar.bz2 |
Update copyright years. Switch to a familiar style.
Diffstat (limited to 'src/gpg.c')
-rw-r--r-- | src/gpg.c | 527 |
1 files changed, 255 insertions, 272 deletions
@@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2010-2011 Sergey Poznyakoff + Copyright (C) 2007, 2010-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -19,322 +19,305 @@ #include "wydawca.h" #include <gpgme.h> -#define fail_if_err(expr) \ - do \ - { \ - int a = expr; \ - if (a) \ - { \ - logmsg (LOG_ERR, _("%s: GPGME error: %s"), #expr, \ - gpgme_strerror (a)); \ - return 1; \ - } \ - } \ - while (0) +#define fail_if_err(expr) do { \ + int a = expr; \ + if (a) { \ + logmsg(LOG_ERR, _("%s: GPGME error: %s"), #expr, \ + gpgme_strerror(a)); \ + return 1; \ + } \ + } while (0) char *temp_homedir; -static int rmdir_r (const char *name); +static int rmdir_r(const char *name); /* Auxiliary function: change to directory NAME and recursively remove everything under it. */ static int -recursive_rmdir (const char *name) +recursive_rmdir(const char *name) { - int rc; - DIR *dir; - struct dirent *ent; - - if (chdir (name)) - { - logmsg (LOG_ERR, _("cannot change to directory %s: %s"), - name, strerror (errno)); - return 1; - } - - dir = opendir ("."); - if (!dir) - { - logmsg (LOG_ERR, _("cannot open directory %s: %s"), - name, strerror (errno)); - return 1; - } - - for (rc = 0; rc == 0 && (ent = readdir (dir));) - { - struct stat st; - - if (strcmp (ent->d_name, ".") == 0 - || strcmp (ent->d_name, "..") == 0) - continue; - - if (stat (ent->d_name, &st) && errno != ENOENT) - { - logmsg (LOG_ERR, _("cannot stat file `%s': %s"), - name, strerror (errno)); - rc = 1; + int rc; + DIR *dir; + struct dirent *ent; + + if (chdir(name)) { + logmsg(LOG_ERR, _("cannot change to directory %s: %s"), + name, strerror(errno)); + return 1; } - else if (S_ISDIR (st.st_mode)) - rc = rmdir_r (ent->d_name); - else if ((rc = unlink (ent->d_name)) != 0 && errno != ENOENT) - logmsg (LOG_ERR, _("cannot unlink %s: %s"), - ent->d_name, strerror (errno)); - } - closedir (dir); - return rc; + + dir = opendir("."); + if (!dir) { + logmsg(LOG_ERR, _("cannot open directory %s: %s"), + name, strerror(errno)); + return 1; + } + + for (rc = 0; rc == 0 && (ent = readdir(dir));) { + struct stat st; + + if (strcmp(ent->d_name, ".") == 0 + || strcmp(ent->d_name, "..") == 0) + continue; + + if (stat(ent->d_name, &st) && errno != ENOENT) { + logmsg(LOG_ERR, _("cannot stat file `%s': %s"), + name, strerror(errno)); + rc = 1; + } else if (S_ISDIR(st.st_mode)) + rc = rmdir_r(ent->d_name); + else if ((rc = unlink(ent->d_name)) != 0 && errno != ENOENT) + logmsg(LOG_ERR, _("cannot unlink %s: %s"), + ent->d_name, strerror(errno)); + } + closedir(dir); + return rc; } /* Recursively remove the contents of the directory NAME and the directory itself. Do not change CWD. */ static int -rmdir_r (const char *name) +rmdir_r(const char *name) { - int rc; - - if (push_dir (NULL)) - { - logmsg (LOG_ERR, _("cannot save current directory: %s"), - strerror (errno)); - return 1; - } - rc = recursive_rmdir (name); - if (pop_dir ()) - { - logmsg (LOG_ERR, _("cannot restore current directory: %s"), - strerror (errno)); - rc = 1; - } - - if (rc == 0 && rmdir (name)) - { - logmsg (LOG_ERR, _("cannot remove directory %s: %s"), - name, strerror (errno)); - return 1; - } - - return rc; + int rc; + + if (push_dir(NULL)) { + logmsg(LOG_ERR, _("cannot save current directory: %s"), + strerror(errno)); + return 1; + } + rc = recursive_rmdir(name); + if (pop_dir()) { + logmsg(LOG_ERR, _("cannot restore current directory: %s"), + strerror(errno)); + rc = 1; + } + + if (rc == 0 && rmdir(name)) { + logmsg(LOG_ERR, _("cannot remove directory %s: %s"), + name, strerror(errno)); + return 1; + } + + return rc; } /* Remove temporary GPG home directory */ static void -remove_homedir () +remove_homedir() { - if (debug_level > 1) - logmsg (LOG_DEBUG, _("removing GNUPG home directory: %s"), temp_homedir); - if (rmdir_r (temp_homedir)) - logmsg (LOG_CRIT, _("failed to remove GPG directory %s"), temp_homedir); + if (debug_level > 1) + logmsg(LOG_DEBUG, _("removing GNUPG home directory: %s"), + temp_homedir); + if (rmdir_r(temp_homedir)) + logmsg(LOG_CRIT, _("failed to remove GPG directory %s"), + temp_homedir); } /* Create a temporary GPG home directory */ static int -create_gpg_homedir () +create_gpg_homedir() { - if (temp_homedir) - return 0; - - temp_homedir = grecs_strdup ("/tmp/wydawca-XXXXXX"); - if (!mkdtemp (temp_homedir)) - { - logmsg (LOG_CRIT, _("cannot create GPG home directory (%s): %s"), - temp_homedir, strerror (errno)); - return 1; - } - atexit (remove_homedir); - if (debug_level > 1) - logmsg (LOG_DEBUG, _("GNUPG home directory: %s"), temp_homedir); - setenv ("GNUPGHOME", temp_homedir, 1); - return 0; + if (temp_homedir) + return 0; + + temp_homedir = grecs_strdup("/tmp/wydawca-XXXXXX"); + if (!mkdtemp(temp_homedir)) { + logmsg(LOG_CRIT, + _("cannot create GPG home directory (%s): %s"), + temp_homedir, strerror(errno)); + return 1; + } + atexit(remove_homedir); + if (debug_level > 1) + logmsg(LOG_DEBUG, _("GNUPG home directory: %s"), temp_homedir); + setenv("GNUPGHOME", temp_homedir, 1); + return 0; } static int -checksig (gpgme_signature_t sig, const char *uid, struct file_triplet *trp) +checksig(gpgme_signature_t sig, const char *uid, struct file_triplet *trp) { - switch (gpg_err_code (sig->status)) - { - case GPG_ERR_NO_ERROR: - if (debug_level) - logmsg (LOG_NOTICE, _("Good signature from %s"), uid); - trp->uploader = uploader_find_frp (trp->uploader_list, sig->fpr); - if (!trp->uploader) - { - logmsg (LOG_ERR, - _("good signature from %s, " - "but the uploader info for %s not found"), - uid, sig->fpr); - return 1; + switch (gpg_err_code(sig->status)) { + case GPG_ERR_NO_ERROR: + if (debug_level) + logmsg(LOG_NOTICE, _("Good signature from %s"), uid); + trp->uploader = uploader_find_frp(trp->uploader_list, + sig->fpr); + if (!trp->uploader) { + logmsg(LOG_ERR, + _("good signature from %s, " + "but the uploader info for %s not found"), + uid, sig->fpr); + return 1; + } + break; + + case GPG_ERR_BAD_SIGNATURE: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("BAD signature from %s"), uid); + return 0; + + case GPG_ERR_NO_PUBKEY: + UPDATE_STATS(STAT_ACCESS_VIOLATIONS); + logmsg(LOG_ERR, _("No public key")); + return 0; + + case GPG_ERR_NO_DATA: + UPDATE_STATS(STAT_BAD_TRIPLETS); + logmsg(LOG_ERR, _("No signature")); + return 0; + + case GPG_ERR_SIG_EXPIRED: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("Expired signature from %s"), uid); + return 0; + + case GPG_ERR_KEY_EXPIRED: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("Key expired (%s)"), uid); + return 0; + + default: + logmsg(LOG_ERR, _("Unknown signature error")); + return 0; } - break; - - case GPG_ERR_BAD_SIGNATURE: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("BAD signature from %s"), uid); - return 0; - - case GPG_ERR_NO_PUBKEY: - UPDATE_STATS (STAT_ACCESS_VIOLATIONS); - logmsg (LOG_ERR, _("No public key")); - return 0; - - case GPG_ERR_NO_DATA: - UPDATE_STATS (STAT_BAD_TRIPLETS); - logmsg (LOG_ERR, _("No signature")); - return 0; - - case GPG_ERR_SIG_EXPIRED: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("Expired signature from %s"), uid); - return 0; - - case GPG_ERR_KEY_EXPIRED: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("Key expired (%s)"), uid); - return 0; - - default: - logmsg (LOG_ERR, _("Unknown signature error")); - return 0; - } - return -1; + return -1; } static int -gpg_verify_signature (gpgme_ctx_t ctx, gpgme_signature_t sig, - struct file_triplet *trp) +gpg_verify_signature(gpgme_ctx_t ctx, gpgme_signature_t sig, + struct file_triplet *trp) { - if (!sig) - return 0; - - for (; sig; sig = sig->next) - { - const char *uid; - gpgme_key_t key; - int rc; - - if (gpgme_get_key (ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR) - uid = key->uids->uid; - else - uid = sig->fpr; - rc = checksig (sig, uid, trp); - gpgme_key_unref (key); - if (rc != -1) - return rc; - } - return 1; + if (!sig) + return 0; + + for (; sig; sig = sig->next) { + const char *uid; + gpgme_key_t key; + int rc; + + if (gpgme_get_key(ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR) + uid = key->uids->uid; + else + uid = sig->fpr; + rc = checksig(sig, uid, trp); + gpgme_key_unref(key); + if (rc != -1) + return rc; + } + return 1; } /* Verify the directive file from TRP using public key PUBKEY */ int -verify_directive_signature (struct file_triplet *trp) +verify_directive_signature(struct file_triplet *trp) { - gpgme_ctx_t ctx; - gpgme_data_t key_data, directive_data, plain = NULL; - gpgme_error_t ec; - int rc; - struct uploader_info *uptr; - - create_gpg_homedir (); - fail_if_err (gpgme_new (&ctx)); - - for (uptr = trp->uploader_list; uptr; uptr = uptr->next) - { - gpgme_import_result_t res; - gpgme_import_status_t pstat; - - fail_if_err (gpgme_data_new_from_mem (&key_data, - uptr->gpg_key, - strlen (uptr->gpg_key), - 0)); - fail_if_err (gpgme_op_import (ctx, key_data)); - res = gpgme_op_import_result (ctx); - pstat = res->imports; - uptr->fpr = grecs_strdup (pstat->fpr); - if (debug_level > 2) - logmsg (LOG_DEBUG, _("imported key: user = %s, fingerprint = %s"), - uptr->name, uptr->fpr); - } - - fail_if_err (gpgme_data_new_from_file (&directive_data, - trp->file[file_directive].name, 1)); - gpgme_data_new (&plain); - ec = gpgme_op_verify (ctx, directive_data, NULL, plain); - if (ec == GPG_ERR_NO_ERROR) - { - gpgme_verify_result_t result; - - result = gpgme_op_verify_result (ctx); - if (!gpg_verify_signature (ctx, result->signatures, trp)) - { - UPDATE_STATS (STAT_BAD_SIGNATURE); - notify (trp->spool->notification, trp, ev_bad_directive_signature); - rc = 1; + gpgme_ctx_t ctx; + gpgme_data_t key_data, directive_data, plain = NULL; + gpgme_error_t ec; + int rc; + struct uploader_info *uptr; + + create_gpg_homedir(); + fail_if_err(gpgme_new(&ctx)); + + for (uptr = trp->uploader_list; uptr; uptr = uptr->next) { + gpgme_import_result_t res; + gpgme_import_status_t pstat; + + fail_if_err(gpgme_data_new_from_mem(&key_data, + uptr->gpg_key, + strlen(uptr->gpg_key), 0)); + fail_if_err(gpgme_op_import(ctx, key_data)); + res = gpgme_op_import_result(ctx); + pstat = res->imports; + uptr->fpr = grecs_strdup(pstat->fpr); + if (debug_level > 2) + logmsg(LOG_DEBUG, + _("imported key: user = %s, fingerprint = %s"), + uptr->name, uptr->fpr); } - else - rc = 0; - } - else - { - rc = 1; - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("%s: directive verification failed: %s"), - trp->name, gpgme_strerror (ec)); - } - - gpgme_data_release (plain); - gpgme_data_release (directive_data); - gpgme_data_release (key_data); - gpgme_release (ctx); - - return rc; + + fail_if_err(gpgme_data_new_from_file(&directive_data, + trp->file[file_directive].name, + 1)); + gpgme_data_new(&plain); + ec = gpgme_op_verify(ctx, directive_data, NULL, plain); + if (ec == GPG_ERR_NO_ERROR) { + gpgme_verify_result_t result; + + result = gpgme_op_verify_result(ctx); + if (!gpg_verify_signature(ctx, result->signatures, trp)) { + UPDATE_STATS(STAT_BAD_SIGNATURE); + notify(trp->spool->notification, trp, + ev_bad_directive_signature); + rc = 1; + } else + rc = 0; + } else { + rc = 1; + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("%s: directive verification failed: %s"), + trp->name, gpgme_strerror(ec)); + } + + gpgme_data_release(plain); + gpgme_data_release(directive_data); + gpgme_data_release(key_data); + gpgme_release(ctx); + + return rc; } /* Verify the detached signature of TRP. NOTE: It is assumed that the public key is already registered (by a previous call to verify_directive_signature). */ int -verify_detached_signature (struct file_triplet *trp) +verify_detached_signature(struct file_triplet *trp) { - gpgme_engine_info_t info; - const char *argv[5]; - const struct spool *spool; - - ASGN_SPOOL (spool, trp, return 1); - - fail_if_err (gpgme_get_engine_info (&info)); - while (info && info->protocol != GPGME_PROTOCOL_OpenPGP) - info = info->next; - if (!info) - { - logmsg (LOG_CRIT, - _("cannot find path to gpg binary (attempting to verify " - "the detached signature for %s"), trp->name); - return 1; - } - - create_gpg_homedir (); - argv[0] = info->file_name; - argv[1] = "--verify"; - argv[2] = trp->file[file_signature].name; - argv[3] = trp->file[file_dist].name; - argv[4] = NULL; - - switch (wydawca_exec (5, argv, NULL)) - { - case exec_success: - if (debug_level) - logmsg (LOG_DEBUG, _("good detached signature for %s"), trp->name); - return 0; - - case exec_fail: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("BAD detached signature for %s"), trp->name); - notify (spool->notification, trp, ev_bad_detached_signature); - break; - - case exec_error: - logmsg (LOG_CRIT, _("cannot verify detached signature for %s"), - trp->name); - break; - } - - return 1; + gpgme_engine_info_t info; + const char *argv[5]; + const struct spool *spool; + + ASGN_SPOOL(spool, trp, return 1); + + fail_if_err(gpgme_get_engine_info(&info)); + while (info && info->protocol != GPGME_PROTOCOL_OpenPGP) + info = info->next; + if (!info) { + logmsg(LOG_CRIT, + _("cannot find path to gpg binary (attempting to " + "verify the detached signature for %s"), trp->name); + return 1; + } + + create_gpg_homedir(); + argv[0] = info->file_name; + argv[1] = "--verify"; + argv[2] = trp->file[file_signature].name; + argv[3] = trp->file[file_dist].name; + argv[4] = NULL; + + switch (wydawca_exec(5, argv, NULL)) { + case exec_success: + if (debug_level) + logmsg(LOG_DEBUG, _("good detached signature for %s"), + trp->name); + return 0; + + case exec_fail: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("BAD detached signature for %s"), trp->name); + notify(spool->notification, trp, ev_bad_detached_signature); + break; + + case exec_error: + logmsg(LOG_CRIT, _("cannot verify detached signature for %s"), + trp->name); + break; + } + + return 1; } |