Class: Arachni::RPC::EM::Server::Proxy

Inherits:
EventMachine::Connection
  • Object
show all
Includes:
ConnectionUtilities, Protocol, Arachni::RPC::Exceptions
Defined in:
lib/arachni/rpc/em/server.rb

Overview

Handles EventMachine’s connection stuff.

It’s responsible for TLS, serializing, transmitting and receiving objects, as well as authenticating the client using the token.

It also handles and forwards exceptions.

@author: Tasos “Zapotek” Laskos <[email protected]>

Constant Summary collapse

INACTIVITY_TIMEOUT =
10

Constants included from Protocol

Protocol::MAX_CHUNK_SIZE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ConnectionUtilities

#peer_ip_addr

Methods included from Protocol

#assume_client_role!, #assume_server_role!, #fallback_serializer, #receive_data, #receive_object, #receive_response, #send_message, #send_object, #serialize, #serializer, #unserialize

Methods included from Arachni::RPC::EM::SSL

#are_we_a_client?, #ca_store, #end_ssl, #ssl_handshake_completed, #ssl_opts?, #ssl_verify_peer, #start_ssl, #verified_peer?

Constructor Details

#initialize(server) ⇒ Proxy

Returns a new instance of Proxy.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/arachni/rpc/em/server.rb', line 46

def initialize( server )
    super
    @server = server
    @opts   = server.opts

    assume_server_role!

    @id = nil
    @request = nil

    # do not tolerate long periods of
    # inactivity in order to avoid zombie connections
    set_comm_inactivity_timeout( INACTIVITY_TIMEOUT )
end

Instance Attribute Details

#requestObject (readonly)

Returns the value of attribute request.



44
45
46
# File 'lib/arachni/rpc/em/server.rb', line 44

def request
  @request
end

Instance Method Details

#authenticate!Object

Authenticates the client based on the token in the request.

It will raise an exception if the token doesn’t check-out.



132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/arachni/rpc/em/server.rb', line 132

def authenticate!
    if !valid_token?( @request.token )

        msg = 'Token missing or invalid while calling: ' + @request.message

        @server.logger.error( 'Authenticator' ){
            msg + " [on behalf of #{peer_ip_addr}]"
        }

        fail InvalidToken.new( msg )
    end
end

#log(severity, progname, msg) ⇒ Object



70
71
72
73
# File 'lib/arachni/rpc/em/server.rb', line 70

def log( severity, progname, msg )
    sev_sym = Logger.const_get( severity.to_s.upcase.to_sym )
    @server.logger.add( sev_sym, msg, progname )
end

#post_initObject

starts TLS



62
63
64
# File 'lib/arachni/rpc/em/server.rb', line 62

def post_init
    start_ssl
end

#receive_request(req) ⇒ Object

Handles requests and sends back the responses.

Parameters:

  • req (Arachni::RPC::EM::Request)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/arachni/rpc/em/server.rb', line 80

def receive_request( req )
    @request = req

    # the method call may block a little so tell EventMachine to
    # stick it in its own thread.
    res  = Response.new
    peer = peer_ip_addr

    begin
        # token-based authentication
        authenticate!

        # grab the result of the method call
        res.merge!( @server.call( self ) )

    # handle exceptions and convert them to a simple hash,
    # ready to be passed to the client.
    rescue Exception => e

        type = ''

        # if it's an RPC exception pass the type along as is
        if e.rpc_exception?
            type = e.class.name.split( ':' )[-1]
        # otherwise set it to a RemoteExeption
        else
            type = 'RemoteException'
        end

        res.obj = {
            'exception' => e.to_s,
            'backtrace' => e.backtrace,
            'type'      => type
        }

        msg = "#{e.to_s}\n#{e.backtrace.join( "\n" )}"
        @server.logger.error( 'Exception' ){ msg + " [on behalf of #{peer}]" }
    end

    #
    # pass the result of the RPC call back to the client
    # along with the callback ID but *only* if it wan't async
    # because server.call() will have already taken care of it
    #
    send_response( res ) if !res.async?
end

#unbindObject



66
67
68
# File 'lib/arachni/rpc/em/server.rb', line 66

def unbind
    end_ssl
end

#valid_token?(token) ⇒ Bool

Compares the authentication token in the param with the one of the server.

Parameters:

  • token (String)

Returns:

  • (Bool)


152
153
154
# File 'lib/arachni/rpc/em/server.rb', line 152

def valid_token?( token )
    token == @server.token
end