implement file format 2.0
[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 Features
16 --------
17
18  * Support for different authentication methods
19
20    In order to prevent random Internet users to eat bandwidth and
21    disk space, Coquelicot limits upload to authenticated users.
22    It currently ships with two authentication mechanisms:
23
24     - "simplepass": users will need to provide a global, pre-shared,
25       password;
26     - "imap": users will need to provide a login and a password,
27       those credentials will be used to authenticate against an existing
28       IMAP server.
29
30    It is possible to integrate more authentication mechanisms by
31    implementing a single method, some Javascript, and a template partial
32    to render the common fields. For more information have a look at the
33    notes below.
34
35  * Mandatory expiration
36
37    When uploading, a time limit has to be specified. The file will be
38    unavailable once this limit has been reached.
39
40    During a configurable period of time, trying to download the file
41    will return a page saying "too late" instead of "not found".
42
43  * Support for one-time download
44
45    An user might want to allow exactly _one_ download of a file, to more
46    closely replace an email attachment. The file will be removed after
47    the first complete download and concurrent downloads are prevented.
48
49  * Upload progress bar
50
51    If the web server tracks upload progress, users having javascript
52    enabled will see a nice progress bar during the file upload.
53
54  * Downgrade nicely
55
56    The application works fine without javascript or CSS.
57
58  * Download URL are hand-writing compatible
59
60    URLs generated to download files uses the Base32 character set. This
61    set is specifically designed to overcome misread of 'l', '1', '0' and
62    'O' characters. Coquelicot will automatically convert case and
63    ambiguous characters to facilitate URL exchanges through
64    hand-writing.
65
66  * Files are stored encrypted on the server
67
68    While being uploaded, files are written to the disk using symmetric
69    encryption. The encryption key is _not_ stored directly by
70    Coquelicot. It is either generated randomly and given as part of the
71    download URL, or specified by the uploader.
72
73  * Download can be protected by a password
74
75    When uploading, a password can be specified which will be used as
76    the encryption key. In order to download the file, the password
77    must be entered through in a POST'ed form, preventing the password
78    from appearing in the server logs.
79
80  * Files are stored with a random name
81
82    To prevent disclosure of the shared file name, it is stored encrypted
83    together with the file content. On the server, this encrypted file is
84    stored with a random name.
85
86  * Download URLs do not reflect stored file names
87
88    The random names given in download URLs do not map directly to file
89    names on the server. This prevent server logs from giving a direct
90    mapping to the shared files.
91
92  * File content is zero'ed before removal
93
94    When a file has expired, it is removed from the server. In order
95    to make it harder to retrieve its content through filesystem
96    analysis, it is filled with zeros first.
97
98 Installation
99 ------------
100
101 Coquelicot is written in Ruby using the Sinatra web framework. Due to
102 reasons detailed below, it needs to be run with the Rainbows! web
103 server. The later should probably be made accessible through a reverse
104 proxy.
105
106 ### Initial setup
107
108 Coquelicot uses Bundler to manage its dependency. To install Bundler on
109 Debian, please issue:
110
111     # apt-get install rubygems
112     $ gem install bundler
113
114 Once Bundler is available, please issue:
115
116     $ bundle install --deployment --binstubs
117
118 Then, to start Coquelicot use:
119
120     $ bin/rackup config.ru
121
122 Coquelicot is intended to be run on a fully encrypted system and
123 accessible only through HTTPS. To configure Apache as a reverse proxy,
124 you will need to add the following directives:
125
126     ProxyPass / http://127.0.0.1:9292/
127     SetEnv proxy-sendchunks 1
128     RequestHeader set X-Forwarded-SSL "on"
129
130 You can also run Coquelicot with mod_passenger, Mongrel, Thin or any
131 Rack compatible webserver.
132
133 ### Configuration
134
135 By default Coquelicot is configured to authenticate with the
136 "simplepass" mechanism and some other reasonable defaults.
137
138 It is possible to overwrite these settings from a configuration file
139 named `settings.yml` that will be used if it is present in the `conf`
140 directory of the application.
141
142 All available settings with their default values are documented in
143 `conf/settings-default.yml`.
144
145 Further settings example:
146
147  * `conf/settings-simplepass.yml`: shows how to change the default
148    password for the "simplepass" mechanism.
149
150  * `conf/settings-imap.yml`: necessary configuration for the "imap"
151    authentication mechanism.
152
153 You can copy one of these examples to `conf/settings.yml` and adjust
154 them according to your environment.
155
156 ### Garbage collection
157
158 To cleanup files automatically when they expired, coquelicot comes with
159 a cleanup script, that does the garbage collection for you. The easiest
160 way is to add `ext/coquelicot_gc.rb` as a cron job that runs every 5
161 minutes (or so).
162
163 ### Migrate from Jyraphe
164
165 [Jyraphe] is another free software web file sharing application.
166 Coquelicot provides a migration script to import Jyraphe 0.5
167 repositories in `tools/migrate_jyraphe.rb`.
168
169 [Jyraphe]: http://home.gna.org/jyraphe/
170
171 Test, development and extensions
172 --------------------------------
173
174 Coquelicot is written in Ruby and should be quite easy to improve for
175 anyone a little bit familiar with the Sinatra web framework. It is
176 mostly written using Behaviour Driven Development, making the test suite
177 a fine net to hack in confidence. So please go ahead!
178
179 ### Setup a work environment
180
181 As Coquelicot uses Bundle, the first step to work on Coquelicot
182 is installing the proper dependencies by issuing:
183
184     bundle install
185
186 ### Basic operations
187
188 Coquelicot test suite is written using RSpec. Running the test suite is
189 just a matter of typing:
190
191     bundle exec rspec
192
193 Running a test server can be done with:
194
195     bundle exec rackup config-development.ru
196
197 To update the translation source files, use:
198
199     bundle exec rake updatepo
200
201 This will update `po/coquelicot.pot` and merge the new strings in the various
202 `po/*/coquelicot.po` files.
203
204 ### Authentication mechanisms
205
206 The authentication part of Coquelicot has been made modular. Adding a
207 new authentication mechanism should be fairly straightforward.
208
209 New authentication mechanism needs to provide the following 3 files,
210 with the following responsabilities:
211
212  * `lib/coquelicot/auth/<METHOD>.rb`:
213
214    A class implementing the actual authentication. This class must
215    implement an `authenticate` method. It will receive the form fields
216    as usual (params). This method should either return true if upload
217    should be allowed.
218
219  * `public/javascripts/coquelicot.auth.<METHOD>.js:`
220
221     This file should define 'authentication' as an object with the
222     following methods:
223
224     - `getData()`: returns an object of all the necessary data
225       to authenticate on the app side. Keys should have the same name
226       as the input fields used to authenticate without Javascript.
227     - `focus()`: set the focus on the first authentication form field.
228     - (optional) `handleSuccess()`: arbitrary action upon successful
229       authentication. This is called after the livebox is closed.
230     - (optional) `handleReject()`: arbitrary action when access
231       get rejected. One can reset authentication fields after a failed
232       authentication.
233     - (optional) `handleFailure()`: arbitrary action when there was
234       a problem in the authentication procedure.
235
236  * `views/auth/<METHOD>.haml`:
237
238    Render the necessary form fields that will be used for
239    authentication.
240
241    The authentication method can be set in the application settings
242    including mandatory options for this method.
243
244 Future
245 ------
246
247  * More flexible expiration
248
249    It might be interesting to also offer a calendar for specifying
250    an exact date after which the file will be unavailable.
251
252  * Hide file size (padding)
253
254    There is currently a real close mapping from original file size to
255    stored file size. Original file size will also be recorded in server
256    logs. Padding could be used to improve this situation.
257
258  * Make a Gem
259
260    Most Ruby stuff is installed using Gem, so Coquelicot should be one.
261
262  * Package for Debian
263
264    A Debian package would be nice to spread Coquelicot setups.
265
266  * Describe more setups
267
268    Describe how to setup Coquelicot with mod_passenger, Mongrel and
269    other webservers.
270
271 Storage details
272 ---------------
273
274 Files are stored in the directory specified by the 'depot_path' setting.
275 One file in Coquelicot is actually stored in two files: one for metadata and
276 one for the file content.
277
278 ### Metadata file
279
280 The format is the following:
281
282     --- 
283     Coquelicot: "2.0"
284     Salt: <8 bytes stored as Base64>
285     Expire-at: <expiration time in seconds since epoch>
286     --- 
287     <encrypted metadata>
288
289 Encryption is done using OpenSSL. Cipher is AES-256-CBC with key and IV
290 created using the `pbkdf2_hmac_sha1()` implementation of PKCS5. The later
291 is fed using the former *Salt* and the given passphrase, using 2000
292 iterations.
293
294 Once decrypted, the metadata have the following format:
295
296     --- 
297     Created-at: <upload time in seconds since epoch>
298     Filename: "<original file name>"
299     Content-Type: "<MIME type>"
300     Length: <content length is bytes>
301     One-time-only: <true|false>
302
303 Headers must be parseable using the YAML standard.
304
305 ### Content file
306
307 The content file contains the stored file in encrypted form. Encryption is done
308 with the same algorithm and keys as the encrypted metadata (see above).
309
310 The file name of the content file is the same as the one for metada, with an
311 added suffix of '.content'. For example, if the metadata file name is
312 `mqeb4pfcru2ymq3e6se7`, the associated content file will be
313 `mqeb4pfcru2ymq3e6se7.content`.
314
315 ### Expired files
316
317 Both the content file and the metadata file are truncated to zero length when
318 they are "expired".
319
320 ### URL mapping
321
322 In order to map download URLs to file name, a simple text file ".links"
323 is used. It contains a line for each file in the form:
324
325     <URL name> <metadata file name>
326
327 ### Changes history
328
329   version 2.0
330   :    Current version described above.
331
332   version 1.0
333   :    File content is in the same file as the metadata. Content is put in the
334        after the metadata and an extra "--- \n".
335
336 Authors
337 -------
338
339     Coquelicot © 2010-2012 potager.org <jardiniers@potager.org>
340                © 2011 mh / immerda.ch  <mh+coquelicot@immerda.ch>
341
342 Coquelicot is distributed under the [GNU Affero General Public License]
343 version 3 or (at your option) any later version.
344
345 Background image (`public/images/background.jpg`) derived from:  
346 [“coquelicot”] © 2008 Jean-Louis Zimmermann  
347 Licensed under [Creative Commons Attributions 2.0 Generic]  
348
349 [“coquelicot”]: https://secure.flickr.com/photos/jeanlouis_zimmermann/2478019744/
350 [GNU Affero General Public License]: http://www.gnu.org/licenses/agpl.txt
351 [Creative Commons Attributions 2.0 Generic]: https://creativecommons.org/licenses/by/2.0/deed