boris 1.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|