rephrase README section about the "download password" feature
[coquelicot.git] / README
1 About “Coquelicot”
2 ==================
3
4 [Coquelicot] is a "one-click" file sharing web application with a specific
5 focus on protecting users' privacy.
6
7 Basic principle: users can upload a file to the server, in return they
8 get a unique URL which can be shared with others in order to download
9 the file.
10
11 Coquelicot aims to protect, to some extent, users and system
12 administrators from disclosure of the files exchanged from passive and
13 not so active attackers.
14
15 [Coquelicot]: https://coquelicot.potager.org/
16
17 Features
18 --------
19
20  * Support for different authentication methods
21
22    In order to prevent random Internet users to eat bandwidth and
23    disk space, Coquelicot limits upload to authenticated users.
24    It currently ships with two authentication mechanisms:
25
26     - "simplepass": users will need to provide a global, pre-shared,
27       password;
28     - "imap": users will need to provide a login and a password,
29       those credentials will be used to authenticate against an existing
30       IMAP server.
31
32    It is possible to integrate more authentication mechanisms by
33    implementing a single method, some Javascript, and a template partial
34    to render the common fields. For more information have a look at the
35    notes below.
36
37  * Mandatory expiration
38
39    When uploading, a time limit has to be specified. The file will be
40    unavailable once this limit has been reached.
41
42    During a configurable period of time, trying to download the file
43    will return a page saying "too late" instead of "not found".
44
45  * Support for one-time download
46
47    An user might want to allow exactly _one_ download of a file, to more
48    closely replace an email attachment. The file will be removed after
49    the first complete download and concurrent downloads are prevented.
50
51  * Upload progress bar
52
53    Users having javascript enabled will see a nice progress bar during
54    the file upload.
55
56  * Downgrade nicely
57
58    The application works fine without javascript or CSS.
59
60  * Download URL are hand-writing compatible
61
62    URLs generated to download files uses the Base32 character set. This
63    set is specifically designed to overcome misread of 'l', '1', '0' and
64    'O' characters. Coquelicot will automatically convert case and
65    ambiguous characters to facilitate URL exchanges through
66    hand-writing.
67
68  * Files are stored encrypted on the server
69
70    While being uploaded, files are written to the disk using symmetric
71    encryption. The encryption key is _not_ stored directly by
72    Coquelicot. It is either generated randomly and given as part of the
73    download URL, or specified by the uploader.
74
75  * Download can be protected by a password
76
77    When uploading, a password can be specified which will then be used
78    to encrypt the file. For subsequent downloads, the password
79    must be entered through in a POST'ed form. This prevents the password
80    from appearing in most server logs.
81
82  * Files are stored with a random name
83
84    To prevent disclosure of the shared file name, it is stored encrypted
85    together with the file content. On the server, this encrypted file is
86    stored with a random name.
87
88  * Download URLs do not reflect stored file names
89
90    The random names given in download URLs do not map directly to file
91    names on the server. This prevent server logs from giving a direct
92    mapping to the shared files.
93
94  * File content is zero'ed before removal
95
96    When a file has expired, it is removed from the server. In order
97    to make it harder to retrieve its content through filesystem
98    analysis, it is filled with zeros first.
99
100 Installation
101 ------------
102
103 Coquelicot is written in Ruby using the Sinatra web framework. Due to
104 reasons detailed below, it needs to be run with the Rainbows! web
105 server. The later should probably be made accessible through a reverse
106 proxy.
107
108 ### Initial setup
109
110 Coquelicot uses Bundler to manage its dependency. To install Bundler on
111 Debian, please issue:
112
113     # apt-get install rubygems
114     $ gem install bundler
115
116 Once Bundler is available, please issue:
117
118     $ bundle install --deployment --binstubs
119
120 Then, to start Coquelicot use:
121
122     $ bin/coquelicot start
123
124 Coquelicot is intended to be run on a fully encrypted system and
125 accessible only through HTTPS. To configure Apache as a reverse proxy,
126 you will need to add the following directives:
127
128     ProxyPass / http://127.0.0.1:51161/
129     SetEnv proxy-sendchunks 1
130     RequestHeader set X-Forwarded-SSL "on"
131
132 Coquelicot has been written to use Rainbows! as its webserver. You can
133 also run Coquelicot with mod_passenger, Mongrel, Thin or any Rack
134 compatible webserver, but please read below about buffered input.
135
136 ### Configuration
137
138 By default Coquelicot is configured to authenticate with the
139 "simplepass" mechanism and some other reasonable defaults.
140
141 It is possible to overwrite these settings from a configuration file
142 named `settings.yml` that will be used if it is present in the `conf`
143 directory of the application.
144
145 All available settings with their default values are documented in
146 `conf/settings-default.yml`.
147
148 Further settings example:
149
150  * `conf/settings-simplepass.yml`: shows how to change the default
151    password for the "simplepass" mechanism.
152
153  * `conf/settings-imap.yml`: necessary configuration for the "imap"
154    authentication mechanism.
155
156 You can copy one of these examples to `conf/settings.yml` and adjust
157 them according to your environment.
158
159 A different location for the configuration file can be specified using
160 the `-c` option when running `bin/coquelicot`.
161
162 ### Garbage collection
163
164 To cleanup files automatically when they expired, coquelicot comes with
165 a cleanup script, that does the garbage collection for you. The easiest
166 way is to set up a cron job that will run every 5 minutes (or so):
167
168     bin/coquelicot gc
169
170 ### Migrate from Jyraphe
171
172 [Jyraphe] is another free software web file sharing application.
173 Coquelicot provides a migration script to import Jyraphe 0.5
174 repositories as `bin/coquelicot migrate-jyraphe`:
175
176     Usage: coquelicot [options] migrate-jyraphe \ 
177                       [command options] JYRAPHE_VAR > REWRITE_RULES
178
179     Options:
180         -c, --config FILE            read settings from FILE
181
182     Command options:
183         -p, --rewrite-prefix PREFIX  prefix URL in rewrite rules
184
185 The last argument must be a path to the `var` directory of the Jyraphe
186 installation. After migrating the files to Coquelicot, directives for
187 Apache mod_rewrite will be printed on stdout which ought to be
188 redirected to a file. The `-p` option can be used to add a specific
189 paths in the redirected URLs.
190
191 [Jyraphe]: http://home.gna.org/jyraphe/
192
193 Test, development and extensions
194 --------------------------------
195
196 Coquelicot is written in Ruby and should be quite easy to improve for
197 anyone a little bit familiar with the Sinatra web framework. It is
198 mostly written using Behaviour Driven Development, making the test suite
199 a fine net to hack in confidence. So please go ahead!
200
201 ### Setup a work environment
202
203 As Coquelicot uses Bundle, the first step to work on Coquelicot
204 is installing the proper dependencies by issuing:
205
206     bundle install
207
208 ### Basic operations
209
210 Coquelicot test suite is written using RSpec. Running the test suite is
211 just a matter of typing:
212
213     bundle exec rspec
214
215 Running a test server can be done with:
216
217     bundle exec coquelicot start --no-daemon
218
219 To update the translation source files, use:
220
221     bundle exec rake updatepo
222
223 This will update `po/coquelicot.pot` and merge the new strings in the various
224 `po/*/coquelicot.po` files.
225
226 ### Authentication mechanisms
227
228 The authentication part of Coquelicot has been made modular. Adding a
229 new authentication mechanism should be fairly straightforward.
230
231 New authentication mechanism needs to provide the following 3 files,
232 with the following responsabilities:
233
234  * `lib/coquelicot/auth/<METHOD>.rb`:
235
236    A class implementing the actual authentication. This class must
237    implement an `authenticate` method. It will receive the form fields
238    as usual (params). This method should either return true if upload
239    should be allowed.
240
241  * `public/javascripts/coquelicot.auth.<METHOD>.js:`
242
243     This file should define 'authentication' as an object with the
244     following methods:
245
246     - `getData()`: returns an object of all the necessary data
247       to authenticate on the app side. Keys should have the same name
248       as the input fields used to authenticate without Javascript.
249     - `focus()`: set the focus on the first authentication form field.
250     - (optional) `handleSuccess()`: arbitrary action upon successful
251       authentication. This is called after the livebox is closed.
252     - (optional) `handleReject()`: arbitrary action when access
253       get rejected. One can reset authentication fields after a failed
254       authentication.
255     - (optional) `handleFailure()`: arbitrary action when there was
256       a problem in the authentication procedure.
257
258  * `views/auth/<METHOD>.haml`:
259
260    Render the necessary form fields that will be used for
261    authentication.
262
263    The authentication method can be set in the application settings
264    including mandatory options for this method.
265
266 ### Watch for buffered inputs!
267
268 Coquelicot is written in Ruby using Sinatra. Sinatra is based on the
269 Rack webserver interface. Rack specification mandates that applications
270 must be able to seek and rewind freely in the request content.
271
272 Request data are always received as a stream through the network. So in
273 order to comply with the specification, webservers implementing Rack will
274 either buffer the input in memory (Webrick) or in a temporary file
275 (Thin, Passenger or Mongrel).
276
277 On top of that, when parsing `multipart/form-data` POST content,
278 `Rack::Request` (used by Sinatra) will create a new temporary file for
279 each files in the POST request.
280
281 For the specific needs of Coquelicot, those behaviours will prevent
282 users from uploading large files (if `/tmp` is in memory) or will be a
283 breach of privacy, as a clear text version will be written to disk.
284
285 To overcome these limitations, Coquelicot first uses a specific feature
286 of the Rainbows! webserver of streaming its input directly to
287 applications, and second bypass `Rack::Request` to directly handle
288 POST content. Usage of any other Rack webserver is strongly discouraged
289 and should be restricted to development and testing.
290
291 ### Implementation details
292
293 Common application code lies in `Coquelicot::Application`. Except for
294 one specific (and important) type of requests, namely `POST /update`.
295 These requests are handled directly at bare Rack level by
296 `Coquelicot::Rack::Upload`.
297
298 This allows to work directly with POST data as the browser is sending
299 them, so we can directly stream the uploaded file to our encrypted
300 on-disk containers.
301
302 The POST data must be in a very specific order, as we need to handle
303 authentication, and various options prior to start recording the file
304 content. Thanks to the W3C, the [HTML specification] states that parts
305 of the POST data must be delivered in the same order the controls
306 appears in the `<form/>` container.
307
308 `Coquelicot::Rack::Multipart` expose a simple DSL to parse the fields as
309 they are delivered. The later is used by `Coquelicot::Rack::Upload` to
310 perform its logic pretty nicely.
311
312 [HTML specification]: http://www.w3.org/TR/html4/interact/forms.html
313
314 Future
315 ------
316
317  * More flexible expiration
318
319    It might be interesting to also offer a calendar for specifying
320    an exact date after which the file will be unavailable.
321
322  * Hide file size (padding)
323
324    There is currently a real close mapping from original file size to
325    stored file size. Original file size will also be recorded in server
326    logs. Padding could be used to improve this situation.
327
328  * Make a usable Gem
329
330    Most Ruby stuff is installed using Gem, so Coquelicot should also be
331    installable that way. What is mostly missing is an easy way to create
332    a default configuration and directories to hold uploaded files and
333    temp. data.
334
335  * Package for Debian
336
337    A Debian package would be nice to spread Coquelicot setups.
338
339 Storage details
340 ---------------
341
342 Files are stored in the directory specified by the 'depot_path' setting.
343 One file in Coquelicot is actually stored in two files: one for metadata and
344 one for the file content.
345
346 ### Metadata file
347
348 The format is the following:
349
350     --- 
351     Coquelicot: "2.0"
352     Salt: <8 bytes stored as Base64>
353     Expire-at: <expiration time in seconds since epoch>
354     --- 
355     <encrypted metadata>
356
357 Encryption is done using OpenSSL. Cipher is AES-256-CBC with key and IV
358 created using the `pbkdf2_hmac_sha1()` implementation of PKCS5. The later
359 is fed using the former *Salt* and the given passphrase, using 2000
360 iterations.
361
362 Once decrypted, the metadata have the following format:
363
364     --- 
365     Created-at: <upload time in seconds since epoch>
366     Filename: "<original file name>"
367     Content-Type: "<MIME type>"
368     Length: <content length is bytes>
369     One-time-only: <true|false>
370
371 Headers must be parseable using the YAML standard.
372
373 ### Content file
374
375 The content file contains the stored file in encrypted form. Encryption is done
376 with the same algorithm and keys as the encrypted metadata (see above).
377
378 The file name of the content file is the same as the one for metada, with an
379 added suffix of '.content'. For example, if the metadata file name is
380 `mqeb4pfcru2ymq3e6se7`, the associated content file will be
381 `mqeb4pfcru2ymq3e6se7.content`.
382
383 ### Expired files
384
385 Both the content file and the metadata file are truncated to zero length when
386 they are "expired".
387
388 ### URL mapping
389
390 In order to map download URLs to file name, a simple text file ".links"
391 is used. It contains a line for each file in the form:
392
393     <URL name> <metadata file name>
394
395 ### Changes history
396
397   version 2.0
398   :    Current version described above.
399
400   version 1.0
401   :    File content is in the same file as the metadata. Content is put in the
402        after the metadata and an extra "--- \n".
403
404 Authors
405 -------
406
407     Coquelicot © 2010-2013 potager.org <jardiniers@potager.org>
408                © 2011 mh / immerda.ch  <mh+coquelicot@immerda.ch>
409
410 Coquelicot is distributed under the [GNU Affero General Public License]
411 version 3 or (at your option) any later version.
412
413 Background image (`public/images/background.jpg`) derived from:  
414 [“coquelicot” picture] © 2008 Jean-Louis Zimmermann  
415 Licensed under [Creative Commons Attributions 2.0 Generic]  
416
417 [“coquelicot” picture]: https://secure.flickr.com/photos/jeanlouis_zimmermann/2478019744/
418 [GNU Affero General Public License]: http://www.gnu.org/licenses/agpl.txt
419 [Creative Commons Attributions 2.0 Generic]: https://creativecommons.org/licenses/by/2.0/deed