def _swallow_error_and_abort(self, fail): """ Internal method that logs an error that would otherwise be unhandled and also *cancels it*. This will also completely abort the session, sending Abort to the other side. DO NOT attach to Deferreds that are returned to calling code. """ self.log.failure("Internal error: {log_failure.value}", failure=fail) # tell other side we're done reply = message.Abort(u"wamp.error.authorization_failed", u"Internal server error") self._transport.send(reply) # cleanup if self._router: self._router.detach(self) self._session_id = None self._pending_session_id = None return None # we've handled the error; don't propagate
def success(res): msg = None if isinstance(res, types.Accept): custom = { u'x_cb_node_id': self._router_factory._node_id } welcome(res.realm, res.authid, res.authrole, res.authmethod, res.authprovider, res.authextra, custom) elif isinstance(res, types.Challenge): msg = message.Challenge(res.method, res.extra) elif isinstance(res, types.Deny): msg = message.Abort(res.reason, res.message) else: pass if msg: self._transport.send(msg)
def _test_wamp_client(event_loop): transport = Mock(spec_set=('abort', 'close', 'write', 'get_extra_info')) transport.write = Mock(side_effect=lambda m: messages.append(m)) client = Mock(spec=['onOpen', 'onMessage']) def fact_client(): return client messages = [] proto = WampRawSocketClientFactory(fact_client)() proto.connection_made(transport) assert proto._serializer s = proto._serializer.RAWSOCKET_SERIALIZER_ID proto.data_received(bytes(bytearray([0x7F, 0xF0 | s, 0, 0]))) client.onOpen.assert_called_once_with(proto) proto.sendMessage(message.Abort('close')) for d in messages[1:]: proto.data_received(d) assert client.onMessage.called assert isinstance(client.onMessage.call_args[0][0], message.Abort)
def error(err): reply = message.Abort(u"wamp.error.cannot_authenticate", u"{0}".format(err.value)) self._transport.send(reply) ## fire callback and close the transport self.onLeave(types.CloseDetails(reply.reason, reply.message))
def test_sers(self): serializers = get_serializers() self.assertTrue(len(serializers) > 0) m = serializers[0]().serialize(message.Abort(u'close')) print(m) self.assertTrue(m)
def test_sers(event_loop): serializers = get_serializers() assert len(serializers) > 0 m = serializers[0]().serialize(message.Abort('close')) assert m
def _process_Hello(self, msg): """ We have received a Hello from the frontend client. Now we do any authentication necessary with them and connect to our backend. """ self.log.info('{klass}._process_Hello(msg={msg})', klass=self.__class__.__name__, msg=msg) self._pending_session_id = util.id() self._goodbye_sent = False extra_auth_methods = self._controller.personality.EXTRA_AUTH_METHODS # allow "Personality" classes to add authmethods authmethods = list(extra_auth_methods.keys()) + (msg.authmethods or ['anonymous']) # if the client had a reassigned realm during authentication, restore it from the cookie if hasattr(self.transport, '_authrealm') and self.transport._authrealm: if 'cookie' in authmethods: realm = self.transport._authrealm # noqa authextra = self.transport._authextra # noqa elif self.transport._authprovider == 'cookie': # revoke authentication and invalidate cookie (will be revalidated if following auth is successful) self.transport._authmethod = None self.transport._authrealm = None self.transport._authid = None if hasattr(self.transport, '_cbtid'): self.transport.factory._cookiestore.setAuth(self.transport._cbtid, None, None, None, None, None) else: pass # TLS authentication is not revoked here # already authenticated, eg via HTTP-cookie or TLS-client-certificate authentication if self.transport._authid is not None and (self.transport._authmethod == 'trusted' or self.transport._authprovider in authmethods): msg.realm = self.transport._realm msg.authid = self.transport._authid msg.authrole = self.transport._authrole details = types.HelloDetails( realm=msg.realm, authmethods=authmethods, authid=msg.authid, authrole=msg.authrole, authextra=msg.authextra, session_roles=msg.roles, pending_session=self._pending_session_id ) auth_config = self._transport_config.get('auth', None) # if authentication is _not_ configured, allow anyone to join as "anonymous"! if not auth_config: # we ignore any details.authid the client might have announced, and use # a cookie value or a random value if hasattr(self.transport, "_cbtid") and self.transport._cbtid: # if cookie tracking is enabled, set authid to cookie value authid = self.transport._cbtid else: # if no cookie tracking, generate a random value for authid authid = util.generate_serial_number() auth_config = { 'anonymous': { 'type': 'static', 'authrole': 'anonymous', 'authid': authid, } } self.log.warn('No authentication configured for proxy frontend: using default anonymous access policy for incoming proxy frontend session') for authmethod in authmethods: # invalid authmethod if authmethod not in AUTHMETHOD_MAP and authmethod not in extra_auth_methods: self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='authmethod "{}" not allowed'.format(authmethod))) return # authmethod is valid, but not configured: continue trying other authmethods the client is announcing if authmethod not in auth_config: continue # authmethod not available if authmethod not in AUTHMETHOD_MAP and authmethod not in extra_auth_methods: self.log.debug("client requested valid, but unavailable authentication method {authmethod}", authmethod=authmethod) continue # create instance of authenticator using authenticator class for the respective authmethod authklass = extra_auth_methods[authmethod] if authmethod in extra_auth_methods else AUTHMETHOD_MAP[authmethod] self._pending_auth = authklass( self._pending_session_id, self.transport._transport_info, self._controller, auth_config[authmethod], ) try: # call into authenticator for processing the HELLO message hello_result = self._pending_auth.hello(msg.realm, details) except Exception as e: self.log.failure() self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='Frontend connection accept failed ({})'.format(e))) return self.log.info('{klass}._process_Hello() processed authmethod "{authmethod}" using {authklass}: {hello_result}', klass=self.__class__.__name__, authmethod=authmethod, authklass=authklass, hello_result=hello_result) # if the frontend session is accepted right away (eg when doing "anonymous" authentication), process the # frontend accept .. if isinstance(hello_result, types.Accept): try: # get a backend session mapped to the incoming frontend session session = yield self._accept(hello_result) except Exception as e: self.log.failure() self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='Frontend connection accept failed ({})'.format(e))) return def _on_backend_joined(session, details): # we now got everything! the frontend is authenticated, and a backend session is associated. msg = message.Welcome(self._session_id, ProxyFrontendSession.ROLES, realm=details.realm, authid=details.authid, authrole=details.authrole, authmethod=hello_result.authmethod, authprovider=hello_result.authprovider, authextra=dict(details.authextra or {}, **self._custom_authextra)) self._backend_session = session self.transport.send(msg) self.log.info('Proxy frontend session WELCOME: session_id={session}, session={session}, session_details={details}', session_id=hlid(self._session_id), session=self, details=details) session.on('join', _on_backend_joined) # if the client is required to do an authentication message exchange, answer sending a CHALLENGE message elif isinstance(hello_result, types.Challenge): self.transport.send(message.Challenge(hello_result.method, extra=hello_result.extra)) # if the client is denied right away, answer by sending an ABORT message elif isinstance(hello_result, types.Deny): self.transport.send(message.Abort(hello_result.reason, message=hello_result.message)) # should not arrive here: internal (logic) error else: self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='internal error: unexpected authenticator return type {}'.format(type(hello_result)))) return self.transport.send(message.Abort(ApplicationError.NO_AUTH_METHOD, message='no suitable authmethod found'))
def _process_Hello(self, msg): """ We have received a Hello from the frontend client. Now we do any authentication necessary with them and connect to our backend. """ self.log.info('{klass}._process_Hello(msg={msg})', klass=self.__class__.__name__, msg=msg) self._pending_session_id = util.id() self._goodbye_sent = False authmethods = msg.authmethods or ['anonymous'] details = types.HelloDetails( realm=msg.realm, authmethods=authmethods, authid=msg.authid, authrole=msg.authrole, authextra=msg.authextra, session_roles=msg.roles, pending_session=self._pending_session_id ) auth_config = self._transport_config.get('auth', None) # allow "Personality" classes to add authmethods extra_auth_methods = dict() # if self._router_factory._worker: # personality = self._router_factory._worker.personality # extra_auth_methods = personality.EXTRA_AUTH_METHODS for authmethod in authmethods: # invalid authmethod if authmethod not in AUTHMETHOD_MAP and authmethod not in extra_auth_methods: self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='authmethod "{}" not allowed'.format(authmethod))) return # authmethod is valid, but not configured: continue trying other authmethods the client is announcing if authmethod not in auth_config: continue # authmethod not available if authmethod not in AUTHMETHOD_MAP and authmethod not in extra_auth_methods: self.log.debug("client requested valid, but unavailable authentication method {authmethod}", authmethod=authmethod) continue PendingAuthKlass = AUTHMETHOD_MAP[authmethod] # pending_session_id, transport_info, realm_container, config self._pending_auth = PendingAuthKlass( self._pending_session_id, self.transport._transport_info, # FIXME * no_such_role self._controller, auth_config[authmethod], ) try: hello_result = self._pending_auth.hello(msg.realm, details) except Exception as e: self.log.failure() self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='Frontend connection accept failed ({})'.format(e))) return self.log.info('{klass}._process_Hello() processed authmethod "{authmethod}" using {authklass}: {hello_result}', klass=self.__class__.__name__, authmethod=authmethod, authklass=PendingAuthKlass, hello_result=hello_result) if isinstance(hello_result, types.Accept): try: session = yield self._accept(hello_result) except Exception as e: self.log.failure() self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='Frontend connection accept failed ({})'.format(e))) return def _on_backend_joined(session, details): msg = message.Welcome(self._session_id, ProxyFrontendSession.ROLES, realm=details.realm, authid=details.authid, authrole=details.authrole, authmethod=hello_result.authmethod, authprovider=hello_result.authprovider, authextra=dict(details.authextra or {}, **self._custom_authextra)) self._backend_session = session self.transport.send(msg) self.log.info('Proxy frontend session WELCOME: session_id={session}, session={session}, session_details={details}', session_id=hlid(self._session_id), session=self, details=details) session.on('join', _on_backend_joined) elif isinstance(hello_result, types.Challenge): self.transport.send(message.Challenge(hello_result.method, extra=hello_result.extra)) elif isinstance(hello_result, types.Deny): self.transport.send(message.Abort(hello_result.reason, message=hello_result.message)) else: # should not arrive here: logic error self.transport.send(message.Abort(ApplicationError.AUTHENTICATION_FAILED, message='internal error: unexpected authenticator return type {}'.format(type(hello_result)))) return self.transport.send(message.Abort(ApplicationError.NO_AUTH_METHOD, message='no suitable authmethod found'))