Add LocalFileSigLevel and RemoteFileSigLevel to control the signature checking for "pacman -U <file>" and "pacman -U <url>" operations respectively. The starting value for both these options is SigLevel, if it is specified in the [options] section, or the built-in system default. The specified values override and/or supplement this initial value. Note there is no destintion between setting "Required" and "PackageRequired" as there is not database options for Upgrade operations. Signed-off-by: Allan McRae <allan@archlinux.org> --- This patch has been floating around for quite some time now. I would like some final comments before I write the documentation and push. I have this in my pacman.conf: SigLevel = Required DatabaseOptional TrustedOnly LocalFileSigLevel = Optional TrustedOnly #RemoteFileSigLevel = Required so if I "pacman -U /path/to/file", a signature is only checked if it is present, but "pacman -U http://...." always checks the signature. It also means that I do not need have my global SigLevel as Optional and add PackageRequired to every Arch repo. I'd like a comment, even if it is a simple "Ack". lib/libalpm/alpm.h | 9 +++++++++ lib/libalpm/handle.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ lib/libalpm/handle.h | 4 ++++ src/pacman/conf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/conf.h | 2 ++ src/pacman/upgrade.c | 21 ++++++++++++++++++--- 6 files changed, 131 insertions(+), 9 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index f524c19..b681840 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -115,6 +115,9 @@ typedef enum _alpm_siglevel_t { ALPM_SIG_DATABASE_MARGINAL_OK = (1 << 12), ALPM_SIG_DATABASE_UNKNOWN_OK = (1 << 13), + ALPM_SIG_PACKAGE_SET = (1 << 27), + ALPM_SIG_PACKAGE_TRUST_SET = (1 << 28), + ALPM_SIG_USE_DEFAULT = (1 << 31) } alpm_siglevel_t; @@ -561,6 +564,12 @@ int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace); alpm_siglevel_t alpm_option_get_default_siglevel(alpm_handle_t *handle); int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t level); +alpm_siglevel_t alpm_option_get_local_file_siglevel(alpm_handle_t *handle); +int alpm_option_set_local_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t level); + +alpm_siglevel_t alpm_option_get_remote_file_siglevel(alpm_handle_t *handle); +int alpm_option_set_remote_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t level); + /** @} */ /** @addtogroup alpm_api_databases Database Functions diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c index 1a840ab..53c86c5 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -594,6 +594,18 @@ int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio) return 0; } +alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); + return handle->db_local; +} + +alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); + return handle->dbs_sync; +} + int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace) { CHECK_HANDLE(handle, return -1); @@ -621,16 +633,44 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle return handle->siglevel; } -alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle) +int SYMEXPORT alpm_option_set_local_file_siglevel(alpm_handle_t *handle, + alpm_siglevel_t level) { - CHECK_HANDLE(handle, return NULL); - return handle->db_local; + CHECK_HANDLE(handle, return -1); +#ifdef HAVE_LIBGPGME + handle->localfilesiglevel = level; +#else + if(level != 0 && level != ALPM_SIG_USE_DEFAULT) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); + } +#endif + return 0; } -alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle) +alpm_siglevel_t SYMEXPORT alpm_option_get_local_file_siglevel(alpm_handle_t *handle) { - CHECK_HANDLE(handle, return NULL); - return handle->dbs_sync; + CHECK_HANDLE(handle, return -1); + return handle->localfilesiglevel; +} + +int SYMEXPORT alpm_option_set_remote_file_siglevel(alpm_handle_t *handle, + alpm_siglevel_t level) +{ + CHECK_HANDLE(handle, return -1); +#ifdef HAVE_LIBGPGME + handle->remotefilesiglevel = level; +#else + if(level != 0 && level != ALPM_SIG_USE_DEFAULT) { + RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); + } +#endif + return 0; +} + +alpm_siglevel_t SYMEXPORT alpm_option_get_remote_file_siglevel(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return -1); + return handle->remotefilesiglevel; } /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h index c24e97a..5e84d58 100644 --- a/lib/libalpm/handle.h +++ b/lib/libalpm/handle.h @@ -92,6 +92,10 @@ struct __alpm_handle_t { int usesyslog; /* Use syslog instead of logfile? */ /* TODO move to frontend */ int checkspace; /* Check disk space before installing */ alpm_siglevel_t siglevel; /* Default signature verification level */ + alpm_siglevel_t localfilesiglevel; /* Signature verification level for local file + upgrade operations */ + alpm_siglevel_t remotefilesiglevel; /* Signature verification level for remote file + upgrade operations */ /* error code */ alpm_errno_t pm_errno; diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 1bea2b0..95dce35 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -56,6 +56,8 @@ config_t *config_new(void) if(alpm_capabilities() & ALPM_CAPABILITY_SIGNATURES) { newconfig->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL | ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; + newconfig->localfilesiglevel = ALPM_SIG_USE_DEFAULT; + newconfig->remotefilesiglevel = ALPM_SIG_USE_DEFAULT; } return newconfig; @@ -279,6 +281,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, if(strcmp(value, "Never") == 0) { if(package) { level &= ~ALPM_SIG_PACKAGE; + level |= ALPM_SIG_PACKAGE_SET; } if(database) { level &= ~ALPM_SIG_DATABASE; @@ -287,6 +290,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, if(package) { level |= ALPM_SIG_PACKAGE; level |= ALPM_SIG_PACKAGE_OPTIONAL; + level |= ALPM_SIG_PACKAGE_SET; } if(database) { level |= ALPM_SIG_DATABASE; @@ -296,6 +300,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, if(package) { level |= ALPM_SIG_PACKAGE; level &= ~ALPM_SIG_PACKAGE_OPTIONAL; + level |= ALPM_SIG_PACKAGE_SET; } if(database) { level |= ALPM_SIG_DATABASE; @@ -305,6 +310,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, if(package) { level &= ~ALPM_SIG_PACKAGE_MARGINAL_OK; level &= ~ALPM_SIG_PACKAGE_UNKNOWN_OK; + level |= ALPM_SIG_PACKAGE_TRUST_SET; } if(database) { level &= ~ALPM_SIG_DATABASE_MARGINAL_OK; @@ -314,6 +320,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, if(package) { level |= ALPM_SIG_PACKAGE_MARGINAL_OK; level |= ALPM_SIG_PACKAGE_UNKNOWN_OK; + level |= ALPM_SIG_PACKAGE_TRUST_SET; } if(database) { level |= ALPM_SIG_DATABASE_MARGINAL_OK; @@ -343,6 +350,30 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage, return ret; } +/** + * Merge the package entires of two signature verification levels. + * @param base initial siglevel + * @param over overridden siglevel, derived value is stored here + */ +static void merge_siglevel(alpm_siglevel_t *base, alpm_siglevel_t *over) +{ + alpm_siglevel_t level = *over; + if(level & ALPM_SIG_USE_DEFAULT) { + level = *base; + } else { + if(!(level & ALPM_SIG_PACKAGE_SET)) { + level |= *base & ALPM_SIG_PACKAGE; + level |= *base & ALPM_SIG_PACKAGE_OPTIONAL; + } + if(!(level & ALPM_SIG_PACKAGE_TRUST_SET)) { + level |= *base & ALPM_SIG_PACKAGE_MARGINAL_OK; + level |= *base & ALPM_SIG_PACKAGE_UNKNOWN_OK; + } + } + + *over = level; +} + static int process_cleanmethods(alpm_list_t *values, const char *file, int linenum) { @@ -484,6 +515,22 @@ static int _parse_options(const char *key, char *value, return 1; } FREELIST(values); + } else if(strcmp(key, "LocalFileSigLevel") == 0) { + alpm_list_t *values = NULL; + setrepeatingoption(value, "LocalFileSigLevel", &values); + if(process_siglevel(values, &config->localfilesiglevel, file, linenum)) { + FREELIST(values); + return 1; + } + FREELIST(values); + } else if(strcmp(key, "RemoteFileSigLevel") == 0) { + alpm_list_t *values = NULL; + setrepeatingoption(value, "RemoteFileSigLevel", &values); + if(process_siglevel(values, &config->remotefilesiglevel, file, linenum)) { + FREELIST(values); + return 1; + } + FREELIST(values); } else { pm_printf(ALPM_LOG_WARNING, _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), @@ -606,6 +653,11 @@ static int setup_libalpm(void) alpm_option_set_default_siglevel(handle, config->siglevel); + merge_siglevel(&config->siglevel, &config->localfilesiglevel); + merge_siglevel(&config->siglevel, &config->remotefilesiglevel); + alpm_option_set_local_file_siglevel(handle, config->localfilesiglevel); + alpm_option_set_remote_file_siglevel(handle, config->remotefilesiglevel); + if(config->xfercommand) { alpm_option_set_fetchcb(handle, download_with_xfercommand); } else if(!(alpm_capabilities() & ALPM_CAPABILITY_DOWNLOADER)) { diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 06d2fd5..ff099fe 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -73,6 +73,8 @@ typedef struct __config_t { unsigned int ask; alpm_transflag_t flags; alpm_siglevel_t siglevel; + alpm_siglevel_t localfilesiglevel; + alpm_siglevel_t remotefilesiglevel; /* conf file options */ /* I Love Candy! */ diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c index 7f69091..222f7fa 100644 --- a/src/pacman/upgrade.c +++ b/src/pacman/upgrade.c @@ -40,8 +40,7 @@ int pacman_upgrade(alpm_list_t *targets) { int retval = 0; - alpm_list_t *i; - alpm_siglevel_t level = alpm_option_get_default_siglevel(config->handle); + alpm_list_t *i, *remote = NULL; if(targets == NULL) { pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n")); @@ -51,6 +50,8 @@ int pacman_upgrade(alpm_list_t *targets) /* Check for URL targets and process them */ for(i = targets; i; i = alpm_list_next(i)) { + int *r = malloc(sizeof(int)); + if(strstr(i->data, "://")) { char *str = alpm_fetch_pkgurl(config->handle, i->data); if(str == NULL) { @@ -60,8 +61,13 @@ int pacman_upgrade(alpm_list_t *targets) } else { free(i->data); i->data = str; + *r = 1; } + } else { + *r = 0; } + + remote = alpm_list_add(remote, r); } if(retval) { @@ -75,9 +81,16 @@ int pacman_upgrade(alpm_list_t *targets) printf(_("loading packages...\n")); /* add targets to the created transaction */ - for(i = targets; i; i = alpm_list_next(i)) { + for(i = targets; i; i = alpm_list_next(i), remote = alpm_list_next(remote)) { const char *targ = i->data; alpm_pkg_t *pkg; + alpm_siglevel_t level; + + if(*(int *)remote->data) { + level = alpm_option_get_remote_file_siglevel(config->handle); + } else { + level = alpm_option_get_local_file_siglevel(config->handle); + } if(alpm_pkg_load(config->handle, targ, 1, level, &pkg) != 0) { pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", @@ -95,6 +108,8 @@ int pacman_upgrade(alpm_list_t *targets) config->explicit_adds = alpm_list_add(config->explicit_adds, pkg); } + FREELIST(remote); + if(retval) { trans_release(); return retval; -- 1.8.1.1