Commit | Line | Data |
---|---|---|
5907154a E |
1 | # GNU MediaGoblin -- federated, autonomous media hosting |
2 | # Copyright (C) 2013 MediaGoblin contributors. See AUTHORS. | |
3 | # | |
4 | # This program is free software: you can redistribute it and/or modify | |
5 | # it under the terms of the GNU Affero General Public License as published by | |
6 | # the Free Software Foundation, either version 3 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU Affero General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
09102e07 BS |
17 | import errno |
18 | import itsdangerous | |
5907154a | 19 | import logging |
09102e07 | 20 | import os.path |
5907154a | 21 | import random |
09102e07 | 22 | import tempfile |
5907154a E |
23 | from mediagoblin import mg_globals |
24 | ||
25 | _log = logging.getLogger(__name__) | |
26 | ||
27 | ||
28 | # Use the system (hardware-based) random number generator if it exists. | |
29 | # -- this optimization is lifted from Django | |
09102e07 | 30 | try: |
5907154a | 31 | getrandbits = random.SystemRandom().getrandbits |
09102e07 | 32 | except AttributeError: |
5907154a E |
33 | getrandbits = random.getrandbits |
34 | ||
35 | ||
36 | __itsda_secret = None | |
37 | ||
38 | ||
09102e07 | 39 | def load_key(filename): |
5907154a | 40 | global __itsda_secret |
09102e07 BS |
41 | key_file = open(filename) |
42 | try: | |
43 | __itsda_secret = key_file.read() | |
44 | finally: | |
45 | key_file.close() | |
5907154a | 46 | |
11780855 | 47 | |
09102e07 BS |
48 | def create_key(key_dir, key_filepath): |
49 | global __itsda_secret | |
50 | old_umask = os.umask(077) | |
51 | key_file = None | |
52 | try: | |
53 | if not os.path.isdir(key_dir): | |
54 | os.makedirs(key_dir) | |
11780855 | 55 | _log.info("Created %s", key_dir) |
09102e07 BS |
56 | key = str(getrandbits(192)) |
57 | key_file = tempfile.NamedTemporaryFile(dir=key_dir, suffix='.bin', | |
58 | delete=False) | |
59 | key_file.write(key) | |
60 | key_file.flush() | |
61 | os.rename(key_file.name, key_filepath) | |
62 | key_file.close() | |
63 | finally: | |
64 | os.umask(old_umask) | |
65 | if (key_file is not None) and (not key_file.closed): | |
66 | key_file.close() | |
67 | os.unlink(key_file.name) | |
68 | __itsda_secret = key | |
69 | _log.info("Saved new key for It's Dangerous") | |
70 | ||
11780855 | 71 | |
09102e07 BS |
72 | def setup_crypto(): |
73 | global __itsda_secret | |
74 | key_dir = mg_globals.app_config["crypto_path"] | |
75 | key_filepath = os.path.join(key_dir, 'itsdangeroussecret.bin') | |
76 | try: | |
77 | load_key(key_filepath) | |
78 | except IOError, error: | |
79 | if error.errno != errno.ENOENT: | |
80 | raise | |
81 | create_key(key_dir, key_filepath) | |
5907154a | 82 | |
11780855 | 83 | |
5907154a | 84 | def get_timed_signer_url(namespace): |
5a8aae3a E |
85 | """ |
86 | This gives a basic signing/verifying object. | |
87 | ||
88 | The namespace makes sure signed tokens can't be used in | |
89 | a different area. Like using a forgot-password-token as | |
90 | a session cookie. | |
91 | ||
92 | Basic usage: | |
93 | ||
94 | .. code-block:: python | |
95 | ||
96 | _signer = None | |
97 | TOKEN_VALID_DAYS = 10 | |
98 | def setup(): | |
99 | global _signer | |
100 | _signer = get_timed_signer_url("session cookie") | |
101 | def create_token(obj): | |
102 | return _signer.dumps(obj) | |
103 | def parse_token(token): | |
104 | # This might raise an exception in case | |
105 | # of an invalid token, or an expired token. | |
106 | return _signer.loads(token, max_age=TOKEN_VALID_DAYS*24*3600) | |
107 | ||
108 | For more details see | |
109 | http://pythonhosted.org/itsdangerous/#itsdangerous.URLSafeTimedSerializer | |
110 | """ | |
5907154a E |
111 | assert __itsda_secret is not None |
112 | return itsdangerous.URLSafeTimedSerializer(__itsda_secret, | |
113 | salt=namespace) |