[pacman-dev] Added SigLevel parsing code
-Kerrick Staley
Added the documentation for the SigLevel to pacman.conf.5.txt; the code that implements this will be put into place with the next commit. Signed-off-by: Kerrick Staley <mail@kerrickstaley.com> --- doc/pacman.conf.5.txt | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index a28e00f..349e4f7 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -156,6 +156,30 @@ Options packages are only cleaned if not installed locally and not present in any known sync database. +*SigLevel =* ...:: + If set to `Never` (the default), signatures won't ever be + checked. Conversely, `Required` will require signatures on all packages + and databases. `PackageHash` will require database signatures but accept + any package as long as the corresponding database gives a secure hash for + it (a good compromise when signing every package is too difficult for a + distribution's maintainers). + A more advanced setting is `Optional`, which will perform signature checks + if signatures are present but will allow unsigned databases/packages; this + can be useful when a distribution is making a transition from unsigned + repositories to signed ones. + For advanced configuration, you can list any of the settings described + hereafter, but the options can't be contradictory; `PackageHash` may also + be included in the list. `PackageRequired` and `DatabaseRequired` work + like `Required`, but only cause checks to be performed on packages and + databases, respectively; `Required` is equivalent to `PackageRequired + DatabaseRequired` with no other options. `PackageOptional` works + similarly to `PackageRequired`, and the two cannot be specified together; + `DatabaseOptional` works similarly for databases. `PackageMarginal` + causes signatures from marginally trusted keys to be accepted on packages; + `DatabaseMarginal` works similarly for databases. `PackageUnknown` + causes signatures made with an unknown key to be accepted on packages; + `DatabaseMarginal` works similarly for databases. + *UseSyslog*:: Log action messages through syslog(). This will insert log entries into +{localstatedir}/log/messages+ or equivalent. -- 1.7.6
On Sun, Jul 17, 2011 at 11:06:29PM -0500, Kerrick Staley wrote:
Added the documentation for the SigLevel to pacman.conf.5.txt; the code that implements this will be put into place with the next commit.
A general comment -- we write our commit messages in the present tense, rather than the past. You'll find that this is a general trend across most git repos.
Signed-off-by: Kerrick Staley <mail@kerrickstaley.com> --- doc/pacman.conf.5.txt | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index a28e00f..349e4f7 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -156,6 +156,30 @@ Options packages are only cleaned if not installed locally and not present in any known sync database.
+*SigLevel =* ...:: + If set to `Never` (the default), signatures won't ever be
We're putting all this work into package signing, and we're not going to enable it by default? Certainly requiring full trust of all packages and DBs isn't realistic for launch day, but if the sig is available, we should be checking it by default.
+ checked. Conversely, `Required` will require signatures on all packages + and databases. `PackageHash` will require database signatures but accept + any package as long as the corresponding database gives a secure hash for + it (a good compromise when signing every package is too difficult for a + distribution's maintainers). + A more advanced setting is `Optional`, which will perform signature checks + if signatures are present but will allow unsigned databases/packages; this + can be useful when a distribution is making a transition from unsigned + repositories to signed ones. + For advanced configuration, you can list any of the settings described + hereafter, but the options can't be contradictory; `PackageHash` may also + be included in the list. `PackageRequired` and `DatabaseRequired` work + like `Required`, but only cause checks to be performed on packages and + databases, respectively; `Required` is equivalent to `PackageRequired + DatabaseRequired` with no other options. `PackageOptional` works + similarly to `PackageRequired`, and the two cannot be specified together; + `DatabaseOptional` works similarly for databases. `PackageMarginal` + causes signatures from marginally trusted keys to be accepted on packages; + `DatabaseMarginal` works similarly for databases. `PackageUnknown` + causes signatures made with an unknown key to be accepted on packages; + `DatabaseMarginal` works similarly for databases. +
Surely there's a typo somewhere in here near the end...
*UseSyslog*:: Log action messages through syslog(). This will insert log entries into +{localstatedir}/log/messages+ or equivalent. -- 1.7.6
I'm going to leave a full grammar review to someone else who can do a more precise job than I can. dave
Changed the SigLevel parsing in conf.c to handle the new options. Signed-off-by: Kerrick Staley <mail@kerrickstaley.com> --- src/pacman/conf.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/pacman/conf.c b/src/pacman/conf.c index fac6da3..f0a6930 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -222,20 +222,83 @@ int config_set_arch(const char *arch) return 0; } -static alpm_siglevel_t option_verifysig(const char *value) +/** + * Parse a signature verification level. Destroys the passed string. + * @param value the string listing the siglevel options + * @return -1 if value was empty, -2 if value contained unknown + * options, -3 if some of the options were contradictory, the siglevel + * value otherwise. + */ +static alpm_siglevel_t option_siglevel(char *value) { - 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 { + alpm_siglevel_t level = 0; + + char *strtok_state; + char *tok = strtok_r(value, " \t", &strtok_state); + + if (!tok) { return -1; } - pm_printf(ALPM_LOG_DEBUG, "config: VerifySig = %s (%d)\n", value, level); + + do { + if(strcmp(tok, "Never") == 0) { + level = level ? -3 : 0; + break; + } else if(strcmp(tok, "Optional") == 0) { + level = level ? -3 : ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL | + ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL; + break; + } else if(strcmp(tok, "Required") == 0) { + level = level ? -3 : ALPM_SIG_PACKAGE | ALPM_SIG_DATABASE; + break; + } else if(strcmp(tok, "PackageHash") == 0) { + if (level & ALPM_SIG_DATABASE_OPTIONAL) { + level = -3; + break; + } + level |= ALPM_SIG_DATABASE | ALPM_SIG_PACKAGE_HASH_OK; + } else if(strcmp(tok, "PackageRequired") == 0) { + if (level & ALPM_SIG_PACKAGE_OPTIONAL) { + level = -3; + break; + } + level |= ALPM_SIG_PACKAGE; + } else if(strcmp(tok, "DatabaseRequired") == 0) { + if (level & ALPM_SIG_DATABASE_OPTIONAL) { + level = -3; + break; + } + level |= ALPM_SIG_DATABASE; + } else if(strcmp(tok, "PackageOptional") == 0) { + if (level & ALPM_SIG_PACKAGE) { + level = -3; + break; + } + level |= ALPM_SIG_PACKAGE_OPTIONAL; + } else if(strcmp(tok, "DatabaseOptional") == 0) { + if (level & ALPM_SIG_PACKAGE) { + level = -3; + break; + } + level |= ALPM_SIG_DATABASE_OPTIONAL; + } else if(strcmp(tok, "PackageAllowMarginal") == 0) { + level |= ALPM_SIG_PACKAGE_MARGINAL_OK; + } else if(strcmp(tok, "DatabaseAllowMarginal") == 0) { + level |= ALPM_SIG_DATABASE_MARGINAL_OK; + } else if(strcmp(tok, "PackageAllowUnknown") == 0) { + level |= ALPM_SIG_PACKAGE_UNKNOWN_OK; + } else if(strcmp(tok, "DatabaseAllowUnknown") == 0) { + level |= ALPM_SIG_DATABASE_UNKNOWN_OK; + } else { + level = -2; + break; + } + } while ((tok = strtok_r(NULL, " \t", &strtok_state))); + + if (level > 0) { + pm_printf(ALPM_LOG_DEBUG, "config: SigLevel = %s (%d)\n", value, level); + } + return level; } @@ -359,9 +422,9 @@ 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) { + } else if(strcmp(key, "SigLevel") == 0) { + alpm_siglevel_t level = option_siglevel(value); + if(level > 0) { config->siglevel = level; } else { pm_printf(ALPM_LOG_ERROR, @@ -727,7 +790,7 @@ static int _parseconfig(const char *file, struct section_t *section, } section->servers = alpm_list_add(section->servers, strdup(value)); } else if(strcmp(key, "VerifySig") == 0) { - alpm_siglevel_t level = option_verifysig(value); + alpm_siglevel_t level = option_siglevel(value); if(level != -1) { section->siglevel = level; } else { -- 1.7.6
I don't know where the summary went, but anyway, this adds parsing to the conf file for the new SigLevel syntax. There are actually some problems with the second patch; I'll get it resent shortly. Also, can anyone recommend a way to easily test a change such as this? Thanks, Kerrick Staley
On Mon, Jul 18, 2011 at 12:16 PM, Kerrick Staley <mail@kerrickstaley.com> wrote:
Also, can anyone recommend a way to easily test a change such as this?
Probably not what you want to hear, but you can create a unit test suite, which would be trivial for a function such as this (no state or I/O). Pacman/libalpm has functional tests, as described in ./test/pacman/README.
On Mon, Jul 18, 2011 at 6:08 AM, Sebastian Nowicki <sebnow@gmail.com> wrote:
On Mon, Jul 18, 2011 at 12:16 PM, Kerrick Staley <mail@kerrickstaley.com> wrote:
Also, can anyone recommend a way to easily test a change such as this?
Probably not what you want to hear, but you can create a unit test suite, which would be trivial for a function such as this (no state or I/O). Pacman/libalpm has functional tests, as described in ./test/pacman/README.
We currently have extremely simplistic support for this in pactest, and it will need some massive improvement in the future. See the one-liner change I had to make in conf.py (s/VerifySig/SigLevel/), but we really need to test all aspects of signing and keyrings and all that, which we currently don't do at all. -Dan
participants (4)
-
Dan McGee
-
Dave Reisner
-
Kerrick Staley
-
Sebastian Nowicki