1
0
mirror of https://github.com/moparisthebest/pacman synced 2024-12-22 15:58:50 -05:00

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>
This commit is contained in:
Dan McGee 2011-07-22 10:48:13 -05:00
parent 6997a738bb
commit b03b06cfd3
2 changed files with 106 additions and 32 deletions

View File

@ -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,

View File

@ -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)))