diff options
author | Dan McGee <dan@archlinux.org> | 2011-07-22 17:48:13 +0200 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2011-08-02 14:25:09 +0200 |
commit | b03b06cfd3afc95c328a166cfb8305a3df97819e (patch) | |
tree | d3e61ceba4344ad6242de581e99c07f32555a99f /src | |
parent | 6997a738bbca209cc6a8a29cdb71830bfb912f18 (diff) | |
download | pacman-b03b06cfd3afc95c328a166cfb8305a3df97819e.tar.gz pacman-b03b06cfd3afc95c328a166cfb8305a3df97819e.tar.xz |
Implement parsing of the new SigLevel directive
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/pacman/conf.c | 136 |
1 files changed, 105 insertions, 31 deletions
diff --git a/src/pacman/conf.c b/src/pacman/conf.c index fac6da34..a5804066 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -222,21 +222,94 @@ 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 + * @param storage location to store the derived signature level; any existing + * value here is used as a starting point + * @return 0 on success, 1 on any parsing error + */ +static int process_siglevel(alpm_list_t *values, 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 = *storage; + alpm_list_t *i; + int ret = 0; + + /* Collapse the option names into a single bitmasked value */ + for(i = values; i; i = alpm_list_next(i)) { + const char *original = i->data, *value; + int package = 0, database = 0; + + if (strncmp(original, "Package", strlen("Package")) == 0) { + /* only packages are affected, don't flip flags for databases */ + value = original + strlen("Package"); + package = 1; + } else if (strncmp(original, "Database", strlen("Database")) == 0) { + /* only databases are affected, don't flip flags for packages */ + value = original + strlen("Database"); + database = 1; + } else { + /* no prefix, so anything found will affect both packages and dbs */ + value = original; + package = database = 1; + } + + /* now parse out and store actual flag if it is valid */ + if(strcmp(value, "Never") == 0) { + if(package) { + level &= ~ALPM_SIG_PACKAGE; + } + if(database) { + level &= ~ALPM_SIG_DATABASE; + } + } else if(strcmp(value, "Optional") == 0) { + if(package) { + level |= ALPM_SIG_PACKAGE; + level |= ALPM_SIG_PACKAGE_OPTIONAL; + } + if(database) { + level |= ALPM_SIG_DATABASE; + level |= ALPM_SIG_DATABASE_OPTIONAL; + } + } else if(strcmp(value, "Required") == 0) { + if(package) { + level |= ALPM_SIG_PACKAGE; + level &= ~ALPM_SIG_PACKAGE_OPTIONAL; + } + if(database) { + level |= ALPM_SIG_DATABASE; + level &= ~ALPM_SIG_DATABASE_OPTIONAL; + } + } else if(strcmp(value, "TrustedOnly") == 0) { + if(package) { + level &= ~ALPM_SIG_PACKAGE_MARGINAL_OK; + level &= ~ALPM_SIG_PACKAGE_UNKNOWN_OK; + } + if(database) { + level &= ~ALPM_SIG_DATABASE_MARGINAL_OK; + level &= ~ALPM_SIG_DATABASE_UNKNOWN_OK; + } + } else if(strcmp(value, "TrustAll") == 0) { + if(package) { + level |= ALPM_SIG_PACKAGE_MARGINAL_OK; + level |= ALPM_SIG_PACKAGE_UNKNOWN_OK; + } + if(database) { + level |= ALPM_SIG_DATABASE_MARGINAL_OK; + level |= ALPM_SIG_DATABASE_UNKNOWN_OK; + } + } else { + pm_printf(ALPM_LOG_ERROR, _("invalid value for 'SigLevel' : '%s'\n"), + original); + ret = 1; + } + level &= ~ALPM_SIG_USE_DEFAULT; } - pm_printf(ALPM_LOG_DEBUG, "config: VerifySig = %s (%d)\n", value, level); - return level; + + if(!ret) { + *storage = level; + } + return ret; } static int process_cleanmethods(alpm_list_t *values) { @@ -359,16 +432,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, &(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,16 +797,19 @@ 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); - ret = 1; - goto cleanup; + } else if(strcmp(key, "SigLevel") == 0) { + alpm_list_t *values = NULL; + setrepeatingoption(value, "SigLevel", &values); + if(values) { + if(section->siglevel == ALPM_SIG_USE_DEFAULT) { + section->siglevel = config->siglevel; + } + if(process_siglevel(values, &(section->siglevel))) { + FREELIST(values); + ret = 1; + goto cleanup; + } + FREELIST(values); } } else { pm_printf(ALPM_LOG_WARNING, |