Use app init enc key by default for all queries

This can be updated later to allow users with cookies enabled to use a
key that is unique to their session (if they want, not mandatory), but
for now it makes more sense to just use a single key for all queries
from all users. This should eliminate a lot of issues that users have
reported where they are unable to decrypt queries or page elements due
to an expired/renewed session key.
main
Ben Busby 2022-12-05 12:14:14 -07:00
parent 1226b8db9c
commit 0310f0f542
No known key found for this signature in database
GPG Key ID: B9B7231E01D924A1
6 changed files with 26 additions and 24 deletions

View File

@ -1,6 +1,6 @@
from app.filter import clean_query from app.filter import clean_query
from app.request import send_tor_signal from app.request import send_tor_signal
from app.utils.session import generate_user_key from app.utils.session import generate_key
from app.utils.bangs import gen_bangs_json from app.utils.bangs import gen_bangs_json
from app.utils.misc import gen_file_hash, read_config_bool from app.utils.misc import gen_file_hash, read_config_bool
from base64 import b64encode from base64 import b64encode
@ -31,7 +31,7 @@ dot_env_path = (
if read_config_bool('WHOOGLE_DOTENV'): if read_config_bool('WHOOGLE_DOTENV'):
load_dotenv(dot_env_path) load_dotenv(dot_env_path)
app.default_key = generate_user_key() app.enc_key = generate_key()
if read_config_bool('HTTPS_ONLY'): if read_config_bool('HTTPS_ONLY'):
app.config['SESSION_COOKIE_NAME'] = '__Secure-session' app.config['SESSION_COOKIE_NAME'] = '__Secure-session'

View File

@ -22,7 +22,7 @@ from app.utils.misc import read_config_bool, get_client_ip, get_request_url, \
from app.utils.results import add_ip_card, bold_search_terms,\ from app.utils.results import add_ip_card, bold_search_terms,\
add_currency_card, check_currency, get_tabs_content add_currency_card, check_currency, get_tabs_content
from app.utils.search import Search, needs_https, has_captcha from app.utils.search import Search, needs_https, has_captcha
from app.utils.session import generate_user_key, valid_user_session from app.utils.session import valid_user_session
from bs4 import BeautifulSoup as bsoup from bs4 import BeautifulSoup as bsoup
from flask import jsonify, make_response, request, redirect, render_template, \ from flask import jsonify, make_response, request, redirect, render_template, \
send_file, session, url_for, g send_file, session, url_for, g
@ -67,11 +67,16 @@ def auth_required(f):
def session_required(f): def session_required(f):
@wraps(f) @wraps(f)
def decorated(*args, **kwargs): def decorated(*args, **kwargs):
if (valid_user_session(session)): if not valid_user_session(session):
g.session_key = session['key']
else:
session.pop('_permanent', None) session.pop('_permanent', None)
g.session_key = app.default_key
# Note: This sets all requests to use the encryption key determined per
# instance on app init. This can be updated in the future to use a key
# that is unique for their session (session['key']) but this should use
# a config setting to enable the session based key. Otherwise there can
# be problems with searches performed by users with cookies blocked if
# a session based key is always used.
g.session_key = app.enc_key
# Clear out old sessions # Clear out old sessions
invalid_sessions = [] invalid_sessions = []
@ -130,14 +135,17 @@ def before_request_func():
if os.path.exists(app.config['DEFAULT_CONFIG']) else {} if os.path.exists(app.config['DEFAULT_CONFIG']) else {}
# Generate session values for user if unavailable # Generate session values for user if unavailable
if (not valid_user_session(session)): if not valid_user_session(session):
session['config'] = default_config session['config'] = default_config
session['uuid'] = str(uuid.uuid4()) session['uuid'] = str(uuid.uuid4())
session['key'] = generate_user_key() session['key'] = app.enc_key
# Establish config values per user session # Establish config values per user session
g.user_config = Config(**session['config']) g.user_config = Config(**session['config'])
# Update user config if specified in search args
g.user_config = g.user_config.from_params(g.request_params)
if not g.user_config.url: if not g.user_config.url:
g.user_config.url = get_request_url(request.url_root) g.user_config.url = get_request_url(request.url_root)
@ -193,9 +201,6 @@ def index():
session['error_message'] = '' session['error_message'] = ''
return render_template('error.html', error_message=error_message) return render_template('error.html', error_message=error_message)
# Update user config if specified in search args
g.user_config = g.user_config.from_params(g.request_params)
return render_template('index.html', return render_template('index.html',
has_update=app.config['HAS_UPDATE'], has_update=app.config['HAS_UPDATE'],
languages=app.config['LANGUAGES'], languages=app.config['LANGUAGES'],
@ -283,9 +288,6 @@ def autocomplete():
@session_required @session_required
@auth_required @auth_required
def search(): def search():
# Update user config if specified in search args
g.user_config = g.user_config.from_params(g.request_params)
search_util = Search(request, g.user_config, g.session_key) search_util = Search(request, g.user_config, g.session_key)
query = search_util.new_search_query() query = search_util.new_search_query()

View File

@ -4,7 +4,7 @@ from flask import current_app as app
REQUIRED_SESSION_VALUES = ['uuid', 'config', 'key'] REQUIRED_SESSION_VALUES = ['uuid', 'config', 'key']
def generate_user_key() -> bytes: def generate_key() -> bytes:
"""Generates a key for encrypting searches and element URLs """Generates a key for encrypting searches and element URLs
Args: Args:

View File

@ -1,5 +1,5 @@
from app import app from app import app
from app.utils.session import generate_user_key from app.utils.session import generate_key
import pytest import pytest
import random import random
@ -18,6 +18,6 @@ def client():
with app.test_client() as client: with app.test_client() as client:
with client.session_transaction() as session: with client.session_transaction() as session:
session['uuid'] = 'test' session['uuid'] = 'test'
session['key'] = generate_user_key() session['key'] = app.enc_key
session['config'] = {} session['config'] = {}
yield client yield client

View File

@ -2,7 +2,7 @@ from cryptography.fernet import Fernet
from app import app from app import app
from app.models.endpoint import Endpoint from app.models.endpoint import Endpoint
from app.utils.session import generate_user_key, valid_user_session from app.utils.session import generate_key, valid_user_session
JAPAN_PREFS = 'uG-gGIJwHdqxl6DrS3mnu_511HlQcRpxYlG03Xs-' \ JAPAN_PREFS = 'uG-gGIJwHdqxl6DrS3mnu_511HlQcRpxYlG03Xs-' \
@ -20,9 +20,9 @@ JAPAN_PREFS = 'uG-gGIJwHdqxl6DrS3mnu_511HlQcRpxYlG03Xs-' \
def test_generate_user_keys(): def test_generate_user_keys():
key = generate_user_key() key = generate_key()
assert Fernet(key) assert Fernet(key)
assert generate_user_key() != key assert generate_key() != key
def test_valid_session(client): def test_valid_session(client):

View File

@ -2,7 +2,7 @@ from bs4 import BeautifulSoup
from app.filter import Filter from app.filter import Filter
from app.models.config import Config from app.models.config import Config
from app.models.endpoint import Endpoint from app.models.endpoint import Endpoint
from app.utils.session import generate_user_key from app.utils.session import generate_key
from datetime import datetime from datetime import datetime
from dateutil.parser import ParserError, parse from dateutil.parser import ParserError, parse
from urllib.parse import urlparse from urllib.parse import urlparse
@ -11,7 +11,7 @@ from test.conftest import demo_config
def get_search_results(data): def get_search_results(data):
secret_key = generate_user_key() secret_key = generate_key()
soup = Filter(user_key=secret_key, config=Config(**demo_config)).clean( soup = Filter(user_key=secret_key, config=Config(**demo_config)).clean(
BeautifulSoup(data, 'html.parser')) BeautifulSoup(data, 'html.parser'))
@ -132,7 +132,7 @@ def test_leading_slash_search(client):
assert rv._status_code == 200 assert rv._status_code == 200
soup = Filter( soup = Filter(
user_key=generate_user_key(), user_key=generate_key(),
config=Config(**demo_config), config=Config(**demo_config),
query=q query=q
).clean(BeautifulSoup(rv.data, 'html.parser')) ).clean(BeautifulSoup(rv.data, 'html.parser'))