clamav-client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ # ClamAV::Client
2
+
3
+ ClamAV::Client is a client library that can talk to the clam daemon.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'clamav-client', require: 'clamav/client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install clamav-client
18
+
19
+ Alternatively, you can spawn a `pry` console right away by just running:
20
+
21
+ $ rake console
22
+
23
+ ## Requirements
24
+
25
+ * Ruby >= 2 (and Ruby >= 2.1 to be able to contribute to the project as it's making use of required keyword arguments)
26
+ * clamd
27
+
28
+ ## Usage
29
+
30
+ The `ClamAV::Client` class is responsible for opening a connection to a remote
31
+ ClamAV clam daemon.
32
+
33
+ You will find below the implemented commands.
34
+
35
+ ### PING => Boolean
36
+
37
+ Pings the daemon to check whether it is alive.
38
+
39
+ client = ClamAV::Client.new
40
+ client.execute(ClamAV::Commands::PingCommand.new)
41
+ => true
42
+
43
+ ### SCAN <file_or_directory> => Array[Response]
44
+
45
+ Scans a file or a directory for the existence of a virus.
46
+
47
+ The absolute path must be given to that command.
48
+
49
+ client = ClamAV::Client.new
50
+
51
+ client.execute(ClamAV::Commands::ScanCommand.new('/tmp/path/foo.c')
52
+ => [#<ClamAV::SuccessResponse:0x007fbf314b9478 @file="/tmp/foo.c">]
53
+
54
+ client.execute(ClamAV::Commands::ScanCommand.new('/tmp/path')
55
+ => [#<ClamAV::SuccessResponse:0x007fc30c273298 @file="/tmp/path/foo.c">,
56
+ #<ClamAV::SuccessResponse:0x007fc30c272910 @file="/tmp/path/foo.cpp">]
57
+
58
+
59
+ ### Custom commands
60
+
61
+ Custom commands can be given to the client. The contract between the client
62
+ and the command is thru the `call` method call. The `call` method is being
63
+ passed a `Connection` object.
64
+
65
+ Here's a simple example that implements the `VERSION` command:
66
+
67
+ # Build the client
68
+ client = ClamAV::Client.new
69
+
70
+ # Create the command lambda
71
+ version_command = lambda { |conn| conn.send_request("VERSION") }
72
+ => #<Proc:0x007fc0d0c14b28>
73
+
74
+ # Execute the command
75
+ client.execute(version_command)
76
+ => "1: ClamAV 0.98.1/18489/Tue Feb 18 16:00:05 2014"
77
+
78
+
79
+ ## Defaults
80
+
81
+ The default values in use are:
82
+
83
+ * clamd socket: UNIX Socket, located at `/tmp/clamd/socket`;
84
+ * New-line terminated commands.
85
+
86
+ These defaults can be changed by injecting new defaults.
87
+
88
+ ## Injecting dependencies
89
+
90
+ ### Client
91
+
92
+ The main object is the `Client` object. It is responsible for executing the commands.
93
+ This object can receive a custom connection object.
94
+
95
+ ### Connection
96
+
97
+ The connection object is the bridge between the raw socket object and the
98
+ protocol being used between the client and the daemon.
99
+
100
+ `clamd` supports two kinds of delimiters:
101
+
102
+ * NULL terminated commands
103
+ * New-line terminated commands
104
+
105
+ The management of those delimiters is done with the wrapper argument.
106
+
107
+ ### Wrapper
108
+
109
+ The wrapper is responsible for taking the incoming request with the
110
+ `wrap_request` method, and parsing the response with the `read_response`
111
+ method.
112
+
113
+
114
+ ## Contributing
115
+
116
+ 1. Fork it ( https://github.com/franckverrot/clamav-client/fork )
117
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
118
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
119
+ 4. Push to the branch (`git push origin my-new-feature`)
120
+ 5. Create new Pull Request
@@ -0,0 +1,104 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'rubygems'
18
+ require 'rubygems/specification'
19
+
20
+ require 'bundler'
21
+ Bundler::GemHelper.install_tasks
22
+
23
+ $:<< 'lib'
24
+ require 'clamav/client'
25
+
26
+ $stdout.puts """
27
+ ClamAV::Client Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
28
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `rake license'.
29
+ This is free software, and you are welcome to redistribute it
30
+ under certain conditions; type `rake license' for details.
31
+
32
+ """
33
+
34
+ require 'rake/testtask'
35
+ Rake::TestTask.new do |t|
36
+ t.libs << "test"
37
+ t.pattern = "test/**/*_test.rb"
38
+ #t.verbose = true
39
+ #t.warning = true
40
+ end
41
+
42
+ Rake::TestTask.new(:unit_tests) do |t|
43
+ t.libs << "test"
44
+ t.pattern = "test/unit/**/*_test.rb"
45
+ #t.verbose = true
46
+ #t.warning = true
47
+ end
48
+
49
+ Rake::TestTask.new(:integration_tests) do |t|
50
+ t.libs << "test"
51
+ t.pattern = "test/integration/**/*_test.rb"
52
+ #t.verbose = true
53
+ #t.warning = true
54
+ end
55
+
56
+
57
+ def gemspec
58
+ @gemspec ||= begin
59
+ file = File.expand_path('../clamav-client.gemspec', __FILE__)
60
+ eval(File.read(file), binding, file)
61
+ end
62
+ end
63
+
64
+ desc "Clean the current directory"
65
+ task :clean do
66
+ rm_rf 'tmp'
67
+ rm_rf 'pkg'
68
+ end
69
+
70
+ desc "Run the full spec suite"
71
+ task :full => ["clean", "test"]
72
+
73
+ desc "install the gem locally"
74
+ task :install => :package do
75
+ sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}}
76
+ end
77
+
78
+ desc "validate the gemspec"
79
+ task :gemspec do
80
+ gemspec.validate
81
+ end
82
+
83
+ desc "Build the gem"
84
+ task :gem => [:gemspec, :build] do
85
+ mkdir_p "pkg"
86
+ sh "gem build clamav-client.gemspec"
87
+ mv "#{gemspec.full_name}.gem", "pkg"
88
+ end
89
+
90
+ desc "Install ClamAV::Client"
91
+ task :install => :gem do
92
+ sh "gem install pkg/#{gemspec.full_name}.gem"
93
+ end
94
+
95
+ task :default => :full
96
+
97
+ task :license do
98
+ `open http://www.gnu.org/licenses/gpl.txt`
99
+ end
100
+
101
+ task :console do
102
+ require 'pry'
103
+ Pry.start
104
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ $:<< 'lib'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "clamav-client"
6
+ spec.version = "1.0.0"
7
+ spec.authors = ["Franck Verrot"]
8
+ spec.email = ["franck@verrot.fr"]
9
+ spec.summary = %q{ClamAV::Client connects to a Clam Anti-Virus clam daemon and send commands.}
10
+ spec.description = spec.summary
11
+ spec.homepage = "https://github.com/franckverrot/clamav-client"
12
+ spec.license = "GPLv3"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.5"
20
+ spec.add_development_dependency "rake"
21
+ spec.add_development_dependency "pry"
22
+ end
@@ -0,0 +1,43 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require "clamav/connection"
18
+ require "clamav/commands/ping_command"
19
+ require "clamav/commands/quit_command"
20
+ require "clamav/commands/scan_command"
21
+ require "clamav/util"
22
+ require "clamav/wrappers/new_line_wrapper"
23
+ require "clamav/wrappers/null_termination_wrapper"
24
+
25
+ module ClamAV
26
+ class Client
27
+ def initialize(connection = default_connection)
28
+ @connection = connection
29
+ connection.establish_connection
30
+ end
31
+
32
+ def execute(command)
33
+ command.(@connection)
34
+ end
35
+
36
+ def default_connection
37
+ ClamAV::Connection.new(
38
+ socket: ::UNIXSocket.new('/tmp/clamd.socket'),
39
+ wrapper: ::ClamAV::Wrappers::NewLineWrapper.new
40
+ )
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ module ClamAV
17
+ module Commands
18
+ class Command
19
+ def call
20
+ raise NotImplementedError.new
21
+ end
22
+
23
+ protected
24
+ def execute
25
+ conn.puts data + "\n"
26
+ response = conn.gets.chomp
27
+ conn.close
28
+ response
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ require 'clamav/commands/command'
17
+
18
+ module ClamAV
19
+ module Commands
20
+ class PingCommand < Command
21
+ def call(conn)
22
+ !!(/\d+: PONG/.match(conn.send_request("PING")))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ require 'clamav/commands/command'
17
+
18
+ module ClamAV
19
+ module Commands
20
+ class QuitCommand < Command
21
+ def call(conn)
22
+ conn.send_request("QUIT").nil?
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'clamav/commands/command'
18
+ require 'clamav/responses/error_response'
19
+ require 'clamav/responses/success_response'
20
+ require 'clamav/responses/virus_response'
21
+ module ClamAV
22
+ module Commands
23
+ class ScanCommand < Command
24
+ Statuses = {
25
+ 'ERROR' => ClamAV::ErrorResponse,
26
+ 'OK' => ClamAV::SuccessResponse,
27
+ 'ClamAV-Test-Signature FOUND' => ClamAV::VirusResponse
28
+ }
29
+
30
+ def initialize(path, path_finder = Util)
31
+ @path, @path_finder = path, path_finder
32
+ end
33
+
34
+ def call(conn)
35
+ @path_finder.path_to_files(@path).map { |file| scan_file(conn, file) }
36
+ end
37
+
38
+ protected
39
+ def scan_file(conn, file)
40
+ get_status_from_response(conn.send_request("SCAN #{file}"))
41
+ end
42
+
43
+ def get_status_from_response(str)
44
+ case str
45
+ when 'Error processing command. ERROR'
46
+ ErrorResponse.new(str)
47
+ else
48
+ /(?<id>\d+): (?<filepath>.*): (?<status>.*)/ =~ str
49
+ Statuses[status].new(filepath)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ # clamav-client - ClamAV client
2
+ # Copyright (C) 2014 Franck Verrot <franck@verrot.fr>
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'socket'
18
+
19
+ module ClamAV
20
+ class Connection
21
+ def initialize(socket:, wrapper:)
22
+ @socket = socket
23
+ @wrapper = wrapper
24
+ end
25
+
26
+ def establish_connection
27
+ wrapped_request = @wrapper.wrap_request("IDSESSION")
28
+ @socket.write wrapped_request
29
+ end
30
+
31
+ def send_request(str)
32
+ wrapped_request = @wrapper.wrap_request(str)
33
+ @socket.write wrapped_request
34
+ @wrapper.read_response(@socket)
35
+ end
36
+ end
37
+ end