Add code to conf.c that parses the new SigLevel directive. An overwhelming number of options are presented, but most users will still be fine with the Never/Optional/Required trio. More advanced users can combine these or any of the other options on a 'SigLevel = ' line, which is parsed in a left-to-right fashion and flags turned on and off accordingly. For example, all three of these will net the same config: SigLevel = Required PackageOptional SigLevel = Optional DatabaseRequired SigLevel = DatabaseRequired PackageOptional Additionally, database-specific lines assume you wish to start with any global default that has been set. For example, if any of the above lines were in the [options] section, something such as: SigLevel = PackageRequired PackageAllowMarginal Would continue to enforce required database signatures. Inspiration-by: Kerrick Staley <mail@kerrickstaley.com> Signed-off-by: Dan McGee <dan@archlinux.org> --- src/pacman/conf.c | 113 ++++++++++++++++++++++++++++++++++++++------------- test/pacman/util.py | 2 +- 2 files changed, 85 insertions(+), 30 deletions(-) diff --git a/src/pacman/conf.c b/src/pacman/conf.c index fac6da3..d654361 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -222,21 +222,80 @@ int config_set_arch(const char *arch) return 0; } -static alpm_siglevel_t option_verifysig(const char *value) +/** + * Parse a signature verification level line. + * @param values the list of parsed option values + * @return 0 on success, 1 on any parsing error + */ +static int process_siglevel(alpm_list_t *values, alpm_siglevel_t startval, + alpm_siglevel_t *storage) { - alpm_siglevel_t level; - if(strcmp(value, "Always") == 0) { - level = ALPM_SIG_PACKAGE | ALPM_SIG_DATABASE; - } else if(strcmp(value, "Optional") == 0) { - level = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL | - ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; - } else if(strcmp(value, "Never") == 0) { - level = 0; - } else { - return -1; + alpm_siglevel_t level = startval; + alpm_list_t *i; + + /* Collapse the option names into a single bitmasked value */ + for(i = values; i; i = alpm_list_next(i)) { + const char *value = i->data; + if(strcmp(value, "Never") == 0) { + level &= ~ALPM_SIG_PACKAGE; + level &= ~ALPM_SIG_DATABASE; + } else if(strcmp(value, "Optional") == 0) { + level |= ALPM_SIG_PACKAGE; + level |= ALPM_SIG_DATABASE; + level |= ALPM_SIG_PACKAGE_OPTIONAL; + level |= ALPM_SIG_DATABASE_OPTIONAL; + } else if(strcmp(value, "Required") == 0) { + level |= ALPM_SIG_PACKAGE; + level |= ALPM_SIG_DATABASE; + level &= ~ALPM_SIG_PACKAGE_OPTIONAL; + level &= ~ALPM_SIG_DATABASE_OPTIONAL; + } else if(strcmp(value, "TrustedOnly") == 0) { + level &= ~ALPM_SIG_PACKAGE_MARGINAL_OK; + level &= ~ALPM_SIG_DATABASE_MARGINAL_OK; + level &= ~ALPM_SIG_PACKAGE_UNKNOWN_OK; + level &= ~ALPM_SIG_DATABASE_UNKNOWN_OK; + } else if(strcmp(value, "AllowMarginal") == 0) { + level |= ALPM_SIG_PACKAGE_MARGINAL_OK; + level |= ALPM_SIG_DATABASE_MARGINAL_OK; + } else if(strcmp(value, "AllowUnknown") == 0) { + level |= ALPM_SIG_PACKAGE_UNKNOWN_OK; + level |= ALPM_SIG_DATABASE_UNKNOWN_OK; + } else if(strcmp(value, "PackageOptional") == 0) { + level |= ALPM_SIG_PACKAGE; + level |= ALPM_SIG_PACKAGE_OPTIONAL; + } else if(strcmp(value, "DatabaseOptional") == 0) { + level |= ALPM_SIG_DATABASE; + level |= ALPM_SIG_DATABASE_OPTIONAL; + } else if(strcmp(value, "PackageRequired") == 0) { + level |= ALPM_SIG_PACKAGE; + level &= ~ALPM_SIG_PACKAGE_OPTIONAL; + } else if(strcmp(value, "DatabaseRequired") == 0) { + level |= ALPM_SIG_DATABASE; + level &= ~ALPM_SIG_DATABASE_OPTIONAL; + } else if(strcmp(value, "PackageTrustedOnly") == 0) { + level &= ~ALPM_SIG_PACKAGE_MARGINAL_OK; + level &= ~ALPM_SIG_PACKAGE_UNKNOWN_OK; + } else if(strcmp(value, "DatabaseTrustedOnly") == 0) { + level &= ~ALPM_SIG_DATABASE_MARGINAL_OK; + level &= ~ALPM_SIG_DATABASE_UNKNOWN_OK; + } else if(strcmp(value, "PackageAllowMarginal") == 0) { + level |= ALPM_SIG_PACKAGE_MARGINAL_OK; + } else if(strcmp(value, "DatabaseAllowMarginal") == 0) { + level |= ALPM_SIG_DATABASE_MARGINAL_OK; + } else if(strcmp(value, "PackageAllowUnknown") == 0) { + level |= ALPM_SIG_PACKAGE_UNKNOWN_OK; + } else if(strcmp(value, "DatabaseAllowUnknown") == 0) { + level |= ALPM_SIG_DATABASE_UNKNOWN_OK; + } else { + pm_printf(ALPM_LOG_ERROR, _("invalid value for 'SigLevel' : '%s'\n"), + value); + return 1; + } + level &= ~ALPM_SIG_USE_DEFAULT; } - pm_printf(ALPM_LOG_DEBUG, "config: VerifySig = %s (%d)\n", value, level); - return level; + + *storage = level; + return 0; } static int process_cleanmethods(alpm_list_t *values) { @@ -359,16 +418,14 @@ static int _parse_options(const char *key, char *value, return 1; } FREELIST(methods); - } else if(strcmp(key, "VerifySig") == 0) { - alpm_siglevel_t level = option_verifysig(value); - if(level != -1) { - config->siglevel = level; - } else { - pm_printf(ALPM_LOG_ERROR, - _("config file %s, line %d: directive '%s' has invalid value '%s'\n"), - file, linenum, key, value); + } else if(strcmp(key, "SigLevel") == 0) { + alpm_list_t *values = NULL; + setrepeatingoption(value, "SigLevel", &values); + if(process_siglevel(values, ALPM_SIG_USE_DEFAULT, &(config->siglevel))) { + 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"), @@ -726,17 +783,15 @@ static int _parseconfig(const char *file, struct section_t *section, goto cleanup; } section->servers = alpm_list_add(section->servers, strdup(value)); - } else if(strcmp(key, "VerifySig") == 0) { - alpm_siglevel_t level = option_verifysig(value); - if(level != -1) { - section->siglevel = level; - } else { - pm_printf(ALPM_LOG_ERROR, - _("config file %s, line %d: directive '%s' has invalid value '%s'\n"), - file, linenum, key, value); + } else if(strcmp(key, "SigLevel") == 0) { + alpm_list_t *values = NULL; + setrepeatingoption(value, "SigLevel", &values); + if(process_siglevel(values, config->siglevel, &(section->siglevel))) { + FREELIST(values); ret = 1; goto cleanup; } + FREELIST(values); } else { pm_printf(ALPM_LOG_WARNING, _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), diff --git a/test/pacman/util.py b/test/pacman/util.py index dbe416f..60dea9e 100644 --- a/test/pacman/util.py +++ b/test/pacman/util.py @@ -118,7 +118,7 @@ def mkcfgfile(filename, root, option, db): if key != "local": value = db[key] data.append("[%s]\n" \ - "VerifySig = %s\n" \ + "SigLevel = %s\n" \ "Server = file://%s" \ % (value.treename, value.getverify(), \ os.path.join(root, SYNCREPO, value.treename))) -- 1.7.6