summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-08-24 19:58:14 -0500
committerDan McGee <dan@archlinux.org>2011-08-25 16:09:52 -0500
commitf7a3c4c8df95ad99e05dfd29c61d6877b13b09da (patch)
tree383d401a7ee8bd9d27f2a1d6a72c69c997986af6 /lib
parent2e7d002315066400ccb1e62dacb3500fa3aa6015 (diff)
downloadpacman-f7a3c4c8df95ad99e05dfd29c61d6877b13b09da.tar.xz
Finish large file download attack prevention
This handles the no Content-Length header problem as stated in the comments of FS#23413. We add a quick check to the callback that will force an abort if the downloaded data exceeds the payload size, and then check for this error in the post-download cleanup code. Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/libalpm/dload.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index 9f085734..6ae69171 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -83,12 +83,18 @@ static int curl_progress(void *file, double dltotal, double dlnow,
return 1;
}
+ current_size = payload->initial_size + (off_t)dlnow;
+
+ /* is our filesize still under any set limit? */
+ if(payload->max_size && current_size > payload->max_size) {
+ return 1;
+ }
+
/* none of what follows matters if the front end has no callback */
if(payload->handle->dlcb == NULL) {
return 0;
}
- current_size = payload->initial_size + (off_t)dlnow;
total_size = payload->initial_size + (off_t)dltotal;
if(DOUBLE_EQ(dltotal, 0.0) || prevprogress == total_size) {
@@ -341,6 +347,15 @@ static int curl_download_internal(struct dload_payload *payload,
}
break;
case CURLE_ABORTED_BY_CALLBACK:
+ /* two cases here- interrupted by user, or we exceeded max file size. */
+ if(!dload_interrupted) {
+ handle->curlerr = CURLE_FILESIZE_EXCEEDED;
+ handle->pm_errno = ALPM_ERR_LIBCURL;
+ /* the hardcoded 'size exceeded' message is same as libcurl's normal */
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("failed retrieving file '%s' from %s : %s\n"),
+ payload->remote_name, hostname, "Maximum file size exceeded");
+ }
goto cleanup;
default:
/* delete zero length downloads */
@@ -349,10 +364,12 @@ static int curl_download_internal(struct dload_payload *payload,
}
if(!payload->errors_ok) {
handle->pm_errno = ALPM_ERR_LIBCURL;
- _alpm_log(handle, ALPM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s\n"),
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("failed retrieving file '%s' from %s : %s\n"),
payload->remote_name, hostname, error_buffer);
} else {
- _alpm_log(handle, ALPM_LOG_DEBUG, "failed retrieving file '%s' from %s : %s\n",
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "failed retrieving file '%s' from %s : %s\n",
payload->remote_name, hostname, error_buffer);
}
goto cleanup;