summaryrefslogtreecommitdiffabout
path: root/src/gpg.c
authorSergey Poznyakoff <gray@gnu.org.ua>2007-08-19 22:43:22 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2007-08-19 22:43:22 (GMT)
commit39a9fb6ab567b48ac8c38b98143d6089e9d16709 (patch) (side-by-side diff)
tree7fa248d8ed2c38ec84a9496de4c2f420ddae5504 /src/gpg.c
parent32d5cff1b7c2266779b63fb97eb6b91cab34e7ad (diff)
downloadwydawca-39a9fb6ab567b48ac8c38b98143d6089e9d16709.tar.gz
wydawca-39a9fb6ab567b48ac8c38b98143d6089e9d16709.tar.bz2
* jabberd/jabberd.h (getmaxfd): moved to gsc.h
* jabberd/main.c (stderr_printer): Minor fix * wydawca/triplet.c (triplet_processor): Minor fix * wydawca/verify.c (verify_triplet): Save owner gid in reg. Call verify_detached_signature * wydawca/wydawca.h (struct file_register): New member gid. (verify_detached_signature): New function * wydawca/gpg.c (verify_detached_signature): New function * lib/Makefile.am: Add userprivs.c * lib/userprivs.c: New file git-svn-id: file:///svnroot/wydawca/trunk@280 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
Diffstat (limited to 'src/gpg.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/gpg.c230
1 files changed, 204 insertions, 26 deletions
diff --git a/src/gpg.c b/src/gpg.c
index ae81989..a722b4e 100644
--- a/src/gpg.c
+++ b/src/gpg.c
@@ -17,6 +17,9 @@
#include "wydawca.h"
#include "save-cwd.h"
#include <gpgme.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
#define fail_if_err(expr) \
do \
@@ -138,51 +141,226 @@ wydawca_gpg_homedir ()
setenv ("GNUPGHOME", homedir, 1);
}
+/* FIXME: dpair currently unused */
int
-verify_signature (struct file_register *reg, struct directory_pair *dpair,
- const char *pubkey)
+verify_directive_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;
-
+ gpgme_error_t ec;
+ int rc;
+
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_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));
+ ec = gpgme_op_verify (ctx, directive_data, NULL, plain);
+ if (ec == GPG_ERR_NO_ERROR)
+ {
+ size_t dcount, i;
+ char *p;
+
+ rc = 0;
+
+ 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;
+ gpgme_data_release (plain);
+
+ 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;
+ }
+ else
+ {
+ rc = 1;
+ logmsg (LOG_ERR, "%s: directive verification failed: %s",
+ reg->name, gpgme_strerror (ec));
+ /* FIXME: Send mail to the project maintainer */
+ }
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;
+ return rc;
+}
- dcount = 1;
- for (p = reg->blurb; *p; p++)
- if (*p == '\n')
- dcount++;
+FILE *
+start_prog (int argc, char **argv, pid_t *ppid)
+{
+ int p[2];
+ FILE *fp;
+ pid_t pid;
+ int i;
- reg->directive = xcalloc (dcount, sizeof reg->directive[0]);
- p = reg->blurb;
- for (i = 0; i < dcount; i++)
+ pipe (p);
+ switch (pid = fork ())
{
- reg->directive[i] = p;
- p = strchr (p, '\n');
- if (!p)
- break;
- *p++ = 0;
+ case 0:
+ /* Child process */
+
+ if (p[1] != 1)
+ dup2 (p[1], 1);
+ if (p[1] != 1)
+ dup2 (p[1], 2);
+ close (p[0]);
+
+ /* Close unneded descripitors */
+ for (i = getmaxfd (); i > 2; i--)
+ close (i);
+
+ execv (argv[0], argv);
+ logmsg (LOG_CRIT, "cannot run %s: %s", argv[0], strerror (errno));
+ exit (1);
+
+ case -1:
+ logmsg (LOG_CRIT, "cannot run `%s': fork failed: %s",
+ argv[0], strerror (errno));
+ return NULL;
+
+ default:
+ /* Master process */
+ close (p[1]);
+ fp = fdopen (p[0], "r");
+ if (!fp)
+ logmsg (LOG_ERR, "cannot fdopen: %s", strerror (errno));
+ *ppid = pid;
}
- reg->directive[i] = NULL;
+ return fp;
+}
- return 0;
+static void
+log_output (int prio, const char *prog, FILE *fp)
+{
+ size_t size = 0;
+ char *buf = NULL;
+
+ logmsg (prio, "%s output follows:", prog);
+ while (getline (&buf, &size, fp) > 0)
+ logmsg (prio, "%s", buf);
+ logmsg (prio, "end of %s output", prog);
+ free (buf);
+}
+
+int
+verify_detached_signature (struct file_register *reg,
+ struct directory_pair *dpair)
+{
+ gpgme_engine_info_t info;
+ const char *gpg_prog;
+ char *argv[5];
+ FILE *fp;
+ pid_t pid, npid;
+ int status;
+ int i;
+ int rc;
+
+ 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", reg->name);
+ return 1;
+ }
+
+ wydawca_gpg_homedir ();
+ argv[0] = info->file_name;
+ argv[1] = "--verify";
+ argv[2] = reg->file[file_signature].name;
+ argv[3] = reg->file[file_dist].name;
+ argv[4] = NULL;
+
+ fp = start_prog (5, argv, &pid);
+ if (!fp)
+ {
+ logmsg (LOG_CRIT,
+ "cannot verify detached signature for %s", reg->name);
+ return 1;
+ }
+
+ for (i = 0; i < 5 && (npid = waitpid (pid, &status, WNOHANG)) == 0; i++)
+ sleep (1);
+
+ switch (npid)
+ {
+ case -1:
+ logmsg (LOG_CRIT,
+ "cannot verify detached signature for %s: "
+ "waitpid failed: %s", reg->name, strerror (errno));
+ return 1;
+
+ case 0:
+ logmsg (LOG_CRIT,
+ "cannot verify detached signature for %s: "
+ "process %s did not respond within 5 seconds: %s",
+ reg->name, argv[0], strerror (errno));
+ kill (pid, SIGKILL);
+ return 1;
+
+ default:
+ break;
+ }
+
+ if (WIFEXITED (status))
+ {
+ rc = WEXITSTATUS (status);
+ if (rc)
+ {
+ size_t size = 0;
+ char *buf = NULL;
+
+ logmsg (LOG_ERR, "bad detached signature for %s", reg->name);
+ log_output (LOG_ERR, argv[0], fp);
+ /* FIXME: email? */
+ }
+ else if (debug_level > 1)
+ log_output (LOG_DEBUG, argv[0], fp);
+ }
+ else
+ {
+ rc = 1;
+ if (WIFSIGNALED (status))
+ logmsg (LOG_ERR,
+ "cannot verify detached signature for %s: "
+ "%s terminated on signal %d",
+ reg->name, argv[0], WTERMSIG (status));
+ else if (WIFSTOPPED (status))
+ logmsg (LOG_ERR,
+ "cannot verify detached signature for %s: "
+ "%s stopped on signal %d",
+ reg->name, argv[0], WTERMSIG (status));
+ else
+ logmsg (LOG_ERR,
+ "cannot verify detached signature for %s: "
+ "%s terminated with unrecognized status",
+ reg->name, argv[0]);
+ }
+ fclose (fp);
+
+ return rc;
}

Return to:

Send suggestions and report system problems to the System administrator.