diff options
-rw-r--r-- | src/config.c | 10 | ||||
-rw-r--r-- | src/gpg.c | 107 | ||||
-rw-r--r-- | src/job.c | 7 | ||||
-rw-r--r-- | src/triplet.c | 3 | ||||
-rw-r--r-- | src/verify.c | 3 | ||||
-rw-r--r-- | src/watcher.c | 16 | ||||
-rw-r--r-- | src/wydawca.c | 2 | ||||
-rw-r--r-- | src/wydawca.h | 3 |
8 files changed, 99 insertions, 52 deletions
diff --git a/src/config.c b/src/config.c index 66d5fb7..509b0d5 100644 --- a/src/config.c +++ b/src/config.c @@ -1149,24 +1149,28 @@ static struct grecs_keyword spool_kw[] = { NULL, offsetof(struct spool, aliases) }, { "source", N_("dir"), N_("Source directory"), grecs_type_string, GRECS_DFLT, NULL, offsetof(struct spool, source_dir) }, { "destination", N_("dir"), N_("Destination directory"), grecs_type_string, GRECS_DFLT, NULL, offsetof(struct spool, dest_url), cb_url }, { "file-sweep-time", N_("interval"), N_("Define file sweep time"), grecs_type_string, GRECS_DFLT, NULL, offsetof(struct spool, file_sweep_time), cb_interval }, + { "inotify", NULL, N_("Enable or disable inotify for this spool"), + grecs_type_bool, GRECS_DFLT, + NULL, offsetof(struct spool, inotify_enable), }, + { "dictionary", N_("ident"), N_("Define data dictionary"), grecs_type_section, GRECS_DFLT, NULL, offsetof(struct spool, dictionary), cb_dictionary, NULL, dictionary_kw }, { "archive", N_("type: string"), N_("Set up archivation"), grecs_type_section, GRECS_DFLT, NULL, offsetof(struct spool, archive), cb_archive, NULL, archive_kw }, { "notify-event", NULL, N_("Configure notification"), grecs_type_section, GRECS_DFLT, NULL, offsetof(struct spool, notification), cb_notify_event, NULL, notify_event_kw }, @@ -1191,24 +1195,25 @@ cb_spool (enum grecs_callback_command cmd, switch (cmd) { case grecs_callback_section_begin: if (!value || value->type != GRECS_TYPE_STRING) { grecs_error (value ? &value->locus : locus, 0, _("tag must be a string")); return 1; } spool = grecs_zalloc (sizeof (*spool)); spool->tag = grecs_strdup (value->v.string); spool->file_sweep_time = file_sweep_time; + spool->inotify_enable = 1; for (i = 0; i < NITEMS (spool->dictionary); i++) spool->dictionary[i] = default_dictionary[i]; spool->archive = default_archive_descr; *pdata = spool; break; case grecs_callback_section_end: rc = 0; spool = *pdata; if (!spool->source_dir) { grecs_error (locus, 0, _("source is not given")); @@ -1409,25 +1414,28 @@ cb_upload_version (enum grecs_callback_command cmd, static struct grecs_keyword wydawca_kw[] = { { "daemon", NULL, N_("Enable daemon mode"), grecs_type_bool, GRECS_DFLT, &daemon_mode }, { "foreground", NULL, N_("Start in foreground even in daemon mode"), grecs_type_bool, GRECS_DFLT, &foreground }, { "single-process", NULL, N_("Do not spawn subprocesses"), grecs_type_bool, GRECS_DFLT, &single_process }, { "wakeup-interval", N_("time"), N_("Set wake-up interval"), grecs_type_string, GRECS_DFLT, &wakeup_interval, 0, cb_interval }, { "pidfile", N_("file"), N_("Set pid file name"), grecs_type_string, GRECS_DFLT, &pidfile }, - + + { "inotify", NULL, N_("Enable or disable inotify support"), + grecs_type_bool, GRECS_DFLT, &inotify_enable }, + { "user", N_("name"), N_("Run with UID and GID of this user"), grecs_type_string, GRECS_DFLT, NULL, 0, cb_user }, { "group", NULL, N_("Retain these supplementary groups"), grecs_type_string, GRECS_LIST, NULL, 0, cb_supp_groups }, { "min-version", N_("major.minor"), N_("Set minimal allowed directive file version"), grecs_type_string, GRECS_DFLT, &min_directive_version, 0, cb_upload_version }, { "max-version", N_("major.minor"), N_("Set maximal allowed directive file version"), grecs_type_string, GRECS_DFLT, @@ -138,95 +138,105 @@ create_gpg_homedir () logmsg (LOG_CRIT, _("cannot create GPG home directory (%s): %s"), temp_homedir, strerror (errno)); return 1; } atexit (remove_homedir); if (debug_level > 1) logmsg (LOG_DEBUG, _("GNUPG home directory: %s"), temp_homedir); setenv ("GNUPGHOME", temp_homedir, 1); return 0; } static int +checksig (gpgme_signature_t sig, const char *uid, struct file_triplet *trp) +{ + switch (gpg_err_code (sig->status)) + { + case GPG_ERR_NO_ERROR: + if (debug_level) + logmsg (LOG_NOTICE, _("Good signature from %s"), uid); + trp->uploader = uploader_find_frp (trp->uploader_list, sig->fpr); + if (!trp->uploader) + { + logmsg (LOG_ERR, + _("good signature from %s, " + "but the uploader info for %s not found"), + uid, sig->fpr); + return 1; + } + break; + + case GPG_ERR_BAD_SIGNATURE: + UPDATE_STATS (STAT_BAD_SIGNATURE); + logmsg (LOG_ERR, _("BAD signature from %s"), uid); + return 0; + + case GPG_ERR_NO_PUBKEY: + UPDATE_STATS (STAT_ACCESS_VIOLATIONS); + logmsg (LOG_ERR, _("No public key")); + return 0; + + case GPG_ERR_NO_DATA: + UPDATE_STATS (STAT_BAD_TRIPLETS); + logmsg (LOG_ERR, _("No signature")); + return 0; + + case GPG_ERR_SIG_EXPIRED: + UPDATE_STATS (STAT_BAD_SIGNATURE); + logmsg (LOG_ERR, _("Expired signature from %s"), uid); + return 0; + + case GPG_ERR_KEY_EXPIRED: + UPDATE_STATS (STAT_BAD_SIGNATURE); + logmsg (LOG_ERR, _("Key expired (%s)"), uid); + return 0; + + default: + logmsg (LOG_ERR, _("Unknown signature error")); + return 0; + } + return -1; +} + +static int gpg_verify_signature (gpgme_ctx_t ctx, gpgme_signature_t sig, struct file_triplet *trp) { if (!sig) return 0; for (; sig; sig = sig->next) { const char *uid; gpgme_key_t key; - + int rc; + if (gpgme_get_key (ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR) uid = key->uids->uid; else uid = sig->fpr; - - switch (gpg_err_code (sig->status)) - { - case GPG_ERR_NO_ERROR: - if (debug_level) - logmsg (LOG_NOTICE, _("Good signature from %s"), uid); - trp->uploader = uploader_find_frp (trp->uploader_list, sig->fpr); - if (!trp->uploader) - { - logmsg (LOG_ERR, - _("good signature from %s, " - "but the uploader info for %s not found"), - uid, sig->fpr); - return 1; - } - break; - - case GPG_ERR_BAD_SIGNATURE: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("BAD signature from %s"), uid); - return 0; - - case GPG_ERR_NO_PUBKEY: - UPDATE_STATS (STAT_ACCESS_VIOLATIONS); - logmsg (LOG_ERR, _("No public key")); - return 0; - - case GPG_ERR_NO_DATA: - UPDATE_STATS (STAT_BAD_TRIPLETS); - logmsg (LOG_ERR, _("No signature")); - return 0; - - case GPG_ERR_SIG_EXPIRED: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("Expired signature from %s"), uid); - return 0; - - case GPG_ERR_KEY_EXPIRED: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("Key expired (%s)"), uid); - return 0; - - default: - logmsg (LOG_ERR, _("Unknown signature error")); - return 0; - } + rc = checksig (sig, uid, trp); + gpgme_key_unref (key); + if (rc != -1) + return rc; } return 1; } /* Verify the directive file from TRP using public key PUBKEY */ int verify_directive_signature (struct file_triplet *trp) { gpgme_ctx_t ctx; - gpgme_data_t key_data, directive_data, plain; + gpgme_data_t key_data, directive_data, plain = NULL; gpgme_error_t ec; int rc; struct uploader_info *uptr; create_gpg_homedir (); fail_if_err (gpgme_new (&ctx)); for (uptr = trp->uploader_list; uptr; uptr = uptr->next) { gpgme_import_result_t res; gpgme_import_status_t pstat; @@ -260,24 +270,25 @@ verify_directive_signature (struct file_triplet *trp) } else rc = 0; } else { rc = 1; UPDATE_STATS (STAT_BAD_SIGNATURE); logmsg (LOG_ERR, _("%s: directive verification failed: %s"), trp->name, gpgme_strerror (ec)); } + gpgme_data_release (plain); gpgme_data_release (directive_data); gpgme_data_release (key_data); gpgme_release (ctx); return rc; } /* Verify the detached signature of TRP. NOTE: It is assumed that the public key is already registered (by a previous call to verify_directive_signature). */ int verify_detached_signature (struct file_triplet *trp) @@ -329,25 +329,30 @@ job_queue_runner () { if (WIFEXITED (job->exit_status) && WEXITSTATUS (job->exit_status) == WYDAWCA_EX_AGAIN) { time_t interval = lock_timeout; if (interval == 0) interval = lock_expire_time; /* Re-queue the job */ job->state = STATE_QUEUED; job->timestamp = now + interval; } else - job_remove (job); + { + job_remove (job); + free (job); + job = next; + continue; + } } } if (job->state == STATE_QUEUED) { if (job->timestamp >= now) { if (job_start (job)) pause (); /* FIXME */ now = time (NULL); } else diff --git a/src/triplet.c b/src/triplet.c index 05b7536..aa74de0 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -118,27 +118,28 @@ triplet_lookup (struct spool *spool, const char *name) struct file_triplet key, *ret; struct file_info finfo; if (!triplet_table) return NULL; parse_file_name (name, &finfo); key.name = grecs_malloc (finfo.root_len + 1); memcpy (key.name, finfo.name, finfo.root_len); key.name[finfo.root_len] = 0; key.spool = spool; + file_info_cleanup (&finfo); ret = grecs_symtab_lookup_or_install (triplet_table, &key, NULL); - file_info_cleanup (&finfo); + free (key.name); return ret; } /* Return true if any part of the triplet TRP was modified more than TTL seconds ago */ static int triplet_expired_p (struct file_triplet *trp, time_t ttl) { int i; time_t now = time (NULL); diff --git a/src/verify.c b/src/verify.c index 4a108bc..dee160f 100644 --- a/src/verify.c +++ b/src/verify.c @@ -87,24 +87,27 @@ extract_plaintext (char *blurb) return 1; } int fill_project_name (struct file_triplet *trp) { char *blurb; size_t size; FILE *fp; char *p; const char *directory; int rc; + + if (trp->blurb) + return 0; 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) { diff --git a/src/watcher.c b/src/watcher.c index f8761ee..c52e3e6 100644 --- a/src/watcher.c +++ b/src/watcher.c @@ -74,27 +74,34 @@ dirwatcher_find_wd (int wd) } static int create_watcher (struct spool *sp, void *data) { int ifd = *(int*)data; struct dirwatcher *dwp; int wd; const char *path = get_path (sp); if (!sp) return 0; + + if (!sp->inotify_enable) + { + if (debug_level > 1) + logmsg (LOG_DEBUG, "disabling inotify support for spool %s", sp->tag); + return 0; + } if (debug_level > 1) - logmsg (LOG_DEBUG, "creating watcher %s", path); + logmsg (LOG_DEBUG, "spool %s: creating watcher %s", sp->tag, path); dwp = malloc (sizeof(*dwp)); if (!dwp) { logmsg (LOG_ERR, "not enough memory"); return 1; } dwp->spool = sp; dwp->parent = NULL; wd = inotify_add_watch (ifd, path, IN_DELETE|IN_CREATE|IN_CLOSE_WRITE| IN_MOVED_FROM|IN_MOVED_TO); if (wd == -1) @@ -104,24 +111,31 @@ create_watcher (struct spool *sp, void *data) return 1; } dwp->wd = wd; dirwatcher_push (&dirwatcher_list, dwp); return 0; } int watcher_init () { int ifd, rc; + + if (!inotify_enable) + { + if (debug_level > 1) + logmsg (LOG_DEBUG, "disabling inotify support"); + return -1; + } if (debug_level > 1) logmsg (LOG_DEBUG, "setting up inotify"); ifd = inotify_init (); if (ifd == -1) { logmsg (LOG_ERR, "inotify_init: %s", strerror (errno)); return -1; } rc = for_each_spool (create_watcher, &ifd); if (rc) diff --git a/src/wydawca.c b/src/wydawca.c index 521d796..45a5cff 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -44,24 +44,26 @@ int foreground; int single_process; time_t wakeup_interval; struct grecs_list *all_spool_aliases; char *wydawca_gpg_homedir; char *default_check_script; struct grecs_sockaddr listen_sockaddr; unsigned wydawca_stat[MAX_STAT]; unsigned min_directive_version = MIN_DIRECTIVE_VERSION; unsigned max_directive_version = MAX_DIRECTIVE_VERSION; +int inotify_enable = 1; + void initstats () { memset (wydawca_stat, 0, sizeof wydawca_stat); } /* Logging */ void syslog_printer (int prio, const char *fmt, va_list ap) { if (syslog_include_prio) diff --git a/src/wydawca.h b/src/wydawca.h index 722fc9b..323d403 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -217,24 +217,25 @@ struct virt_tab /* An upload spool. This structure contains all data necessary for releasing files from source to destination */ struct spool { char *tag; struct grecs_list *aliases; char *url; /* Download URL */ char *source_dir; /* Source directory */ mu_url_t dest_url; /* Destination URL */ const char *dest_dir; /* Directory part of the above */ struct virt_tab vtab; /* Virtual method table */ + int inotify_enable; time_t file_sweep_time; /* Remove invalid/unprocessed files after this amount of time */ struct dictionary *dictionary[dictionary_count]; int dict_inited; struct archive_descr archive; /* Archivation data */ struct notification *notification; char *check_script; }; #define ASGN_SPOOL(spool, trp, faction) \ do \ @@ -368,24 +369,26 @@ extern struct grecs_sockaddr listen_sockaddr; extern struct grecs_list *all_spool_aliases; extern char *wydawca_gpg_homedir; extern char *default_check_script; extern char *temp_homedir; extern unsigned min_directive_version; extern unsigned max_directive_version; extern struct spool fake_spool; extern struct spool inotify_spool; +extern int inotify_enable; + #define UPDATE_STATS(what) \ do \ { \ if (what >= MAX_STAT) abort(); \ wydawca_stat[what]++; \ } \ while (0) int stat_mask_p (unsigned long mask); struct metadef *make_stat_expansion (size_t count); void initstats (void); void logstats (void); |