docs: Document video resolution config.
[mediagoblin.git] / mediagoblin / plugins / basic_auth / tools.py
CommitLineData
5b6923ab
RE
1# GNU MediaGoblin -- federated, autonomous media hosting
2# Copyright (C) 2011, 2012 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/>.
16import bcrypt
14efa7bd 17import random
5b6923ab 18
e49b7e02
BP
19import six
20
33b5cebe
RE
21from mediagoblin import mg_globals
22from mediagoblin.tools.crypto import get_timed_signer_url
23from mediagoblin.tools.mail import send_email
24from mediagoblin.tools.template import render_template
25
5b6923ab
RE
26
27def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None):
28 """
29 Check to see if this password matches.
30
31 Args:
32 - raw_pass: user submitted password to check for authenticity.
33 - stored_hash: The hash of the raw password (and possibly extra
34 salt) to check against
35 - extra_salt: (optional) If this password is with stored with a
36 non-database extra salt (probably in the config file) for extra
37 security, factor this into the check.
38
39 Returns:
40 True or False depending on success.
41 """
42 if extra_salt:
43 raw_pass = u"%s:%s" % (extra_salt, raw_pass)
44
45 hashed_pass = bcrypt.hashpw(raw_pass.encode('utf-8'), stored_hash)
46
47 # Reduce risk of timing attacks by hashing again with a random
48 # number (thx to zooko on this advice, which I hopefully
49 # incorporated right.)
50 #
51 # See also:
52 rand_salt = bcrypt.gensalt(5)
53 randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt)
54 randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
55
56 return randplus_stored_hash == randplus_hashed_pass
57
58
59def bcrypt_gen_password_hash(raw_pass, extra_salt=None):
60 """
61 Generate a salt for this new password.
62
63 Args:
64 - raw_pass: user submitted password
65 - extra_salt: (optional) If this password is with stored with a
66 non-database extra salt
67 """
68 if extra_salt:
69 raw_pass = u"%s:%s" % (extra_salt, raw_pass)
70
e49b7e02 71 return six.text_type(
5b6923ab
RE
72 bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt()))
73
74
14efa7bd
RE
75def fake_login_attempt():
76 """
77 Pretend we're trying to login.
78
79 Nothing actually happens here, we're just trying to take up some
80 time, approximately the same amount of time as
81 bcrypt_check_password, so as to avoid figuring out what users are
82 on the system by intentionally faking logins a bunch of times.
83 """
84 rand_salt = bcrypt.gensalt(5)
85
86 hashed_pass = bcrypt.hashpw(str(random.random()), rand_salt)
87
88 randplus_stored_hash = bcrypt.hashpw(str(random.random()), rand_salt)
89 randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
90
91 randplus_stored_hash == randplus_hashed_pass
aeae6cc2
RE
92
93
94EMAIL_FP_VERIFICATION_TEMPLATE = (
95 u"{uri}?"
96 u"token={fp_verification_key}")
97
98
99def send_fp_verification_email(user, request):
100 """
101 Send the verification email to users to change their password.
102
103 Args:
104 - user: a user object
105 - request: the request
106 """
107 fp_verification_key = get_timed_signer_url('mail_verification_token') \
108 .dumps(user.id)
109
110 rendered_email = render_template(
33b5cebe 111 request, 'mediagoblin/plugins/basic_auth/fp_verification_email.txt',
aeae6cc2
RE
112 {'username': user.username,
113 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format(
33b5cebe 114 uri=request.urlgen('mediagoblin.plugins.basic_auth.verify_forgot_password',
aeae6cc2
RE
115 qualified=True),
116 fp_verification_key=fp_verification_key)})
117
118 # TODO: There is no error handling in place
119 send_email(
120 mg_globals.app_config['email_sender_address'],
121 [user.email],
122 'GNU MediaGoblin - Change forgotten password!',
123 rendered_email)