summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/be_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/be_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/be_sync.c')
-rw-r--r--lib/libalpm/be_sync.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index a784536b..f681fc8e 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -172,16 +172,21 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
for(i = db->servers; i; i = i->next) {
const char *server = i->data;
- char *fileurl;
+ struct dload_payload *payload;
size_t len;
int sig_ret = 0;
+ CALLOC(payload, 1, sizeof(*payload), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+
+ /* set hard upper limit of 25MiB */
+ payload->max_size = 25 * 1024 * 1024;
+
/* print server + filename into a buffer (leave space for .sig) */
len = strlen(server) + strlen(db->treename) + 9;
- CALLOC(fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
- snprintf(fileurl, len, "%s/%s.db", server, db->treename);
+ CALLOC(payload->fileurl, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+ snprintf(payload->fileurl, len, "%s/%s.db", server, db->treename);
- ret = _alpm_download(handle, fileurl, syncpath, NULL, force, 0, 0);
+ ret = _alpm_download(handle, payload, syncpath, NULL, force, 0, 0);
if(ret == 0 && (level & ALPM_SIG_DATABASE)) {
/* an existing sig file is no good at this point */
@@ -195,14 +200,17 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
int errors_ok = (level & ALPM_SIG_DATABASE_OPTIONAL);
/* if we downloaded a DB, we want the .sig from the same server */
- snprintf(fileurl, len, "%s/%s.db.sig", server, db->treename);
+ snprintf(payload->fileurl, len, "%s/%s.db.sig", server, db->treename);
+
+ /* set hard upper limit of 16KiB */
+ payload->max_size = 16 * 1024;
- sig_ret = _alpm_download(handle, fileurl, syncpath, NULL, 1, 0, errors_ok);
+ sig_ret = _alpm_download(handle, payload, syncpath, NULL, 1, 0, errors_ok);
/* errors_ok suppresses error messages, but not the return code */
sig_ret = errors_ok ? 0 : sig_ret;
}
- FREE(fileurl);
+ _alpm_dload_payload_free(payload);
if(ret != -1 && sig_ret != -1) {
break;
}