[pacman-dev] [PATCH] [FINAL RFC] Add configuration option for Upgrade operation SigLevel

Allan McRae allan at archlinux.org
Mon Jan 28 19:01:57 EST 2013


Add LocalFileSigLevel and RemoteFileSigLevel to control the signature
checking for "pacman -U <file>" and "pacman -U <url>" operations
respectively. The starting value for both these options is SigLevel,
if it is specified in the [options] section, or the built-in system
default. The specified values override and/or supplement this initial
value. Note there is no destintion between setting "Required" and
"PackageRequired" as there is not database options for Upgrade
operations.

Signed-off-by: Allan McRae <allan at archlinux.org>
---

This patch has been floating around for quite some time now.  I would like some final
comments before I write the documentation and push.

I have this in my pacman.conf:

SigLevel    = Required DatabaseOptional TrustedOnly
LocalFileSigLevel = Optional TrustedOnly
#RemoteFileSigLevel = Required

so if I "pacman -U /path/to/file", a signature is only checked if it is present, but
"pacman -U http://...." always checks the signature.  It also means that I do not need
have my global SigLevel as Optional and add PackageRequired to every Arch repo.

I'd like a comment, even if it is a simple "Ack".


 lib/libalpm/alpm.h   |  9 +++++++++
 lib/libalpm/handle.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
 lib/libalpm/handle.h |  4 ++++
 src/pacman/conf.c    | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/pacman/conf.h    |  2 ++
 src/pacman/upgrade.c | 21 ++++++++++++++++++---
 6 files changed, 131 insertions(+), 9 deletions(-)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index f524c19..b681840 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -115,6 +115,9 @@ typedef enum _alpm_siglevel_t {
 	ALPM_SIG_DATABASE_MARGINAL_OK = (1 << 12),
 	ALPM_SIG_DATABASE_UNKNOWN_OK = (1 << 13),
 
+	ALPM_SIG_PACKAGE_SET = (1 << 27),
+	ALPM_SIG_PACKAGE_TRUST_SET = (1 << 28),
+
 	ALPM_SIG_USE_DEFAULT = (1 << 31)
 } alpm_siglevel_t;
 
@@ -561,6 +564,12 @@ int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace);
 alpm_siglevel_t alpm_option_get_default_siglevel(alpm_handle_t *handle);
 int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t level);
 
+alpm_siglevel_t alpm_option_get_local_file_siglevel(alpm_handle_t *handle);
+int alpm_option_set_local_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t level);
+
+alpm_siglevel_t alpm_option_get_remote_file_siglevel(alpm_handle_t *handle);
+int alpm_option_set_remote_file_siglevel(alpm_handle_t *handle, alpm_siglevel_t level);
+
 /** @} */
 
 /** @addtogroup alpm_api_databases Database Functions
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 1a840ab..53c86c5 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -594,6 +594,18 @@ int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio)
 	return 0;
 }
 
+alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle)
+{
+	CHECK_HANDLE(handle, return NULL);
+	return handle->db_local;
+}
+
+alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle)
+{
+	CHECK_HANDLE(handle, return NULL);
+	return handle->dbs_sync;
+}
+
 int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace)
 {
 	CHECK_HANDLE(handle, return -1);
@@ -621,16 +633,44 @@ alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle
 	return handle->siglevel;
 }
 
-alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle)
+int SYMEXPORT alpm_option_set_local_file_siglevel(alpm_handle_t *handle,
+		alpm_siglevel_t level)
 {
-	CHECK_HANDLE(handle, return NULL);
-	return handle->db_local;
+	CHECK_HANDLE(handle, return -1);
+#ifdef HAVE_LIBGPGME
+	handle->localfilesiglevel = level;
+#else
+	if(level != 0 && level != ALPM_SIG_USE_DEFAULT) {
+		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+	}
+#endif
+	return 0;
 }
 
-alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle)
+alpm_siglevel_t SYMEXPORT alpm_option_get_local_file_siglevel(alpm_handle_t *handle)
 {
-	CHECK_HANDLE(handle, return NULL);
-	return handle->dbs_sync;
+	CHECK_HANDLE(handle, return -1);
+	return handle->localfilesiglevel;
+}
+
+int SYMEXPORT alpm_option_set_remote_file_siglevel(alpm_handle_t *handle,
+		alpm_siglevel_t level)
+{
+	CHECK_HANDLE(handle, return -1);
+#ifdef HAVE_LIBGPGME
+	handle->remotefilesiglevel = level;
+#else
+	if(level != 0 && level != ALPM_SIG_USE_DEFAULT) {
+		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+	}
+#endif
+	return 0;
+}
+
+alpm_siglevel_t SYMEXPORT alpm_option_get_remote_file_siglevel(alpm_handle_t *handle)
+{
+	CHECK_HANDLE(handle, return -1);
+	return handle->remotefilesiglevel;
 }
 
 /* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index c24e97a..5e84d58 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -92,6 +92,10 @@ struct __alpm_handle_t {
 	int usesyslog;           /* Use syslog instead of logfile? */ /* TODO move to frontend */
 	int checkspace;          /* Check disk space before installing */
 	alpm_siglevel_t siglevel;   /* Default signature verification level */
+	alpm_siglevel_t localfilesiglevel;  /* Signature verification level for local file
+	                                       upgrade operations */
+	alpm_siglevel_t remotefilesiglevel; /* Signature verification level for remote file
+	                                       upgrade operations */
 
 	/* error code */
 	alpm_errno_t pm_errno;
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 1bea2b0..95dce35 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -56,6 +56,8 @@ config_t *config_new(void)
 	if(alpm_capabilities() & ALPM_CAPABILITY_SIGNATURES) {
 		newconfig->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
 			ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;
+		newconfig->localfilesiglevel = ALPM_SIG_USE_DEFAULT;
+		newconfig->remotefilesiglevel = ALPM_SIG_USE_DEFAULT;
 	}
 
 	return newconfig;
@@ -279,6 +281,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage,
 		if(strcmp(value, "Never") == 0) {
 			if(package) {
 				level &= ~ALPM_SIG_PACKAGE;
+				level |= ALPM_SIG_PACKAGE_SET;
 			}
 			if(database) {
 				level &= ~ALPM_SIG_DATABASE;
@@ -287,6 +290,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage,
 			if(package) {
 				level |= ALPM_SIG_PACKAGE;
 				level |= ALPM_SIG_PACKAGE_OPTIONAL;
+				level |= ALPM_SIG_PACKAGE_SET;
 			}
 			if(database) {
 				level |= ALPM_SIG_DATABASE;
@@ -296,6 +300,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage,
 			if(package) {
 				level |= ALPM_SIG_PACKAGE;
 				level &= ~ALPM_SIG_PACKAGE_OPTIONAL;
+				level |= ALPM_SIG_PACKAGE_SET;
 			}
 			if(database) {
 				level |= ALPM_SIG_DATABASE;
@@ -305,6 +310,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage,
 			if(package) {
 				level &= ~ALPM_SIG_PACKAGE_MARGINAL_OK;
 				level &= ~ALPM_SIG_PACKAGE_UNKNOWN_OK;
+				level |= ALPM_SIG_PACKAGE_TRUST_SET;
 			}
 			if(database) {
 				level &= ~ALPM_SIG_DATABASE_MARGINAL_OK;
@@ -314,6 +320,7 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage,
 			if(package) {
 				level |= ALPM_SIG_PACKAGE_MARGINAL_OK;
 				level |= ALPM_SIG_PACKAGE_UNKNOWN_OK;
+				level |= ALPM_SIG_PACKAGE_TRUST_SET;
 			}
 			if(database) {
 				level |= ALPM_SIG_DATABASE_MARGINAL_OK;
@@ -343,6 +350,30 @@ static int process_siglevel(alpm_list_t *values, alpm_siglevel_t *storage,
 	return ret;
 }
 
+/**
+ * Merge the package entires of two signature verification levels.
+ * @param base initial siglevel
+ * @param over overridden siglevel, derived value is stored here
+ */
+static void merge_siglevel(alpm_siglevel_t *base, alpm_siglevel_t *over)
+{
+	alpm_siglevel_t level = *over;
+	if(level & ALPM_SIG_USE_DEFAULT) {
+		level = *base;
+	} else {
+		if(!(level & ALPM_SIG_PACKAGE_SET)) {
+			level |= *base & ALPM_SIG_PACKAGE;
+			level |= *base & ALPM_SIG_PACKAGE_OPTIONAL;
+		}
+		if(!(level & ALPM_SIG_PACKAGE_TRUST_SET)) {
+			level |= *base & ALPM_SIG_PACKAGE_MARGINAL_OK;
+			level |= *base & ALPM_SIG_PACKAGE_UNKNOWN_OK;
+		}
+	}
+
+	*over = level;
+}
+
 static int process_cleanmethods(alpm_list_t *values,
 		const char *file, int linenum)
 {
@@ -484,6 +515,22 @@ static int _parse_options(const char *key, char *value,
 				return 1;
 			}
 			FREELIST(values);
+		} else if(strcmp(key, "LocalFileSigLevel") == 0) {
+			alpm_list_t *values = NULL;
+			setrepeatingoption(value, "LocalFileSigLevel", &values);
+			if(process_siglevel(values, &config->localfilesiglevel, file, linenum)) {
+				FREELIST(values);
+				return 1;
+			}
+			FREELIST(values);
+		} else if(strcmp(key, "RemoteFileSigLevel") == 0) {
+			alpm_list_t *values = NULL;
+			setrepeatingoption(value, "RemoteFileSigLevel", &values);
+			if(process_siglevel(values, &config->remotefilesiglevel, file, linenum)) {
+				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"),
@@ -606,6 +653,11 @@ static int setup_libalpm(void)
 
 	alpm_option_set_default_siglevel(handle, config->siglevel);
 
+	merge_siglevel(&config->siglevel, &config->localfilesiglevel);
+	merge_siglevel(&config->siglevel, &config->remotefilesiglevel);
+	alpm_option_set_local_file_siglevel(handle, config->localfilesiglevel);
+	alpm_option_set_remote_file_siglevel(handle, config->remotefilesiglevel);
+
 	if(config->xfercommand) {
 		alpm_option_set_fetchcb(handle, download_with_xfercommand);
 	} else if(!(alpm_capabilities() & ALPM_CAPABILITY_DOWNLOADER)) {
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 06d2fd5..ff099fe 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -73,6 +73,8 @@ typedef struct __config_t {
 	unsigned int ask;
 	alpm_transflag_t flags;
 	alpm_siglevel_t siglevel;
+	alpm_siglevel_t localfilesiglevel;
+	alpm_siglevel_t remotefilesiglevel;
 
 	/* conf file options */
 	/* I Love Candy! */
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index 7f69091..222f7fa 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -40,8 +40,7 @@
 int pacman_upgrade(alpm_list_t *targets)
 {
 	int retval = 0;
-	alpm_list_t *i;
-	alpm_siglevel_t level = alpm_option_get_default_siglevel(config->handle);
+	alpm_list_t *i, *remote = NULL;
 
 	if(targets == NULL) {
 		pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
@@ -51,6 +50,8 @@ int pacman_upgrade(alpm_list_t *targets)
 	/* Check for URL targets and process them
 	 */
 	for(i = targets; i; i = alpm_list_next(i)) {
+		int *r = malloc(sizeof(int));
+
 		if(strstr(i->data, "://")) {
 			char *str = alpm_fetch_pkgurl(config->handle, i->data);
 			if(str == NULL) {
@@ -60,8 +61,13 @@ int pacman_upgrade(alpm_list_t *targets)
 			} else {
 				free(i->data);
 				i->data = str;
+				*r = 1;
 			}
+		} else {
+			*r = 0;
 		}
+
+		remote = alpm_list_add(remote, r);
 	}
 
 	if(retval) {
@@ -75,9 +81,16 @@ int pacman_upgrade(alpm_list_t *targets)
 
 	printf(_("loading packages...\n"));
 	/* add targets to the created transaction */
-	for(i = targets; i; i = alpm_list_next(i)) {
+	for(i = targets; i; i = alpm_list_next(i), remote = alpm_list_next(remote)) {
 		const char *targ = i->data;
 		alpm_pkg_t *pkg;
+		alpm_siglevel_t level;
+
+		if(*(int *)remote->data) {
+			level = alpm_option_get_remote_file_siglevel(config->handle);
+		} else {
+			level = alpm_option_get_local_file_siglevel(config->handle);
+		}
 
 		if(alpm_pkg_load(config->handle, targ, 1, level, &pkg) != 0) {
 			pm_printf(ALPM_LOG_ERROR, "'%s': %s\n",
@@ -95,6 +108,8 @@ int pacman_upgrade(alpm_list_t *targets)
 		config->explicit_adds = alpm_list_add(config->explicit_adds, pkg);
 	}
 
+	FREELIST(remote);
+
 	if(retval) {
 		trans_release();
 		return retval;
-- 
1.8.1.1



More information about the pacman-dev mailing list