diff --git a/securedrop/source_app/main.py b/securedrop/source_app/main.py index d6c90f0fae..0921398597 100644 --- a/securedrop/source_app/main.py +++ b/securedrop/source_app/main.py @@ -2,6 +2,7 @@ import os import io +from base64 import urlsafe_b64encode from datetime import datetime from flask import (Blueprint, render_template, flash, redirect, url_for, g, session, current_app, request, Markup, abort) @@ -37,9 +38,17 @@ def generate(): return redirect(url_for('.lookup')) codename = generate_unique_codename(config) - session['codename'] = codename + + # Generate a unique id for each browser tab and associate the codename with this id. + # This will allow retrieval of the codename displayed in the tab from which the source has + # clicked to proceed to /generate (ref. issue #4458) + tab_id = urlsafe_b64encode(os.urandom(64)).decode() + codenames = session.get('codenames', {}) + codenames[tab_id] = codename + session['codenames'] = codenames + session['new_user'] = True - return render_template('generate.html', codename=codename) + return render_template('generate.html', codename=codename, tab_id=tab_id) @view.route('/org-logo') def select_logo(): @@ -51,33 +60,43 @@ def select_logo(): @view.route('/create', methods=['POST']) def create(): - filesystem_id = current_app.crypto_util.hash_codename( - session['codename']) - - source = Source(filesystem_id, current_app.crypto_util.display_id()) - db.session.add(source) - try: - db.session.commit() - except IntegrityError as e: - db.session.rollback() - current_app.logger.error( - "Attempt to create a source with duplicate codename: %s" % - (e,)) - - # Issue 2386: don't log in on duplicates - del session['codename'] - - # Issue 4361: Delete 'logged_in' if it's in the session - try: - del session['logged_in'] - except KeyError: - pass - - abort(500) + if session.get('logged_in', False): + flash(gettext("You are already logged in. Please verify your codename below as it " + + "may differ from the one displayed on the previous page."), + 'notification') else: - os.mkdir(current_app.storage.path(filesystem_id)) + tab_id = request.form['tab_id'] + codename = session['codenames'][tab_id] + session['codename'] = codename + + del session['codenames'] + + filesystem_id = current_app.crypto_util.hash_codename(codename) + + source = Source(filesystem_id, current_app.crypto_util.display_id()) + db.session.add(source) + try: + db.session.commit() + except IntegrityError as e: + db.session.rollback() + current_app.logger.error( + "Attempt to create a source with duplicate codename: %s" % + (e,)) + + # Issue 2386: don't log in on duplicates + del session['codename'] + + # Issue 4361: Delete 'logged_in' if it's in the session + try: + del session['logged_in'] + except KeyError: + pass + + abort(500) + else: + os.mkdir(current_app.storage.path(filesystem_id)) - session['logged_in'] = True + session['logged_in'] = True return redirect(url_for('.lookup')) @view.route('/lookup', methods=('GET',)) diff --git a/securedrop/source_templates/generate.html b/securedrop/source_templates/generate.html index 51136ad8b6..4be2171061 100644 --- a/securedrop/source_templates/generate.html +++ b/securedrop/source_templates/generate.html @@ -38,6 +38,7 @@