/* wydawca - automatic release submission daemon Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff Wydawca 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. Wydawca 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 wydawca. If not, see . */ #include "wydawca.h" #include "sql.h" /* Return the length of the string without trailing whitespace */ size_t trim_length (const char *str) { size_t len; for (len = strlen (str); len > 0 && isspace (str[len-1]); len--) ; return len; } /* Chop off any trailing whitespace. Return the length of the resulting string. */ size_t trim (char *str) { size_t len = trim_length (str); str[len] = 0; return len; } int fill_project_name (struct file_triplet *trp) { char *project; const char *directory; char *p; if (trp->project) return 1; if (directive_get_value (trp, "directory", &directory)) { logmsg (LOG_ERR, _("%s: missing `directory' directive"), trp->file[file_directive].name); return 1; } p = strchr (directory, '/'); if (p) { size_t len = p - directory; if (len == 0) { logmsg (LOG_ERR, _("%s: empty `directory' directive"), trp->file[file_directive].name); return 1; } project = xmalloc (len + 1); memcpy (project, directory, len); project[len] = 0; } else project = xstrdup (directory); trp->project = project; return 0; } /* Verify if USER has upload rights on the directory (project) requested by TRP */ int check_access_rights (struct file_triplet *trp, const struct spool *spool, const char *user) { struct access_method *method = spool->access_method[verify_method]; int rc; char *command; const char *result; void *md; struct group *grp; 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; command = triplet_expand_method_query (method, md, trp); 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); return 1; } result = method_result (method, md, 0, 0); if (!result || strcmp (result, user)) { 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); 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) { logmsg (LOG_ERR, _("%s: getpwuid failed: %s"), trp->name, strerror (errno)); 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) { logmsg (LOG_ERR, _("cannot get PGP key for %s"), trp->user); method_close (method, md); return 1; } pubkey = method_result (method, md, 0, 0); if (!pubkey || pubkey[0] == 0) { logmsg (LOG_ERR, _("no GPG key for %s"), trp->user); method_close (method, md); return 1; } if (debug_level > 3) logmsg (LOG_DEBUG, _("public key: %s"), pubkey); if (verify_directive_signature (trp, spool, pubkey)) { /*FIXME: Update stats */ logmsg (LOG_ERR, _("invalid signature for %s"), trp->name); method_close (method, md); 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; for (i = 0; trp->directive[i]; i++) logmsg (LOG_DEBUG, "directive[%d] = %s", i, trp->directive[i]); } if (verify_directive_format (trp)) return 1; if (check_access_rights (trp, spool, trp->user)) return 1; return 0; }