utm-plc 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.mkd +7 -0
- data/bin/plc +2 -1
- data/lib/utm-plc.rb +226 -147
- metadata +40 -25
- data/bin/plc.rb +0 -227
data/README.mkd
CHANGED
@@ -39,6 +39,13 @@ Here is a general overview of how it works.
|
|
39
39
|
-) If the action doesn't log both accessed and logged pages, add to the list of results
|
40
40
|
5) Print results.
|
41
41
|
|
42
|
+
### Does it have to have root? ###
|
43
|
+
|
44
|
+
Sadly yes. One would hope that you could have read-only access to `cc` as `loginuser` but trying
|
45
|
+
this simply results in a "Permission denied" error and `cc` fails to open. As an interface with
|
46
|
+
WebAdmin is not yet available, root access is required to access the information from the
|
47
|
+
back-end.
|
48
|
+
|
42
49
|
### What does it look like? ###
|
43
50
|
|
44
51
|
Here, let me show you. In this configuration, the main web filter (under Web Protection -> Web Filter)
|
data/bin/plc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#!/usr/bin/env
|
1
|
+
#!/usr/bin/env ruby1.9.1
|
2
2
|
require 'fileutils'
|
3
3
|
#Add the library from the source tree if exists, this allows
|
4
4
|
#testing without installing the gem first
|
@@ -6,5 +6,6 @@ if File.exist? File.join('lib', 'utm-plc.rb')
|
|
6
6
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
7
7
|
end
|
8
8
|
require 'utm-plc'
|
9
|
+
$logging=true
|
9
10
|
|
10
11
|
run
|
data/lib/utm-plc.rb
CHANGED
@@ -22,216 +22,295 @@ require 'pty'
|
|
22
22
|
require 'timeout'
|
23
23
|
require 'pp'
|
24
24
|
|
25
|
-
def _host;
|
26
|
-
def _port;
|
27
|
-
def _lu_password; prompt('What is the password for loginuser?: ', true)
|
28
|
-
def _ru_password;
|
25
|
+
def _host; prompt('Which host?: ') end
|
26
|
+
def _port; prompt('What port?: ') end
|
27
|
+
def _lu_password; prompt('What is the password for loginuser?: ', true) end
|
28
|
+
def _ru_password; prompt('What is the password for root?: ', true) end
|
29
29
|
|
30
30
|
$logging=false
|
31
31
|
$debugging=false
|
32
32
|
|
33
|
+
def fingerprint_prompt? string
|
34
|
+
!string[/\(yes\/no\)\?/].nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
def wrong_password? buffer, regexp
|
38
|
+
!buffer[ Regexp.new( regexp ) ].nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
def err_check buffer
|
42
|
+
if fingerprint_prompt?(buffer)
|
43
|
+
printf "SSH Fingerprint prompt detected.\nPlease SSH to this system at least once before using this program to verify the SSH fingerprint manually, then run this program again.\n\n"
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
|
47
|
+
if wrong_password?(buffer, 'Permission denied')
|
48
|
+
printf "Permission denied! Get off my lawn!\n"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
if wrong_password?(buffer, 'incorrect password')
|
53
|
+
printf "Bad root password! Go away!\n"
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def until_prompt( prompt, alt=false )
|
59
|
+
buffer= ""
|
60
|
+
begin
|
61
|
+
Timeout.timeout( 60 ) {
|
62
|
+
loop do
|
63
|
+
buffer << $out.getc.chr
|
64
|
+
err_check( buffer )
|
65
|
+
break if buffer =~ Regexp.new(prompt)
|
66
|
+
end
|
67
|
+
}
|
68
|
+
return buffer
|
69
|
+
rescue Timeout::Error => error
|
70
|
+
printf "Error - Timed out waiting for \"#{prompt.gsub('"','\"') }\", printing stacktrace...\n "
|
71
|
+
printf error.backtrace.join("\n") + "\n"
|
72
|
+
printf "Dumping buffer...\n"
|
73
|
+
pp buffer
|
74
|
+
printf "-------\n\n"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
33
78
|
def disable_echo &block
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
79
|
+
system('stty -echo')
|
80
|
+
x=yield
|
81
|
+
system('stty echo')
|
82
|
+
#so that the next line doesn't start on the same line as the password prompt
|
83
|
+
log
|
84
|
+
x
|
40
85
|
end
|
41
86
|
|
42
87
|
def add_nl s
|
43
|
-
|
44
|
-
|
88
|
+
#append a "\n" (newline) to a string if it doesn't already end with one.
|
89
|
+
(s[/\\n$/].nil? ? s+"\n" : s)
|
45
90
|
end
|
46
91
|
|
47
92
|
def log string=String.new
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
93
|
+
if $logging==true
|
94
|
+
printf add_nl(string)
|
95
|
+
end
|
96
|
+
string
|
52
97
|
end
|
53
98
|
|
54
99
|
def debug string
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
100
|
+
if $logging and $debugging
|
101
|
+
printf add_nl(string)
|
102
|
+
end
|
103
|
+
string
|
59
104
|
end
|
60
105
|
|
61
106
|
def login
|
62
|
-
|
63
|
-
|
64
|
-
|
107
|
+
log "Logging in as loginuser..."
|
108
|
+
$in.printf( _lu_password + "\n" )
|
109
|
+
debug until_prompt( '/home/login >', :check_badpass )
|
65
110
|
end
|
66
111
|
|
67
112
|
def become_root
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
113
|
+
log "Using su to become root..."
|
114
|
+
$in.printf( "su\n" )
|
115
|
+
debug until_prompt( 'Password:' )
|
116
|
+
$in.printf( "#{_ru_password}\n" )
|
117
|
+
debug until_prompt( '/home/login #', :check_badpass )
|
118
|
+
log "Am now root."
|
74
119
|
end
|
75
120
|
|
76
121
|
def extract_profiles http
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
122
|
+
debug "Extracting profiles from 'http'="
|
123
|
+
profiles=http[/'profiles' => \[[^\]]*/].gsub( "'profiles' => \[",'' ).split(',').collect {|p|
|
124
|
+
p.strip.gsub(/^'/,'').gsub(/'$/,'')
|
125
|
+
}
|
126
|
+
debug "Found #{profiles.size} profiles:"
|
127
|
+
profiles.each {|p|
|
128
|
+
debug " -- "+p
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def extract_exceptions http
|
133
|
+
exceptions=http[/'exceptions' => \[[^\]]*/].gsub("'exceptions' => \[",'').split(',').collect {|l|
|
134
|
+
l.gsub(/'/,'').strip
|
135
|
+
}
|
136
|
+
debug "Found #{exceptions.size} exceptions:"
|
137
|
+
exceptions.each {|e| debug " -- "+e }
|
85
138
|
end
|
86
139
|
|
87
140
|
def extract_cff_profiles raw_proxy_profile
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
141
|
+
debug "Found cff_profiles: "
|
142
|
+
cff_p=raw_proxy_profile[/'cff_profiles' => \[[^\]]*/].gsub( "'cff_profiles' => \[",'' ).
|
143
|
+
strip.gsub(',','').strip.gsub(/^'/,'').gsub(/'$/,'').strip.gsub(/^'/,'').gsub(/'$/,'')
|
144
|
+
debug " -- "+cff_p
|
145
|
+
cff_p
|
93
146
|
end
|
94
147
|
|
95
148
|
def extract_action raw_assignment
|
96
|
-
|
149
|
+
raw_assignment[/'action' => '[^']*/].gsub(/'action' => '/,'').strip
|
150
|
+
end
|
151
|
+
|
152
|
+
def search_exceptions exceptions
|
153
|
+
if exceptions.class!=Array
|
154
|
+
raise ArgumentError "search_exceptions(exceptions): 'exceptions' must be an array but it's something else, possibly a cheeseburger..."
|
155
|
+
elsif exceptions.empty?
|
156
|
+
raise ArgumentError "search_exceptions(exceptions): 'exceptions' must be a non-empty array! What have you done?!?"
|
157
|
+
end
|
158
|
+
|
159
|
+
results={:exceptions=>[]}
|
160
|
+
exceptions.each {|exception|
|
161
|
+
debug raw_exception=get_object(exception)
|
162
|
+
log "Checking exception: #{get_name(raw_exception)}"
|
163
|
+
if _e_log_accessed?(raw_exception)
|
164
|
+
results[:exceptions] << exception
|
165
|
+
elsif _e_log_blocked?(raw_exception)
|
166
|
+
results[:exceptions] << exception
|
167
|
+
end
|
168
|
+
}
|
169
|
+
results
|
97
170
|
end
|
98
171
|
|
99
172
|
def search_profiles profiles
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
def
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
def
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
173
|
+
if profiles.class!=Array
|
174
|
+
raise ArgumentError "search_profiles(profiles): 'profiles' must be an array but it's something else, possibly a cheeseburger..."
|
175
|
+
elsif profiles.empty?
|
176
|
+
raise ArgumentError "search_profiles(profiles): 'profiles' must be a non-empty array! What have you done?!?"
|
177
|
+
end
|
178
|
+
results={:profiles=>[]}
|
179
|
+
profiles.each {|profile|
|
180
|
+
debug raw_proxy_profile=get_object(profile)
|
181
|
+
log "Checking profile: #{get_name(raw_proxy_profile)}"
|
182
|
+
debug raw_assignment=get_object( extract_cff_profiles(raw_proxy_profile) )
|
183
|
+
log "Got the assignment for that profile..."
|
184
|
+
action= get_action(raw_assignment)
|
185
|
+
raw_action= get_object( extract_action(raw_assignment) )
|
186
|
+
log "Got the action for that assignment..."
|
187
|
+
|
188
|
+
if !_p_log_accessed?(raw_action) || !_p_log_blocked?(raw_action)
|
189
|
+
log "Found an action that isn't logging everything: #{get_name(raw_action)}"
|
190
|
+
results[:profiles] << raw_action
|
191
|
+
end
|
192
|
+
}
|
193
|
+
results
|
194
|
+
end
|
195
|
+
|
196
|
+
def _p_log_accessed? action
|
197
|
+
if action[/'log_access' => \d/].nil?
|
198
|
+
raise ArgumentError "_p_log_accessed?(action): action doesn't contain a 'log_access' attribute?"
|
199
|
+
end
|
200
|
+
action[/'log_access' => \d/].gsub(/'log_access' => /,'')=='1'
|
201
|
+
end
|
202
|
+
|
203
|
+
def _p_log_blocked? action
|
204
|
+
if action[/'log_blocked' => \d/].nil?
|
205
|
+
raise ArgumentError "_p_log_blocked?(action): action doesn't contain a 'log_blocked' attribute?"
|
206
|
+
end
|
207
|
+
action[/'log_blocked' => \d/].gsub(/'log_blocked' => /,'')=='1'
|
208
|
+
end
|
209
|
+
|
210
|
+
def _e_log_accessed? raw_exception
|
211
|
+
raw_exception[/'skiplist' => \[[^\]]*/].gsub("'skiplist' => \[",'').split(',').collect {|l|
|
212
|
+
l.gsub(/'/,'').strip
|
213
|
+
}.include? 'log_access'
|
214
|
+
end
|
215
|
+
|
216
|
+
def _e_log_blocked? raw_exception
|
217
|
+
raw_exception[/'skiplist' => \[[^\]]*/].gsub("'skiplist' => \[",'').split(',').collect {|l|
|
218
|
+
l.gsub(/'/,'').strip
|
219
|
+
}.include? 'log_blocked'
|
135
220
|
end
|
136
221
|
|
137
222
|
def print_results results
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
223
|
+
log "\n\nPrinting results:"
|
224
|
+
results.each {|x,y|
|
225
|
+
if x==:profiles
|
226
|
+
y.each {|z|
|
227
|
+
if !_p_log_accessed?(z)
|
228
|
+
log "Please activate the 'Log Accessed Pages' option for the Web Filter Action named: #{get_name(z)}"
|
229
|
+
end
|
230
|
+
if !_p_log_blocked?(z)
|
231
|
+
log "Please activate the 'Log Blocked Pages' option for the Web Filter Action named: #{get_name(z)}"
|
232
|
+
end
|
233
|
+
}
|
234
|
+
elsif x==:exceptions
|
235
|
+
y.each {|z|
|
236
|
+
if _e_log_accessed?(get_object(z))
|
237
|
+
log "Please deactivate the option to skip logging of accessed pages for the Exception named: #{get_name(get_object(z))}"
|
238
|
+
end
|
239
|
+
if _e_log_blocked?(get_object(z))
|
240
|
+
log "Please deactivate the option to skip logging of blocked pages for the Exception named: #{get_name(get_object(z))}"
|
241
|
+
end
|
242
|
+
}
|
243
|
+
end
|
244
|
+
}
|
146
245
|
end
|
147
246
|
|
148
247
|
def get x, command='get'
|
149
|
-
|
150
|
-
|
151
|
-
|
248
|
+
debug "Running: 'cc #{command} #{x}'..."
|
249
|
+
$in.printf("cc #{command} #{x}\n")
|
250
|
+
debug until_prompt(':/home/login #')
|
152
251
|
end
|
153
252
|
|
154
253
|
def print_raction raw_action
|
155
|
-
|
156
|
-
|
254
|
+
log "Name: #{get_name(raw_action)}"
|
255
|
+
log "Comment: #{get_comment(raw_action)}"
|
157
256
|
end
|
158
257
|
|
159
258
|
def get_name raw
|
160
|
-
|
259
|
+
raw[/'name' => '[^']*/].gsub(/'name' => '/,'')
|
161
260
|
end
|
162
261
|
|
163
262
|
def get_comment raw
|
164
|
-
|
263
|
+
raw[/'comment' => '[^']*/].gsub(/'comment' => '/,'')
|
165
264
|
end
|
166
265
|
|
167
266
|
def get_action raw_assignment
|
168
|
-
|
267
|
+
raw_assignment[/'action' => '[^']*/].gsub(/'action' => '/,'').strip
|
169
268
|
end
|
170
269
|
|
171
270
|
def get_object x
|
172
|
-
|
271
|
+
get x, 'get_object'
|
173
272
|
end
|
174
273
|
|
175
|
-
|
176
|
-
!string[/\(yes\/no\)\?/].nil?
|
177
|
-
end
|
178
|
-
|
179
|
-
def until_prompt( prompt )
|
180
|
-
buffer= ""
|
181
|
-
begin
|
182
|
-
Timeout.timeout( 5 ) {
|
183
|
-
loop do
|
184
|
-
buffer << $out.getc.chr
|
185
|
-
if fingerprint_prompt?(buffer)
|
186
|
-
printf "SSH Fingerprint prompt detected.\nPlease SSH to this system at least once before using this program to verify the SSH fingerprint manually, then run this program again.\n\n"
|
187
|
-
exit
|
188
|
-
end
|
189
|
-
break if buffer =~ Regexp.new(prompt)
|
190
|
-
end
|
191
|
-
}
|
192
|
-
buffer
|
193
|
-
rescue Timeout::Error => error
|
194
|
-
printf "Error - Timed out waiting for \"#{prompt.gsub('"','\"') }\", printing stacktrace...\n "
|
195
|
-
printf error.backtrace.join("\n") + "\n"
|
196
|
-
printf "Dumping buffer...\n"
|
197
|
-
pp buffer
|
198
|
-
printf "-------\n\n"
|
199
|
-
end
|
200
|
-
end
|
274
|
+
|
201
275
|
|
202
276
|
def prompt question, password=false
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
277
|
+
printf question
|
278
|
+
if password==true
|
279
|
+
disable_echo {
|
280
|
+
(s=gets.strip).empty? ? prompt(question) : s
|
281
|
+
}
|
282
|
+
else
|
283
|
+
(s=gets.strip).empty? ? prompt(question) : s
|
284
|
+
end
|
211
285
|
end
|
212
286
|
|
213
287
|
def run
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
288
|
+
PTY.spawn("ssh -p #{_port} loginuser@#{_host}") {|stdout,stdin,pid|
|
289
|
+
begin
|
290
|
+
old_out=$out; $out=stdout
|
291
|
+
old_in=$in; $in =stdin
|
218
292
|
|
219
|
-
|
220
|
-
|
221
|
-
|
293
|
+
debug( until_prompt('password:') )
|
294
|
+
login
|
295
|
+
become_root
|
222
296
|
|
223
|
-
|
224
|
-
|
225
|
-
|
297
|
+
#Because the main Web Filter is treated as a profile, this
|
298
|
+
#will operate on all Web Filters and proxy profiles.
|
299
|
+
results= search_profiles( extract_profiles( http=get('http') ) )
|
300
|
+
results.merge!( search_exceptions( extract_exceptions( http ) ) )
|
226
301
|
|
227
|
-
|
302
|
+
print_results( results )
|
228
303
|
|
229
|
-
|
230
|
-
|
231
|
-
|
304
|
+
stdin.printf( "exit\n" )
|
305
|
+
until_prompt( ":/home/login >" )
|
306
|
+
stdin.printf( "exit\n" )
|
232
307
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
308
|
+
$out=old_out
|
309
|
+
$in=old_in
|
310
|
+
rescue Errno::EIO
|
311
|
+
printf "SSH Connection failed. Are you able to ssh in from this machine? If not, start troubleshooting from here.\n"
|
312
|
+
exit
|
313
|
+
end
|
314
|
+
}
|
315
|
+
log 'Done'
|
237
316
|
end
|
metadata
CHANGED
@@ -1,53 +1,68 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: utm-plc
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
11
|
+
authors:
|
8
12
|
- Jeff Welling
|
9
13
|
autorequire:
|
10
14
|
bindir: bin
|
11
15
|
cert_chain: []
|
12
|
-
|
16
|
+
|
17
|
+
date: 2013-06-10 23:37:19 -07:00
|
18
|
+
default_executable:
|
13
19
|
dependencies: []
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
email:
|
20
|
+
|
21
|
+
description: This tool logs in to your UTM and interacts with 'cc' to check the configuration of every web filter configuration in use and list the ones that are not configured to log accessed and blocked pages.
|
22
|
+
email:
|
18
23
|
- jeff.welling@gmail.com
|
19
|
-
executables:
|
24
|
+
executables:
|
20
25
|
- plc
|
21
26
|
extensions: []
|
27
|
+
|
22
28
|
extra_rdoc_files: []
|
23
|
-
|
29
|
+
|
30
|
+
files:
|
24
31
|
- bin/plc
|
25
|
-
- bin/plc.rb
|
26
32
|
- lib/utm-plc.rb
|
27
33
|
- LICENSE
|
28
34
|
- README.mkd
|
35
|
+
has_rdoc: true
|
29
36
|
homepage: https://github.com/jeffWelling/UTM-plc
|
30
37
|
licenses: []
|
38
|
+
|
31
39
|
post_install_message:
|
32
40
|
rdoc_options: []
|
33
|
-
|
41
|
+
|
42
|
+
require_paths:
|
34
43
|
- lib
|
35
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
45
|
none: false
|
37
|
-
requirements:
|
38
|
-
- -
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
|
41
|
-
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
segments:
|
50
|
+
- 0
|
51
|
+
version: "0"
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
53
|
none: false
|
43
|
-
requirements:
|
44
|
-
- -
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
47
60
|
requirements: []
|
61
|
+
|
48
62
|
rubyforge_project:
|
49
|
-
rubygems_version: 1.
|
63
|
+
rubygems_version: 1.3.7
|
50
64
|
signing_key:
|
51
65
|
specification_version: 3
|
52
66
|
summary: Tool to check if your UTM's Web Filter is logging
|
53
67
|
test_files: []
|
68
|
+
|
data/bin/plc.rb
DELETED
@@ -1,227 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# This file is part of UTM_plc.
|
3
|
-
# Copyright 2013 Jeff Welling (jeff.welling@gmail.com)
|
4
|
-
#
|
5
|
-
# UTM_plc is free software: you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
7
|
-
# the Free Software Foundation, either version 3 of the License, or
|
8
|
-
# (at your option) any later version.
|
9
|
-
#
|
10
|
-
# UTM_plc is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
# GNU General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU General Public License
|
16
|
-
# along with tget. If not, see <http://www.gnu.org/licenses/>.
|
17
|
-
#
|
18
|
-
# Add the library from the source tree to the front of the load path.
|
19
|
-
# This allows tget to run without first installing the tget gem, which is
|
20
|
-
# important when testing multiple branches of development.
|
21
|
-
require 'pty'
|
22
|
-
require 'timeout'
|
23
|
-
require 'pp'
|
24
|
-
|
25
|
-
def _host; prompt('Which host?: ') end
|
26
|
-
def _port; prompt('What port?: ') end
|
27
|
-
def _lu_password; disable_echo {prompt('What is the password for loginuser?: ')} end
|
28
|
-
def _ru_password; disable_echo {prompt('What is the password for root?: ')} end
|
29
|
-
|
30
|
-
$logging=false
|
31
|
-
$debugging=false
|
32
|
-
|
33
|
-
def disable_echo &block
|
34
|
-
system('stty -echo')
|
35
|
-
x=yield
|
36
|
-
system('stty echo')
|
37
|
-
#so that the next line doesn't start on the same line as the password prompt
|
38
|
-
log
|
39
|
-
x
|
40
|
-
end
|
41
|
-
|
42
|
-
def add_nl s
|
43
|
-
#append a "\n" (newline) to a string if it doesn't already end with one.
|
44
|
-
(s[/\\n$/].nil? ? s+"\n" : s)
|
45
|
-
end
|
46
|
-
|
47
|
-
def log string=String.new
|
48
|
-
if $logging==true
|
49
|
-
printf add_nl(string)
|
50
|
-
end
|
51
|
-
string
|
52
|
-
end
|
53
|
-
|
54
|
-
def debug string
|
55
|
-
if $logging and $debugging
|
56
|
-
printf add_nl(string)
|
57
|
-
end
|
58
|
-
string
|
59
|
-
end
|
60
|
-
|
61
|
-
def login
|
62
|
-
log "Logging in as loginuser..."
|
63
|
-
$in.printf( _lu_password + "\n" )
|
64
|
-
debug until_prompt( '/home/login >' )
|
65
|
-
end
|
66
|
-
|
67
|
-
def become_root
|
68
|
-
log "Using su to become root..."
|
69
|
-
$in.printf( "su\n" )
|
70
|
-
debug until_prompt( 'Password:' )
|
71
|
-
$in.printf( "#{_ru_password}\n" )
|
72
|
-
debug until_prompt( '/home/login #' )
|
73
|
-
log "Am now root."
|
74
|
-
end
|
75
|
-
|
76
|
-
def extract_profiles http
|
77
|
-
debug "Extracting profiles from 'http'="
|
78
|
-
profiles=http[/'profiles' => \[[^\]]*/].gsub( "'profiles' => \[",'' ).split(',').collect {|p|
|
79
|
-
p.strip.gsub(/^'/,'').gsub(/'$/,'')
|
80
|
-
}
|
81
|
-
log "Found #{profiles.size} profiles:"
|
82
|
-
profiles.each {|p|
|
83
|
-
log " -- "+p
|
84
|
-
}
|
85
|
-
end
|
86
|
-
|
87
|
-
def extract_cff_profiles raw_proxy_profile
|
88
|
-
log "Found cff_profiles: "
|
89
|
-
cff_p=raw_proxy_profile[/'cff_profiles' => \[[^\]]*/].gsub( "'cff_profiles' => \[",'' ).
|
90
|
-
strip.gsub(',','').strip.gsub(/^'/,'').gsub(/'$/,'').strip.gsub(/^'/,'').gsub(/'$/,'')
|
91
|
-
log " -- "+cff_p
|
92
|
-
cff_p
|
93
|
-
end
|
94
|
-
|
95
|
-
def extract_action raw_assignment
|
96
|
-
raw_assignment[/'action' => '[^']*/].gsub(/'action' => '/,'').strip
|
97
|
-
end
|
98
|
-
|
99
|
-
def search_profiles profiles
|
100
|
-
if profiles.class!=Array
|
101
|
-
raise ArgumentError "search_profiles(profiles): 'profiles' must be an array but it's something else, possibly a cheeseburger..."
|
102
|
-
elsif profiles.empty?
|
103
|
-
raise ArgumentError "search_profiles(profiles): 'profiles' must be a non-empty array! What have you done?!?"
|
104
|
-
end
|
105
|
-
results=[]
|
106
|
-
profiles.each {|profile|
|
107
|
-
debug raw_proxy_profile=get_object(profile)
|
108
|
-
log "\nChecking profile: #{get_name(raw_proxy_profile)}"
|
109
|
-
debug raw_assignment=get_object( extract_cff_profiles(raw_proxy_profile) )
|
110
|
-
log "Got the assignment for that profile..."
|
111
|
-
action= get_action(raw_assignment)
|
112
|
-
raw_action= get_object( extract_action(raw_assignment) )
|
113
|
-
log "Got the action for that assignment..."
|
114
|
-
|
115
|
-
if !log_accessed?(raw_action) || !log_blocked?(raw_action)
|
116
|
-
log "Found an action that isn't logging everything: #{get_name(raw_action)}"
|
117
|
-
results << raw_action
|
118
|
-
end
|
119
|
-
}
|
120
|
-
results
|
121
|
-
end
|
122
|
-
|
123
|
-
def log_accessed? action
|
124
|
-
if action[/'log_access' => \d/].nil?
|
125
|
-
raise ArgumentError "log_accessed?(action): action doesn't contain a 'log_access' attribute?"
|
126
|
-
end
|
127
|
-
action[/'log_access' => \d/].gsub(/'log_access' => /,'')=='1'
|
128
|
-
end
|
129
|
-
|
130
|
-
def log_blocked? action
|
131
|
-
if action[/'log_blocked' => \d/].nil?
|
132
|
-
raise ArgumentError "log_blocked?(action): action doesn't contain a 'log_blocked' attribute?"
|
133
|
-
end
|
134
|
-
action[/'log_blocked' => \d/].gsub(/'log_blocked' => /,'')=='1'
|
135
|
-
end
|
136
|
-
|
137
|
-
def print_results results
|
138
|
-
log "\n\nPrinting results:"
|
139
|
-
results.each {|action|
|
140
|
-
if !log_accessed?(action)
|
141
|
-
log "Please activate the 'Log Accessed Pages' option for the Web Filter Action named: #{get_name(action)}"
|
142
|
-
elsif !log_blocked?(action)
|
143
|
-
log "Please activate the 'Log Blocked Pages' option for the Web Filter Action named: #{get_name(action)}"
|
144
|
-
end
|
145
|
-
}
|
146
|
-
end
|
147
|
-
|
148
|
-
def get x, command='get'
|
149
|
-
debug "Running: 'cc #{command} #{x}'..."
|
150
|
-
$in.printf("cc #{command} #{x}\n")
|
151
|
-
debug until_prompt(':/home/login #')
|
152
|
-
end
|
153
|
-
|
154
|
-
def print_raction raw_action
|
155
|
-
log "Name: #{get_name(raw_action)}"
|
156
|
-
log "Comment: #{get_comment(raw_action)}"
|
157
|
-
end
|
158
|
-
|
159
|
-
def get_name raw
|
160
|
-
raw[/'name' => '[^']*/].gsub(/'name' => '/,'')
|
161
|
-
end
|
162
|
-
|
163
|
-
def get_comment raw
|
164
|
-
raw[/'comment' => '[^']*/].gsub(/'comment' => '/,'')
|
165
|
-
end
|
166
|
-
|
167
|
-
def get_action raw_assignment
|
168
|
-
raw_assignment[/'action' => '[^']*/].gsub(/'action' => '/,'').strip
|
169
|
-
end
|
170
|
-
|
171
|
-
def get_object x
|
172
|
-
get x, 'get_object'
|
173
|
-
end
|
174
|
-
|
175
|
-
def until_prompt( prompt )
|
176
|
-
buffer= ""
|
177
|
-
begin
|
178
|
-
Timeout.timeout( 30 ) {
|
179
|
-
loop do
|
180
|
-
buffer << $out.getc.chr
|
181
|
-
break if buffer =~ Regexp.new(prompt)
|
182
|
-
end
|
183
|
-
}
|
184
|
-
buffer
|
185
|
-
rescue Timeout::Error => error
|
186
|
-
printf "Error - Timed out waiting for \"#{prompt.gsub('"','\"') }\", printing stacktrace...\n "
|
187
|
-
printf error.backtrace.join("\n") + "\n"
|
188
|
-
printf "Dumping buffer...\n"
|
189
|
-
pp buffer
|
190
|
-
printf "-------\n\n"
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def prompt *question
|
195
|
-
printf *question
|
196
|
-
(s=gets.strip).empty? ? prompt(*question) : s
|
197
|
-
end
|
198
|
-
|
199
|
-
def run
|
200
|
-
PTY.spawn("ssh -p #{_port} loginuser@#{_host}") {|stdout,stdin,pid|
|
201
|
-
old_out=$out; $out=stdout
|
202
|
-
old_in=$in; $in =stdin
|
203
|
-
$logging=true
|
204
|
-
|
205
|
-
debug( until_prompt('password:') )
|
206
|
-
login
|
207
|
-
become_root
|
208
|
-
|
209
|
-
#Because the main Web Filter is treated as a profile, this
|
210
|
-
#will operate on all Web Filters and proxy profiles.
|
211
|
-
results= search_profiles( extract_profiles( get('http') ) )
|
212
|
-
|
213
|
-
print_results( results )
|
214
|
-
|
215
|
-
stdin.printf( "exit\n" )
|
216
|
-
until_prompt( ":/home/login >" )
|
217
|
-
stdin.printf( "exit\n" )
|
218
|
-
|
219
|
-
$out=old_out
|
220
|
-
$in=old_in
|
221
|
-
}
|
222
|
-
log 'Done'
|
223
|
-
end
|
224
|
-
|
225
|
-
if __FILE__ == './plc.rb'
|
226
|
-
run
|
227
|
-
end
|