summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mod_secdownload.c38
-rw-r--r--tests/lighttpd.conf1
-rwxr-xr-xtests/mod-secdownload.t16
3 files changed, 54 insertions, 1 deletions
diff --git a/src/mod_secdownload.c b/src/mod_secdownload.c
index f7848391..4a00c933 100644
--- a/src/mod_secdownload.c
+++ b/src/mod_secdownload.c
@@ -96,6 +96,8 @@ typedef struct {
secdl_algorithm algorithm;
unsigned int timeout;
+ unsigned short path_segments;
+ unsigned short hash_querystr;
} plugin_config;
typedef struct {
@@ -282,6 +284,8 @@ SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
{ "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
{ "secdownload.timeout", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
{ "secdownload.algorithm", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+ { "secdownload.path-segments", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
+ { "secdownload.hash-querystr", NULL, T_CONFIG_BOOLEAN,T_CONFIG_SCOPE_CONNECTION }, /* 6 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -299,12 +303,16 @@ SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
s->doc_root = buffer_init();
s->uri_prefix = buffer_init();
s->timeout = 60;
+ s->path_segments = 0;
+ s->hash_querystr = 0;
cv[0].destination = s->secret;
cv[1].destination = s->doc_root;
cv[2].destination = s->uri_prefix;
cv[3].destination = &(s->timeout);
cv[4].destination = algorithm;
+ cv[5].destination = &(s->path_segments);
+ cv[6].destination = &(s->hash_querystr);
p->config_storage[i] = s;
@@ -402,6 +410,8 @@ static int mod_secdownload_patch_connection(server *srv, connection *con, plugin
PATCH(uri_prefix);
PATCH(timeout);
PATCH(algorithm);
+ PATCH(path_segments);
+ PATCH(hash_querystr);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -425,6 +435,10 @@ static int mod_secdownload_patch_connection(server *srv, connection *con, plugin
PATCH(timeout);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.algorithm"))) {
PATCH(algorithm);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.path-segments"))) {
+ PATCH(path_segments);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.hash-querystr"))) {
+ PATCH(hash_querystr);
}
}
}
@@ -499,6 +513,30 @@ URIHANDLER_FUNC(mod_secdownload_uri_handler) {
rel_uri = ts_str + 8;
+ if (p->conf.path_segments) {
+ const char *rel_uri_end = rel_uri;
+ unsigned int count = p->conf.path_segments;
+ do {
+ rel_uri_end = strchr(rel_uri_end+1, '/');
+ } while (rel_uri_end && --count);
+ if (rel_uri_end) {
+ buffer_copy_string_len(srv->tmp_buf, protected_path,
+ rel_uri_end - protected_path);
+ protected_path = srv->tmp_buf->ptr;
+ }
+ }
+
+ if (p->conf.hash_querystr && !buffer_is_empty(con->uri.query)) {
+ buffer *b = srv->tmp_buf;
+ if (protected_path != b->ptr) {
+ buffer_copy_string(b, protected_path);
+ }
+ buffer_append_string_len(b, CONST_STR_LEN("?"));
+ buffer_append_string_buffer(b, con->uri.query);
+ /* assign last in case b->ptr is reallocated */
+ protected_path = b->ptr;
+ }
+
if (!secdl_verify_mac(srv, &p->conf, protected_path, mac_str, mac_len)) {
con->http_status = 403;
diff --git a/tests/lighttpd.conf b/tests/lighttpd.conf
index 3fd8b0da..c2fae77d 100644
--- a/tests/lighttpd.conf
+++ b/tests/lighttpd.conf
@@ -199,6 +199,7 @@ $HTTP["host"] == "vvv-sha256.example.org" {
secdownload.uri-prefix = "/sec/"
secdownload.timeout = 120
secdownload.algorithm = "hmac-sha256"
+ secdownload.hash-querystr = "enable"
}
$HTTP["host"] == "zzz.example.org" {
diff --git a/tests/mod-secdownload.t b/tests/mod-secdownload.t
index 96baf9d7..8881df68 100755
--- a/tests/mod-secdownload.t
+++ b/tests/mod-secdownload.t
@@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
-use Test::More tests => 15;
+use Test::More tests => 16;
use LightyTest;
use Digest::MD5 qw(md5_hex);
use Digest::SHA qw(hmac_sha1 hmac_sha256);
@@ -142,6 +142,20 @@ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'secdownload (hmac-sha256)');
+## HMAC-SHA256
+$f = "/index.html?qs=1";
+$thex = sprintf("%08x", time);
+$m = encode_base64url(hmac_sha256("/$thex$f", $secret));
+
+$t->{REQUEST} = ( <<EOF
+GET /sec/$m/$thex$f HTTP/1.0
+Host: vvv-sha256.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+
+ok($tf->handle_http($t) == 0, 'secdownload (hmac-sha256) with hash-querystr');
+
$thex = sprintf("%08x", time - 1800);
$m = encode_base64url(hmac_sha256("/$thex$f", $secret));