summaryrefslogtreecommitdiff
path: root/doc/secdownload.txt
blob: fb946edac7f7cff0a9ccd6be4ff153d3f7303e33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
===========================
Secure and Fast Downloading
===========================

-----------------------
Module: mod_secdownload
-----------------------

:Author: Jan Kneschke
:Date: $Date: 2004/08/01 07:01:29 $
:Revision: $Revision: 1.1 $

:abstract:
  authenticated file requests and a counter measurement against 
  deep-linking can be achieved easily by using mod_secdownload
  
.. meta::
  :keywords: lighttpd, secure, fast, downloads
  
.. contents:: Table of Contents

Options
=======

::

  secdownload.secret        = <string>
  secdownload.document-root = <string>
  secdownload.uri-prefix    = <string>  (default: /)
  secdownload.timeout       = <short>   (default: 60 seconds)

Description
===========

there are multiple way to handle secured download mechanisms:

1. use the webserver and the internal HTTP-authentication 
2. use the application to authenticate and send the file 
   through the application
     
Both way have limitations:

webserver:

- ``+`` fast download 
- ``+`` no additional system load 
- ``-`` unflexible authentication handling
  
application:

- ``+`` integrated into the overall layout
- ``+`` very flexible permission management
- ``-`` the download occupies a application thread/process
  
A simple way to combine the two way could be:

1. app authenticates user and checks permissions to
   download the file.
2. app redirectes user the file accessable by the webserver
   for further downloading
3. the webserver transfers the file to the user

As the webserver doesn't know anything about the permissions
used in the app the resulting URL would be available to every 
user who knows the URL. 
 
mod_secdownload removes this problem by introducing a way to 
authenticate a URL for a specified time. The application has
to generate a token and a timestamp which are checked by the
webserver before it allows the file to be downloaded by the 
webserver.

The generated URL has to have the format:

<uri-prefix><token>/<timestamp-in-hex><rel-path>

<token> is a MD5 of 

1. a secret string (user supplied)
2. <rel-path> (startes with /)
3. <timestamp-in-hex>


As you can see the token is not bound to the user at all. The 
only limiting factor is the timestamp which is used to 
invalidate the URL after a given timeout (secdownload.timeout).

.. Note::
  Be sure to choose a another secret then used in the examples 
  as this is the only part of the token that is not known to 
  the user.
  
  
  
If the user tries to fake the URL by choosing a random token
status 403 'Forbidden' will be sent out.

If the timeout is reached status 408 'Request Timeout' will be
sent (this not really standard conforming but should do the 
trick).

If token and timeout are valid the <rel-path> is taken and 
appended at the configured (secdownload.document-root) and 
passed to the normal internal file transfer functionality.
This might lead to status 200 or 404.

Example
=======

Application
-----------

Your application has to generate the correct URLs. The following sample
code for PHP should be easily adaptable to any other language: ::

  <?php
  
  $secret = "verysecret";
  $uri_prefix = "/dl/";
  
  # filename
  $f = "/secret-file.txt";
  
  # current timestamp
  $t = time();
  
  $t_hex = sprintf("%08x", $t);
  $m = md5($secret.$f.$t_hex);
  
  # generate link
  printf('<a href="%s%s/%s%s">%s</a>',
         $uri_prefix, $m, $t_hex, $f, $f);
  ?>

Webserver
---------

The server has to configured in the same way. The uri-prefix and secret have
to match: ::

  server.modules = ( ..., "mod_secdownload", ... )
  
  secdownload.secret          = "verysecret"
  secdownload.document-root   = "/home/www/servers/download-area/"
  secdownload.uri-prefix      = "/dl/"
  secdownload.timeout         = 120