def post(self): """ Receipt login handler used by whistleblowers """ request = self.validate_message(self.request.content.read(), requests.ReceiptAuthDesc) receipt = request['receipt'] delay = random_login_delay() if delay: yield deferred_sleep(delay) user_id = yield login_whistleblower(receipt, self.request.client_using_tor) GLSessions.revoke_all_sessions(user_id) session = new_session(user_id, 'whistleblower', 'Enabled') returnValue({ 'session_id': session.id, 'role': session.user_role, 'user_id': session.user_id, 'session_expiration': int(session.getTime()) })
def post(self): """ Login """ request = self.validate_message(self.request.content.read(), requests.AuthDesc) username = request['username'] password = request['password'] user_id, status, role, pcn = yield login(username, password, self.request.client_using_tor) # Revoke all other sessions for the newly authenticated user GLSessions.revoke_all_sessions(user_id) session = new_session(user_id, role, status) returnValue({ 'session_id': session.id, 'role': session.user_role, 'user_id': session.user_id, 'session_expiration': int(session.getTime()), 'status': session.user_status, 'password_change_needed': pcn })
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 new_session(tid, wbtip.id, 'whistleblower', False)
def post(self): request = self.validate_message(self.request.content.read(), requests.AuthDesc) delay = random_login_delay() if delay: yield deferred_sleep(delay) user_id, status, role, pcn = yield login(self.request.tid, request['username'], request['password'], self.request.client_using_tor, self.request.client_ip, request['token']) session = new_session(self.request.tid, user_id, role, status) returnValue({ 'session_id': session.id, 'role': session.user_role, 'user_id': session.user_id, 'session_expiration': int(session.getTime()), 'status': session.user_status, 'password_change_needed': pcn })
def request(self, body='', uri=b'https://www.globaleaks.org/', user_id=None, role=None, multilang=False, headers=None, client_addr=None, method='GET', handler_cls=None, attached_file={}, 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', attached_file=attached_file) 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: api.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 role is not None: session = new_session(1, user_id, role, 'enabled') handler.request.headers[b'x-session'] = session.id.encode() if handler.upload_handler: handler.uploaded_file = self.get_dummy_file('upload.pdf') return handler
def test_session_management_sched(self): new_session('admin', 'admin', 'enabled') # 1! new_session('admin', 'admin', 'enabled') # 2! new_session('admin', 'admin', 'enabled') # 3! self.assertEqual(len(GLSessions), 3) self.test_reactor.pump([1] * (GLSettings.authentication_lifetime - 1)) self.assertEqual(len(GLSessions), 3) self.test_reactor.advance(1) self.assertEqual(len(GLSessions), 0) yield session_management_sched.SessionManagementSchedule().run()
def post(self): request = self.validate_message(self.request.content.read(), requests.AuthDesc) delay = random_login_delay() if delay: yield deferred_sleep(delay) user_id, status, role, pcn, login_step = yield login( self.request.tid, request['username'], request['password'], request['receiver_second_login'], request['receiver_auth_code'], self.request.client_using_tor, self.request.client_ip, request['token']) if role == 'receiver' and login_step == 'second_login_to_complete': session = new_session_rec_auth(self.request.tid, user_id, role, status, login_step) returnValue({ 'session_id': session.id, 'role': session.user_role, 'user_id': session.user_id, 'session_expiration': 1, 'status': session.user_status, 'password_change_needed': pcn, 'receiverLoginState': login_step }) else: session = new_session(self.request.tid, user_id, role, status, login_step) returnValue({ 'session_id': session.id, 'role': session.user_role, 'user_id': session.user_id, 'session_expiration': int(session.getTime()), 'status': session.user_status, 'password_change_needed': pcn, 'receiverLoginState': login_step })
def post(self): request = self.validate_message(self.request.content.read(), requests.AuthDesc) delay = random_login_delay() if delay: yield deferred_sleep(delay) tid = int(request['tid']) if tid == 0: tid = self.request.tid user_id, status, role, pcn = yield login(tid, request['username'], request['password'], self.request.client_using_tor, self.request.client_ip, request['token']) if tid == self.request.tid: session = new_session(self.request.tid, user_id, role, status) returnValue({ 'session_id': session.id, 'role': session.user_role, 'user_id': session.user_id, 'session_expiration': int(session.getTime()), 'status': session.user_status, 'password_change_needed': pcn }) else: token = yield get_multitenant_auth_token(user_id, tid) if token: returnValue({ 'redirect': 'https://%s/#/login?token=%s' % (State.tenant_cache[tid].hostname, token) })
def request(self, jbody=None, user_id=None, role=None, headers=None, body='', path=None, remote_ip='0.0.0.0', method='MOCK', handler_cls=None, attached_file={}, kwargs={}): """ Constructs a handler for preforming mock requests using the bag of params described below. Args: jbody: The body of the request as a dict (it will be automatically converted to string) body: The body of the request as a string user_id: when simulating authentication the session should be bound to a certain user_id. role: when simulating authentication the session should be bound to a certain role. method: HTTP method, e.g. "GET" or "POST" headers: Dict of headers to pass on the request remote_ip: If a particular remote_ip should be set. handler_cls: The type of handler that will respond to the request. If this is not set self._handler is used. attached_file: A dict to place in the request.args.files obj """ if jbody and not body: body = json.dumps(jbody) elif body and jbody: raise ValueError('jbody and body in conflict') if handler_cls is None: handler_cls = self._handler request = DummyRequest(['']) def getResponseBody(): return ''.join(request.written) request.path = '' request.code = 200 request.language = 'en' request.client_ip = '127.0.0.1' request.client_proto = 'https' request.client_using_tor = False request.getResponseBody = getResponseBody request.client = IPv4Address('TCP', '1.2.3.4', 12345) request.args = {} if attached_file is not None: request.args = {'file': [attached_file]} if headers is not None: for k, v in headers.iteritems(): request.requestHeaders.setRawHeaders(bytes(k), [bytes(v)]) request.headers = request.getAllHeaders() from globaleaks.rest import api x = api.APIResourceWrapper() x.preprocess(request) if path is not None: if not path.startswith('/'): raise ValueError('Must pass a valid url path') request.path = path class fakeBody(object): def read(self): return body def close(self): pass request.content = fakeBody() from globaleaks.rest.api import decorate_method if not getattr(handler_cls, 'decorated', False): for method in ['get', 'post', 'put', 'delete']: if getattr(handler_cls, method, None) is not None: decorate_method(handler_cls, method) handler_cls.decorated = True handler = handler_cls(request, **kwargs) 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 role is not None: session = new_session(user_id, role, 'enabled') handler.request.headers['x-session'] = session.id return handler
def login(session, tid, username, password, client_using_tor, client_ip, token=''): """ login returns a session """ user = None tenant_condition = and_(UserTenant.user_id == User.id, UserTenant.tenant_id == tid) if token: user = session.query(User).filter(User.auth_token == token, User.state != u'disabled', tenant_condition).one_or_none() else: users = session.query(User).filter(User.username == username, User.state != u'disabled', tenant_condition).distinct() for u in users: if security.check_password(password, u.salt, u.password): user = u 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() return new_session(tid, user.id, user.role, user.password_change_needed)