Migrating from Lighttpd : mod_secdownload show-stopper ?

ntr0py nginx-forum at nginx.us
Wed Apr 13 11:39:38 MSD 2011


Hello there,

since the only option is to modify the C source code of
nginx/src/http/modules/ngx_http_secure_link_module.c to support
hexadecimal md5 encoding in addition to base64 encoding besides
specifying an optional ttl value to add to expiration time (e.g. 3600
sec in example below) I made a patch to provide this functions in
addition to the documented behavior.
It can be used with a variant of the the configuration Igor suggested:

        location /get/ {
                #location ~
^/get/(?<HASH>[\w-=]+)/(?<TIME>\d+)(?<PATH>/.+)$ { #
/get/<md5_base64>/<time_dec><path>
                location ~
^/get/(?<HASH>[[:xdigit:]]+)/(?<TIME>\d+)(?<PATH>/.+)$ { #
/get/<md5_hex>/<time_dec><path>
                        set $PASS sn983pjcnhupclavsnda; # secret string

                        secure_link $HASH,$TIME+3600;
                        secure_link_md5 $PASS$PATH$TIME;

                        if ($secure_link = "") { # invalid
                                return 403;
                        }

                        if ($secure_link = 0) { # expired
                                return 410;
                        }

                        if ($secure_link = 1) { # correct
                                rewrite ^ /media$PATH last;
                        }
                }

                return 404;

                error_page 403 /forbidden.html;
                error_page 404 /not_found.html;
                error_page 410 =403 /link_expired.html;
        }

I would recommend to specify /media/ as internal location to make it
accessible only for internal requests.
It should be noted that the time value here is in decimal encoding in
opposition to lighttpd's mod_secure_dowload.c hexadecimal encoding, with
the advantege that it can easily be created via 
nginx/src/http/modules/ngx_http_ssi_filter_module.c:

<!--#config timefmt="%s" --><!--# echo var="date_local" -->

With this example it should be possible to support software like
flowplayer (maybe with additional mod_h264_streaming) without any
serverside scripting requirements.

Since i suspect the diff to get corrupted by posting, here is the
original: http://pastebin.com/Ln7bS48n

Maybe someone with more experience in C programming / nginx source can
look over the following patch to
nginx/src/http/modules/ngx_http_secure_link_module.c:


--- nginx.orig/src/http/modules/ngx_http_secure_link_module.c	2010-09-13
14:44:43.000000000 +0200
+++ nginx/src/http/modules/ngx_http_secure_link_module.c	2011-04-10
17:12:55.000000000 +0200
@@ -100,13 +100,15 @@
 ngx_http_secure_link_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    u_char                       *p, *last;
+    u_char                       *p, *q, *last;
     ngx_str_t                     val, hash;
-    time_t                        expires;
+    time_t                        expires, ttl;
     ngx_md5_t                     md5;
     ngx_http_secure_link_ctx_t   *ctx;
     ngx_http_secure_link_conf_t  *conf;
     u_char                        hash_buf[16], md5_buf[16];
+    ngx_int_t                     n;
+    ngx_uint_t                    i;
 
     conf = ngx_http_get_module_loc_conf(r,
ngx_http_secure_link_module);
 
@@ -128,16 +130,33 @@
     last = val.data + val.len;
 
     p = ngx_strlchr(val.data, last, ',');
+
     expires = 0;
+    ttl = 0;
 
-    if (p) {
-        val.len = p++ - val.data;
+    if (p) { // expires
+        val.len = p - val.data;
 
-        expires = ngx_atotm(p, last - p);
-        if (expires <= 0) {
+        if (last - ++p < 0) {
             goto not_found;
         }
 
+        q = ngx_strlchr(p, last, '+');
+
+        if (q) { // ttl
+            if (last - ++q < 0 || (ttl = ngx_atotm(q, last - q)) < 0 ||
--q - p <= 0) {
+                goto not_found;
+            }
+        } else {
+                q = last;
+        }
+
+        if ((expires = ngx_atotm(p, q - p)) <= 0) {
+            goto not_found;
+        }
+
+        expires += ttl;
+
         ctx = ngx_pcalloc(r->pool,
sizeof(ngx_http_secure_link_ctx_t));
         if (ctx == NULL) {
             return NGX_ERROR;
@@ -145,22 +164,26 @@
 
         ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module);
 
-        ctx->expires.len = last - p;
+        ctx->expires.len = q - p;
         ctx->expires.data = p;
     }
 
-    if (val.len > 24) {
-        goto not_found;
-    }
-
     hash.len = 16;
     hash.data = hash_buf;
 
-    if (ngx_decode_base64url(&hash, &val) != NGX_OK) {
-        goto not_found;
-    }
-
-    if (hash.len != 16) {
+    if (val.len == 32) { // hexadecimal md5
+       for (i = 0; i < 16; i++) {
+            n = ngx_hextoi(&val.data[2 * i], 2);
+            if (n == NGX_ERROR) {
+                goto not_found;
+            }
+            hash.data[i] = n;
+        }
+    } else if (val.len <= 24) { // base64 md5
+        if (ngx_decode_base64url(&hash, &val) != NGX_OK || hash.len !=
16)  {
+            goto not_found;
+        }
+    } else {
         goto not_found;
     }

Posted at Nginx Forum: http://forum.nginx.org/read.php?2,173863,190786#msg-190786




More information about the nginx mailing list