boris 1.0.0.beta.1
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.
- data/LICENSE.md +9 -0
- data/README.md +94 -0
- data/boris.gemspec +28 -0
- data/doc/Array.html +437 -0
- data/doc/Boris.html +230 -0
- data/doc/Boris/ConnectionAlreadyActive.html +123 -0
- data/doc/Boris/ConnectionFailed.html +127 -0
- data/doc/Boris/Connector.html +794 -0
- data/doc/Boris/InvalidCredentials.html +131 -0
- data/doc/Boris/InvalidOption.html +123 -0
- data/doc/Boris/InvalidTargetName.html +123 -0
- data/doc/Boris/Lumberjack.html +466 -0
- data/doc/Boris/MissingCredentials.html +123 -0
- data/doc/Boris/NoActiveConnection.html +123 -0
- data/doc/Boris/NoProfileDetected.html +123 -0
- data/doc/Boris/Options.html +783 -0
- data/doc/Boris/Profiles.html +117 -0
- data/doc/Boris/Profiles/Linux.html +1151 -0
- data/doc/Boris/Profiles/RedHat.html +875 -0
- data/doc/Boris/Profiles/Solaris.html +1230 -0
- data/doc/Boris/Profiles/Structure.html +2050 -0
- data/doc/Boris/Profiles/UNIX.html +893 -0
- data/doc/Boris/Profiles/Windows.html +1846 -0
- data/doc/Boris/Profiles/Windows/Windows2003.html +304 -0
- data/doc/Boris/Profiles/Windows/Windows2008.html +379 -0
- data/doc/Boris/Profiles/Windows/Windows2012.html +304 -0
- data/doc/Boris/SNMPConnector.html +512 -0
- data/doc/Boris/SSHConnector.html +633 -0
- data/doc/Boris/Target.html +2002 -0
- data/doc/Boris/WMIConnector.html +1134 -0
- data/doc/BorisLogger.html +217 -0
- data/doc/Hash.html +195 -0
- data/doc/String.html +1246 -0
- data/doc/_index.html +420 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +183 -0
- data/doc/file_list.html +55 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +183 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +1468 -0
- data/doc/top-level-namespace.html +126 -0
- data/lib/boris.rb +30 -0
- data/lib/boris/connectors.rb +47 -0
- data/lib/boris/connectors/snmp.rb +56 -0
- data/lib/boris/connectors/ssh.rb +110 -0
- data/lib/boris/connectors/wmi.rb +186 -0
- data/lib/boris/errors.rb +17 -0
- data/lib/boris/helpers/array.rb +63 -0
- data/lib/boris/helpers/constants.rb +20 -0
- data/lib/boris/helpers/hash.rb +8 -0
- data/lib/boris/helpers/scrubber.rb +51 -0
- data/lib/boris/helpers/string.rb +130 -0
- data/lib/boris/lumberjack.rb +47 -0
- data/lib/boris/options.rb +86 -0
- data/lib/boris/profiles/linux/redhat.rb +77 -0
- data/lib/boris/profiles/linux_core.rb +216 -0
- data/lib/boris/profiles/unix/solaris.rb +307 -0
- data/lib/boris/profiles/unix_core.rb +85 -0
- data/lib/boris/profiles/windows/windows2003.rb +15 -0
- data/lib/boris/profiles/windows/windows2008.rb +23 -0
- data/lib/boris/profiles/windows/windows2012.rb +15 -0
- data/lib/boris/profiles/windows_core.rb +530 -0
- data/lib/boris/structure.rb +167 -0
- data/lib/boris/target.rb +340 -0
- data/test/connector_tests/test_snmp.rb +35 -0
- data/test/connector_tests/test_ssh.rb +51 -0
- data/test/connector_tests/test_wmi.rb +129 -0
- data/test/helper_tests/test_array.rb +25 -0
- data/test/helper_tests/test_hash.rb +10 -0
- data/test/helper_tests/test_string.rb +136 -0
- data/test/profile_tests/test_core_skeleton +107 -0
- data/test/profile_tests/test_linux_core.rb +331 -0
- data/test/profile_tests/test_redhat.rb +134 -0
- data/test/profile_tests/test_solaris.rb +523 -0
- data/test/profile_tests/test_unix_core.rb +117 -0
- data/test/profile_tests/test_windows.rb +536 -0
- data/test/setup_tests.rb +14 -0
- data/test/test_all.rb +8 -0
- data/test/test_options.rb +44 -0
- data/test/test_structure.rb +136 -0
- data/test/test_target.rb +146 -0
- metadata +241 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.8.3
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
hasFrames = window.top.frames.main ? true : false;
|
19
|
+
relpath = '';
|
20
|
+
framesUrl = "frames.html#!" + escape(window.location.href);
|
21
|
+
</script>
|
22
|
+
|
23
|
+
|
24
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
25
|
+
|
26
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
27
|
+
|
28
|
+
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="header">
|
32
|
+
<div id="menu">
|
33
|
+
|
34
|
+
<a href="_index.html">Index</a> »
|
35
|
+
|
36
|
+
|
37
|
+
<span class="title">Top Level Namespace</span>
|
38
|
+
|
39
|
+
|
40
|
+
<div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<div id="search">
|
44
|
+
|
45
|
+
<a class="full_list_link" id="class_list_link"
|
46
|
+
href="class_list.html">
|
47
|
+
Class List
|
48
|
+
</a>
|
49
|
+
|
50
|
+
<a class="full_list_link" id="method_list_link"
|
51
|
+
href="method_list.html">
|
52
|
+
Method List
|
53
|
+
</a>
|
54
|
+
|
55
|
+
<a class="full_list_link" id="file_list_link"
|
56
|
+
href="file_list.html">
|
57
|
+
File List
|
58
|
+
</a>
|
59
|
+
|
60
|
+
</div>
|
61
|
+
<div class="clear"></div>
|
62
|
+
</div>
|
63
|
+
|
64
|
+
<iframe id="search_frame"></iframe>
|
65
|
+
|
66
|
+
<div id="content"><h1>Top Level Namespace
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
</h1>
|
71
|
+
|
72
|
+
<dl class="box">
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
</dl>
|
82
|
+
<div class="clear"></div>
|
83
|
+
|
84
|
+
<h2>Defined Under Namespace</h2>
|
85
|
+
<p class="children">
|
86
|
+
|
87
|
+
|
88
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Boris.html" title="Boris (module)">Boris</a></span>
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Array.html" title="Array (class)">Array</a></span>, <span class='object_link'><a href="BorisLogger.html" title="BorisLogger (class)">BorisLogger</a></span>, <span class='object_link'><a href="Hash.html" title="Hash (class)">Hash</a></span>, <span class='object_link'><a href="String.html" title="String (class)">String</a></span>
|
93
|
+
|
94
|
+
|
95
|
+
</p>
|
96
|
+
|
97
|
+
<h2>Constant Summary</h2>
|
98
|
+
|
99
|
+
<dl class="constants">
|
100
|
+
|
101
|
+
<dt id="PLATFORM-constant" class="">PLATFORM =
|
102
|
+
|
103
|
+
</dt>
|
104
|
+
<dd><pre class="code"><span class='const'>RbConfig</span><span class='op'>::</span><span class='const'>CONFIG</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>host_os</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span> <span class='op'>=~</span> <span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>mswin|mingw|cygwin</span><span class='regexp_end'>/</span></span> <span class='op'>?</span> <span class='symbol'>:win32</span> <span class='op'>:</span> <span class='const'>RbConfig</span><span class='op'>::</span><span class='const'>CONFIG</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>host_os</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span></pre></dd>
|
105
|
+
|
106
|
+
</dl>
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
</div>
|
118
|
+
|
119
|
+
<div id="footer">
|
120
|
+
Generated on Sun Feb 3 16:32:41 2013 by
|
121
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
122
|
+
0.8.3 (ruby-1.9.3).
|
123
|
+
</div>
|
124
|
+
|
125
|
+
</body>
|
126
|
+
</html>
|
data/lib/boris.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
PLATFORM = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ ? :win32 : RbConfig::CONFIG['host_os']
|
4
|
+
|
5
|
+
require 'date'
|
6
|
+
require 'json'
|
7
|
+
require 'logger'
|
8
|
+
require 'netaddr'
|
9
|
+
require 'net/ssh'
|
10
|
+
require 'rbconfig'
|
11
|
+
require 'snmp'
|
12
|
+
require 'socket'
|
13
|
+
require 'thread'
|
14
|
+
require 'win32ole' if PLATFORM == :win32
|
15
|
+
|
16
|
+
require 'boris/lumberjack'
|
17
|
+
|
18
|
+
require 'boris/errors'
|
19
|
+
require 'boris/options'
|
20
|
+
require 'boris/target'
|
21
|
+
|
22
|
+
require 'boris/helpers/array'
|
23
|
+
require 'boris/helpers/constants'
|
24
|
+
require 'boris/helpers/hash'
|
25
|
+
require 'boris/helpers/scrubber'
|
26
|
+
require 'boris/helpers/string'
|
27
|
+
|
28
|
+
module Boris
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Boris
|
2
|
+
class Connector
|
3
|
+
include Lumberjack
|
4
|
+
|
5
|
+
attr_reader :connected
|
6
|
+
attr_reader :host
|
7
|
+
attr_reader :options
|
8
|
+
attr_reader :reconnectable
|
9
|
+
|
10
|
+
def initialize(host, cred, options, logger=nil)
|
11
|
+
debug 'creating connection object'
|
12
|
+
|
13
|
+
@host = host
|
14
|
+
@user = cred[:user]
|
15
|
+
@password = cred[:password]
|
16
|
+
@connected = false
|
17
|
+
@reconnectable = true
|
18
|
+
|
19
|
+
@logger = logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def connected?
|
23
|
+
@connected
|
24
|
+
end
|
25
|
+
|
26
|
+
def disconnect
|
27
|
+
debug 'closing connection to host'
|
28
|
+
@connected = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def establish_connection
|
32
|
+
debug 'attempting connection'
|
33
|
+
end
|
34
|
+
|
35
|
+
def values_at(request, limit)
|
36
|
+
if !limit.kind_of?(Integer)
|
37
|
+
raise ArgumentError, "non-integer limit specified (#{limit.inspect})"
|
38
|
+
elsif limit < 1
|
39
|
+
raise ArgumentError, "specified limit must be greater than 1 (or nil for no limit) (#{limit.inspect})"
|
40
|
+
end unless limit.nil?
|
41
|
+
|
42
|
+
amount = limit == 1 ? 'single value' : 'multiple values'
|
43
|
+
|
44
|
+
debug "issuing request for #{amount} (#{request.inspect})"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'boris/connectors'
|
2
|
+
|
3
|
+
module Boris
|
4
|
+
class SNMPConnector < Connector
|
5
|
+
def initialize(host, cred, options, logger=nil)
|
6
|
+
super(host, cred, options, logger)
|
7
|
+
@snmp_options = options[:snmp_options].merge(:host=>@host, :version=>:SNMPv1, :community=>@user)
|
8
|
+
|
9
|
+
#snmp connections are always reconnectable
|
10
|
+
@reconnectable = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def disconnect
|
14
|
+
super
|
15
|
+
@transport = nil
|
16
|
+
debug 'connections closed'
|
17
|
+
end
|
18
|
+
|
19
|
+
def establish_connection
|
20
|
+
super
|
21
|
+
|
22
|
+
begin
|
23
|
+
@transport = SNMP::Manager.new(@snmp_options)
|
24
|
+
value_at('sysDescr')
|
25
|
+
debug 'connection established'
|
26
|
+
@connected = true
|
27
|
+
rescue SNMP::RequestTimeout
|
28
|
+
warn 'connection failed (connection timeout)'
|
29
|
+
rescue => error
|
30
|
+
warn "connection failed (#{error.message})"
|
31
|
+
end
|
32
|
+
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
def value_at(request)
|
37
|
+
values_at(request, 1)[0]
|
38
|
+
end
|
39
|
+
|
40
|
+
def values_at(request, limit=nil)
|
41
|
+
super(request, limit)
|
42
|
+
|
43
|
+
return_data = []
|
44
|
+
|
45
|
+
@transport.walk(request) do |row|
|
46
|
+
row.each {|item| return_data << {:name=>item.name.to_s, :value=>item.value}}
|
47
|
+
end
|
48
|
+
|
49
|
+
info "#{return_data.size} row(s) returned"
|
50
|
+
|
51
|
+
limit = return_data.size if limit.nil?
|
52
|
+
|
53
|
+
return_data[0..limit]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'boris/connectors'
|
2
|
+
|
3
|
+
module Boris
|
4
|
+
class SSHConnector < Connector
|
5
|
+
def initialize(host, cred, options, logger=nil)
|
6
|
+
@ssh_options = options[:ssh_options]
|
7
|
+
@ssh_options[:password] = @password if @password
|
8
|
+
|
9
|
+
invalid_ssh_options = @ssh_options.keys - Net::SSH::VALID_OPTIONS
|
10
|
+
raise ArgumentError, "invalid ssh option(s): #{invalid_ssh_options.join(', ')}" if invalid_ssh_options.any?
|
11
|
+
|
12
|
+
super(host, cred, options, logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
def disconnect
|
16
|
+
super
|
17
|
+
@transport = nil
|
18
|
+
debug 'connections closed'
|
19
|
+
end
|
20
|
+
|
21
|
+
def establish_connection
|
22
|
+
super
|
23
|
+
|
24
|
+
begin
|
25
|
+
@transport = Net::SSH.start(@host, @user, @ssh_options)
|
26
|
+
debug 'connection established'
|
27
|
+
@connected = @reconnectable = true
|
28
|
+
rescue Net::SSH::AuthenticationFailed
|
29
|
+
warn "connection failed (connection made but credentials not accepted with user #{@user})"
|
30
|
+
@reconnectable = true
|
31
|
+
rescue Net::SSH::HostKeyMismatch
|
32
|
+
warn 'connection failed (host key mismatch)'
|
33
|
+
@reconnectable = false
|
34
|
+
rescue => error
|
35
|
+
warn "connection failed (#{error.message})"
|
36
|
+
@reconnectable = true
|
37
|
+
end
|
38
|
+
|
39
|
+
if @reconnectable == true
|
40
|
+
info 'connection available for retry'
|
41
|
+
elsif @reconnectable == false
|
42
|
+
info 'connection does not seem to be available (so we will not retry)'
|
43
|
+
end unless @transport
|
44
|
+
|
45
|
+
return self
|
46
|
+
end
|
47
|
+
|
48
|
+
def value_at(request, request_pty=false)
|
49
|
+
values_at(request, request_pty, 1)[0]
|
50
|
+
end
|
51
|
+
|
52
|
+
def values_at(request, request_pty=false, limit=nil)
|
53
|
+
super(request, limit)
|
54
|
+
|
55
|
+
error_messages = []
|
56
|
+
reconnect = false
|
57
|
+
return_data = []
|
58
|
+
|
59
|
+
chan = @transport.open_channel do |chan|
|
60
|
+
if request_pty
|
61
|
+
debug 'requsting pty...'
|
62
|
+
chan.request_pty()
|
63
|
+
debug 'pty successfully requested'
|
64
|
+
end
|
65
|
+
|
66
|
+
chan.on_data do |ch, data|
|
67
|
+
if data =~ /^\[sudo\] password for/i
|
68
|
+
debug 'system asking for password for sudo request'
|
69
|
+
if @password
|
70
|
+
ch.send_data "#{@password}\n"
|
71
|
+
debug 'password sent'
|
72
|
+
else
|
73
|
+
ch.close
|
74
|
+
info "channel closed (we don't have a password to supply)"
|
75
|
+
end
|
76
|
+
elsif data =~ /sorry, try again/i
|
77
|
+
ch.close
|
78
|
+
return_data = []
|
79
|
+
info "channel closed (we have a password to supply but system its not accepted)"
|
80
|
+
elsif data =~ /permission denied/i
|
81
|
+
warn "permission denied for this request (#{data.gsub(/\n|\s+/, ', ')})"
|
82
|
+
else
|
83
|
+
return_data << data
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# called when something is written to stderr
|
88
|
+
chan.on_extended_data do |ch, type, data|
|
89
|
+
error_messages.concat(data.split(/\n/))
|
90
|
+
end
|
91
|
+
|
92
|
+
chan.exec(request)
|
93
|
+
end
|
94
|
+
|
95
|
+
chan.wait
|
96
|
+
|
97
|
+
if !error_messages.empty?
|
98
|
+
warn "message written to STDERR for this request (#{error_messages.join('. ')})"
|
99
|
+
end
|
100
|
+
|
101
|
+
return_data = return_data.join.split(/\n/)
|
102
|
+
|
103
|
+
info "#{return_data.size} row(s) returned"
|
104
|
+
|
105
|
+
limit = return_data.size if limit.nil?
|
106
|
+
|
107
|
+
return_data[0..limit]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'boris/connectors'
|
2
|
+
|
3
|
+
module Boris
|
4
|
+
class WMIConnector < Connector
|
5
|
+
attr_accessor :wmi, :root_wmi, :registry
|
6
|
+
|
7
|
+
HKEY_LOCAL_MACHINE = 0x80000002
|
8
|
+
KEY_QUERY_VALUE = 1
|
9
|
+
KEY_ENUMERATE_SUB_KEYS = 8
|
10
|
+
|
11
|
+
def initialize(host, cred, options, logger=nil)
|
12
|
+
super(host, cred, options, logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
def disconnect
|
16
|
+
super
|
17
|
+
@wmi = nil
|
18
|
+
@registry = nil
|
19
|
+
@root_wmi = nil
|
20
|
+
|
21
|
+
debug 'connections closed'
|
22
|
+
end
|
23
|
+
|
24
|
+
def establish_connection
|
25
|
+
super
|
26
|
+
|
27
|
+
begin
|
28
|
+
locator = WIN32OLE.new('WbemScripting.SWbemLocator')
|
29
|
+
|
30
|
+
debug 'attempting connection to cimv2 namespace'
|
31
|
+
@wmi = locator.ConnectServer(@host, 'root\cimv2', @user, @password, nil, nil, 128)
|
32
|
+
debug 'connection to cimv2 namespace successful'
|
33
|
+
|
34
|
+
debug 'attempting connection to wmi root namespace'
|
35
|
+
@root_wmi = locator.ConnectServer(@host, 'root\WMI', @user, @password, nil, nil, 128)
|
36
|
+
debug 'connection to wmi root namespace successful'
|
37
|
+
|
38
|
+
debug 'attempting connection to registry'
|
39
|
+
@registry = locator.ConnectServer(@host, 'root\default', @user, @password, nil, nil, 128).Get('StdRegProv')
|
40
|
+
debug 'connection to registry successful'
|
41
|
+
|
42
|
+
debug 'all required connections established'
|
43
|
+
@connected = @reconnectable = true
|
44
|
+
|
45
|
+
rescue WIN32OLERuntimeError => error
|
46
|
+
@connected = false
|
47
|
+
if error.message =~ /access is denied/i
|
48
|
+
warn "connection failed (connection made but credentials not accepted with user #{@user})"
|
49
|
+
@reconnectable = true
|
50
|
+
elsif error.message =~ /rpc server is unavailable/i
|
51
|
+
warn 'connection failed (rpc server not available)'
|
52
|
+
@reconnectable = false
|
53
|
+
else
|
54
|
+
warn "connection failed (#{error.message.gsub(/\n\s*/, '. ')})"
|
55
|
+
@reconnectable = true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if @reconnectable == true
|
60
|
+
info 'connection available for retry'
|
61
|
+
elsif @reconnectable == false
|
62
|
+
info 'connection does not seem to be available (so we will not retry)'
|
63
|
+
end unless @transport
|
64
|
+
|
65
|
+
return self
|
66
|
+
end
|
67
|
+
|
68
|
+
def value_at(request, conn=:wmi)
|
69
|
+
values_at(request, conn, limit=1)[0]
|
70
|
+
end
|
71
|
+
|
72
|
+
def values_at(request, conn=:wmi, limit=nil)
|
73
|
+
super(request, limit)
|
74
|
+
|
75
|
+
rows = case conn
|
76
|
+
when :root_wmi
|
77
|
+
@root_wmi.ExecQuery(request, nil, 48)
|
78
|
+
when :wmi
|
79
|
+
@wmi.ExecQuery(request, nil, 48)
|
80
|
+
end
|
81
|
+
|
82
|
+
return_data = []
|
83
|
+
|
84
|
+
i = 0
|
85
|
+
|
86
|
+
rows.each do |row|
|
87
|
+
i += 1
|
88
|
+
|
89
|
+
return_hash = {}
|
90
|
+
|
91
|
+
row.Properties_.each do |property|
|
92
|
+
if property.Name =~ /^attributes/i && property.Value.kind_of?(WIN32OLE)
|
93
|
+
row.Attributes.Properties_.each do |property|
|
94
|
+
return_hash[property.Name.downcase.to_sym] = property.Value
|
95
|
+
end
|
96
|
+
else
|
97
|
+
return_hash[property.Name.downcase.to_sym] = property.Value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
return_data << return_hash
|
102
|
+
|
103
|
+
break if (limit.nil? && i == limit)
|
104
|
+
end
|
105
|
+
|
106
|
+
info "#{return_data.size} row(s) returned"
|
107
|
+
|
108
|
+
return return_data
|
109
|
+
end
|
110
|
+
|
111
|
+
def has_access_for(key_path, permission_to_check=nil)
|
112
|
+
debug "checking for registry read access for #{key_path}"
|
113
|
+
|
114
|
+
access_params = @registry.Methods_('CheckAccess').inParameters.SpawnInstance_
|
115
|
+
|
116
|
+
access_params.hDefKey = HKEY_LOCAL_MACHINE
|
117
|
+
access_params.sSubKeyName = key_path
|
118
|
+
access_params.uRequired = permission_to_check
|
119
|
+
|
120
|
+
@registry.ExecMethod_('CheckAccess', access_params).bGranted
|
121
|
+
end
|
122
|
+
|
123
|
+
def registry_subkeys_at(key_path)
|
124
|
+
return_data = []
|
125
|
+
|
126
|
+
debug "reading registry subkeys at path #{key_path}"
|
127
|
+
|
128
|
+
if has_access_for(key_path, KEY_ENUMERATE_SUB_KEYS)
|
129
|
+
in_params = @registry.Methods_('EnumKey').inParameters.SpawnInstance_
|
130
|
+
in_params.hDefKey = HKEY_LOCAL_MACHINE
|
131
|
+
in_params.sSubKeyName = key_path
|
132
|
+
|
133
|
+
@registry.ExecMethod_('EnumKey', in_params).sNames.each do |key|
|
134
|
+
return_data << key_path + '\\' + key
|
135
|
+
end
|
136
|
+
else
|
137
|
+
info "no access for enumerating keys at (#{key_path})"
|
138
|
+
end
|
139
|
+
|
140
|
+
return return_data
|
141
|
+
end
|
142
|
+
|
143
|
+
def registry_values_at(key_path)
|
144
|
+
values = Hash.new
|
145
|
+
|
146
|
+
debug "reading registry values at path #{key_path}"
|
147
|
+
|
148
|
+
if has_access_for(key_path, KEY_QUERY_VALUE)
|
149
|
+
in_params = @registry.Methods_('EnumValues').inParameters.SpawnInstance_
|
150
|
+
in_params.hDefKey = HKEY_LOCAL_MACHINE
|
151
|
+
in_params.sSubKeyName = key_path
|
152
|
+
|
153
|
+
str_params = @registry.Methods_('GetStringValue').inParameters.SpawnInstance_
|
154
|
+
str_params.sSubKeyName = key_path
|
155
|
+
|
156
|
+
subkey_values = @registry.ExecMethod_('EnumValues', in_params).sNames
|
157
|
+
subkey_values ||= []
|
158
|
+
|
159
|
+
subkey_values.each do |value|
|
160
|
+
if !value.empty?
|
161
|
+
str_params.sValueName = value
|
162
|
+
|
163
|
+
begin
|
164
|
+
x = @registry.ExecMethod_('GetStringValue', str_params).sValue
|
165
|
+
x = @registry.ExecMethod_('GetBinaryValue', str_params).uValue unless x
|
166
|
+
x = @registry.ExecMethod_('GetDWORDValue', str_params).uValue unless x
|
167
|
+
x = @registry.ExecMethod_('GetExpandedStringValue', str_params).sValue unless x
|
168
|
+
x = @registry.ExecMethod_('GetMultiStringValue', str_params).sValue unless x
|
169
|
+
x = @registry.ExecMethod_('GetQWORDValue', str_params).uValue unless x
|
170
|
+
|
171
|
+
values[value.downcase.to_sym] = x
|
172
|
+
rescue
|
173
|
+
if $!.message =~ /#{invalid method}/i
|
174
|
+
warn "unreadable registry value (#{key_path}\\#{value})"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
else
|
180
|
+
info "no access for enumerating values at (#{key_path})"
|
181
|
+
end
|
182
|
+
|
183
|
+
return values
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|