diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-08-19 13:30:35 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-08-19 13:30:35 +0000 |
commit | 32d5cff1b7c2266779b63fb97eb6b91cab34e7ad (patch) | |
tree | a6334d3ceff71716e9e1399fb376963782a5404b /src/gpg.c | |
parent | 106472e9039e46a5468ed15f118a2cf7d74f6ec8 (diff) | |
download | wydawca-32d5cff1b7c2266779b63fb97eb6b91cab34e7ad.tar.gz wydawca-32d5cff1b7c2266779b63fb97eb6b91cab34e7ad.tar.bz2 |
New module: wydawca
git-svn-id: file:///svnroot/wydawca/trunk@279 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
Diffstat (limited to 'src/gpg.c')
-rw-r--r-- | src/gpg.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/gpg.c b/src/gpg.c new file mode 100644 index 0000000..ae81989 --- /dev/null +++ b/src/gpg.c @@ -0,0 +1,188 @@ +/* wydawca - FTP release synchronisation daemon + Copyright (C) 2007 Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "wydawca.h" +#include "save-cwd.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) + +static char *homedir; + +static int rmdir_r (const char *name); + +static int +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; + } + 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; +} + +static int +rmdir_r (const char *name) +{ + int rc; + struct saved_cwd cwd; + + if (save_cwd (&cwd)) + { + logmsg (LOG_ERR, "cannot save current directory: %s", + strerror (errno)); + return 1; + } + rc = recursive_rmdir (name); + if (restore_cwd (&cwd)) + { + 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; +} + +static void +remove_homedir () +{ + if (debug_level > 1) + logmsg (LOG_DEBUG, "Removing GNUPG home directory: %s", homedir); + if (rmdir_r (homedir)) + logmsg (LOG_CRIT, "Failed to remove GPG directory %s", homedir); +} + +int +wydawca_gpg_homedir () +{ + if (homedir) + return; + + homedir = xstrdup ("/tmp/wydawca-XXXXXX"); + if (!mkdtemp (homedir)) + { + logmsg (LOG_CRIT, "cannot create GPG home directory (%s): %s", + homedir, strerror (errno)); + return 1; + } + atexit (remove_homedir); + if (debug_level > 1) + logmsg (LOG_DEBUG, "GNUPG home directory: %s", homedir); + setenv ("GNUPGHOME", homedir, 1); +} + +int +verify_signature (struct file_register *reg, struct directory_pair *dpair, + const char *pubkey) +{ + gpgme_ctx_t ctx; + gpgme_data_t key_data, directive_data, plain; + off_t size; + size_t dcount, i; + char *p; + + wydawca_gpg_homedir (); + fail_if_err (gpgme_new (&ctx)); + fail_if_err (gpgme_data_new_from_mem (&key_data, pubkey, strlen (pubkey), 0)); + fail_if_err (gpgme_op_import (ctx, key_data)); + + fail_if_err (gpgme_data_new_from_file (&directive_data, + reg->file[file_directive].name, 1)); + gpgme_data_new (&plain); + fail_if_err (gpgme_op_verify (ctx, directive_data, NULL, plain)); + + gpgme_data_release (directive_data); + gpgme_data_release (key_data); + + size = gpgme_data_seek (plain, 0, SEEK_END); + gpgme_data_seek (plain, 0, SEEK_SET); + reg->blurb = xmalloc (size + 1); + gpgme_data_read (plain, reg->blurb, size); + reg->blurb[size] = 0; + + dcount = 1; + for (p = reg->blurb; *p; p++) + if (*p == '\n') + dcount++; + + reg->directive = xcalloc (dcount, sizeof reg->directive[0]); + p = reg->blurb; + for (i = 0; i < dcount; i++) + { + reg->directive[i] = p; + p = strchr (p, '\n'); + if (!p) + break; + *p++ = 0; + } + reg->directive[i] = NULL; + + return 0; +} |