Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
uffd
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
rixx
uffd
Commits
95209e6f
Commit
95209e6f
authored
4 years ago
by
Julian
Browse files
Options
Downloads
Patches
Plain Diff
fixed linter errors
parent
44faccf2
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
uffd/mfa/models.py
+22
-19
22 additions, 19 deletions
uffd/mfa/models.py
uffd/mfa/views.py
+13
-12
13 additions, 12 deletions
uffd/mfa/views.py
uffd/template_helper.py
+7
-6
7 additions, 6 deletions
uffd/template_helper.py
with
42 additions
and
37 deletions
uffd/mfa/models.py
+
22
−
19
View file @
95209e6f
import
enum
import
datetime
import
secrets
,
time
,
struct
,
hmac
,
hashlib
,
base64
,
urllib
.
parse
import
secrets
# imports for totp
import
time
import
struct
import
hmac
import
hashlib
import
base64
import
urllib.parse
# imports for recovery codes
import
crypt
from
flask
import
request
,
current_app
from
sqlalchemy
import
Column
,
Integer
,
Enum
,
Boolean
,
String
,
DateTime
,
Text
from
sqlalchemy
import
Column
,
Integer
,
Enum
,
String
,
DateTime
,
Text
from
uffd.database
import
db
from
uffd.user.models
import
User
...
...
@@ -29,15 +37,15 @@ class MFAMethod(db.Model):
def
__init__
(
self
,
user
,
name
=
None
):
self
.
user
=
user
self
.
name
=
name
self
.
created
=
datetime
.
datetime
.
now
()
;
self
.
created
=
datetime
.
datetime
.
now
()
@property
def
user
(
self
):
return
User
.
from_ldap_dn
(
self
.
dn
)
@user.setter
def
user
(
self
,
u
):
self
.
dn
=
u
.
dn
def
user
(
self
,
new_user
):
self
.
dn
=
new_user
.
dn
class
RecoveryCodeMethod
(
MFAMethod
):
code_salt
=
Column
(
'
recovery_salt
'
,
String
(
64
))
...
...
@@ -54,18 +62,14 @@ class RecoveryCodeMethod(MFAMethod):
def
verify
(
self
,
code
):
code
=
code
.
replace
(
'
'
,
''
).
lower
()
if
crypt
.
crypt
(
code
,
self
.
code_hash
)
==
self
.
code_hash
:
return
True
else
:
return
False
return
crypt
.
crypt
(
code
,
self
.
code_hash
)
==
self
.
code_hash
def
_hotp
(
counter
,
key
,
digits
=
6
):
'''
Generates HMAC-based one-time password according to RFC4226
:param counter: Positive integer smaller than 2**64
:param key: Bytes object of arbitrary length (should be at least 160 bits)
:param digits: Length of resulting value (integer between 1 and 9, minimum
of 6 is recommended)
:param digits: Length of resulting value (integer between 1 and 9, minimum of 6 is recommended)
:returns: String object representing human-readable HOTP value
'''
msg
=
struct
.
pack
(
'
>Q
'
,
counter
)
...
...
@@ -89,8 +93,8 @@ class TOTPMethod(MFAMethod):
@property
def
raw_key
(
self
):
s
=
self
.
key
+
'
=
'
*
(
8
-
(
len
(
self
.
key
)
%
8
))
return
base64
.
b32decode
(
s
.
encode
())
tmp
=
self
.
key
+
'
=
'
*
(
8
-
(
len
(
self
.
key
)
%
8
))
return
base64
.
b32decode
(
tmp
.
encode
())
@property
def
issuer
(
self
):
...
...
@@ -135,10 +139,9 @@ class WebauthnMethod(MFAMethod):
@property
def
cred
(
self
):
from
fido2.ctap2
import
AttestedCredentialData
from
fido2.ctap2
import
AttestedCredentialData
#pylint: disable=import-outside-toplevel
return
AttestedCredentialData
(
base64
.
b64decode
(
self
.
_cred
))
@cred.setter
def
cred
(
self
,
d
):
self
.
_cred
=
base64
.
b64encode
(
bytes
(
d
))
def
cred
(
self
,
newcred
):
self
.
_cred
=
base64
.
b64encode
(
bytes
(
newcred
))
This diff is collapsed.
Click to expand it.
uffd/mfa/views.py
+
13
−
12
View file @
95209e6f
from
flask
import
Blueprint
,
render_template
,
session
,
request
,
redirect
,
url_for
,
flash
,
current_app
,
abort
import
urllib.parse
from
warnings
import
warn
import
urllib.parse
from
flask
import
Blueprint
,
render_template
,
session
,
request
,
redirect
,
url_for
,
flash
,
current_app
,
abort
from
uffd.database
import
db
from
uffd.mfa.models
import
MFAMethod
,
TOTPMethod
,
WebauthnMethod
,
RecoveryCodeMethod
from
uffd.session.views
import
get_current_user
,
login_required
,
is_valid_session
from
uffd.session.views
import
get_current_user
,
login_required
from
uffd.ldap
import
uid_to_dn
from
uffd.user.models
import
User
from
uffd.csrf
import
csrf_protect
...
...
@@ -91,7 +92,7 @@ def setup_totp_finish():
@bp.route
(
'
/setup/totp/<int:id>/delete
'
)
@login_required
()
@csrf_protect
(
blueprint
=
bp
)
def
delete_totp
(
id
):
def
delete_totp
(
id
):
#pylint: disable=redefined-builtin
user
=
get_current_user
()
method
=
TOTPMethod
.
query
.
filter_by
(
dn
=
user
.
dn
,
id
=
id
).
first_or_404
()
db
.
session
.
delete
(
method
)
...
...
@@ -106,14 +107,14 @@ try:
from
fido2.server
import
Fido2Server
,
RelyingParty
from
fido2.ctap2
import
AttestationObject
,
AuthenticatorData
from
fido2
import
cbor
webauthn_supported
=
True
except
ImportError
as
e
:
warn
(
'
2FA WebAuthn support disabled because import of the fido2 module failed (%s)
'
%
e
)
webauthn_supported
=
False
WEBAUTHN_SUPPORTED
=
True
except
ImportError
as
e
rr
:
warn
(
'
2FA WebAuthn support disabled because import of the fido2 module failed (%s)
'
%
e
rr
)
WEBAUTHN_SUPPORTED
=
False
bp
.
add_app_template_global
(
webauthn_supported
,
name
=
'
webauthn_supported
'
)
bp
.
add_app_template_global
(
WEBAUTHN_SUPPORTED
,
name
=
'
webauthn_supported
'
)
if
webauthn_supported
:
if
WEBAUTHN_SUPPORTED
:
def
get_webauthn_server
():
return
Fido2Server
(
RelyingParty
(
current_app
.
config
.
get
(
'
MFA_RP_ID
'
,
urllib
.
parse
.
urlsplit
(
request
.
url
).
hostname
),
current_app
.
config
[
'
MFA_RP_NAME
'
]))
...
...
@@ -195,7 +196,7 @@ if webauthn_supported:
@bp.route
(
'
/setup/webauthn/<int:id>/delete
'
)
@login_required
()
@csrf_protect
(
blueprint
=
bp
)
def
delete_webauthn
(
id
):
def
delete_webauthn
(
id
):
#pylint: disable=redefined-builtin
user
=
get_current_user
()
method
=
WebauthnMethod
.
query
.
filter_by
(
dn
=
user
.
dn
,
id
=
id
).
first_or_404
()
db
.
session
.
delete
(
method
)
...
...
@@ -234,7 +235,7 @@ def auth_finish():
if
len
(
recovery_methods
)
<=
1
:
flash
(
'
You have exhausted your recovery codes. Please generate new ones now!
'
)
return
redirect
(
url_for
(
'
mfa.setup
'
))
el
if
len
(
recovery_methods
)
<=
5
:
if
len
(
recovery_methods
)
<=
5
:
flash
(
'
You only have a few recovery codes remaining. Make sure to generate new ones before they run out.
'
)
return
redirect
(
url_for
(
'
mfa.setup
'
))
return
redirect
(
request
.
values
.
get
(
'
ref
'
,
url_for
(
'
index
'
)))
...
...
This diff is collapsed.
Click to expand it.
uffd/template_helper.py
+
7
−
6
View file @
95209e6f
from
flask
import
Markup
import
qrcode
,
qrcode
.
image
.
svg
import
random
import
subprocess
import
base64
from
datetime
import
timedelta
,
datetime
import
io
from
flask
import
Markup
import
qrcode
import
qrcode.image.svg
def
register_template_helper
(
app
):
# debian ships jinja2 without this test...
def
equalto
(
a
,
b
):
return
a
==
b
@app.template_filter
()
def
qrcode_svg
(
content
,
**
attrs
):
def
qrcode_svg
(
content
,
**
attrs
):
#pylint: disable=unused-variable
img
=
qrcode
.
make
(
content
,
image_factory
=
qrcode
.
image
.
svg
.
SvgPathImage
,
border
=
0
)
svg
=
img
.
get_image
()
for
key
,
value
,
in
attrs
.
items
():
...
...
@@ -24,7 +25,7 @@ def register_template_helper(app):
return
Markup
(
buf
.
getvalue
().
decode
())
@app.template_filter
()
def
datauri
(
data
,
mimetype
=
'
text/plain
'
):
def
datauri
(
data
,
mimetype
=
'
text/plain
'
):
#pylint: disable=unused-variable
return
Markup
(
'
data:%s;base64,%s
'
%
(
mimetype
,
base64
.
b64encode
(
data
.
encode
()).
decode
()))
@app.url_defaults
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment