summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/sync.c
diff options
context:
space:
mode:
authorDave Reisner <d@falconindy.com>2011-06-24 06:18:01 +0200
committerDave Reisner <dreisner@archlinux.org>2011-07-06 04:58:55 +0200
commit6dc71926f9b16ebcf11b924941092d6eab204224 (patch)
tree5e90f3b970a257687f9a123590b4ff3c94d1812f /lib/libalpm/sync.c
parent6c9b82e72ac067207b1d66a3112485ad8d690f32 (diff)
downloadpacman-6dc71926f9b16ebcf11b924941092d6eab204224.tar.gz
pacman-6dc71926f9b16ebcf11b924941092d6eab204224.tar.xz
lib/dload: prevent large file attacks
This means creating a new struct which can pass more descriptive data from the back end sync functions to the downloader. In particular, we're interested in the download size read from the sync DB. When the remote server reports a size larger than this (via a content-length header), abort the transfer. In cases where the size is unknown, we set a hard upper limit of: * 25MiB for a sync DB * 16KiB for a signature For reference, 25MiB is more than twice the size of all of the current binary repos (with files) combined, and 16KiB is a truly gargantuan signature. Signed-off-by: Dave Reisner <dreisner@archlinux.org>
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r--lib/libalpm/sync.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 54b96a7a..969af3c0 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -765,10 +765,6 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)
alpm_pkg_t *spkg = j->data;
if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) {
- const char *fname = NULL;
-
- fname = alpm_pkg_get_filename(spkg);
- ASSERT(fname != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
alpm_list_t *delta_path = spkg->delta_path;
if(delta_path) {
/* using deltas */
@@ -776,14 +772,27 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)
for(dlts = delta_path; dlts; dlts = dlts->next) {
alpm_delta_t *delta = dlts->data;
if(delta->download_size != 0) {
- files = alpm_list_add(files, strdup(delta->delta));
+ struct dload_payload *dpayload;
+
+ CALLOC(dpayload, 1, sizeof(*dpayload), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ STRDUP(dpayload->filename, delta->delta, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ dpayload->max_size = delta->download_size;
+
+ files = alpm_list_add(files, dpayload);
}
/* keep a list of all the delta files for md5sums */
*deltas = alpm_list_add(*deltas, delta);
}
} else if(spkg->download_size != 0) {
- files = alpm_list_add(files, strdup(fname));
+ struct dload_payload *payload;
+
+ ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
+ CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ STRDUP(payload->filename, spkg->filename, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ payload->max_size = alpm_pkg_get_size(spkg);
+
+ files = alpm_list_add(files, payload);
}
}
@@ -792,21 +801,19 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)
if(files) {
EVENT(handle->trans, ALPM_TRANS_EVT_RETRIEVE_START, current->treename, NULL);
for(j = files; j; j = j->next) {
- const char *filename = j->data;
+ struct dload_payload *payload = j->data;
alpm_list_t *server;
int ret = -1;
for(server = current->servers; server; server = server->next) {
const char *server_url = server->data;
- char *fileurl;
size_t len;
/* print server + filename into a buffer */
- len = strlen(server_url) + strlen(filename) + 2;
- CALLOC(fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- snprintf(fileurl, len, "%s/%s", server_url, filename);
+ len = strlen(server_url) + strlen(payload->filename) + 2;
+ CALLOC(payload->fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ snprintf(payload->fileurl, len, "%s/%s", server_url, payload->filename);
- ret = _alpm_download(handle, fileurl, cachedir, NULL, 0, 1, 0);
- FREE(fileurl);
+ ret = _alpm_download(handle, payload, cachedir, NULL, 0, 1, 0);
if(ret != -1) {
break;
}
@@ -816,7 +823,9 @@ static int download_files(alpm_handle_t *handle, alpm_list_t **deltas)
}
}
- FREELIST(files);
+ alpm_list_free_inner(files, (alpm_list_fn_free)_alpm_dload_payload_free);
+ alpm_list_free(files);
+ files = NULL;
if(errors) {
_alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files from %s\n"),
current->treename);