-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathconnection.lua
126 lines (104 loc) · 2.82 KB
/
connection.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
require 'socket'
require 'ssl'
require 'yaml'
--
-- Arachni RPC Connection handler
--
-- Takes care of:
-- * SSL
-- * Buffering
-- * Object serialization and transmission
--
ArachniRPCConnection = {}
--
-- opts:
-- * host
-- * port
-- * key = SSL key in PEM format
-- * certificate = SSL cert in PEM format
-- * cafile = CA file in PEM format
--
function ArachniRPCConnection:new( opts )
opts = opts or {}
setmetatable( opts, self )
self.__index = self
-- create SSL socket
conn = socket.tcp()
opts.mode = 'client'
opts.protocol = 'tlsv1'
if opts.key and opts.certificate and opts.cafile then
opts.verify = { "peer", "fail_if_no_peer_cert" }
end
conn:connect( opts.host, opts.port )
conn = ssl.wrap( conn, opts )
conn:dohandshake()
self.socket = conn
-- this will be our receive buffer
self.buffer = ''
return self
end
function ArachniRPCConnection:close()
self.socket:close()
end
--
-- Serializes, packs and sends an object
--
function ArachniRPCConnection:send_object( obj )
self.socket:send( self:pack_with_size( yaml.dump( obj ) ) )
end
--
-- Waits until done receiving an object and returns said object
--
function ArachniRPCConnection:receive_object()
local serialized = self:receive_data()
-- print( serialized )
return yaml.load( serialized )
end
--
-- Pay no attention to the man behind the curtain,
-- i.e. don't count on the following functions.
--
--
-- Waits until a serialized object has been received and returns
-- the serialized version.
--
function ArachniRPCConnection:receive_data()
-- wait until the header, which is basically the size
-- of the response, arrives
header = nil
while not header do
header = self.socket:receive( 4 )
end
-- wait until the whole response arrives
return self.socket:receive( self:get_size( header ) )
end
--
-- Unpacks the received payload and returns its size.
--
function ArachniRPCConnection:get_size( payload )
-- first 4 chars are the size packed as
-- null-padded, 32-bit unsigned, network (big-endian) byte order
-- so we need to convert them from binary to proper ASCII...
local size = 4
local val = payload:sub( 1, size )
local value = 0
for j= 1, size do
value = value * 256 + val:byte( j )
end
return unpack( {value} )
end
--
-- Prepares a payload for transmission by packing it with its size.
--
function ArachniRPCConnection:pack_with_size( payload )
local bin = ''
print( payload )
length = payload:len()
for i = 1, 4 do
bin = bin .. string.char( length % 256 )
length = math.floor( length / 256 )
end
-- prefix the payload with its size packed as
-- 4 char, null-padded, 32-bit unsigned, network (big-endian) byte order
return string.reverse( bin ) .. payload
end