nasl-pedant 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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