nasl-pedant 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/Rakefile +38 -0
  2. data/bin/pedant +1 -1
  3. data/lib/pedant.rb +3 -1
  4. data/lib/pedant/check.rb +20 -12
  5. data/lib/pedant/checks/conditional_or_loop_is_empty.rb +1 -1
  6. data/lib/pedant/checks/contains_ip_address_literals.rb +1 -1
  7. data/lib/pedant/checks/contains_no_carriage_returns.rb +1 -1
  8. data/lib/pedant/checks/contains_no_tabs.rb +1 -1
  9. data/lib/pedant/checks/contains_registration_section.rb +10 -4
  10. data/lib/pedant/checks/contains_unreachable_code.rb +2 -2
  11. data/lib/pedant/checks/ends_with_newline.rb +1 -1
  12. data/lib/pedant/checks/{files_parse_without_error.rb → files_parse_without_errors.rb} +1 -1
  13. data/lib/pedant/checks/local_variable_unused.rb +51 -0
  14. data/lib/pedant/checks/parse_test_code.rb +1 -1
  15. data/lib/pedant/checks/plugin_type_not_specified.rb +4 -3
  16. data/lib/pedant/checks/script_category.rb +111 -0
  17. data/lib/pedant/checks/script_family_not_specified.rb +53 -16
  18. data/lib/pedant/checks/script_id.rb +115 -0
  19. data/lib/pedant/checks/script_name.rb +133 -0
  20. data/lib/pedant/checks/script_summary.rb +142 -0
  21. data/lib/pedant/cli.rb +41 -31
  22. data/lib/pedant/command.rb +16 -29
  23. data/lib/pedant/commands/check.rb +105 -6
  24. data/lib/pedant/commands/test.rb +24 -2
  25. data/lib/pedant/knowledge_base.rb +1 -1
  26. data/lib/pedant/test.rb +5 -5
  27. data/lib/pedant/version.rb +1 -1
  28. data/pedant.gemspec +33 -6
  29. data/test/test_helper.rb +26 -0
  30. data/test/unit/checks/test_conditional_or_loop_is_empty.rb +1 -1
  31. data/test/unit/checks/test_contains_ip_address_literals.rb +1 -1
  32. data/test/unit/checks/test_contains_no_carriage_returns.rb +1 -1
  33. data/test/unit/checks/test_contains_no_tabs.rb +1 -1
  34. data/test/unit/checks/test_contains_registration_section.rb +17 -1
  35. data/test/unit/checks/test_contains_unreachable_code.rb +11 -1
  36. data/test/unit/checks/test_ends_with_newline.rb +1 -1
  37. data/test/unit/checks/test_plugin_type_not_specified.rb +9 -1
  38. data/test/unit/checks/test_script_family_not_specified.rb +54 -13
  39. metadata +30 -20
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,10 @@ module Pedant
38
38
  all << cls
39
39
  end
40
40
 
41
+ def self.list
42
+ all.map{ |cls| cls.binding }.sort
43
+ end
44
+
41
45
  def self.find(cmd)
42
46
  all.each do |cls|
43
47
  return cls if cls.binding == cmd
@@ -61,36 +65,19 @@ module Pedant
61
65
  left + middle + right
62
66
  end
63
67
 
64
- def self.run(cfg, args)
65
- # Separate plugins and libraries from the rest of the arguments.
66
- paths = args.select { |arg| arg =~ /(\/|\.(inc|nasl))$/ }
67
- args -= paths
68
-
69
- # If we have no paths to process, there's a problem. Special purpose
70
- # commands that don't require files to be declared should override this
71
- # method.
72
- if paths.empty?
73
- puts "No directories (/), libraries (.inc), or plugins (.nasl) were specified."
74
- exit 1
75
- end
68
+ def self.run(opts, args)
69
+ # Parse the command's arguments.
70
+ opts, args = optparse(opts, args)
76
71
 
77
- # Collect all the paths together, recursively.
78
- dirents = []
79
- paths.each do |path|
80
- Pathname.new(path).find do |dirent|
81
- if dirent.file? && dirent.extname =~ /inc|nasl/
82
- dirents << dirent
83
- end
84
- end
85
- end
72
+ # Run the command.
73
+ self.run_all(opts, args)
74
+ end
86
75
 
87
- # If the command is capable of handling all the paths at once, send them
88
- # in a group, otherwise send them individually.
89
- if self.respond_to? :analyze_all then
90
- analyze_all(cfg, dirents, args)
91
- else
92
- dirents.each { |d| analyze(cfg, d, args) }
93
- end
76
+ def self.usage(msg)
77
+ puts Rainbow(msg).color(:red)
78
+ puts
79
+ puts help
80
+ exit 1
94
81
  end
95
82
  end
96
83
  end
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -24,17 +24,116 @@
24
24
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
25
  ################################################################################
26
26
 
27
+ require 'set'
28
+
27
29
  module Pedant
28
30
  class CommandCheck < Command
29
31
  def self.binding
30
32
  'check'
31
33
  end
32
34
 
33
- def self.analyze(cfg, path, args)
35
+ def self.help
36
+ @@optparse.to_s
37
+ end
38
+
39
+ def self.optparse(options, args)
40
+ options[:checks] = Set.new
41
+
42
+ @@optparse = OptionParser.new do |opts|
43
+ opts.banner = "Usage: pedant [global-options] #{binding} [command-options] [args]"
44
+
45
+ opts.separator ""
46
+ opts.separator "Input formats:"
47
+
48
+ opts.on('-f', '--filesystem', 'Read input from the filesystem.') do
49
+ options[:input_mode] = :filesystem
50
+ end
51
+
52
+ opts.on('-g', '--git', 'Read input from a Git repository.') do
53
+ options[:input_mode] = :git
54
+ end
55
+
56
+ opts.separator ""
57
+ opts.separator "Output formats:"
58
+
59
+ opts.on('-e', '--email', 'Output in a form suitable for an email.') do
60
+ options[:output_mode] = :email
61
+ end
62
+
63
+ opts.on('-t', '--terminal', 'Output in a form suitable for a terminal.') do
64
+ options[:output_mode] = :terminal
65
+ end
66
+
67
+ opts.separator ""
68
+ opts.separator "Common operations:"
69
+
70
+ opts.on('-c=NAME', '--check=NAME', 'Run only the check named, and its dependencies.') do |name|
71
+ # Unmangle class name and be very forgiving.
72
+ name = "Check" + name.gsub(/[-._ ]/, '')
73
+
74
+ begin
75
+ cls = Pedant.const_get(name)
76
+ rescue NameError => e
77
+ usage(e.message)
78
+ end
79
+
80
+ options[:checks] << cls
81
+ end
82
+
83
+ opts.on('-h', '--help', 'Display this help screen.') do
84
+ puts opts
85
+ exit 1
86
+ end
87
+
88
+ opts.on('-l', '--list', 'List the available checks.') do
89
+ puts Check.list
90
+ exit 0
91
+ end
92
+ end
93
+
94
+ # Load all of the checks.
34
95
  Check.initialize!
35
96
 
36
- # Get a list of every existing check.
37
- pending = Check.all
97
+ @@optparse.order!(args)
98
+
99
+ return options, args
100
+ end
101
+
102
+ def self.run_all(opts, args)
103
+ # Separate plugins and libraries from the rest of the arguments.
104
+ paths = args.select { |a| a =~ /(\/|\.(inc|nasl))$/ }
105
+ args -= paths
106
+
107
+ # If we have paths that aren't acceptable, there's a problem.
108
+ usage("One or more unacceptable files were specified.") unless args.empty?
109
+
110
+ # If we have no paths to process, there's a problem.
111
+ usage("No directories (/), libraries (.inc), or plugins (.nasl) were specified.") if paths.empty?
112
+
113
+ # Collect all the paths together, recursively.
114
+ dirents = []
115
+ paths.each do |path|
116
+ begin
117
+ Pathname.new(path).find do |dirent|
118
+ if dirent.file? && dirent.extname =~ /inc|nasl/
119
+ dirents << dirent
120
+ end
121
+ end
122
+ rescue SystemCallError => e
123
+ usage(e.message)
124
+ end
125
+ end
126
+
127
+ dirents.each { |d| run_one(opts, d) }
128
+ end
129
+
130
+ def self.run_one(opts, path)
131
+ # Get a list of the checks we're going to be running.
132
+ if not opts[:checks].empty?
133
+ pending = opts[:checks].to_a
134
+ else
135
+ pending = Check.all
136
+ end
38
137
 
39
138
  # Initialize the knowledge base where checks can store information for
40
139
  # other checks.
@@ -63,14 +162,14 @@ module Pedant
63
162
  end
64
163
 
65
164
  # Display the results of the check.
66
- puts chk.report(cfg[:verbose])
165
+ puts chk.report(opts[:verbosity])
67
166
  end
68
167
  end
69
168
 
70
169
  # Notify the user if any checks did not run due to unsatisfied
71
170
  # dependencies or a fatal error occurring before they had the chance to
72
171
  # run.
73
- pending.each { |cls| puts cls.new(kb).report(cfg[:verbose]) }
172
+ pending.each { |cls| puts cls.new(kb).report(opts[:verbosity]) }
74
173
  end
75
174
  end
76
175
  end
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,29 @@ module Pedant
30
30
  'test'
31
31
  end
32
32
 
33
- def self.run(cfg, args)
33
+ def self.help
34
+ @@optparse.to_s
35
+ end
36
+
37
+ def self.optparse(options, args)
38
+ @@optparse = OptionParser.new do |opts|
39
+ opts.banner = "Usage: pedant [global-options] #{binding} [command-options] [args]"
40
+
41
+ opts.separator ""
42
+ opts.separator "Common operations:"
43
+
44
+ opts.on('-h', '--help', 'Display this help screen.') do
45
+ puts opts
46
+ exit 1
47
+ end
48
+ end
49
+
50
+ @@optparse.order!(args)
51
+
52
+ return options, args
53
+ end
54
+
55
+ def self.run_all(opts, args)
34
56
  Test.initialize!(args)
35
57
  end
36
58
  end
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
data/lib/pedant/test.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -28,13 +28,13 @@ require 'test/unit'
28
28
 
29
29
  module Pedant
30
30
  module Test
31
- def self.initialize!(args)
31
+ def self.initialize!(args=[])
32
32
  # Run all tests by default.
33
- args = ['unit/*', 'unit/*/*'] if args.empty?
33
+ args = ['unit/**/*'] if args.empty?
34
34
 
35
35
  # Run each test or category of tests specified on the command line.
36
- args.each do |test|
37
- Dir.glob(Pedant.test + (test + '.rb')).each { |f| load(f) }
36
+ args.each do |path|
37
+ Dir.glob(Pedant.test + (path + '.rb')).each { |f| load(f) }
38
38
  end
39
39
 
40
40
  Check.initialize!
@@ -1,3 +1,3 @@
1
1
  module Pedant
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
data/pedant.gemspec CHANGED
@@ -1,3 +1,29 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
1
27
  # -*- encoding: utf-8 -*-
2
28
  $:.push File.expand_path('../lib', __FILE__)
3
29
 
@@ -8,10 +34,11 @@ Gem::Specification.new do |s|
8
34
  s.version = Pedant::VERSION
9
35
  s.license = 'BSD'
10
36
  s.homepage = 'http://github.com/tenable/pedant'
11
- s.summary = 'A static analysis framework for the Nessus Attack Scripting Language.'
37
+ s.summary = 'A framework for the Nessus Attack Scripting Language.'
38
+ s.description = 'A static analysis framework for the Nessus Attack Scripting Language.'
12
39
 
13
- s.authors = ['Mak Kolybabi']
14
- s.email = ['mak@kolybabi.com']
40
+ s.authors = ['Mak Kolybabi', 'Alex Weber', 'Jacob Hammack']
41
+ s.email = ['mak@kolybabi.com', 'aweber@tenable.com', 'jhammack@tenable.com']
15
42
 
16
43
  s.rubyforge_project = 'nasl-pedant'
17
44
 
@@ -20,8 +47,8 @@ Gem::Specification.new do |s|
20
47
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
48
  s.require_paths = ['lib']
22
49
 
23
- s.add_development_dependency 'rake'
50
+ s.add_development_dependency 'rake', '~> 0'
24
51
 
25
- s.add_runtime_dependency 'rainbow'
26
- s.add_runtime_dependency 'nasl', '>= 0.0.7'
52
+ s.add_runtime_dependency 'rainbow', '=2.0.0'
53
+ s.add_runtime_dependency 'nasl', '~> 0.2', '>= 0.2.0'
27
54
  end
data/test/test_helper.rb CHANGED
@@ -1,3 +1,29 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
1
27
  require 'pedant'
2
28
  require 'test/unit'
3
29
 
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -98,4 +98,20 @@ class TestContainsRegistrationSection < Test::Unit::TestCase
98
98
  %q|if (description) { exit(0, foo); }|
99
99
  )
100
100
  end
101
+
102
+ def test_indexed_description
103
+ check(
104
+ :fail,
105
+ :CheckContainsRegistrationSection,
106
+ %q|if (description["foo"]) { exit(0); }|
107
+ )
108
+ end
109
+
110
+ def test_indexed_exit
111
+ check(
112
+ :fail,
113
+ :CheckContainsRegistrationSection,
114
+ %q|if (description) { exit[foo](0); }|
115
+ )
116
+ end
101
117
  end
@@ -1,5 +1,5 @@
1
1
  ################################################################################
2
- # Copyright (c) 2011, Mak Kolybabi
2
+ # Copyright (c) 2011-2014, Tenable Network Security
3
3
  # All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
@@ -90,4 +90,14 @@ class TestContainsUnreachableCode < Test::Unit::TestCase
90
90
  %q|{ continue; foo(); }|
91
91
  )
92
92
  end
93
+
94
+ # exit() is a special case in this check, because it's a function instead of a
95
+ # language keyword.
96
+ def test_indexed_exit
97
+ check(
98
+ :pass,
99
+ :CheckContainsUnreachableCode,
100
+ %q|{ exit.foo(); foo(); }|
101
+ )
102
+ end
93
103
  end