Module: Arachni::RPC::EM::Protocol

Includes:
SSL
Included in:
Client::Handler, Server::Proxy
Defined in:
lib/arachni/rpc/em/protocol.rb

Overview

Provides helper transport methods for Message transmission.

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

Constant Summary collapse

MAX_CHUNK_SIZE =

send a maximum of 16kb of data per tick

1024 * 16

Instance Method Summary collapse

Methods included from SSL

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

Methods included from ConnectionUtilities

#peer_ip_addr

Instance Method Details

#assume_client_role!Object

become a client



30
31
32
# File 'lib/arachni/rpc/em/protocol.rb', line 30

def assume_client_role!
    @role = :client
end

#assume_server_role!Object

become a server



25
26
27
# File 'lib/arachni/rpc/em/protocol.rb', line 25

def assume_server_role!
    @role = :server
end

#fallback_serializerObject



151
152
153
# File 'lib/arachni/rpc/em/protocol.rb', line 151

def fallback_serializer
    @opts[:fallback_serializer] ? @opts[:serializer] : YAML
end

#receive_data(data) ⇒ Object

Receives data from the network.

In this case the data will be chunks of a serialized object which will be buffered until the whole transmission has finished.

It will then unresialize it and pass it to receive_object().



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
# File 'lib/arachni/rpc/em/protocol.rb', line 86

def receive_data( data )
    #
    # cut them out as soon as possible
    #
    # don't buffer any data from unverified peers if SSL peer
    # verification has been enabled
    #
    if ssl_opts? && !verified_peer? && @role == :server
        e = Arachni::RPC::Exceptions::SSLPeerVerificationFailed.new( 'Could not verify peer.' )
        send_response Response.new( :obj => {
            'exception' => e.to_s,
            'backtrace' => e.backtrace,
            'type'      => 'SSLPeerVerificationFailed'
        })

        log( :error, 'SSL', " Could not verify peer. ['#{peer_ip_addr}']." )
        return
    end

    (@buf ||= '') << data

    while @buf.size >= 4
        if @buf.size >= 4 + ( size = @buf.unpack( 'N' ).first )
            @buf.slice!( 0, 4 )
            receive_object( unserialize( @buf.slice!( 0, size ) ) )
        else
            break
        end
    end
end

#receive_object(obj) ⇒ Object

Converts incoming hash objects to Requests or Response (depending on the assumed role) and calls receive_request() or receive_response() accordingly.

Parameters:

  • obj (Hash)


59
60
61
62
63
64
65
# File 'lib/arachni/rpc/em/protocol.rb', line 59

def receive_object( obj )
    if @role == :server
        receive_request( Request.new( obj ) )
    else
        receive_response( Response.new( obj ) )
    end
end

#receive_request(request) ⇒ Object

Stub method, should be implemented by servers.

Parameters:

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


39
40
41
# File 'lib/arachni/rpc/em/protocol.rb', line 39

def receive_request( request )
    p request
end

#receive_response(response) ⇒ Object

Stub method, should be implemented by clients.

Parameters:

  • response (Arachni::RPC::EM::Response)


48
49
50
# File 'lib/arachni/rpc/em/protocol.rb', line 48

def receive_response( response )
    p response
end

#send_message(msg) ⇒ Object Also known as: send_request, send_response

Sends a message to the peer.

Parameters:

  • msg (Arachni::RPC::EM::Message)


72
73
74
# File 'lib/arachni/rpc/em/protocol.rb', line 72

def send_message( msg )
    ::EM.schedule { send_object( msg.prepare_for_tx ) }
end

#send_object(obj) ⇒ Object

Sends a ruby object over the network

Will split the object in chunks of MAX_CHUNK_SIZE and transmit one at a time.



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/arachni/rpc/em/protocol.rb', line 122

def send_object( obj )
    data = serialize( obj )
    packed = [data.bytesize, data].pack( 'Na*' )

    while packed
        if packed.bytesize > MAX_CHUNK_SIZE
            send_data( packed.slice!( 0, MAX_CHUNK_SIZE ) )
        else
            send_data( packed )
            break
        end
    end
end

#serialize(obj) ⇒ Object



155
156
157
# File 'lib/arachni/rpc/em/protocol.rb', line 155

def serialize( obj )
    serializer.dump obj
end

#serializerClass

Returns the preferred based on the ‘serializer’ option of the server.

Defaults to YAML.



145
146
147
148
149
# File 'lib/arachni/rpc/em/protocol.rb', line 145

def serializer
    return @client_serializer if @client_serializer

    @opts[:serializer] ? @opts[:serializer] : YAML
end

#unserialize(obj) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/arachni/rpc/em/protocol.rb', line 159

def unserialize( obj )
    begin
        r = serializer.load( obj )

        if !r.is_a?( Hash ) && @opts[:fallback_serializer]
            r = @opts[:fallback_serializer].load( obj )
            @client_serializer = @opts[:fallback_serializer]
        end

        r
    rescue Exception => e
        raise if !@opts[:fallback_serializer]

        @client_serializer = @opts[:fallback_serializer]

        @opts[:fallback_serializer].load obj
    end
end