diff options
Diffstat (limited to 'src/verify.c')
-rw-r--r-- | src/verify.c | 278 |
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; } |