aboutsummaryrefslogtreecommitdiff
path: root/src/gpg.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-08-19 13:30:35 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-08-19 13:30:35 +0000
commit32d5cff1b7c2266779b63fb97eb6b91cab34e7ad (patch)
treea6334d3ceff71716e9e1399fb376963782a5404b /src/gpg.c
parent106472e9039e46a5468ed15f118a2cf7d74f6ec8 (diff)
downloadwydawca-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.c188
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;
+}

Return to:

Send suggestions and report system problems to the System administrator.