[pacman-dev] [RFC] Add Server-specific options, currently only PinnedPubKey
Hi all, Here is a rough go at a patch for server-specific options. It works, but what still needs done is: 1. Changing alpm_db_remove_server, does it still take a char* url? or the entire alpm_server_t struct that alpm_db_add_server does? 2. Deciding what to do with alpm_cb_fetch's signature, should a new struct be added to make adding new server options easier? Should alpm_server_t be sent in instead? (this gets messy in some places). 3. Documentation updates. The end result looks like: Server = https://example.org/ PinnedPubKey=sha256//eEHQC9au2QRAP1FnvcYEsmvXT7511EXQ2gw8ppBfseM= Is this a sound approach? Any other comments appreciated. Thanks, Travis
From ebf448cd4da77bdea833dc75e60de5c992f21eaf Mon Sep 17 00:00:00 2001 From: Travis Burtrum
Date: Tue, 1 Nov 2016 23:02:43 -0400 Subject: [PATCH] [RFC] Add Server-specific options, currently only PinnedPubKey supported
---
lib/libalpm/Makefile.am | 1 +
lib/libalpm/alpm.c | 1 +
lib/libalpm/alpm.h | 18 ++++++++--
lib/libalpm/be_sync.c | 7 +++-
lib/libalpm/db.c | 16 ++++++---
lib/libalpm/dload.c | 8 ++++-
lib/libalpm/dload.h | 1 +
lib/libalpm/hook.c | 10 +++---
lib/libalpm/server.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
lib/libalpm/server.h | 36 +++++++++++++++++++
lib/libalpm/sync.c | 4 ++-
src/pacman/conf.c | 68 ++++++++++++++++++++++++++++--------
12 files changed, 234 insertions(+), 27 deletions(-)
create mode 100644 lib/libalpm/server.c
create mode 100644 lib/libalpm/server.h
diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am
index f4f20e6..197459c 100644
--- a/lib/libalpm/Makefile.am
+++ b/lib/libalpm/Makefile.am
@@ -48,6 +48,7 @@ libalpm_la_SOURCES = \
libarchive-compat.h \
log.h log.c \
package.h package.c \
+ server.h server.c \
pkghash.h pkghash.c \
rawstr.c \
remove.h remove.c \
diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c
index 5225e4f..82df39f 100644
--- a/lib/libalpm/alpm.c
+++ b/lib/libalpm/alpm.c
@@ -29,6 +29,7 @@
#include "alpm.h"
#include "alpm_list.h"
#include "handle.h"
+#include "server.h"
#include "log.h"
#include "util.h"
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 2d2491d..53b48e5 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -48,6 +48,7 @@ typedef struct __alpm_handle_t alpm_handle_t;
typedef struct __alpm_db_t alpm_db_t;
typedef struct __alpm_pkg_t alpm_pkg_t;
typedef struct __alpm_trans_t alpm_trans_t;
+typedef struct __alpm_server_t alpm_server_t;
/** @addtogroup alpm_api_errors Error Codes
* @{
@@ -750,11 +751,12 @@ typedef void (*alpm_cb_totaldl)(off_t total);
* @param url the URL of the file to be downloaded
* @param localpath the directory to which the file should be downloaded
* @param force whether to force an update, even if the file is the same
+ * @param pinnedpubkey a pinned public key string
* @return 0 on success, 1 if the file exists and is identical, -1 on
* error.
*/
typedef int (*alpm_cb_fetch)(const char *url, const char *localpath,
- int force);
+ int force, const char *pinnedpubkey);
/** Fetch a remote pkg.
* @param handle the context handle
@@ -998,7 +1000,7 @@ int alpm_db_get_valid(alpm_db_t *db);
*/
alpm_list_t *alpm_db_get_servers(const alpm_db_t *db);
int alpm_db_set_servers(alpm_db_t *db, alpm_list_t *servers);
-int alpm_db_add_server(alpm_db_t *db, const char *url);
+int alpm_db_add_server(alpm_db_t *db, alpm_server_t *url);
int alpm_db_remove_server(alpm_db_t *db, const char *url);
/** @} */
@@ -1061,6 +1063,18 @@ int alpm_db_get_usage(alpm_db_t *db, int *usage);
/** @} */
+alpm_server_t *alpm_server_new(void);
+int alpm_server_free(alpm_server_t *server);
+
+const char *alpm_server_get_url(const alpm_server_t *server);
+const char *alpm_server_get_pinnedpubkey(const alpm_server_t *server);
+int alpm_server_set_url(alpm_server_t *server, const char *url);
+int alpm_server_set_pinnedpubkey(alpm_server_t *server, const char *pinnedpubkey);
+
+char **alpm_wordsplit(char *str);
+int alpm_wordsplit_free(char **ws);
+
+
/** @addtogroup alpm_api_packages Package Functions
* Functions to manipulate libalpm packages
* @{
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 7774975..79a35d2 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -219,7 +219,8 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
dbext = db->handle->dbext;
for(i = db->servers; i; i = i->next) {
- const char *server = i->data, *final_db_url = NULL;
+ alpm_server_t *server_t = i->data;
+ const char *server = alpm_server_get_url(server_t), *final_db_url = NULL;
struct dload_payload payload;
size_t len;
int sig_ret = 0;
@@ -242,6 +243,8 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
payload.handle = handle;
payload.force = force;
payload.unlink_on_fail = 1;
+
+ payload.pinnedpubkey = alpm_server_get_pinnedpubkey(server_t);
ret = _alpm_download(&payload, syncpath, NULL, &final_db_url);
_alpm_dload_payload_reset(&payload);
@@ -297,6 +300,8 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
/* set hard upper limit of 16KiB */
payload.max_size = 16 * 1024;
+ payload.pinnedpubkey = alpm_server_get_pinnedpubkey(server_t);
+
sig_ret = _alpm_download(&payload, syncpath, NULL, NULL);
/* errors_ok suppresses error messages, but not the return code */
sig_ret = payload.errors_ok ? 0 : sig_ret;
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 5d78ee5..7c8dd4b 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -150,7 +150,8 @@ alpm_list_t SYMEXPORT *alpm_db_get_servers(const alpm_db_t *db)
int SYMEXPORT alpm_db_set_servers(alpm_db_t *db, alpm_list_t *servers)
{
ASSERT(db != NULL, return -1);
- FREELIST(db->servers);
+ alpm_list_free_inner(db->servers, (alpm_list_fn_free) alpm_server_free);
+ alpm_list_free(db->servers);
db->servers = servers;
return 0;
}
@@ -173,9 +174,10 @@ static char *sanitize_url(const char *url)
* @param url url of the server
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url)
+int SYMEXPORT alpm_db_add_server(alpm_db_t *db, alpm_server_t *server)
{
char *newurl;
+ const char *url = alpm_server_get_url(server);
/* Sanity checks */
ASSERT(db != NULL, return -1);
@@ -186,7 +188,12 @@ int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url)
if(!newurl) {
return -1;
}
- db->servers = alpm_list_add(db->servers, newurl);
+
+ alpm_server_t *copy = alpm_server_new();
+ alpm_server_set_url(copy, newurl);
+ alpm_server_set_pinnedpubkey(copy, alpm_server_get_pinnedpubkey(server));
+
+ db->servers = alpm_list_add(db->servers, copy);
_alpm_log(db->handle, ALPM_LOG_DEBUG, "adding new server URL to database '%s': %s\n",
db->treename, newurl);
@@ -348,7 +355,8 @@ void _alpm_db_free(alpm_db_t *db)
/* cleanup pkgcache */
_alpm_db_free_pkgcache(db);
/* cleanup server list */
- FREELIST(db->servers);
+ alpm_list_free_inner(db->servers, (alpm_list_fn_free) alpm_server_free);
+ alpm_list_free(db->servers);
FREE(db->_path);
FREE(db->treename);
FREE(db);
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 9d80358..6d5b371 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -327,6 +327,12 @@ static void curl_set_handle_opts(struct dload_payload *payload,
curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent);
}
+ if(payload->pinnedpubkey != NULL) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "using curl pinnedpubkey: %s\n", payload->pinnedpubkey);
+ curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, payload->pinnedpubkey);
+ }
+
if(!payload->allow_resume && !payload->force && payload->destfile_name &&
stat(payload->destfile_name, &st) == 0) {
/* start from scratch, but only download if our local is out of date. */
@@ -646,7 +652,7 @@ int _alpm_download(struct dload_payload *payload, const char *localpath,
RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1);
#endif
} else {
- int ret = handle->fetchcb(payload->fileurl, localpath, payload->force);
+ int ret = handle->fetchcb(payload->fileurl, localpath, payload->force, payload->pinnedpubkey);
if(ret == -1 && !payload->errors_ok) {
RET_ERR(handle, ALPM_ERR_EXTERNAL_DOWNLOAD, -1);
}
diff --git a/lib/libalpm/dload.h b/lib/libalpm/dload.h
index 427c486..9b8453a 100644
--- a/lib/libalpm/dload.h
+++ b/lib/libalpm/dload.h
@@ -41,6 +41,7 @@ struct dload_payload {
int errors_ok;
int unlink_on_fail;
int trust_remote_name;
+ const char *pinnedpubkey;
#ifdef HAVE_LIBCURL
CURLcode curlerr; /* last error produced by curl */
#endif
diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c
index ccde225..9e84d78 100644
--- a/lib/libalpm/hook.c
+++ b/lib/libalpm/hook.c
@@ -71,7 +71,7 @@ static void _alpm_trigger_free(struct _alpm_trigger_t *trigger)
}
}
-static void _alpm_wordsplit_free(char **ws)
+int SYMEXPORT alpm_wordsplit_free(char **ws)
{
if(ws) {
char **c;
@@ -79,7 +79,9 @@ static void _alpm_wordsplit_free(char **ws)
free(*c);
}
free(ws);
+ return 0;
}
+ return -1;
}
static void _alpm_hook_free(struct _alpm_hook_t *hook)
@@ -87,7 +89,7 @@ static void _alpm_hook_free(struct _alpm_hook_t *hook)
if(hook) {
free(hook->name);
free(hook->desc);
- _alpm_wordsplit_free(hook->cmd);
+ alpm_wordsplit_free(hook->cmd);
alpm_list_free_inner(hook->triggers, (alpm_list_fn_free) _alpm_trigger_free);
alpm_list_free(hook->triggers);
alpm_list_free(hook->matches);
@@ -158,7 +160,7 @@ static int _alpm_hook_validate(alpm_handle_t *handle,
return ret;
}
-static char **_alpm_wordsplit(char *str)
+char SYMEXPORT **alpm_wordsplit(char *str)
{
char *c = str, *end;
char **out = NULL, **outsave;
@@ -330,7 +332,7 @@ static int _alpm_hook_parse_cb(const char *file, int line,
} else if(strcmp(key, "NeedsTargets") == 0) {
hook->needs_targets = 1;
} else if(strcmp(key, "Exec") == 0) {
- if((hook->cmd = _alpm_wordsplit(value)) == NULL) {
+ if((hook->cmd = alpm_wordsplit(value)) == NULL) {
if(errno == EINVAL) {
error(_("hook %s line %d: invalid value %s\n"), file, line, value);
} else {
diff --git a/lib/libalpm/server.c b/lib/libalpm/server.c
new file mode 100644
index 0000000..29aa365
--- /dev/null
+++ b/lib/libalpm/server.c
@@ -0,0 +1,91 @@
+/*
+ * server.c
+ *
+ * Copyright (c) 2006-2016 Pacman Development Team
participants (1)
-
Travis Burtrum