File Coverage

blib/lib/OpenVAS/OMP.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             #
3             # Filename: OMP.pm
4             # Description: Pure-Perl interface to the OpenVAS Management Protocol
5             # Creator: Winfried Neessen
6             #
7             # $Id$
8             #
9             # Last modified: [ 2013-06-12 12:13:43 ]
10              
11             ## This is the OpenVAS::OMP package {{{
12             package OpenVAS::OMP;
13              
14             ### Global modules {{{
15 1     1   41671 use strict;
  1         2  
  1         44  
16 1     1   7 use warnings;
  1         3  
  1         39  
17 1     1   6 use Carp;
  1         8  
  1         111  
18 1     1   1597 use IO::Socket::SSL;
  1         200402  
  1         12  
19 1     1   2950 use XML::Simple qw( :strict );
  0            
  0            
20             # }}}
21              
22             ### Global variables {{{
23             our $VERSION = '0.04';
24             # }}}
25              
26             ### Constants definitions {{{
27             use constant CHUNK_SIZE => 8192;
28             use constant CONN_TIMEOUT => 30;
29             use constant DEFAULT_PORT => 9390;
30             use constant DEFAULT_HOST => 'localhost';
31             use constant DEFAULT_SSL_VERIFY => 0;
32             # }}}
33              
34             #### Public methods
35              
36             ### Module constructor // new() {{{
37             sub new
38             {
39              
40             ## Create class and read arguments
41             my ( $class, %args ) = @_;
42             my $self = bless {}, $class;
43              
44             ## Read arguments
45             $self->{ 'host' } = delete( $args{ 'host' } ) || DEFAULT_HOST;
46             $self->{ 'timeout' } = delete( $args{ 'timeout' } ) || CONN_TIMEOUT;
47             $self->{ 'port' } = delete( $args{ 'port' } ) || DEFAULT_PORT;
48             $self->{ 'ssl_verify' } = delete( $args{ 'ssl_verify' } ) || DEFAULT_SSL_VERIFY;
49             $self->{ 'username' } = delete( $args{ 'username' } );
50             $self->{ 'password' } = delete( $args{ 'password' } );
51              
52             ## Check for mantatory arguments
53             croak( 'No host argument given' )
54             unless( defined( $self->{ 'host' } ) and $self->{ 'host' } ne '' );
55             croak( 'No port argument given' )
56             unless( defined( $self->{ 'port' } ) and $self->{ 'port' } ne '' );
57             croak( 'Unsupported value "' . $self->{ 'ssl_verify' } . '" for argument "ssl_verify".' )
58             if( $self->{ 'ssl_verify' } < 0 or $self->{ 'ssl_verify' } > 1 );
59              
60             ## Warn about unrecognized arguments
61             carp( "Unrecognized arguments: @{ [ sort keys %args ] }" ) if %args;
62              
63             ## Return object
64             return $self;
65              
66             }
67             # }}}
68              
69             ### Send a request (hashref) to the OMP and return a XML hashref (or raw XML) // commandHash() {{{
70             sub commandHash
71             {
72              
73             ## Get object and arguments
74             my ( $self, $cmdHash, $raw ) = @_;
75              
76             ## cmdHash needs to be a hash/hashref
77             croak( 'Method "commandHash()" requires the first argument to be a hash/hashref' )
78             unless( ref( $cmdHash ) eq 'HASH' );
79              
80             ## Convert command hash to XML
81             my $cmdXML = XMLout( $cmdHash, NoEscape => 0, SuppressEmpty => 1, KeepRoot => 1, KeyAttr => 'command' );
82              
83             ## Send commandXML to server
84             my $response = $self->_sendSock( $cmdXML );
85              
86             ## Close socket connection
87             $self->{ 'socket' }->close();
88              
89             ## Return RAW or hashref version
90             if( defined( $raw ) )
91             {
92             return $response;
93             } else {
94             return XMLin( $response, ForceArray => 1, KeyAttr => 'command_response' );
95             }
96              
97             }
98             # }}}
99              
100             ### Send a request (pure XML) to the OMP and return a XML hashref (or raw XML) // commandXML() {{{
101             sub commandXML
102             {
103              
104             ## Get object and arguments
105             my ( $self, $cmdXML, $raw ) = @_;
106              
107             ## cmdHash needs to be a hash/hashref
108             croak( 'Method "commandXML()" requires the first argument to be a hash/hashref' )
109             unless( defined( $cmdXML ) and ref( $cmdXML ) eq '' );
110              
111             ## Send commandXML to server
112             my $response = $self->_sendSock( $cmdXML );
113              
114             ## Close socket connection
115             $self->{ 'socket' }->close();
116              
117             ## Return RAW or hashref version
118             if( defined( $raw ) )
119             {
120             return $response;
121             } else {
122             return XMLin( $response, ForceArray => 1, KeyAttr => 'command_response' );
123             }
124              
125             }
126             # }}}
127              
128             ### Request version string from OMP server // getVersion() {{{
129             sub getVersion
130             {
131              
132             ## Get object
133             my $self = shift;
134              
135             ## Connect and authenticate with OMP server
136             $self->_connect();
137              
138             ## Send commandXML to server
139             $self->{ 'socket' }->syswrite( '' );
140             my $response = XMLin( $self->_readSock, ForceArray => 1, KeyAttr => 'command_response' );
141              
142             ## Check respone
143             croak( 'getVersion failed: ' . $response->{ 'status_text' } )
144             unless( defined( $response->{ 'status' } ) and $response->{ 'status' } eq '200' );
145            
146             ## Return response
147             print STDERR 'OMP server version: ' . $response->{ 'version' }->[0] . "\n";
148             return $response->{ 'version' }->[0];
149              
150             }
151             # }}}
152              
153              
154             #### Private methods
155              
156             ### Initiate a SSL connection with the server // _connect() {{{
157             sub _connect
158             {
159              
160             ## Get object
161             my $self = shift;
162              
163             ## Create a SSL socket
164             my $socket = IO::Socket::SSL->new
165             (
166              
167             PeerHost => $self->{ 'host' },
168             PeerPort => $self->{ 'port' },
169              
170             Timeout => $self->{ 'timeout' },
171             Proto => 'tcp',
172              
173             SSL_verify_mode => $self->{ 'ssl_verify' },
174            
175             ) or croak( 'Unable to connect to host ' . $self->{ 'host' } . ':' . $self->{ 'port' } . ': ' . &IO::Socket::SSL::errstr );
176              
177             ## Reference socket in the object
178             $self->{ 'socket' } = \*$socket;
179              
180             }
181             # }}}
182              
183             ### Authenticate with the OMP server // _authenticate() {{{
184             sub _authenticate
185             {
186              
187             ## Get object
188             my $self = shift;
189              
190             ## Make sure the everything required is available
191             croak( 'Not connected with the OMP server' )
192             unless( defined( $self->{ 'socket' } ) and ref( $self->{ 'socket' } ) eq 'IO::Socket::SSL' );
193             croak( 'Username or password not provided' )
194             unless( defined( $self->{ 'username' } ) and defined( $self->{ 'password' } ) );
195              
196             ## Generate XML authentication string
197             my ( $auth, $authXML );
198             $auth->{ 'authenticate' }->{ 'credentials' } = [ { 'username' => [ $self->{ 'username' } ], 'password' => [ $self->{ 'password' } ] } ];
199             $authXML = XMLout( $auth, NoEscape => 0, SuppressEmpty => 1, KeepRoot => 1, KeyAttr => 'authenticate' );
200              
201             ## Send authentication string to OMP server and read response
202             $self->{ 'socket' }->syswrite( $authXML );
203             my $response = $self->_readSock;
204              
205             ## Check repsonse
206             my $authResponse = XMLin( $response, ForceArray => 1, KeyAttr => 'authenticate_response' );
207             if( defined( $authResponse->{ 'status' } ) and $authResponse->{ 'status' } eq '200' )
208             {
209             return 1;
210             }
211             elsif( defined( $authResponse->{ 'status' } ) and $authResponse->{ 'status' } ne '200' )
212             {
213             carp( 'Error: ' . $authResponse->{ 'status_text' } );
214             return undef;
215             }
216             else
217             {
218             carp( 'Unexpected failure.' );
219             return undef;
220             }
221              
222             }
223             # }}}
224              
225             ### Send date to socket // _sendSock() {{{
226             sub _sendSock
227             {
228              
229             ## Get object
230             my ( $self, $cmdXML ) = @_;
231              
232             ## Connect and authenticate with OMP server
233             $self->_connect();
234             $self->_authenticate();
235              
236             ## Send commandXML to server
237             $self->{ 'socket' }->syswrite( $cmdXML );
238             my $response = $self->_readSock;
239              
240             ## Return the server response
241             return $response;
242              
243             }
244             # }}}
245              
246             ### Read from socket // _readSock() {{{
247             sub _readSock
248             {
249              
250             ## Get object
251             my $self = shift;
252              
253             ## Make sure we are connected to the OMP server
254             croak( 'Not connected with the OMP server' )
255             unless( defined( $self->{ 'socket' } ) and ref( $self->{ 'socket' } ) eq 'IO::Socket::SSL' );
256              
257             ## Read from socket
258             my ( $length, $response );
259             do {
260              
261             $length = $self->{ 'socket' }->sysread( my $buffer, CHUNK_SIZE );
262             undef $length if( $length == 0 );
263             undef $length if( $length < CHUNK_SIZE );
264              
265             $response .= $buffer if defined( $buffer );
266              
267             } while ( $length );
268              
269             ## Return the response
270             return $response;
271              
272             }
273             # }}}
274              
275              
276              
277             1;
278             __END__