[pacman-dev] [PATCH] Implement parsing of the new SigLevel directive

Dan McGee dan at archlinux.org
Mon Jul 18 21:06:01 EDT 2011


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 at kerrickstaley.com>
Signed-off-by: Dan McGee <dan at 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



More information about the pacman-dev mailing list