aboutsummaryrefslogtreecommitdiff
path: root/src/verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/verify.c')
-rw-r--r--src/verify.c278
1 files changed, 199 insertions, 79 deletions
diff --git a/src/verify.c b/src/verify.c
index 15a2d8b..ed5f0cf 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -38,15 +38,112 @@ trim (char *str)
return len;
}
+#define MSG_BEGIN_MARKER_STR "-----BEGIN PGP SIGNED MESSAGE-----\n"
+#define MSG_BEGIN_MARKER_LEN (sizeof (MSG_BEGIN_MARKER_STR) - 1)
+
+#define SIG_BEGIN_MARKER_STR "-----BEGIN PGP SIGNATURE-----\n"
+#define SIG_BEGIN_MARKER_LEN (sizeof (SIG_BEGIN_MARKER_STR) - 1)
+
+static int
+extract_plaintext (char *blurb)
+{
+ char *start, *p;
+
+ if (memcmp (blurb, MSG_BEGIN_MARKER_STR, MSG_BEGIN_MARKER_LEN))
+ return 1;
+
+ p = blurb + MSG_BEGIN_MARKER_LEN;
+ while (*p)
+ {
+ if (*p == '\n')
+ {
+ p++;
+ break;
+ }
+
+ p = strchr (p, '\n');
+ if (!p)
+ return 1;
+ p++;
+ }
+
+ if (!*p)
+ return 1;
+
+ start = p;
+ while (*p)
+ {
+ if (strncmp (p, SIG_BEGIN_MARKER_STR, SIG_BEGIN_MARKER_LEN) == 0)
+ {
+ *p++ = 0;
+ memmove (blurb, start, p - start);
+ return 0;
+ }
+ p = strchr (p, '\n');
+ if (!p)
+ return 1;
+ p++;
+ }
+ return 1;
+}
+
int
fill_project_name (struct file_triplet *trp)
{
- char *project;
- const char *directory;
- char *p;
+ char *blurb;
+ size_t size;
+ FILE *fp;
+ char *project, *p;
+ const char *directory;
+ int rc;
+
+ size = trp->file[file_directive].sb.st_size;
+ if (size <= MSG_BEGIN_MARKER_LEN)
+ {
+ logmsg (LOG_ERR, _("too small directive file %s"),
+ trp->file[file_directive].name);
+ return 1;
+ }
+
+ fp = fopen (trp->file[file_directive].name, "r");
+ if (!fp)
+ {
+ logmsg (LOG_ERR, _("cannot open file %s: %s"),
+ trp->file[file_directive].name, strerror (errno));
+ return 1;
+ }
- if (trp->project)
- return 1;
+ blurb = xmalloc (size + 1);
+
+ rc = fread (blurb, size, 1, fp);
+ fclose (fp);
+
+ if (rc != 1)
+ {
+ logmsg (LOG_ERR, _("error reading file %s: %s"),
+ trp->file[file_directive].name, strerror (errno));
+ free (blurb);
+ return 1;
+ }
+
+ blurb[size] = 0;
+ if (extract_plaintext (blurb))
+ {
+ logmsg (LOG_ERR, _("%s: unrecognized format"),
+ trp->file[file_directive].name);
+ free (blurb);
+ return 1;
+ }
+
+ trp->blurb = blurb;
+
+ if (directive_parse (trp))
+ {
+ free (blurb);
+ trp->blurb = NULL;
+ return 1;
+ }
+
if (directive_get_value (trp, "directory", &directory))
{
logmsg (LOG_ERR, _("%s: missing `directory' directive"),
@@ -69,35 +166,49 @@ fill_project_name (struct file_triplet *trp)
}
else
project = xstrdup (directory);
- trp->project = project;
+ trp->project = xstrdup (project);
return 0;
}
-/* Verify if USER has upload rights on the directory (project) requested
- by TRP */
+struct uploader_info *
+new_uploader_info (struct uploader_info *src)
+{
+ struct uploader_info *p = xmalloc (sizeof (*p));
+ p->next = NULL;
+ p->name = src->name;
+ p->realname = src->realname;
+ p->gpg_key = src->gpg_key;
+ p->email = src->email;
+ p->fpr = NULL;
+ return p;
+}
+
+struct uploader_info *
+uploader_find_frp (struct uploader_info *list, const char *fpr)
+{
+ for (; list; list = list->next)
+ if (list->fpr && strcmp (list->fpr, fpr) == 0)
+ break;
+ return list;
+}
+
int
-check_access_rights (struct file_triplet *trp, const struct spool *spool,
- const char *user)
+verify_directive_file (struct file_triplet *trp, const struct spool *spool)
{
- struct access_method *method = spool->access_method[verify_method];
- int rc;
char *command;
- const char *result;
+ struct access_method *method = spool->access_method[project_uploader_method];
+ int rc;
void *md;
- struct group *grp;
+
+ size_t nrows, ncols, i;
+ struct uploader_info *head, *tail;
+ if (!trp->file[file_directive].name)
+ return 1;
+
if (fill_project_name (trp))
return 1;
- grp = getgrnam (trp->project);
- if (grp)
- trp->gid = grp->gr_gid;
- else
- logmsg (LOG_NOTICE, _("no such group: %s"), trp->project);
- if (debug_level)
- logmsg (LOG_DEBUG, _("verifying access rights for user %s to project %s"),
- user, trp->project);
-
md = method_open (method);
if (!md)
return 1;
@@ -106,88 +217,100 @@ check_access_rights (struct file_triplet *trp, const struct spool *spool,
rc = method_run (method, md, command);
free (command);
- method_close (method, md);
if (rc)
{
- logmsg (LOG_ERR, _("cannot verify access rights for %s on %s"),
- user, trp->project);
+ logmsg (LOG_ERR, _("cannot get uploaders for %s"), trp->name);
+ method_close (method, md);
return 1;
}
- result = method_result (method, md, 0, 0);
- if (!result || strcmp (result, user))
+ nrows = method_num_rows (method);
+ if (nrows == 0)
{
- UPDATE_STATS (STAT_ACCESS_VIOLATIONS);
- logmsg (LOG_ERR, _("%s: %s has no rights on %s"),
- trp->name, user, trp->project);
- notify (spool->notification, trp, ev_bad_ownership);
+ logmsg (LOG_ERR, _("found no uploaders for %s"), trp->name);
+ method_close (method, md);
return 1;
}
- return 0;
-}
-
-int
-verify_directive_file (struct file_triplet *trp, const struct spool *spool)
-{
- struct passwd *pw;
- char *command;
- struct access_method *method = spool->access_method[gpg_key_method];
- const char *pubkey;
- int rc;
- void *md;
-
- if (!trp->file[file_directive].name)
- return 1;
-
- md = method_open (method);
- if (!md)
- return 1;
- pw = getpwuid (TRIPLET_UID (trp));
- if (!pw)
+ ncols = method_num_cols (method);
+ if (ncols < 4)
{
- logmsg (LOG_ERR, _("%s: getpwuid failed: %s"),
- trp->name, strerror (errno));
+ logmsg (LOG_ERR,
+ _("project-uploader method error: too few columns (%lu)"),
+ (unsigned long) ncols);
method_close (method, md);
return 1;
}
- trp->gid = pw->pw_gid;
- trp->user = xstrdup (pw->pw_name);
-
- command = triplet_expand_method_query (method, md, trp);
- rc = method_run (method, md, command);
- free (command);
- if (rc)
+ head = tail = NULL;
+ for (i = 0; i < nrows; i++)
{
- logmsg (LOG_ERR, _("cannot get PGP key for %s"), trp->user);
- method_close (method, md);
- return 1;
+ const char *p;
+ struct uploader_info info, *ptr;
+
+ memset (&info, 0, sizeof (info));
+ p = method_result (method, md, i, 0);
+ if (p)
+ info.name = xstrdup (p);
+ p = method_result (method, md, i, 1);
+ if (p)
+ info.realname = xstrdup (p);
+ p = method_result (method, md, i, 2);
+ if (p)
+ info.email = xstrdup (p);
+ p = method_result (method, md, i, 3);
+ if (p)
+ info.gpg_key = xstrdup (p);
+
+ if (debug_level > 3)
+ {
+ logmsg (LOG_DEBUG, _("name: %s"), SP (info.name));
+ logmsg (LOG_DEBUG, _("realname: %s"), SP (info.realname));
+ logmsg (LOG_DEBUG, _("gpg-key: %s"), SP (info.gpg_key));
+ logmsg (LOG_DEBUG, _("email: %s"), SP (info.email));
+ }
+
+ if (!info.name || !info.realname || !info.gpg_key || !info.email)
+ {
+ logmsg (LOG_ERR,
+ _("project-uploader method error: malformed row %lu"),
+ (unsigned long) i);
+ free (info.name);
+ free (info.realname);
+ free (info.gpg_key);
+ free (info.email);
+ continue;
+ }
+
+ ptr = new_uploader_info (&info);
+ if (tail)
+ tail->next = ptr;
+ else
+ head = ptr;
+ tail = ptr;
}
+
+ method_close (method, md);
- pubkey = method_result (method, md, 0, 0);
- if (!pubkey || pubkey[0] == 0)
+ if (!head)
{
- logmsg (LOG_ERR, _("no GPG key for %s"), trp->user);
- method_close (method, md);
+ logmsg (LOG_ERR, _("no valid uploaders found for %s"), trp->name);
return 1;
}
- if (debug_level > 3)
- logmsg (LOG_DEBUG, _("public key: %s"), pubkey);
+ trp->uploader_list = head;
+ trp->uploader = NULL;
- if (verify_directive_signature (trp, spool, pubkey))
+ if (verify_directive_signature (trp, spool))
{
/*FIXME: Update stats */
- logmsg (LOG_ERR, _("invalid signature for %s"), trp->name);
- method_close (method, md);
+ logmsg (LOG_ERR, _("invalid signature for %s"),
+ trp->name ? trp->name : "[unknown]");
return 1;
}
else if (debug_level)
logmsg (LOG_DEBUG, _("%s: directive file signature OK"), trp->name);
- method_close (method, md);
-
if (debug_level > 1)
{
int i;
@@ -198,9 +321,6 @@ verify_directive_file (struct file_triplet *trp, const struct spool *spool)
if (verify_directive_format (trp))
return 1;
- if (check_access_rights (trp, spool, trp->user))
- return 1;
-
return 0;
}

Return to:

Send suggestions and report system problems to the System administrator.