コード例 #1
0
ファイル: authentication.py プロジェクト: hevelius/GlobaLeaks
def login_whistleblower(session, tid, receipt):
    """
    Login transaction for whistleblowers' access

    :param session: An ORM session
    :param tid: A tenant ID
    :param receipt: A provided receipt
    :return: Returns a user session in case of success
    """
    x = None

    algorithms = [x[0] for x in session.query(WhistleblowerTip.hash_alg).filter(WhistleblowerTip.tid == tid).distinct()]

    if algorithms:
        hashes = [GCE.hash_password(receipt, State.tenant_cache[tid].receipt_salt, alg) for alg in algorithms]

        x = session.query(WhistleblowerTip, InternalTip) \
                   .filter(WhistleblowerTip.receipt_hash.in_(hashes),
                           WhistleblowerTip.tid == tid,
                           InternalTip.id == WhistleblowerTip.id).one_or_none()

    if x is None:
        login_failure(tid, 1)

    wbtip = x[0]
    itip = x[1]

    itip.wb_last_access = datetime_now()

    crypto_prv_key = ''
    if wbtip.crypto_prv_key:
        user_key = GCE.derive_key(receipt.encode(), State.tenant_cache[tid].receipt_salt)
        crypto_prv_key = GCE.symmetric_decrypt(user_key, Base64Encoder.decode(wbtip.crypto_prv_key))

    return Sessions.new(tid, wbtip.id, tid, 'whistleblower', False, False, crypto_prv_key, '')
コード例 #2
0
def login_whistleblower(session, tid, receipt, client_using_tor):
    """
    login_whistleblower returns a session
    """
    hashed_receipt = security.hash_password(
        receipt, State.tenant_cache[tid].receipt_salt)
    result = session.query(WhistleblowerTip, InternalTip) \
                    .filter(WhistleblowerTip.receipt_hash == text_type(hashed_receipt, 'utf-8'),
                            WhistleblowerTip.tid == tid,
                            InternalTip.id == WhistleblowerTip.id,
                            InternalTip.tid == WhistleblowerTip.tid).first()

    if result is None:
        log.debug("Whistleblower login: Invalid receipt")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    wbtip, itip = result[0], result[1]

    if not client_using_tor and not State.tenant_cache[tid][
            'https_whistleblower']:
        log.err("Denied login request over clear Web for role 'whistleblower'")
        raise errors.TorNetworkRequired

    itip.wb_last_access = datetime_now()

    return Sessions.new(tid, wbtip.id, 'whistleblower', False)
コード例 #3
0
def login_whistleblower(session, tid, receipt):
    """
    login_whistleblower returns a session
    """
    x = None

    algorithms = [x[0] for x in session.query(WhistleblowerTip.hash_alg).filter(WhistleblowerTip.tid == tid).distinct()]
    if algorithms:
        hashes = []
        for alg in algorithms:
            hashes.append(GCE.hash_password(receipt, State.tenant_cache[tid].receipt_salt, alg))

        x  = session.query(WhistleblowerTip, InternalTip) \
                    .filter(WhistleblowerTip.receipt_hash.in_(hashes),
                            WhistleblowerTip.tid == tid,
                            InternalTip.id == WhistleblowerTip.id,
                            InternalTip.tid == WhistleblowerTip.tid).one_or_none()

    if x is None:
        log.debug("Whistleblower login: Invalid receipt")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    wbtip = x[0]
    itip = x[1]

    itip.wb_last_access = datetime_now()

    crypto_prv_key = ''
    if State.tenant_cache[tid].encryption and wbtip.crypto_prv_key:
        user_key = GCE.derive_key(receipt.encode('utf-8'), State.tenant_cache[tid].receipt_salt)
        crypto_prv_key = GCE.symmetric_decrypt(user_key, wbtip.crypto_prv_key)

    return Sessions.new(tid, wbtip.id, tid, 'whistleblower', False, crypto_prv_key)
コード例 #4
0
def login(session, tid, username, password, authcode, client_using_tor,
          client_ip):
    """
    login returns a session
    """
    user = None

    users = session.query(User).filter(User.username == username,
                                       User.state != 'disabled',
                                       User.tid == tid).distinct()
    for u in users:
        if GCE.check_password(u.hash_alg, password, u.salt, u.password):
            user = u
            break

        # Fix for issue: https://github.com/globaleaks/GlobaLeaks/issues/2563
        if State.tenant_cache[1].creation_date < 1551740400:
            u_password = '******'' + u.password + '\''
            if GCE.check_password(u.hash_alg, password, u.salt, u_password):
                user = u
                break

    if user is None:
        log.debug("Login: Invalid credentials")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    connection_check(client_ip, tid, user.role, client_using_tor)

    crypto_prv_key = ''
    if State.tenant_cache[tid].encryption:
        if user.crypto_prv_key:
            user_key = GCE.derive_key(password.encode('utf-8'), user.salt)
            crypto_prv_key = GCE.symmetric_decrypt(user_key,
                                                   user.crypto_prv_key)
        else:
            # Force the password change on which the user key will be created
            user.password_change_needed = True

    if user.two_factor_enable:
        if authcode != '':
            if user.crypto_pub_key:
                two_factor_secret = GCE.asymmetric_decrypt(
                    crypto_prv_key, user.two_factor_secret).decode('utf-8')
            else:
                two_factor_secret = user.two_factor_secret.decode('utf-8')

            # RFC 6238: step size 30 sec; valid_window = 1; total size of the window: 1.30 sec
            if not pyotp.TOTP(two_factor_secret).verify(authcode,
                                                        valid_window=1):
                raise errors.InvalidTwoFactorAuthCode

        else:
            raise errors.TwoFactorAuthCodeRequired

    user.last_login = datetime_now()

    return Sessions.new(tid, user.id, user.tid, user.role,
                        user.password_change_needed, user.two_factor_enable,
                        crypto_prv_key)
コード例 #5
0
ファイル: authentication.py プロジェクト: chojar/GlobaLeaks
def login_whistleblower(session, tid, receipt):
    """
    login_whistleblower returns a session
    """
    x = None

    algorithms = [x[0] for x in session.query(WhistleblowerTip.hash_alg).filter(WhistleblowerTip.tid == tid).distinct()]
    if algorithms:
        hashes = []
        for alg in algorithms:
            hashes.append(GCE.hash_password(receipt, State.tenant_cache[tid].receipt_salt, alg))

        x  = session.query(WhistleblowerTip, InternalTip) \
                    .filter(WhistleblowerTip.receipt_hash.in_(hashes),
                            WhistleblowerTip.tid == tid,
                            InternalTip.id == WhistleblowerTip.id,
                            InternalTip.tid == WhistleblowerTip.tid).one_or_none()

    if x is None:
        log.debug("Whistleblower login: Invalid receipt")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    wbtip = x[0]
    itip = x[1]

    itip.wb_last_access = datetime_now()

    crypto_prv_key = ''
    if State.tenant_cache[1].encryption and wbtip.crypto_prv_key:
        user_key = GCE.derive_key(receipt.encode('utf-8'), State.tenant_cache[tid].receipt_salt)
        crypto_prv_key = GCE.symmetric_decrypt(user_key, wbtip.crypto_prv_key)

    return Sessions.new(tid, wbtip.id, 'whistleblower', False, crypto_prv_key)
コード例 #6
0
    def request(self,
                body='',
                uri=b'https://www.globaleaks.org/',
                user_id=None,
                role=None,
                multilang=False,
                headers=None,
                client_addr=None,
                handler_cls=None,
                attached_file=None,
                kwargs={}):
        """
        Constructs a handler for preforming mock requests using the bag of params described below.
        """
        from globaleaks.rest import api

        if handler_cls is None:
            handler_cls = self._handler

        request = forge_request(uri=uri,
                                headers=headers,
                                body=body,
                                client_addr=client_addr,
                                method=b'GET')

        x = api.APIResourceWrapper()
        x.preprocess(request)

        if not getattr(handler_cls, 'decorated', False):
            for method in ['get', 'post', 'put', 'delete']:
                if getattr(handler_cls, method, None) is not None:
                    decorators.decorate_method(handler_cls, method)
                    handler_cls.decorated = True

        handler = handler_cls(self.state, request, **kwargs)

        if multilang:
            request.language = None

        if user_id is None and role is not None:
            if role == 'admin':
                user_id = self.dummyAdminUser['id']
            elif role == 'receiver':
                user_id = self.dummyReceiverUser_1['id']
            elif role == 'custodian':
                user_id = self.dummyCustodianUser['id']

        if headers is not None and headers.get('x-session', None) is not None:
            handler.request.headers[b'x-session'] = headers.get(
                'x-session').encode()

        elif role is not None:
            session = Sessions.new(1, user_id, role, False, USER_PRV_KEY)
            handler.request.headers[b'x-session'] = session.id.encode()

        if handler.upload_handler:
            handler.uploaded_file = self.get_dummy_file(
                u'upload.raw', attached_file)

        return handler
コード例 #7
0
ファイル: authentication.py プロジェクト: MrMEEE/GlobaLeaks
def login(session, tid, username, password, authcode, client_using_tor,
          client_ip):
    """
    Login transaction for users' access

    :param session: An ORM session
    :param tid: A tenant ID
    :param username: A provided username
    :param password: A provided password
    :param authcode: A provided authcode
    :param client_using_tor: A boolean signaling Tor usage
    :param client_ip:  The client IP
    :return: Returns a user session in case of success
    """
    user = None

    for u in session.query(User).filter(User.username == username,
                                        User.state == 'enabled',
                                        User.tid == tid):
        if GCE.check_password(u.hash_alg, password, u.salt, u.password):
            user = u
            break

    if user is None:
        log.debug("Login: Invalid credentials")
        login_error(tid)

    connection_check(tid, client_ip, user.role, client_using_tor)

    crypto_prv_key = ''
    if user.crypto_prv_key:
        user_key = GCE.derive_key(password.encode(), user.salt)
        crypto_prv_key = GCE.symmetric_decrypt(
            user_key, Base64Encoder.decode(user.crypto_prv_key))
    elif State.tenant_cache[tid].encryption:
        # Force the password change on which the user key will be created
        user.password_change_needed = True

    # Require password change if password change threshold is exceeded
    if State.tenant_cache[tid].password_change_period > 0 and \
       user.password_change_date < datetime_now() - timedelta(days=State.tenant_cache[tid].password_change_period):
        user.password_change_needed = True

    if user.two_factor_enable:
        if authcode != '':
            # RFC 6238: step size 30 sec; valid_window = 1; total size of the window: 1.30 sec
            if not pyotp.TOTP(user.two_factor_secret).verify(authcode,
                                                             valid_window=1):
                raise errors.InvalidTwoFactorAuthCode

        else:
            raise errors.TwoFactorAuthCodeRequired

    user.last_login = datetime_now()

    return Sessions.new(tid, user.id, user.tid, user.role,
                        user.password_change_needed, user.two_factor_enable,
                        crypto_prv_key, user.crypto_escrow_prv_key)
コード例 #8
0
def login(session, tid, username, password, authcode, client_using_tor,
          client_ip):
    """
    login returns a session
    """
    user = None

    users = session.query(User).filter(User.username == username,
                                       User.state != u'disabled',
                                       UserTenant.user_id == User.id,
                                       UserTenant.tenant_id == tid).distinct()
    for u in users:
        if GCE.check_password(u.hash_alg, password, u.salt, u.password):
            user = u
            break

    if user is None:
        log.debug("Login: Invalid credentials")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    connection_check(client_ip, tid, user.role, client_using_tor)

    if State.tenant_cache[
            1].two_factor_auth and user.last_login != datetime_null():
        token = TwoFactorTokens.get(user.id)

        if token is not None and authcode != '':
            if token.token == authcode:
                TwoFactorTokens.revoke(user.id)
            else:
                raise errors.InvalidTwoFactorAuthCode

        elif token is None and authcode == '':
            token = TwoFactorTokens.new(user.id)

            data = {'type': '2fa', 'authcode': str(token.token)}

            data['node'] = db_admin_serialize_node(session, tid, user.language)
            data['notification'] = db_get_notification(session, tid,
                                                       user.language)

            subject, body = Templating().get_mail_subject_and_body(data)
            State.sendmail(1, user.mail_address, subject, body)
            raise errors.TwoFactorAuthCodeRequired
        else:
            raise errors.TwoFactorAuthCodeRequired

    user.last_login = datetime_now()

    crypto_prv_key = ''
    if State.tenant_cache[1].encryption and user.crypto_prv_key:
        user_key = GCE.derive_key(password.encode('utf-8'), user.salt)
        crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key)

    return Sessions.new(tid, user.id, user.role, user.password_change_needed,
                        crypto_prv_key)
コード例 #9
0
ファイル: authentication.py プロジェクト: chojar/GlobaLeaks
    def get(self, tid):
        tid = int(tid)
        check = yield check_tenant_auth_switch(self.current_user, tid)
        if check:
            session = Sessions.new(tid, self.current_user.user_id, self.current_user.user_role, self.current_user.pcn, self.current_user.cc)

        returnValue({
            'redirect': '/t/%d/#/login?token=%s' % (tid, session.id)
        })
コード例 #10
0
    def get(self, tid):
        tid = int(tid)
        check = yield check_tenant_auth_switch(self.current_user, tid)
        if check:
            session = Sessions.new(tid, self.current_user.user_id, self.current_user.user_tid, self.current_user.user_role, self.current_user.pcn, self.current_user.cc)

        returnValue({
            'redirect': '/t/%d/#/login?token=%s' % (tid, session.id)
        })
コード例 #11
0
def validate_password_reset(session, reset_token, auth_code, recovery_key):
    """
    Retrieves a user given a password reset validation token

    :param session: An ORM session
    :param reset_token: A reset token
    :param auth_code: A two factor authentication code (optional)
    :param recovery_key: An encryption recovery key (optional)
    :return: A descriptor describing the result of the operation
    """
    now = datetime.now()
    prv_key = ''

    user = session.query(models.User).filter(
        models.User.reset_password_token == reset_token,
        models.User.reset_password_date >= now - timedelta(hours=72)
    ).one_or_none()

    # If the authentication token is invalid
    if user is None:
        return {'status': 'invalid_reset_token_provided'}

    # If encryption is enabled require the recovery key
    if user.crypto_prv_key:
        try:
            x = State.TempKeys.pop(user.id, None)
            if x:
                enc_key = GCE.derive_key(reset_token.encode(), user.salt)
                prv_key = GCE.symmetric_decrypt(enc_key, Base64Encoder.decode(x.key))
            else:
                recovery_key = recovery_key.replace('-', '').upper() + '===='
                recovery_key = Base32Encoder.decode(recovery_key.encode())
                prv_key = GCE.symmetric_decrypt(recovery_key, Base64Encoder.decode(user.crypto_bkp_key))
        except:
            return {'status': 'require_recovery_key'}

    elif user.two_factor_enable:
        two_factor_secret = user.two_factor_secret
        if not pyotp.TOTP(two_factor_secret).verify(auth_code, valid_window=1):
            return {'status': 'require_two_factor_authentication'}

    # Token is used, void it out
    user.reset_password_token = None
    user.reset_password_date = now

    # Require password change
    user.password_change_needed = True

    session = Sessions.new(user.tid, user.id,
                           user.tid, user.role,
                           user.password_change_needed,
                           user.two_factor_enable,
                           prv_key,
                           user.crypto_escrow_prv_key)

    return {'status': 'success', 'token': session.id}
コード例 #12
0
def login(session, tid, username, password, client_using_tor, client_ip):
    """
    login returns a session
    """
    user = None

    users = session.query(User).filter(User.username == username,
                                       User.state != u'disabled',
                                       UserTenant.user_id == User.id,
                                       UserTenant.tenant_id == tid).distinct()
    for u in users:
        if GCE.check_password(u.hash_alg, password, u.salt, u.password):
            user = u
            break

    if user is None:
        log.debug("Login: Invalid credentials")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    if not client_using_tor and not State.tenant_cache[tid]['https_' +
                                                            user.role]:
        log.err("Denied login request over Web for role '%s'" % user.role)
        raise errors.TorNetworkRequired

    # Check if we're doing IP address checks today
    if State.tenant_cache[tid]['ip_filter_authenticated_enable']:
        ip_networks = parse_csv_ip_ranges_to_ip_networks(
            State.tenant_cache[tid]['ip_filter_authenticated'])

        if isinstance(client_ip, binary_type):
            client_ip = client_ip.decode()

        client_ip_obj = ipaddress.ip_address(client_ip)

        # Safety check, we always allow localhost to log in
        success = False
        if client_ip_obj.is_loopback is True:
            success = True

        for ip_network in ip_networks:
            if client_ip_obj in ip_network:
                success = True

        if success is not True:
            raise errors.AccessLocationInvalid

    user.last_login = datetime_now()

    crypto_prv_key = ''
    if State.tenant_cache[1].encryption and user.crypto_prv_key:
        user_key = GCE.derive_key(password.encode('utf-8'), user.salt)
        crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key)

    return Sessions.new(tid, user.id, user.role, user.password_change_needed,
                        crypto_prv_key)
コード例 #13
0
    def get(self, tid):
        check = yield check_tenant_auth_switch(self.current_user, tid)
        if check:
            session = Sessions.new(tid, self.current_user.user_id,
                                   self.current_user.user_role,
                                   self.current_user.pcn, self.current_user.cc)

        returnValue({
            'redirect':
            'https://%s/#/login?token=%s' %
            (State.tenant_cache[tid].hostname, session.id)
        })
コード例 #14
0
ファイル: authentication.py プロジェクト: MrMEEE/GlobaLeaks
    def get(self, tid):
        if self.request.tid != 1:
            raise errors.InvalidAuthentication

        tid = int(tid)
        session = Sessions.new(tid, self.current_user.user_id,
                               self.current_user.user_tid,
                               self.current_user.user_role, False, True,
                               self.current_user.cc, self.current_user.ek,
                               True)

        return {'redirect': '/t/%d/#/login?token=%s' % (tid, session.id)}
コード例 #15
0
ファイル: helpers.py プロジェクト: globaleaks/GlobaLeaks
    def request(self, body='', uri=b'https://www.globaleaks.org/',
                user_id=None, role=None, multilang=False, headers=None,
                client_addr=None, handler_cls=None, attached_file=None,
                kwargs={}):
        """
        Constructs a handler for preforming mock requests using the bag of params described below.
        """
        from globaleaks.rest import api

        if handler_cls is None:
            handler_cls = self._handler

        request = forge_request(uri=uri,
                                headers=headers,
                                body=body,
                                client_addr=client_addr,
                                method=b'GET')

        x = api.APIResourceWrapper()
        x.preprocess(request)

        if not getattr(handler_cls, 'decorated', False):
            for method in ['get', 'post', 'put', 'delete']:
                if getattr(handler_cls, method, None) is not None:
                    decorators.decorate_method(handler_cls, method)
                    handler_cls.decorated = True

        handler = handler_cls(self.state, request, **kwargs)

        if multilang:
            request.language = None

        if user_id is None and role is not None:
            if role == 'admin':
                user_id = self.dummyAdminUser['id']
            elif role == 'receiver':
                user_id = self.dummyReceiverUser_1['id']
            elif role == 'custodian':
                user_id = self.dummyCustodianUser['id']

        if headers is not None and headers.get('x-session', None) is not None:
            handler.request.headers[b'x-session'] = headers.get('x-session').encode()

        elif role is not None:
            session = Sessions.new(1, user_id, role, False, USER_PRV_KEY)
            handler.request.headers[b'x-session'] = session.id.encode()

        if handler.upload_handler:
            handler.uploaded_file = self.get_dummy_file(u'upload.raw', attached_file)

        return handler
コード例 #16
0
def validate_password_reset(session, tid, reset_token):
    """Retrieves a user given a password reset validation token"""
    user = session.query(models.User).filter(
        models.User.reset_password_token == reset_token,
        models.User.reset_password_date >= datetime.now() - timedelta(hours=72)
    ).one_or_none()

    if user is None:
        return

    # Token is used, void it out
    user.reset_password_token = None
    user.reset_password_date = datetime_now()
    user.password_change_needed = True

    session = Sessions.new(tid, user.id, user.role, user.password_change_needed)

    return session.id
コード例 #17
0
ファイル: password_reset.py プロジェクト: chojar/GlobaLeaks
def validate_password_reset(session, tid, reset_token):
    """Retrieves a user given a password reset validation token"""
    user = session.query(models.User).filter(
        models.User.reset_password_token == reset_token,
        models.User.reset_password_date >= datetime.now() - timedelta(hours=72)
    ).one_or_none()

    if user is None:
        return

    # Token is used, void it out
    user.reset_password_token = None
    user.reset_password_date = datetime_now()
    user.password_change_needed = True

    session = Sessions.new(tid, user.id, user.role, user.password_change_needed, '')

    return session.id
コード例 #18
0
def validate_password_reset(session, tid, reset_token, auth_code,
                            recovery_key):
    """Retrieves a user given a password reset validation token"""
    now = datetime.now()
    prv_key = ''

    user = session.query(models.User).filter(
        models.User.reset_password_token == reset_token,
        models.User.reset_password_date >=
        now - timedelta(hours=72)).one_or_none()

    # If the authentication token is invalid
    if user is None:
        return {'status': 'invalid_reset_token_provided'}

    # If encryption is enabled require the recovery key
    if user.crypto_prv_key:
        try:
            recovery_key = recovery_key.replace('-', '').upper() + '===='
            recovery_key = Base32Encoder().decode(recovery_key.encode('utf-8'))
            prv_key = GCE.symmetric_decrypt(recovery_key, user.crypto_bkp_key)
        except:
            return {'status': 'require_recovery_key'}

    elif user.two_factor_enable:
        two_factor_secret = user.two_factor_secret.decode('utf-8')
        if not pyotp.TOTP(two_factor_secret).verify(auth_code, valid_window=1):
            return {'status': 'require_two_factor_authentication'}

    # Token is used, void it out
    user.reset_password_token = None
    user.reset_password_date = now
    user.password_change_needed = True

    session = Sessions.new(tid, user.id, user.tid, user.role,
                           user.password_change_needed, user.two_factor_enable,
                           prv_key)

    return {'status': 'success', 'token': session.id}
コード例 #19
0
 def setUp(self):
     yield helpers.TestHandlerWithPopulatedDB.setUp(self)
     session = Sessions.new(1, self.dummyReceiver_1['id'], 'receiver', False, '')
     self.token = session.id
コード例 #20
0
 def setUp(self):
     yield helpers.TestHandlerWithPopulatedDB.setUp(self)
     session = Sessions.new(1, self.dummyReceiver_1['id'], 1, 'receiver',
                            False, False, '')
     self.token = session.id
コード例 #21
0
def login(session, tid, username, password, authcode, client_using_tor,
          client_ip):
    """
    Login transaction for users' access

    :param session: An ORM session
    :param tid: A tenant ID
    :param username: A provided username
    :param password: A provided password
    :param authcode: A provided authcode
    :param client_using_tor: A boolean signaling Tor usage
    :param client_ip:  The client IP
    :return: Returns a user session in case of success
    """
    user = None

    users = session.query(User).filter(User.username == username,
                                       User.state != 'disabled',
                                       User.tid == tid).distinct()
    for u in users:
        if GCE.check_password(u.hash_alg, password, u.salt, u.password):
            user = u
            break

        # Fix for issue: https://github.com/globaleaks/GlobaLeaks/issues/2563
        if State.tenant_cache[1].creation_date < 1551740400:
            u_password = '******'' + u.password + '\''
            if GCE.check_password(u.hash_alg, password, u.salt, u_password):
                user = u
                break

    if user is None:
        log.debug("Login: Invalid credentials")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    connection_check(client_ip, tid, user.role, client_using_tor)

    crypto_prv_key = ''
    if user.crypto_prv_key:
        user_key = GCE.derive_key(password.encode(), user.salt)
        crypto_prv_key = GCE.symmetric_decrypt(
            user_key, Base64Encoder.decode(user.crypto_prv_key))
    elif State.tenant_cache[tid].encryption:
        # Force the password change on which the user key will be created
        user.password_change_needed = True

    if user.two_factor_enable:
        if authcode != '':
            # RFC 6238: step size 30 sec; valid_window = 1; total size of the window: 1.30 sec
            if not pyotp.TOTP(user.two_factor_secret).verify(authcode,
                                                             valid_window=1):
                raise errors.InvalidTwoFactorAuthCode

        else:
            raise errors.TwoFactorAuthCodeRequired

    user.last_login = datetime_now()

    return Sessions.new(tid, user.id, user.tid, user.role,
                        user.password_change_needed, user.two_factor_enable,
                        crypto_prv_key, user.crypto_escrow_prv_key)
コード例 #22
0
ファイル: authentication.py プロジェクト: chojar/GlobaLeaks
def login(session, tid, username, password, authcode, client_using_tor, client_ip):
    """
    login returns a session
    """
    user = None

    users = session.query(User).filter(User.username == username,
                                       User.state != u'disabled',
                                       UserTenant.user_id == User.id,
                                       UserTenant.tenant_id == tid).distinct()
    for u in users:
        if GCE.check_password(u.hash_alg, password, u.salt, u.password):
            user = u
            break

        # Fix for issue: https://github.com/globaleaks/GlobaLeaks/issues/2563
        if State.tenant_cache[1].creation_date < datetime.timestamp(datetime(2019, 5, 3, 0, 0)):
            u_password = '******'' + u.password + '\''
            if GCE.check_password(u.hash_alg, password, u.salt, u_password):
                user = u
                break

    if user is None:
        log.debug("Login: Invalid credentials")
        Settings.failed_login_attempts += 1
        raise errors.InvalidAuthentication

    connection_check(client_ip, tid, user.role, client_using_tor)

    if State.tenant_cache[1].two_factor_auth and user.last_login != datetime_null():
        token = TwoFactorTokens.get(user.id)

        if token is not None and authcode != '':
            if token.token == authcode:
                TwoFactorTokens.revoke(user.id)
            else:
                raise errors.InvalidTwoFactorAuthCode

        elif token is None and authcode == '':
            token = TwoFactorTokens.new(user.id)

            data = {
                'type': '2fa',
                'authcode': str(token.token)
            }

            data['node'] = db_admin_serialize_node(session, tid, user.language)
            data['notification'] = db_get_notification(session, tid, user.language)

            subject, body = Templating().get_mail_subject_and_body(data)
            State.sendmail(1, user.mail_address, subject, body)
            raise errors.TwoFactorAuthCodeRequired
        else:
            raise errors.TwoFactorAuthCodeRequired

    user.last_login = datetime_now()

    crypto_prv_key = ''
    if State.tenant_cache[1].encryption and user.crypto_prv_key:
        user_key = GCE.derive_key(password.encode('utf-8'), user.salt)
        crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key)

    return Sessions.new(tid, user.id, user.role, user.password_change_needed, crypto_prv_key)