ipaccess 0.0.4 → 1.2.0
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.
- checksums.yaml +15 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/.rspec +1 -0
- data/.yardopts +12 -0
- data/ChangeLog +1495 -0
- data/{docs/LGPL-LICENSE → LGPL-LICENSE} +0 -0
- data/Manifest.txt +76 -0
- data/README.md +96 -0
- data/Rakefile +65 -42
- data/docs/COPYING +41 -45
- data/docs/FAQ +12 -0
- data/docs/HISTORY +17 -0
- data/docs/LEGAL +1 -1
- data/docs/LGPL +166 -0
- data/docs/TODO +150 -7
- data/docs/images/ipaccess.png +0 -0
- data/docs/images/ipaccess_ac_for_args.png +0 -0
- data/docs/images/ipaccess_ac_for_socket.png +0 -0
- data/docs/images/ipaccess_logo.png +0 -0
- data/docs/images/ipaccess_relations.png +0 -0
- data/docs/images/ipaccess_setup_origin.png +0 -0
- data/docs/images/ipaccess_setup_origin_tab.png +0 -0
- data/docs/images/ipaccess_view.png +0 -0
- data/docs/rdoc.css +22 -0
- data/examples/ftp.rb +62 -0
- data/examples/http.rb +81 -0
- data/examples/imap.rb +37 -0
- data/examples/pop.rb +31 -0
- data/examples/smtp.rb +26 -0
- data/examples/tcp_server.rb +32 -0
- data/examples/tcp_socket.rb +7 -3
- data/examples/telnet.rb +32 -0
- data/examples/text_message.rb +45 -0
- data/lib/ipaccess.rb +557 -7
- data/lib/ipaccess/arm_sockets.rb +7 -4
- data/lib/ipaccess/ghost_doc/ghost_doc.rb +23 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_acl.rb +54 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_net_ftp.rb +213 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_net_http.rb +272 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_net_smtp.rb +186 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_net_telnet.rb +227 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_blacklist.rb +36 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_blacklist_e.rb +7 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unblacklist.rb +36 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unblacklist_e.rb +7 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unwhitelist.rb +36 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unwhitelist_e.rb +7 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_whitelist.rb +36 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_p_whitelist_e.rb +7 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_patched_usage.rb +64 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_sockets.rb +571 -0
- data/lib/ipaccess/ip_access_check.rb +508 -0
- data/lib/ipaccess/ip_access_errors.rb +186 -40
- data/lib/ipaccess/ip_access_list.rb +955 -1122
- data/lib/ipaccess/ip_access_set.rb +212 -0
- data/lib/ipaccess/net/ftp.rb +39 -0
- data/lib/ipaccess/net/http.rb +39 -0
- data/lib/ipaccess/net/https.rb +30 -0
- data/lib/ipaccess/net/imap.rb +39 -0
- data/lib/ipaccess/net/pop.rb +46 -0
- data/lib/ipaccess/net/smtp.rb +39 -0
- data/lib/ipaccess/net/telnet.rb +38 -0
- data/lib/ipaccess/patches/generic.rb +807 -0
- data/lib/ipaccess/patches/net_ftp.rb +165 -0
- data/lib/ipaccess/patches/net_http.rb +175 -0
- data/lib/ipaccess/patches/net_https.rb +29 -0
- data/lib/ipaccess/patches/net_imap.rb +117 -0
- data/lib/ipaccess/patches/net_pop.rb +171 -0
- data/lib/ipaccess/patches/net_smtp.rb +130 -0
- data/lib/ipaccess/patches/net_telnet.rb +103 -0
- data/lib/ipaccess/{netaddr_patch.rb → patches/netaddr.rb} +20 -11
- data/lib/ipaccess/patches/sockets.rb +586 -0
- data/lib/ipaccess/socket.rb +52 -1
- data/lib/ipaccess/sockets.rb +4 -30
- data/spec/ip_access_list_spec.rb +33 -21
- data/spec/spec.opts +2 -2
- metadata +289 -63
- metadata.gz.sig +0 -0
- data/docs/DOWNLOAD +0 -17
- data/docs/README +0 -95
- data/docs/WELCOME +0 -8
- data/lib/ipaccess/ghost_doc.rb +0 -206
- data/lib/ipaccess/ghost_doc_acl.rb +0 -31
- data/lib/ipaccess/ip_access.rb +0 -456
- data/lib/ipaccess/ip_access_patches.rb +0 -431
- data/spec/core_spec.rb +0 -5
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Author:: Paweł Wilk (mailto:pw@gnu.org)
|
|
4
|
+
# Copyright:: Copyright (c) 2009-2014 by Paweł Wilk
|
|
5
|
+
# License:: This program is licensed under the terms of {GNU Lesser General Public License}[link:docs/LGPL.html] or {Ruby License}[link:docs/COPYING.html].
|
|
6
|
+
#
|
|
7
|
+
# Classes contained in this file are subclasses
|
|
8
|
+
# of Ruby Telnet handling classes equipped
|
|
9
|
+
# with IP access control.
|
|
10
|
+
#
|
|
11
|
+
#--
|
|
12
|
+
#
|
|
13
|
+
# Copyright (C) 2009 by Paweł Wilk. All Rights Reserved.
|
|
14
|
+
#
|
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
|
16
|
+
# it under the terms of either: 1) the GNU Lesser General Public License
|
|
17
|
+
# as published by the Free Software Foundation; either version 3 of the
|
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
|
19
|
+
#
|
|
20
|
+
# See the file COPYING for complete licensing information.
|
|
21
|
+
#
|
|
22
|
+
#
|
|
23
|
+
# See ipaccess/ghost_doc/ghost_doc.rb for documentation of this classes.
|
|
24
|
+
#
|
|
25
|
+
#++
|
|
26
|
+
|
|
27
|
+
require 'net/telnet'
|
|
28
|
+
require 'ipaccess/ip_access_set'
|
|
29
|
+
require 'ipaccess/patches/net_telnet'
|
|
30
|
+
|
|
31
|
+
module IPAccess::Net
|
|
32
|
+
|
|
33
|
+
class Telnet < ::Net::Telnet
|
|
34
|
+
include IPAccess::Patches::Net::Telnet
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Author:: Paweł Wilk (mailto:pw@gnu.org)
|
|
4
|
+
# Copyright:: Copyright (c) 2009-2014 by Paweł Wilk
|
|
5
|
+
# License:: This program is licensed under the terms of {GNU Lesser General Public License}[link:docs/LGPL.html] or {Ruby License}[link:docs/COPYING.html].
|
|
6
|
+
#
|
|
7
|
+
# Modules contained in this file are meant for
|
|
8
|
+
# patching Ruby classes in order to add
|
|
9
|
+
# IP access control to them.
|
|
10
|
+
#
|
|
11
|
+
#--
|
|
12
|
+
#
|
|
13
|
+
# Copyright (C) 2009 by Paweł Wilk. All Rights Reserved.
|
|
14
|
+
#
|
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
|
16
|
+
# it under the terms of either: 1) the GNU Lesser General Public License
|
|
17
|
+
# as published by the Free Software Foundation; either version 3 of the
|
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
|
19
|
+
#
|
|
20
|
+
# See the file COPYING for complete licensing information.
|
|
21
|
+
#
|
|
22
|
+
#++
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
require 'singleton'
|
|
26
|
+
require 'ipaccess/ip_access_errors'
|
|
27
|
+
|
|
28
|
+
module IPAccess
|
|
29
|
+
|
|
30
|
+
class Set
|
|
31
|
+
|
|
32
|
+
# This is global access set, used by
|
|
33
|
+
# default by all socket handling
|
|
34
|
+
# classes with enabled IP access control.
|
|
35
|
+
# It has just one instance called IPAccess::Set.Global.
|
|
36
|
+
# It is present only when patching engine is loaded.
|
|
37
|
+
|
|
38
|
+
class GlobalClass < Set
|
|
39
|
+
|
|
40
|
+
# :stopdoc:
|
|
41
|
+
|
|
42
|
+
include Singleton
|
|
43
|
+
|
|
44
|
+
def global?; true end
|
|
45
|
+
|
|
46
|
+
def ==(obj)
|
|
47
|
+
return true if obj.object_id == IPAccess::Set::GlobalSet.instance.object_id
|
|
48
|
+
super(obj)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def ===(obj)
|
|
52
|
+
return true if obj.object_id == IPAccess::Set::GlobalSet.instance.object_id
|
|
53
|
+
super(obj)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def to_s
|
|
57
|
+
"#<IPAccess::Set:Global>"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# :startdoc:
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# This is global access set, used by
|
|
65
|
+
# default by all socket handling
|
|
66
|
+
# classes with enabled IP access control.
|
|
67
|
+
# It is present only when patching engine is loaded.
|
|
68
|
+
|
|
69
|
+
Global = GlobalClass.instance
|
|
70
|
+
Global.name = 'global'
|
|
71
|
+
|
|
72
|
+
# This method returns +true+ when
|
|
73
|
+
# the current instance is not regular IPAccess::Set object
|
|
74
|
+
# but a reference to the IPAccess::Set.Global,
|
|
75
|
+
# which should be reached by that name. It returns
|
|
76
|
+
# +false+ in case of regular IPAccess::Set objects.
|
|
77
|
+
#
|
|
78
|
+
# This method is present only if
|
|
79
|
+
# patching engine had been loaded.
|
|
80
|
+
|
|
81
|
+
def global?; false end
|
|
82
|
+
|
|
83
|
+
end # class Set
|
|
84
|
+
|
|
85
|
+
# :call-seq:
|
|
86
|
+
# arm(klass, acl=nil)<br />
|
|
87
|
+
# arm(klass, :opened_on_deny)<br />
|
|
88
|
+
# arm(klass, acl, :opened_on_deny)
|
|
89
|
+
#
|
|
90
|
+
# This special method patches Ruby's standard
|
|
91
|
+
# library classes and enables IP access control
|
|
92
|
+
# for them. Instances of such altered classes
|
|
93
|
+
# will be equipped with member called +acl+,
|
|
94
|
+
# which is a kind of IPAccess::Set and allows you
|
|
95
|
+
# to manipulate access rules. It is also
|
|
96
|
+
# able to patch single instance of supported
|
|
97
|
+
# classes.
|
|
98
|
+
#
|
|
99
|
+
# This method returns object that has
|
|
100
|
+
# been patched.
|
|
101
|
+
#
|
|
102
|
+
# ==== Supported classes
|
|
103
|
+
#
|
|
104
|
+
# Currently supported classes are:
|
|
105
|
+
#
|
|
106
|
+
# – Socket, UDPSocket, SOCKSSocket, TCPSocket, TCPServer,
|
|
107
|
+
# – Net::HTTP,
|
|
108
|
+
# – Net::Telnet,
|
|
109
|
+
# – Net::FTP,
|
|
110
|
+
# – Net::POP3,
|
|
111
|
+
# – Net::IMAP,
|
|
112
|
+
# – Net::SMTP.
|
|
113
|
+
#
|
|
114
|
+
# ==== Patching classes
|
|
115
|
+
#
|
|
116
|
+
# Passed argument may be a class object,
|
|
117
|
+
# a string representation of a class object
|
|
118
|
+
# or a symbol representing a class object.
|
|
119
|
+
#
|
|
120
|
+
# ==== Patching single instances
|
|
121
|
+
#
|
|
122
|
+
# Passed argument may be an instance of
|
|
123
|
+
# supported class. It's possible to
|
|
124
|
+
# pass second, optional argument, which
|
|
125
|
+
# should be an initial access set. If
|
|
126
|
+
# this argument is omited then IPAccess::Set.Global
|
|
127
|
+
# is used. If +:opened_on_deny+ is passed then
|
|
128
|
+
# any connection remains opened in case of IPAccessDenied
|
|
129
|
+
# exception during arming.
|
|
130
|
+
#
|
|
131
|
+
# ==== Patching Ruby's sockets
|
|
132
|
+
#
|
|
133
|
+
# To quickly patch all Ruby's socket classes
|
|
134
|
+
# you may pass symbol +:sockets+ as an
|
|
135
|
+
# argument.
|
|
136
|
+
#
|
|
137
|
+
# === Examples
|
|
138
|
+
#
|
|
139
|
+
# ==== Example 1 – sockets
|
|
140
|
+
#
|
|
141
|
+
# require 'ipaccess/socket' # load sockets subsystem and IPAccess.arm method
|
|
142
|
+
#
|
|
143
|
+
# IPAccess.arm TCPSocket # arm TCPSocket class
|
|
144
|
+
# IPAccess::Set::Global.output.blacklist 'randomseed.pl' # add host to black list of the global set
|
|
145
|
+
# TCPSocket.new('randomseed.pl', 80) # try to connect
|
|
146
|
+
#
|
|
147
|
+
# ==== Example 2 – HTTP
|
|
148
|
+
#
|
|
149
|
+
# require 'ipaccess/net/http' # load net/http subsystem and IPAccess.arm method
|
|
150
|
+
#
|
|
151
|
+
# IPAccess.arm Net::HTTP # arm TCPSocket class
|
|
152
|
+
# IPAccess::Set::Global.output.blacklist 'randomseed.pl' # add host to black list of the global set
|
|
153
|
+
# Net::HTTP.get_print('randomseed.pl', '/i.html') # try to connect
|
|
154
|
+
#
|
|
155
|
+
# ==== Example 3 – single network object
|
|
156
|
+
#
|
|
157
|
+
# require 'ipaccess/net/telnet' # load Net::Telnet version and IPAccess.arm method
|
|
158
|
+
#
|
|
159
|
+
# opts = {}
|
|
160
|
+
# opts["Host"] = 'randomseed.pl'
|
|
161
|
+
# opts["Port"] = '80'
|
|
162
|
+
#
|
|
163
|
+
# t = Net::Telnet.new(opts) # try to connect to remote host
|
|
164
|
+
#
|
|
165
|
+
# acl = IPAccess::Set.new # create custom access set
|
|
166
|
+
# acl.output.blacklist 'randomseed.pl' # blacklist host
|
|
167
|
+
# IPAccess.arm t, acl # arm Telnet object and pass optional ACL
|
|
168
|
+
|
|
169
|
+
def self.arm(*args)
|
|
170
|
+
cod = args.delete(:opened_on_deny).nil? ? true : false
|
|
171
|
+
klass, acl = *args
|
|
172
|
+
singleton_obj = nil
|
|
173
|
+
if klass.is_a?(Class) # regular class
|
|
174
|
+
klass_name = klass.name
|
|
175
|
+
elsif (klass.is_a?(Symbol) || klass.is_a?(String))
|
|
176
|
+
klass_name = klass.to_s
|
|
177
|
+
if klass.name.downcase == "sockets" # just a bunch of sockets
|
|
178
|
+
require 'ipaccess/arm_sockets'
|
|
179
|
+
return
|
|
180
|
+
else # regular class as a string or symbol
|
|
181
|
+
klass = Kernel
|
|
182
|
+
klass_name.to_s.split('::').each do |k|
|
|
183
|
+
klass = klass.const_get(k)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
else # regular object (will patch singleton of this object)
|
|
187
|
+
klass_name = klass.class.name
|
|
188
|
+
singleton_obj = klass
|
|
189
|
+
klass = (class <<klass; self; end)
|
|
190
|
+
end
|
|
191
|
+
begin
|
|
192
|
+
patch_klass = IPAccess::Patches
|
|
193
|
+
klass_name.split('::').each do |k|
|
|
194
|
+
patch_klass = patch_klass.const_get(k)
|
|
195
|
+
end
|
|
196
|
+
rescue NameError
|
|
197
|
+
raise ArgumentError, "cannot enable IP access control for class #{klass_name}"
|
|
198
|
+
end
|
|
199
|
+
klass.__send__(:include, patch_klass)
|
|
200
|
+
singleton_obj.__send__(:__ipa_singleton_hook, acl, cod) unless singleton_obj.nil?
|
|
201
|
+
return klass
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# :stopdoc:
|
|
205
|
+
|
|
206
|
+
# This module patches network classes
|
|
207
|
+
# to enforce IP access control for them. Each patched
|
|
208
|
+
# class has the acl member, which is an IPAccess::Set object.
|
|
209
|
+
|
|
210
|
+
module Patches
|
|
211
|
+
|
|
212
|
+
# This class is a proxy that raises an exception when
|
|
213
|
+
# any method other than defined in Object class is called.
|
|
214
|
+
# It behaves like NilClass. Do not use this class, use
|
|
215
|
+
# IPAccess::Set.Global constant instead.
|
|
216
|
+
|
|
217
|
+
class IPAccess::Set::GlobalSet
|
|
218
|
+
|
|
219
|
+
include Singleton
|
|
220
|
+
|
|
221
|
+
# imitate nil
|
|
222
|
+
def nil?; true end
|
|
223
|
+
|
|
224
|
+
# This method returns +true+ if current object is IPAccess::Set.Global.
|
|
225
|
+
# Otherwise it returns +false+.
|
|
226
|
+
def global?; true end
|
|
227
|
+
|
|
228
|
+
# return +true+ when compared to IPAccess::Set.Global
|
|
229
|
+
def ==(obj)
|
|
230
|
+
return true if obj.object_id == IPAccess::Set::Global.object_id
|
|
231
|
+
method_missing(:==, obj)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def ===(obj)
|
|
235
|
+
return true if obj.object_id == IPAccess::Set::Global.object_id
|
|
236
|
+
method_missing(:===, obj)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# imitate IPAccess::Set.Global when inspected
|
|
240
|
+
def inspect
|
|
241
|
+
IPAccess::Set::Global.inspect
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# imitate nil even more and disallow direct ACL modifications
|
|
245
|
+
def method_missing(name, *args)
|
|
246
|
+
return nil.method(name).call(*args) if nil.respond_to?(name)
|
|
247
|
+
raise ArgumentError, "cannot access global set from object's scope, use IPAccess::Set::Global"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
end # class IPAccess::Set.GlobalSet
|
|
251
|
+
|
|
252
|
+
# The ACL module contains methods
|
|
253
|
+
# that are present in all network
|
|
254
|
+
# objects with IP access control enabled.
|
|
255
|
+
|
|
256
|
+
module ACL
|
|
257
|
+
|
|
258
|
+
# This method is used to safely
|
|
259
|
+
# pass an eventual exception
|
|
260
|
+
# and fill its useables field with a current
|
|
261
|
+
# object.
|
|
262
|
+
|
|
263
|
+
def __ipa_wrap_socket_call(*args, &block)
|
|
264
|
+
IPAccess.take_care(self, *args, &block)
|
|
265
|
+
end
|
|
266
|
+
protected :__ipa_wrap_socket_call
|
|
267
|
+
|
|
268
|
+
# This method enables usage of internal IP access list for object.
|
|
269
|
+
# If argument is IPAccess::Set object then it is used.
|
|
270
|
+
#
|
|
271
|
+
# ==== Example
|
|
272
|
+
#
|
|
273
|
+
# socket.acl = :global # use global access set
|
|
274
|
+
# socket.acl = :private # create and use individual access set
|
|
275
|
+
# socket.acl = IPAccess::Set.new # use external (shared) access set
|
|
276
|
+
|
|
277
|
+
def acl=(access_set)
|
|
278
|
+
new_acl = nil
|
|
279
|
+
prev_acl = @acl
|
|
280
|
+
if access_set.is_a?(Symbol)
|
|
281
|
+
case access_set
|
|
282
|
+
when :global
|
|
283
|
+
new_acl = IPAccess::Set::GlobalSet.instance
|
|
284
|
+
when :private
|
|
285
|
+
new_acl = IPAccess::Set.new
|
|
286
|
+
else
|
|
287
|
+
raise ArgumentError, "bad access list selector, use: :global or :private"
|
|
288
|
+
end
|
|
289
|
+
elsif access_set.is_a?(IPAccess::Set)
|
|
290
|
+
if access_set == IPAccess::Set::Global
|
|
291
|
+
new_acl = IPAccess::Set::GlobalSet.instance
|
|
292
|
+
else
|
|
293
|
+
new_acl = access_set
|
|
294
|
+
end
|
|
295
|
+
elsif access_set.nil?
|
|
296
|
+
new_acl = IPAccess::Set::GlobalSet.instance
|
|
297
|
+
else
|
|
298
|
+
raise ArgumentError, "bad access list"
|
|
299
|
+
end
|
|
300
|
+
unless (new_acl.nil? || prev_acl.object_id == new_acl.object_id)
|
|
301
|
+
@acl = new_acl
|
|
302
|
+
self.acl_recheck if self.respond_to?(:acl_recheck)
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# This method returns +true+ if the given object can be used to initialize ACL.
|
|
307
|
+
# Otherwise it returns +false+.
|
|
308
|
+
|
|
309
|
+
def IPAccess.valid_acl?(obj)
|
|
310
|
+
if obj.is_a?(Symbol)
|
|
311
|
+
return true if (obj == :global || obj == :private)
|
|
312
|
+
elsif obj.is_a?(IPAccess::Set)
|
|
313
|
+
return true
|
|
314
|
+
end
|
|
315
|
+
return false
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# This method returns +true+ if the given object can be used to initialize ACL.
|
|
319
|
+
# Otherwise it returns +false+.
|
|
320
|
+
|
|
321
|
+
def valid_acl?(obj)
|
|
322
|
+
IPAccess.valid_acl?(obj)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# This method should be called each time the access set related to an object
|
|
326
|
+
# is changed and there is a need to validate remote peer again, since it might be
|
|
327
|
+
# blacklisted.
|
|
328
|
+
#
|
|
329
|
+
# Each class that patches Ruby's network class should redefine this method
|
|
330
|
+
# and call it in a proper place (e.g. from hook executed when singleton methods
|
|
331
|
+
# are added to network object).
|
|
332
|
+
|
|
333
|
+
def acl_recheck
|
|
334
|
+
;
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# This method return current access set for an object.
|
|
338
|
+
#
|
|
339
|
+
# Ifaccess set (@acl) is somehow set to +nil+
|
|
340
|
+
# (which should never happend) or to IPAccess::Set.GlobalSet
|
|
341
|
+
# (which is internal singleton used to mark that @acl should
|
|
342
|
+
# point to the global set) it will return a reference
|
|
343
|
+
# to the global access set IPAccess::Set.Global.
|
|
344
|
+
|
|
345
|
+
def real_acl
|
|
346
|
+
@acl.nil? ? IPAccess::Set::Global : @acl
|
|
347
|
+
end
|
|
348
|
+
private :real_acl
|
|
349
|
+
|
|
350
|
+
attr_reader :acl
|
|
351
|
+
alias_method :access=, :acl=
|
|
352
|
+
alias_method :access, :acl
|
|
353
|
+
|
|
354
|
+
# This method returns default access list indicator
|
|
355
|
+
# used by protected object; usually +:input+ or
|
|
356
|
+
# +:output+.
|
|
357
|
+
|
|
358
|
+
def default_list; :output end
|
|
359
|
+
|
|
360
|
+
# :call-seq:
|
|
361
|
+
# whitelist(list, *addresses)
|
|
362
|
+
# whitelist(*addresses)
|
|
363
|
+
#
|
|
364
|
+
# This method whitelists IP address(-es) in
|
|
365
|
+
# the input or output access list selected
|
|
366
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
367
|
+
# If the access list selector is omited it
|
|
368
|
+
# operates on the default access list that certain
|
|
369
|
+
# kind of network object uses. The allowed format of address
|
|
370
|
+
# is the same as for IPAccess.to_cidrs.
|
|
371
|
+
# This method will not add nor remove any
|
|
372
|
+
# blacklisted item.
|
|
373
|
+
#
|
|
374
|
+
# It will return the result of calling
|
|
375
|
+
# IPAccess::List#whitelist on the list.
|
|
376
|
+
#
|
|
377
|
+
# This method won't allow you to modify the list if
|
|
378
|
+
# the global access set is associated with an object.
|
|
379
|
+
# You may operate on IPAccess::Set.Global or use
|
|
380
|
+
# whitelist! instead.
|
|
381
|
+
#
|
|
382
|
+
# === Revalidation
|
|
383
|
+
#
|
|
384
|
+
# After modyfing access set current connection
|
|
385
|
+
# is validated again to avoid access leaks.
|
|
386
|
+
#
|
|
387
|
+
# === DNS Warning
|
|
388
|
+
#
|
|
389
|
+
# You should avoid passing hostnames as arguments since
|
|
390
|
+
# DNS is not reliable and responses may change with time,
|
|
391
|
+
# which may cause security flaws.
|
|
392
|
+
|
|
393
|
+
def whitelist(*addresses)
|
|
394
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
395
|
+
r = @acl.send(aclist).whitelist(*addresses)
|
|
396
|
+
self.acl_recheck
|
|
397
|
+
return r
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
alias_method :add_white, :whitelist
|
|
401
|
+
alias_method :allow, :whitelist
|
|
402
|
+
alias_method :permit, :whitelist
|
|
403
|
+
|
|
404
|
+
# This method works like whitelist but allows
|
|
405
|
+
# to set reason.
|
|
406
|
+
|
|
407
|
+
def whitelist_reasonable(reason, *addresses)
|
|
408
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
409
|
+
r = @acl.send(aclist).whitelist_reasonable(reason, *addresses)
|
|
410
|
+
self.acl_recheck
|
|
411
|
+
return r
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# :call-seq:
|
|
415
|
+
# whitelist!(list, *addresses)
|
|
416
|
+
# whitelist!(*addresses)
|
|
417
|
+
#
|
|
418
|
+
# This method whitelists IP address(-es) in
|
|
419
|
+
# the input or output access list selected
|
|
420
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
421
|
+
# If the access list selector is omited it
|
|
422
|
+
# operates on the default access list that certain
|
|
423
|
+
# kind of network object uses. The allowed format of address
|
|
424
|
+
# is the same as for IPAccess.to_cidrs.
|
|
425
|
+
# This method will not add nor remove any
|
|
426
|
+
# blacklisted item.
|
|
427
|
+
#
|
|
428
|
+
# It will return the result of calling
|
|
429
|
+
# IPAccess::List#whitelist on the list.
|
|
430
|
+
#
|
|
431
|
+
# This method will allow you to modify the list
|
|
432
|
+
# even if the global access set is used by object.
|
|
433
|
+
#
|
|
434
|
+
# === Revalidation
|
|
435
|
+
#
|
|
436
|
+
# After modyfing access set current connection
|
|
437
|
+
# is validated again to avoid access leaks.
|
|
438
|
+
#
|
|
439
|
+
# === DNS Warning
|
|
440
|
+
#
|
|
441
|
+
# You should avoid passing hostnames as arguments since
|
|
442
|
+
# DNS is not reliable and responses may change with time,
|
|
443
|
+
# which may cause security flaws.
|
|
444
|
+
|
|
445
|
+
def whitelist!(*addresses)
|
|
446
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
447
|
+
r = real_acl.send(aclist).whitelist(*addresses)
|
|
448
|
+
self.acl_recheck
|
|
449
|
+
return r
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
alias_method :add_white!, :whitelist!
|
|
453
|
+
alias_method :allow!, :whitelist!
|
|
454
|
+
alias_method :permit!, :whitelist!
|
|
455
|
+
|
|
456
|
+
# This method works like whitelist! but
|
|
457
|
+
# allows to set reason.
|
|
458
|
+
|
|
459
|
+
def whitelist_reasonable!(*addresses)
|
|
460
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
461
|
+
r = real_acl.send(aclist).whitelist_reasonable(reason, *addresses)
|
|
462
|
+
self.acl_recheck
|
|
463
|
+
return r
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# :call-seq:
|
|
467
|
+
# unwhitelist(list, *addresses)
|
|
468
|
+
# unwhitelist(*addresses)
|
|
469
|
+
#
|
|
470
|
+
# This method removes whitelisted IP address(-es)
|
|
471
|
+
# from the input or output access list selected
|
|
472
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
473
|
+
# If the access list selector is omited it
|
|
474
|
+
# operates on the default access list that certain
|
|
475
|
+
# kind of network object uses. The allowed format of address
|
|
476
|
+
# is the same as for IPAccess.to_cidrs.
|
|
477
|
+
# This method will not add nor remove any
|
|
478
|
+
# blacklisted item.
|
|
479
|
+
#
|
|
480
|
+
# It will return the result of calling
|
|
481
|
+
# IPAccess::List#unwhitelist on the list.
|
|
482
|
+
#
|
|
483
|
+
# This method won't allow you to modify the list if
|
|
484
|
+
# the global access set is associated with an object.
|
|
485
|
+
# You may operate on IPAccess::Set.Global or use
|
|
486
|
+
# unwhitelist! instead.
|
|
487
|
+
#
|
|
488
|
+
# === Revalidation
|
|
489
|
+
#
|
|
490
|
+
# After modyfing access set current connection
|
|
491
|
+
# is validated again to avoid access leaks.
|
|
492
|
+
#
|
|
493
|
+
# === DNS Warning
|
|
494
|
+
#
|
|
495
|
+
# You should avoid passing hostnames as arguments since
|
|
496
|
+
# DNS is not reliable and responses may change with time,
|
|
497
|
+
# which may cause security flaws.
|
|
498
|
+
|
|
499
|
+
def unwhitelist(*addresses)
|
|
500
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
501
|
+
r = @acl.send(aclist).unwhitelist(*addresses)
|
|
502
|
+
self.acl_recheck
|
|
503
|
+
return r
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
alias_method :unwhite, :unwhitelist
|
|
507
|
+
alias_method :del_white, :unwhitelist
|
|
508
|
+
alias_method :unallow, :unwhitelist
|
|
509
|
+
alias_method :unpermit, :unwhitelist
|
|
510
|
+
|
|
511
|
+
# :call-seq:
|
|
512
|
+
# unwhitelist!(list, *addresses)
|
|
513
|
+
# unwhitelist!(*addresses)
|
|
514
|
+
#
|
|
515
|
+
# This method removes whitelisted IP address(-es)
|
|
516
|
+
# from the input or output access list selected
|
|
517
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
518
|
+
# If the access list selector is omited it
|
|
519
|
+
# operates on the default access list that certain
|
|
520
|
+
# kind of network object uses. The allowed format of address
|
|
521
|
+
# is the same as for IPAccess.to_cidrs.
|
|
522
|
+
# This method will not add nor remove any
|
|
523
|
+
# blacklisted item.
|
|
524
|
+
#
|
|
525
|
+
# It will return the result of calling
|
|
526
|
+
# IPAccess::List#unwhitelist on the list.
|
|
527
|
+
#
|
|
528
|
+
# This method will allow you to modify the list
|
|
529
|
+
# even if the global access set is used by object.
|
|
530
|
+
#
|
|
531
|
+
# === Revalidation
|
|
532
|
+
#
|
|
533
|
+
# After modyfing access set current connection
|
|
534
|
+
# is validated again to avoid access leaks.
|
|
535
|
+
#
|
|
536
|
+
# === DNS Warning
|
|
537
|
+
#
|
|
538
|
+
# You should avoid passing hostnames as arguments since
|
|
539
|
+
# DNS is not reliable and responses may change with time,
|
|
540
|
+
# which may cause security flaws.
|
|
541
|
+
|
|
542
|
+
def unwhitelist!(*addresses)
|
|
543
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
544
|
+
r = real_acl.send(aclist).unwhitelist(*addresses)
|
|
545
|
+
self.acl_recheck
|
|
546
|
+
return r
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
alias_method :unwhite!, :unwhitelist!
|
|
550
|
+
alias_method :del_white!, :unwhitelist!
|
|
551
|
+
alias_method :unallow!, :unwhitelist!
|
|
552
|
+
alias_method :unpermit!, :unwhitelist!
|
|
553
|
+
|
|
554
|
+
# :call-seq:
|
|
555
|
+
# blacklist(list, *addresses)
|
|
556
|
+
# blacklist(*addresses)
|
|
557
|
+
#
|
|
558
|
+
# This method blacklists IP address(-es) in
|
|
559
|
+
# the input or output access list selected
|
|
560
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
561
|
+
# If the access list selector is omited it
|
|
562
|
+
# operates on the default access list that certain
|
|
563
|
+
# kind of network object uses. The allowed format of address
|
|
564
|
+
# is the same as for IPAccess.to_cidrs.
|
|
565
|
+
# This method will not add nor remove any
|
|
566
|
+
# whitelisted item.
|
|
567
|
+
#
|
|
568
|
+
# It will return the result of calling
|
|
569
|
+
# IPAccess::List#blacklist on the list.
|
|
570
|
+
#
|
|
571
|
+
# This method won't allow you to modify the list if
|
|
572
|
+
# the global access set is associated with an object.
|
|
573
|
+
# You may operate on IPAccess::Set.Global or use
|
|
574
|
+
# blacklist! instead.
|
|
575
|
+
#
|
|
576
|
+
# === Revalidation
|
|
577
|
+
#
|
|
578
|
+
# After modyfing access set current connection
|
|
579
|
+
# is validated again to avoid access leaks.
|
|
580
|
+
#
|
|
581
|
+
# === DNS Warning
|
|
582
|
+
#
|
|
583
|
+
# You should avoid passing hostnames as arguments since
|
|
584
|
+
# DNS is not reliable and responses may change with time,
|
|
585
|
+
# which may cause security flaws.
|
|
586
|
+
|
|
587
|
+
def blacklist(*addresses)
|
|
588
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
589
|
+
r = @acl.send(aclist).blacklist(*addresses)
|
|
590
|
+
self.acl_recheck
|
|
591
|
+
return r
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
alias_method :add_black, :blacklist
|
|
595
|
+
alias_method :deny, :blacklist
|
|
596
|
+
alias_method :block, :blacklist
|
|
597
|
+
|
|
598
|
+
# This method works like blacklist but allows to
|
|
599
|
+
# set reason.
|
|
600
|
+
|
|
601
|
+
def blacklist_reasonable(reason, *addresses)
|
|
602
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
603
|
+
r = @acl.send(aclist).blacklist_reasonable(reason, *addresses)
|
|
604
|
+
self.acl_recheck
|
|
605
|
+
return r
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
# :call-seq:
|
|
609
|
+
# blacklist!(list, *addresses)
|
|
610
|
+
# blacklist!(*addresses)
|
|
611
|
+
#
|
|
612
|
+
# This method blacklists IP address(-es) in
|
|
613
|
+
# the input or output access list selected
|
|
614
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
615
|
+
# If the access list selector is omited it
|
|
616
|
+
# operates on the default access list that certain
|
|
617
|
+
# kind of network object uses. The allowed format of address
|
|
618
|
+
# is the same as for IPAccess.to_cidrs.
|
|
619
|
+
# This method will not add nor remove any
|
|
620
|
+
# whitelisted item.
|
|
621
|
+
#
|
|
622
|
+
# It will return the result of calling
|
|
623
|
+
# IPAccess::List#blacklist on the list.
|
|
624
|
+
#
|
|
625
|
+
# This method will allow you to modify the list
|
|
626
|
+
# even if the global access set is used by object.
|
|
627
|
+
#
|
|
628
|
+
# === Revalidation
|
|
629
|
+
#
|
|
630
|
+
# After modyfing access set current connection
|
|
631
|
+
# is validated again to avoid access leaks.
|
|
632
|
+
#
|
|
633
|
+
# === DNS Warning
|
|
634
|
+
#
|
|
635
|
+
# You should avoid passing hostnames as arguments since
|
|
636
|
+
# DNS is not reliable and responses may change with time,
|
|
637
|
+
# which may cause security flaws.
|
|
638
|
+
|
|
639
|
+
def blacklist!(*addresses)
|
|
640
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
641
|
+
r = real_acl.send(aclist).blacklist(*addresses)
|
|
642
|
+
self.acl_recheck
|
|
643
|
+
return r
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
alias_method :add_black!, :blacklist!
|
|
647
|
+
alias_method :deny!, :blacklist!
|
|
648
|
+
alias_method :block!, :blacklist!
|
|
649
|
+
|
|
650
|
+
# This method works like blacklist! but allows
|
|
651
|
+
# to set reason.
|
|
652
|
+
|
|
653
|
+
def blacklist_reasonable!(reason, *addresses)
|
|
654
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
655
|
+
r = real_acl.send(aclist).blacklist(reason, *addresses)
|
|
656
|
+
self.acl_recheck
|
|
657
|
+
return r
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
# :call-seq:
|
|
661
|
+
# unblacklist(list, *addresses)
|
|
662
|
+
# unblacklist(*addresses)
|
|
663
|
+
#
|
|
664
|
+
# This method removes blacklisted IP address(-es)
|
|
665
|
+
# from the input or output access list selected
|
|
666
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
667
|
+
# If the access list selector is omited it
|
|
668
|
+
# operates on the default access list that certain
|
|
669
|
+
# kind of network object uses. The allowed format of address
|
|
670
|
+
# is the same as for IPAccess.to_cidrs.
|
|
671
|
+
# This method will not add nor remove any
|
|
672
|
+
# whitelisted item.
|
|
673
|
+
#
|
|
674
|
+
# It will return the result of calling
|
|
675
|
+
# IPAccess::List#unblacklist on the list.
|
|
676
|
+
#
|
|
677
|
+
# This method won't allow you to modify the list if
|
|
678
|
+
# the global access set is associated with an object.
|
|
679
|
+
# You may operate on IPAccess::Set.Global or use
|
|
680
|
+
# unwhitelist! instead.
|
|
681
|
+
#
|
|
682
|
+
# === Revalidation
|
|
683
|
+
#
|
|
684
|
+
# After modyfing access set current connection
|
|
685
|
+
# is validated again to avoid access leaks.
|
|
686
|
+
#
|
|
687
|
+
# === DNS Warning
|
|
688
|
+
#
|
|
689
|
+
# You should avoid passing hostnames as arguments since
|
|
690
|
+
# DNS is not reliable and responses may change with time,
|
|
691
|
+
# which may cause security flaws.
|
|
692
|
+
|
|
693
|
+
def unblacklist(*addresses)
|
|
694
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
695
|
+
r = @acl.send(aclist).unblacklist(*addresses)
|
|
696
|
+
self.acl_recheck
|
|
697
|
+
return r
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
alias_method :unblack, :unblacklist
|
|
701
|
+
alias_method :undeny, :unblacklist
|
|
702
|
+
alias_method :unblock, :unblacklist
|
|
703
|
+
alias_method :del_black, :unblacklist
|
|
704
|
+
|
|
705
|
+
# :call-seq:
|
|
706
|
+
# unblacklist!(list, *addresses)
|
|
707
|
+
# unblacklist!(*addresses)
|
|
708
|
+
#
|
|
709
|
+
# This method removes blacklisted IP address(-es)
|
|
710
|
+
# from the input or output access list selected
|
|
711
|
+
# by the *list* argument (+:input+ or +:output+).
|
|
712
|
+
# If the access list selector is omited it
|
|
713
|
+
# operates on the default access list that certain
|
|
714
|
+
# kind of network object uses. The allowed format of address
|
|
715
|
+
# is the same as for IPAccess.to_cidrs.
|
|
716
|
+
# This method will not add nor remove any
|
|
717
|
+
# whitelisted item.
|
|
718
|
+
#
|
|
719
|
+
# It will return the result of calling
|
|
720
|
+
# IPAccess::List#unblacklist on the list.
|
|
721
|
+
#
|
|
722
|
+
# This method will allow you to modify the list
|
|
723
|
+
# even if the global access set is used by object.
|
|
724
|
+
#
|
|
725
|
+
# === Revalidation
|
|
726
|
+
#
|
|
727
|
+
# After modyfing access set current connection
|
|
728
|
+
# is validated again to avoid access leaks.
|
|
729
|
+
#
|
|
730
|
+
# === DNS Warning
|
|
731
|
+
#
|
|
732
|
+
# You should avoid passing hostnames as arguments since
|
|
733
|
+
# DNS is not reliable and responses may change with time,
|
|
734
|
+
# which may cause security flaws.
|
|
735
|
+
|
|
736
|
+
def unblacklist!(*addresses)
|
|
737
|
+
aclist = ( addresses.first.is_a?(Symbol) && [:input,:output].include?(addresses.first) ) ? addresses.shift : self.default_list
|
|
738
|
+
r = real_acl.send(aclist).unblacklist(*addresses)
|
|
739
|
+
self.acl_recheck
|
|
740
|
+
return r
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
alias_method :unblack!, :unblacklist!
|
|
744
|
+
alias_method :undeny!, :unblacklist!
|
|
745
|
+
alias_method :unblock!, :unblacklist!
|
|
746
|
+
alias_method :del_black!, :unblacklist!
|
|
747
|
+
|
|
748
|
+
# Setting it to +false+ disables closing connection
|
|
749
|
+
# when raising access denied exception
|
|
750
|
+
|
|
751
|
+
attr_accessor :opened_on_deny
|
|
752
|
+
|
|
753
|
+
# Setting it to +true+ disables closing connection
|
|
754
|
+
# when raising access denied exception
|
|
755
|
+
|
|
756
|
+
def close_on_deny=(x)
|
|
757
|
+
self.open_on_deny = !x
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
def close_on_deny
|
|
761
|
+
not self.open_on_deny
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
# This method is universal wrapper for
|
|
765
|
+
# closing connection. Classes should
|
|
766
|
+
# override it.
|
|
767
|
+
|
|
768
|
+
def terminate
|
|
769
|
+
self.close unless self.closed?
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
# This method will try to close
|
|
773
|
+
# session/connection for network object
|
|
774
|
+
# if +open_on_deny+ member is set to +false+
|
|
775
|
+
|
|
776
|
+
def try_terminate
|
|
777
|
+
terminate unless @opened_on_deny
|
|
778
|
+
return nil
|
|
779
|
+
end
|
|
780
|
+
private :try_terminate
|
|
781
|
+
|
|
782
|
+
# helper for dropping unwanted connections
|
|
783
|
+
def try_terminate_subsocket(sock)
|
|
784
|
+
sock.close unless (@opened_on_deny || sock.closed?)
|
|
785
|
+
return nil
|
|
786
|
+
end
|
|
787
|
+
private :try_terminate_subsocket
|
|
788
|
+
|
|
789
|
+
# This method will be called when
|
|
790
|
+
# instance is patched.
|
|
791
|
+
|
|
792
|
+
def __ipa_singleton_hook(acl=nil, open_on_deny=false)
|
|
793
|
+
@opened_on_deny = open_on_deny
|
|
794
|
+
acl = @options["ACL"] if (acl.nil? && instance_variable_defined?(:@options) && @options.respond_to?(:has_key?))
|
|
795
|
+
self.acl = acl
|
|
796
|
+
end
|
|
797
|
+
private :__ipa_singleton_hook
|
|
798
|
+
|
|
799
|
+
end # module ACL
|
|
800
|
+
|
|
801
|
+
end # module Patches
|
|
802
|
+
|
|
803
|
+
# :startdoc:
|
|
804
|
+
|
|
805
|
+
end # module IPAccess
|
|
806
|
+
|
|
807
|
+
|