From fd043890746fd13f8c736470f95662c8509c29c0 Mon Sep 17 00:00:00 2001 From: Julian Rother <julianr@fsmpi.rwth-aachen.de> Date: Sat, 15 May 2021 21:46:01 +0200 Subject: [PATCH] Limited invite validity period, extended token entropy, other small fixes --- uffd/default_config.cfg | 2 ++ uffd/invite/models.py | 2 +- uffd/invite/templates/invite/new.html | 8 ++++---- uffd/invite/views.py | 5 ++++- uffd/signup/models.py | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/uffd/default_config.cfg b/uffd/default_config.cfg index debf69eb..55962602 100644 --- a/uffd/default_config.cfg +++ b/uffd/default_config.cfg @@ -69,6 +69,8 @@ ENABLE_PASSWORDRESET=True # Do not enable this on a public service! There is no spam protection implemented at the moment. SELF_SIGNUP=False +INVITE_MAX_VALID_DAYS=21 + LOGINNAME_BLACKLIST=['^admin$', '^root$'] #MFA_ICON_URL = 'https://example.com/logo.png' diff --git a/uffd/invite/models.py b/uffd/invite/models.py index eb441fb9..47826cd0 100644 --- a/uffd/invite/models.py +++ b/uffd/invite/models.py @@ -19,7 +19,7 @@ invite_roles = db.Table('invite_roles', class Invite(db.Model): __tablename__ = 'invite' id = Column(Integer(), primary_key=True, autoincrement=True) - token = Column(String(128), unique=True, nullable=False, default=lambda: secrets.token_urlsafe(32)) + token = Column(String(128), unique=True, nullable=False, default=lambda: secrets.token_urlsafe(48)) created = Column(DateTime, default=datetime.datetime.now, nullable=False) creator_dn = Column(String(128), nullable=True) creator = DBRelationship('creator_dn', User) diff --git a/uffd/invite/templates/invite/new.html b/uffd/invite/templates/invite/new.html index d1f913ac..a27d50d6 100644 --- a/uffd/invite/templates/invite/new.html +++ b/uffd/invite/templates/invite/new.html @@ -10,8 +10,9 @@ </select> </div> <div class="form-group"> - <label for="valid-until">Expires After</label> + <label for="valid-until">Valid Until</label> <input class="form-control" type="datetime-local" id="valid-until" name="valid-until" value="{{ (datetime.now() + timedelta(hours=36)).replace(hour=23, minute=59, second=59, microsecond=0).isoformat(timespec='minutes') }}"> + <small class="text-muted">Must be within the next {{ config['INVITE_MAX_VALID_DAYS'] }} days</small> </div> {% if allow_signup %} <div class="form-group"> @@ -24,6 +25,7 @@ {% else %} <input type="hidden" name="allow-signup" value="0"> {% endif %} + {% if roles %} <div class="form-group"> <label for="valid-until">Granted Roles</label> <table class="table table-sm"> @@ -46,12 +48,10 @@ <td>{{ role.description }}</td> </tr> {% endfor %} - {% if not roles %} - <tr><td colspan="3" class="bg-light text-muted text-center">There are no (non-base) roles yet</td></tr> - {% endif %} </tbody> </table> </div> + {% endif %} <button type="submit" class="btn btn-primary"><i class="fa fa-save" aria-hidden="true"></i> Create Link</button> <a href="{{ url_for("invite.index") }}" class="btn btn-secondary">Cancel</a> </form> diff --git a/uffd/invite/views.py b/uffd/invite/views.py index d7a9eedc..bfe9af36 100644 --- a/uffd/invite/views.py +++ b/uffd/invite/views.py @@ -76,10 +76,13 @@ def new_submit(): invite = Invite(creator=user, single_use=(request.values['single-use'] == '1'), valid_until=datetime.datetime.fromisoformat(request.values['valid-until']), - allow_signup=(request.values['allow-signup'] == '1')) + allow_signup=(request.values.get('allow-signup', '0') == '1')) for key, value in request.values.items(): if key.startswith('role-') and value == '1': invite.roles.append(Role.query.get(key[5:])) + if invite.valid_until > datetime.datetime.now() + datetime.timedelta(days=current_app.config['INVITE_MAX_VALID_DAYS']): + flash('The "Expires After" date is too far in the future') + return redirect(url_for('invite.new')) if not invite.permitted: flash('You are not allowed to create invite links with these permissions') return redirect(url_for('invite.new')) diff --git a/uffd/signup/models.py b/uffd/signup/models.py index a2f4b721..2fabc8e5 100644 --- a/uffd/signup/models.py +++ b/uffd/signup/models.py @@ -28,7 +28,7 @@ class Signup(db.Model): As long as they are not completed, signup requests have no effect each other or different parts of the application.''' __tablename__ = 'signup' - token = Column(String(128), primary_key=True, default=lambda: secrets.token_urlsafe(32)) + token = Column(String(128), primary_key=True, default=lambda: secrets.token_urlsafe(48)) created = Column(DateTime, default=datetime.datetime.now, nullable=False) loginname = Column(Text) displayname = Column(Text) -- GitLab