ipaccess 1.2.0 → 1.2.2
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 +5 -13
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.yardopts +2 -0
- data/ChangeLog +66 -0
- data/Manifest.txt +5 -10
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/docs/HISTORY +11 -0
- data/docs/TODO +1 -1
- data/docs/yard-tpl/default/fulldoc/html/css/common.css +5 -0
- data/examples/open-uri.rb +14 -0
- data/examples/telnet.rb +1 -1
- data/ipaccess.gemspec +62 -0
- data/lib/ipaccess.rb +2 -566
- data/lib/ipaccess/arm_sockets.rb +0 -1
- data/lib/ipaccess/core.rb +523 -0
- data/lib/ipaccess/ghost_doc/ghost_doc.rb +1 -1
- data/lib/ipaccess/ghost_doc/ghost_doc_acl.rdoc +54 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_net_ftp.rb +35 -19
- data/lib/ipaccess/ghost_doc/ghost_doc_net_http.rb +34 -18
- data/lib/ipaccess/ghost_doc/ghost_doc_net_smtp.rb +35 -19
- data/lib/ipaccess/ghost_doc/ghost_doc_net_telnet.rb +35 -19
- data/lib/ipaccess/ghost_doc/ghost_doc_patched_usage.rdoc +65 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_sockets.rb +353 -125
- data/lib/ipaccess/ip_access_check.rb +2 -2
- data/lib/ipaccess/ip_access_errors.rb +2 -2
- data/lib/ipaccess/ip_access_list.rb +3 -3
- data/lib/ipaccess/patches/generic.rb +150 -183
- data/lib/ipaccess/patches/net_ftp.rb +1 -2
- data/lib/ipaccess/patches/net_http.rb +10 -14
- data/lib/ipaccess/patches/net_imap.rb +1 -2
- data/lib/ipaccess/patches/net_pop.rb +2 -4
- data/lib/ipaccess/patches/net_smtp.rb +2 -4
- data/lib/ipaccess/patches/net_telnet.rb +1 -2
- data/lib/ipaccess/patches/sockets.rb +67 -69
- data/lib/ipaccess/socket.rb +0 -17
- metadata +70 -100
- metadata.gz.sig +0 -0
- data/lib/ipaccess/ghost_doc/ghost_doc_acl.rb +0 -54
- data/lib/ipaccess/ghost_doc/ghost_doc_p_blacklist.rb +0 -36
- data/lib/ipaccess/ghost_doc/ghost_doc_p_blacklist_e.rb +0 -7
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unblacklist.rb +0 -36
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unblacklist_e.rb +0 -7
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unwhitelist.rb +0 -36
- data/lib/ipaccess/ghost_doc/ghost_doc_p_unwhitelist_e.rb +0 -7
- data/lib/ipaccess/ghost_doc/ghost_doc_p_whitelist.rb +0 -36
- data/lib/ipaccess/ghost_doc/ghost_doc_p_whitelist_e.rb +0 -7
- data/lib/ipaccess/ghost_doc/ghost_doc_patched_usage.rb +0 -64
data/lib/ipaccess/arm_sockets.rb
CHANGED
@@ -0,0 +1,523 @@
|
|
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 library allow you to create
|
8
|
+
# and manage IP access lists in an easy way. You may use
|
9
|
+
# IPAccess::Set class to maintain inpu/output traffic control.
|
10
|
+
# You also may use IPAccess::List class directly to build
|
11
|
+
# your own access sets based on black lists and white lists.
|
12
|
+
|
13
|
+
require 'ipaccess/patches/netaddr'
|
14
|
+
require 'ipaccess/ip_access_list'
|
15
|
+
require 'ipaccess/ip_access_set'
|
16
|
+
|
17
|
+
# This module contains classes that are used to control IP access.
|
18
|
+
# There are three major components you may want to use:
|
19
|
+
#
|
20
|
+
# === IPAccess::List class
|
21
|
+
#
|
22
|
+
# This class lets you create IP access list with blacklisted
|
23
|
+
# and whitelisted elements. It also has methods for checking
|
24
|
+
# whether given IP matches the list.
|
25
|
+
#
|
26
|
+
# === IPAccess::Set class
|
27
|
+
#
|
28
|
+
# This class contains two objects that are instances
|
29
|
+
# of IPAccess::List class. It allows you to create so
|
30
|
+
# called access set. The access set contains members named
|
31
|
+
# +input+ and +output+. All methods that validate IP access do it
|
32
|
+
# against one of the lists. Input access list is for incomming
|
33
|
+
# and output for outgoing IP traffic. In case of connection-oriented
|
34
|
+
# sockets and other network objects the convention is to use output access
|
35
|
+
# list to validate connections that we initiate. The incomming traffic
|
36
|
+
# in that model means the connections initiated by a remote peer.
|
37
|
+
#
|
38
|
+
# === Patching engine
|
39
|
+
#
|
40
|
+
# IPAccess was initialy considered as a set of classes that you may use
|
41
|
+
# in your own programs to control IP access. That means your own classes
|
42
|
+
# used for communication should use access lists or sets before making any
|
43
|
+
# real connections or sending any datagrams.
|
44
|
+
#
|
45
|
+
# Fortunately there are many network classes, including sockets, that Ruby ships with.
|
46
|
+
# It would be waste of resources to not modify them to support IP access control
|
47
|
+
# and automagically throw exceptions when access should be denied.
|
48
|
+
#
|
49
|
+
# And here the special module method called +IPAccess.arm+
|
50
|
+
# comes in. It lets you patch most of Ruby's networking classes and objects. Besides
|
51
|
+
# equipping them in IPAccess::Set instance it also adds some methods for doing quick
|
52
|
+
# checks and changes in access lists.
|
53
|
+
#
|
54
|
+
# The patching engine can arm network classes and single network objects.
|
55
|
+
# It is not loaded by default since you may not want extra code attached to a
|
56
|
+
# program that uses access lists or sets with own access checking code.
|
57
|
+
#
|
58
|
+
# === Variants of popular classes
|
59
|
+
#
|
60
|
+
# Sometimes you want to write a code that uses standard Ruby's network objects
|
61
|
+
# but you find it dirty to alter classes or objects. In that case you may
|
62
|
+
# want to use static variants of Ruby's network classes that are not patches
|
63
|
+
# but derived classes.
|
64
|
+
#
|
65
|
+
# === Exceptions
|
66
|
+
#
|
67
|
+
# When you are dealing with patched (armed) versions of classes and objects
|
68
|
+
# or when you are using special variants of popular network classes, you have
|
69
|
+
# to rely on exceptions as the only way for access checking methods to tell
|
70
|
+
# your program that an event (like access denied) happened.
|
71
|
+
#
|
72
|
+
# Note that when exception is thrown the communication session is closed in case
|
73
|
+
# of connection-oriented network objects. You may change it by setting
|
74
|
+
# +opened_on_deny+ attribute to +true+.
|
75
|
+
#
|
76
|
+
# See IPAccess::Set#check_in to know more about tracking original network object
|
77
|
+
# that caused exception to happend. Note that in case of armed versions of network
|
78
|
+
# classes (or access-contolled variants) an information about original network
|
79
|
+
# object stored within an exception will be set to +nil+ if access had been denied before
|
80
|
+
# object was initialized. This shouldn't happend often, since access checks are lazy
|
81
|
+
# (they are performed only when connection is going to be made).
|
82
|
+
#
|
83
|
+
# See IPAccessDenied for more information about what you can do with exceptions.
|
84
|
+
#
|
85
|
+
# === Sockets in armed network objects
|
86
|
+
#
|
87
|
+
# Specialized Ruby's network classes, such as Net::HTTP or Net::Telnet
|
88
|
+
# and their variants created by this library, make use of socket objects.
|
89
|
+
# For example Net::HTTP class uses TCPSocket instance to
|
90
|
+
# create TCP connection. When versions of these <tt>Net::</tt> objects with
|
91
|
+
# enabled access control are used then the internal routines of IPAccess
|
92
|
+
# will also try to patch underlying sockets and assign to them the same
|
93
|
+
# access set that is used by main object. It is done to avoid access leaks.
|
94
|
+
# However, such armed internal sockets will have +opened_on_deny+ flag switched on
|
95
|
+
# since closing session (and an eventual connection) should be settled by main object.
|
96
|
+
#
|
97
|
+
# === Ordination of elements
|
98
|
+
#
|
99
|
+
# To properly understand what are the most important structures mentioned above it's worth
|
100
|
+
# to look at the diagram:
|
101
|
+
#
|
102
|
+
# link:images/ipaccess_view.png
|
103
|
+
#
|
104
|
+
# == Usage
|
105
|
+
#
|
106
|
+
# === Handling access sets and access lists
|
107
|
+
#
|
108
|
+
# If you need just IP access lists that you will handle in your own way
|
109
|
+
# you may want to use two classes:
|
110
|
+
#
|
111
|
+
# * IPAccess::Set to maintain access sets (containing input and output access lists),
|
112
|
+
# * IPAccess::List to maintain single access list.
|
113
|
+
#
|
114
|
+
# === Using socket classes
|
115
|
+
#
|
116
|
+
# If you want standard sockets to have access control enabled
|
117
|
+
# you may want to use:
|
118
|
+
#
|
119
|
+
# * IPAccess::Socket (or issue <tt>IPAccess.arm Socket</tt>)
|
120
|
+
# * IPAccess::TCPSocket (or issue <tt>IPAccess.arm TCPSocket</tt>)
|
121
|
+
# * IPAccess::UDPSocket (or issue <tt>IPAccess.arm UDPSocket</tt>)
|
122
|
+
# * IPAccess::SOCKSocket (or issue <tt>IPAccess.arm SOCKSocket</tt>)
|
123
|
+
# * IPAccess::TCPServer (or issue <tt>IPAccess.arm TCPServer</tt>)
|
124
|
+
#
|
125
|
+
# Before using any of them you must issue:
|
126
|
+
#
|
127
|
+
# * <tt>require 'ipaccess/socket'</tt>
|
128
|
+
#
|
129
|
+
# Using the IPAccess.arm causes standard socket class to be altered,
|
130
|
+
# while <tt>IPAccess::</tt> classes are just new variants of socket
|
131
|
+
# handling classes.
|
132
|
+
#
|
133
|
+
# ==== Using other supported network classes
|
134
|
+
#
|
135
|
+
# If you want some working objects to have access control enabled
|
136
|
+
# you may want to use:
|
137
|
+
#
|
138
|
+
# * IPAccess::Net::Telnet (or issue <tt>IPAccess.arm Net::Telnet</tt>)
|
139
|
+
# * IPAccess::Net::HTTP (or issue <tt>IPAccess.arm Net::HTTP</tt>)
|
140
|
+
# * IPAccess::Net::FTP (or issue <tt>IPAccess.arm Net::FTP</tt>)
|
141
|
+
# * IPAccess::Net::POP3 (or issue <tt>IPAccess.arm Net::POP3</tt>)
|
142
|
+
# * IPAccess::Net::IMAP (or issue <tt>IPAccess.arm Net::IMAP</tt>)
|
143
|
+
# * IPAccess::Net::SMTP (or issue <tt>IPAccess.arm Net::SMTP</tt>)
|
144
|
+
#
|
145
|
+
# ==== Using single network objects
|
146
|
+
#
|
147
|
+
# If you want to enable access control for single network
|
148
|
+
# object from the list shown above you may issue:
|
149
|
+
#
|
150
|
+
# require 'ipaccess/net/http'
|
151
|
+
# obj = Net::HTTP.new(host, port)
|
152
|
+
# IPAccess.arm obj
|
153
|
+
#
|
154
|
+
# or
|
155
|
+
#
|
156
|
+
# require 'ipaccess/socket'
|
157
|
+
# socket = IPAccess::TCPServer.new(31337)
|
158
|
+
# IPAccess.arm socket
|
159
|
+
#
|
160
|
+
# ..and so on.
|
161
|
+
#
|
162
|
+
# === Structures
|
163
|
+
#
|
164
|
+
# IP addresses used by the classes are internaly and interfacialy
|
165
|
+
# represented by NetAddr::CIDR[http://netaddr.rubyforge.org/classes/NetAddr/CIDR.html]
|
166
|
+
# objects (NetAddr::CIDRv4[http://netaddr.rubyforge.org/classes/NetAddr/CIDRv4.html] and
|
167
|
+
# NetAddr::CIDRv6[http://netaddr.rubyforge.org/classes/NetAddr/CIDRv6.html]). Due to
|
168
|
+
# performance reasons any access list internally is represented as a tree
|
169
|
+
# (slightly modified NetAddr::Tree[http://netaddr.rubyforge.org/classes/NetAddr/Tree.html])
|
170
|
+
# with special tags assigning rules to virtual lists.
|
171
|
+
#
|
172
|
+
# === Relations
|
173
|
+
#
|
174
|
+
# Here is a diagram which shows relations
|
175
|
+
# between the IPAccess::TCPSocket class
|
176
|
+
# and other classes from this module:
|
177
|
+
#
|
178
|
+
# link:images/ipaccess_relations.png
|
179
|
+
|
180
|
+
module IPAccess
|
181
|
+
|
182
|
+
# This method converts names to NetAddr::CIDR objects. It returns an array of CIDR objects.
|
183
|
+
#
|
184
|
+
# Allowed input are strings (DNS names or IP addresses optionally with masks),
|
185
|
+
# numbers (IP addresses representation), IPSocket objects, URI objects, IPAddr objects,
|
186
|
+
# Net::HTTP objects, IPAddrList objects, NetAddr::CIDR objects, NetAddr::Tree objects,
|
187
|
+
# IPAccess::List objects, symbols, objects that contain file descriptors bound to sockets
|
188
|
+
# (including OpenSSL sockets) and arrays of these.
|
189
|
+
#
|
190
|
+
# In case of resolving the IPv6 link-local addresses
|
191
|
+
# zone index is removed. In case of DNS names there may
|
192
|
+
# occur Resolv::ResolvError exception. If there is an
|
193
|
+
# object that cannot be converted the ArgumentError
|
194
|
+
# exception is raised.
|
195
|
+
#
|
196
|
+
# When an argument called +:include_origins+ is present then the method will attach
|
197
|
+
# original converted objects to results as the +:Origin+ tag of CIDR objects
|
198
|
+
# (<tt>tag[:Origin]</tt>). This rule applies only to single objects or objects
|
199
|
+
# inside of arrays or sets. Objects that are kind of NetAddr::CIDR, IPAccess::Set,
|
200
|
+
# NetAddr::Tree and arrays will never be set as originators.
|
201
|
+
#
|
202
|
+
# ==== Examples
|
203
|
+
#
|
204
|
+
# to_cidrs("127.0.0.1") # uses the IP address
|
205
|
+
# to_cidrs(2130706433) # uses numeric representation of 127.0.0.1
|
206
|
+
# to_cidrs(:private, "localhost") # uses special symbol and DNS hostname
|
207
|
+
# to_cidrs(:private, :localhost) # uses special symbols
|
208
|
+
# to_cidrs [:private, :auto] # other way to write the above
|
209
|
+
# to_cidrs "10.0.0.0/8" # uses masked IP address
|
210
|
+
# to_cidrs "10.0.0.0/255.0.0.0" # uses masked IP address
|
211
|
+
# to_cidrs IPSocket.new("www.pl", 80) # uses the socket
|
212
|
+
# to_cidrs IPAddr("10.0.0.1") # uses IPAddr object
|
213
|
+
# to_cidrs NetAddr::CIDR.create("10.0.0.1") # uses NetAddr object
|
214
|
+
# to_cidrs URI('http://www.pl/') # uses URI
|
215
|
+
# to_cidrs 'http://www.pl/' # uses the extracted host string
|
216
|
+
# to_cidrs 'somehost.xx' # uses the host string (fetches ALL addresses from DNS)
|
217
|
+
# to_cidrs 'somehost.xx/16' # uses the host string and a netmask
|
218
|
+
#
|
219
|
+
# ==== Special symbols
|
220
|
+
#
|
221
|
+
# When symbol is passed to this method it tries to find out if it has special meaning.
|
222
|
+
# That allows you to create access rules in an easy way. For most of them you may
|
223
|
+
# also specify IP protocol version using +ipv4_+ or +ipv6_+ prefix.
|
224
|
+
#
|
225
|
+
# Known symbols are:
|
226
|
+
#
|
227
|
+
# <b>+:all+</b> (+:any+, +:anyone+, +:world+, +:internet+, +:net+, +:everything+, +:everyone+, +:everybody+, +:anybody+)
|
228
|
+
#
|
229
|
+
# variants: +:ipv4_+ and +:ipv6_+
|
230
|
+
#
|
231
|
+
# Creates masked IP address that matches all networks:
|
232
|
+
# – 0.0.0.0/0
|
233
|
+
# – ::/0
|
234
|
+
#
|
235
|
+
# <b>+:broadcast+</b> (+:brd+)
|
236
|
+
#
|
237
|
+
# variants: +:ipv4_+ and +:ipv6_+
|
238
|
+
#
|
239
|
+
# Creates masked IP address that matches generic broadcast address:
|
240
|
+
# – 255.255.255.255/32
|
241
|
+
# – ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128
|
242
|
+
#
|
243
|
+
# <b>+:local+</b> (+:localhost+, +:localdomain+, +:loopback+, +:lo+)
|
244
|
+
#
|
245
|
+
# variants: +:ipv4_+ and +:ipv6_+
|
246
|
+
#
|
247
|
+
# Creates masked IP addresses that match localhost:
|
248
|
+
# – 127.0.0.1/8
|
249
|
+
# – ::1/128
|
250
|
+
#
|
251
|
+
# <b>+:auto+</b> (+:automatic+, +:linklocal+)
|
252
|
+
#
|
253
|
+
# variants: +:ipv4_+ and +:ipv6_+
|
254
|
+
#
|
255
|
+
# Creates masked IP addresses that match automatically assigned address ranges:
|
256
|
+
# – 169.254.0.0/16
|
257
|
+
# – fe80::/10
|
258
|
+
#
|
259
|
+
# <b>+:private+</b> (+:intra+, +:intranet+, +:internal+)
|
260
|
+
#
|
261
|
+
# variants: +:ipv4_+ and +:ipv6_+
|
262
|
+
#
|
263
|
+
# Creates masked IP addresses that match private ranges:
|
264
|
+
# – 10.0.0.0/8
|
265
|
+
# – 172.16.0.0/12
|
266
|
+
# – 192.168.0.0/16
|
267
|
+
# – 2001:10::/28
|
268
|
+
# – 2001:db8::/32
|
269
|
+
# – fc00::/7
|
270
|
+
# – fdde:9e1a:dc85:7374::/64
|
271
|
+
#
|
272
|
+
# <b>+:multicast+</b> (+:multi+, +:multiemission+)
|
273
|
+
#
|
274
|
+
# variants: +:ipv4_+ and +:ipv6_+
|
275
|
+
#
|
276
|
+
# Creates masked IP addresses that match multicast addresses ranges:
|
277
|
+
# – 224.0.0.0/4
|
278
|
+
# – ff00::/8
|
279
|
+
# – ff02::1:ff00:0/104
|
280
|
+
#
|
281
|
+
# <b>+:reserved+</b> (+:example+)
|
282
|
+
#
|
283
|
+
# variants: +:ipv4_+
|
284
|
+
#
|
285
|
+
# Creates masked IP addresses that match reserved addresses ranges:
|
286
|
+
# – 192.0.2.0/24
|
287
|
+
# – 128.0.0.0/16
|
288
|
+
# – 191.255.0.0/16
|
289
|
+
# – 192.0.0.0/24
|
290
|
+
# – 198.18.0.0/15
|
291
|
+
# – 223.255.255.0/24
|
292
|
+
# – 240.0.0.0/4
|
293
|
+
#
|
294
|
+
# <b>+:strange+</b> (+:unusual+, +:nonpublic+, +:unpublic+)
|
295
|
+
#
|
296
|
+
# Creates masked IP addressess that match the following sets (both IPv4 and IPv6):
|
297
|
+
# – :local
|
298
|
+
# – :auto
|
299
|
+
# – :private
|
300
|
+
# – :reserved
|
301
|
+
# – :multicast
|
302
|
+
|
303
|
+
def self.to_cidrs(*addresses)
|
304
|
+
obj = addresses.flatten
|
305
|
+
include_origins = !!obj.reject!{ |x| x.is_a?(Symbol) && x == :include_origins }
|
306
|
+
if obj.size == 1
|
307
|
+
obj = obj.first
|
308
|
+
else
|
309
|
+
ary = []
|
310
|
+
obj.each do |o|
|
311
|
+
ary += ( include_origins ? to_cidrs(o, :include_origins) : to_cidrs(o) )
|
312
|
+
end
|
313
|
+
ary.flatten!
|
314
|
+
return ary
|
315
|
+
end
|
316
|
+
|
317
|
+
ori_obj = obj
|
318
|
+
|
319
|
+
# NetAddr::CIDR - immediate generation
|
320
|
+
if obj.is_a?(NetAddr::CIDR)
|
321
|
+
r = obj.dup
|
322
|
+
r.tag[:Originator] = ori_obj if include_origins
|
323
|
+
return [r]
|
324
|
+
end
|
325
|
+
|
326
|
+
# IPAccess::List - immediate generation
|
327
|
+
return obj.to_a if obj.is_a?(IPAccess::List)
|
328
|
+
|
329
|
+
# NetAddr::Tree - immediate generation
|
330
|
+
return obj.dump.map { |addr| addr[:CIDR] } if obj.is_a?(NetAddr::Tree)
|
331
|
+
|
332
|
+
# number or nil - immediate generation or exception
|
333
|
+
if (obj.is_a?(Numeric) || obj.nil?)
|
334
|
+
r = NetAddr::CIDR.create(obj)
|
335
|
+
r.tag[:Originator] = ori_obj if include_origins
|
336
|
+
return [r]
|
337
|
+
end
|
338
|
+
|
339
|
+
# object containing socket member (e.g. Net::HTTP) - fetch socket
|
340
|
+
if obj.respond_to?(:socket)
|
341
|
+
obj = obj.socket
|
342
|
+
elsif obj.respond_to?(:sock)
|
343
|
+
obj = obj.sock
|
344
|
+
elsif obj.respond_to?(:client_socket)
|
345
|
+
obj = obj.client_socket
|
346
|
+
elsif obj.instance_variable_defined?(:@socket)
|
347
|
+
obj = obj.instance_variable_get(:@socket)
|
348
|
+
elsif obj.instance_variable_defined?(:@client_socket)
|
349
|
+
obj = obj.instance_variable_get(:@client_socket)
|
350
|
+
elsif obj.instance_variable_defined?(:@sock)
|
351
|
+
obj = obj.instance_variable_get(:@sock)
|
352
|
+
end
|
353
|
+
obj = obj.io if (obj.respond_to?(:io) && obj.io.respond_to?(:getpeername))
|
354
|
+
|
355
|
+
# some file descriptor but not socket - fetch socket
|
356
|
+
obj = ::Socket.for_fd(obj.fileno) if (!obj.respond_to?(:getpeername) && obj.respond_to?(:fileno))
|
357
|
+
|
358
|
+
# Socket - immediate generation
|
359
|
+
if obj.respond_to?(:getpeername)
|
360
|
+
peeraddr = ::Socket.unpack_sockaddr_in(obj.getpeername).last.split('%').first
|
361
|
+
r = NetAddr::CIDR.create(peeraddr)
|
362
|
+
r.tag[:Originator] = ori_obj if include_origins
|
363
|
+
return [r]
|
364
|
+
end
|
365
|
+
|
366
|
+
# symbol - immediate generation
|
367
|
+
r_args = nil
|
368
|
+
if obj.is_a?(Symbol)
|
369
|
+
case obj
|
370
|
+
when :ipv4_all, :ipv4_any, :ipv4_anyone, :ipv4_world, :ipv4_internet, :ipv4_net, :ipv4_everything, :ipv4_everyone, :ipv4_everybody, :ipv4_anybody
|
371
|
+
obj = [ "0.0.0.0/0" ]
|
372
|
+
when :ipv6_all, :ipv6_any, :ipv6_anyone, :ipv6_world, :ipv6_internet, :ipv6_net, :ipv6_everything, :ipv6_everyone, :ipv6_everybody, :ipv6_anybody
|
373
|
+
obj = [ "0.0.0.0/0", "::/0" ]
|
374
|
+
when :ipv4_broadcast, :ipv4_brd
|
375
|
+
obj = [ "255.255.255.255/32" ]
|
376
|
+
when :ipv6_broadcast, :ipv6_brd
|
377
|
+
obj = [ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" ]
|
378
|
+
when :ipv4_local, :ipv4_localhost, :ipv4_loopback, :ipv4_lo
|
379
|
+
obj = [ "127.0.0.1/8" ]
|
380
|
+
when :ipv6_local, :ipv6_localhost, :ipv6_loopback, :ipv6_lo
|
381
|
+
obj = [ "::1/128" ]
|
382
|
+
when :ipv4_auto, :ipv4_automatic, :ipv4_linklocal
|
383
|
+
obj = [ "169.254.0.0/16" ]
|
384
|
+
when :ipv6_auto, :ipv6_automatic, :ipv6_linklocal
|
385
|
+
obj = [ "fe80::/10" ]
|
386
|
+
when :ipv4_private, :ipv4_intra, :ipv4_intranet, :ipv4_internal
|
387
|
+
obj = [ "10.0.0.0/8",
|
388
|
+
"172.16.0.0/12",
|
389
|
+
"192.168.0.0/16" ]
|
390
|
+
when :ipv6_private, :ipv6_intra, :ipv6_intranet, :ipv6_internal, :ipv6_ula, :ipv6_unique
|
391
|
+
obj = [ "2001:10::/28",
|
392
|
+
"2001:db8::/32",
|
393
|
+
"fc00::/7",
|
394
|
+
"fdde:9e1a:dc85:7374::/64" ]
|
395
|
+
when :ipv4_multicast, :ipv4_multi, :ipv4_multiemission
|
396
|
+
obj = [ "224.0.0.0/4" ]
|
397
|
+
when :ipv6_multicast, :ipv6_multi, :ipv6_multiemission
|
398
|
+
obj = [ "ff00::/8",
|
399
|
+
"ff02::1:ff00:0/104" ]
|
400
|
+
when :ipv4_example, :ipv4_reserved
|
401
|
+
obj = [ "192.0.2.0/24",
|
402
|
+
"128.0.0.0/16",
|
403
|
+
"191.255.0.0/16",
|
404
|
+
"192.0.0.0/24",
|
405
|
+
"198.18.0.0/15",
|
406
|
+
"223.255.255.0/24",
|
407
|
+
"240.0.0.0/4" ]
|
408
|
+
when :all, :any, :anyone, :world, :internet, :net, :everything, :everyone, :everybody, :anybody
|
409
|
+
r_args = [ :ipv4_all,
|
410
|
+
:ipv6_all ]
|
411
|
+
when :broadcast, :brd
|
412
|
+
r_args = [ :ipv4_broadcast,
|
413
|
+
:ipv6_broadcast ]
|
414
|
+
when :local, :localhost, :localdomain, :loopback, :lo
|
415
|
+
r_args = [ :ipv4_local,
|
416
|
+
:ipv6_local ]
|
417
|
+
when :auto, :automatic, :linklocal
|
418
|
+
r_args = [ :ipv4_auto,
|
419
|
+
:ipv6_auto ]
|
420
|
+
when :private, :intra, :intranet, :internal
|
421
|
+
r_args = [ :ipv4_private,
|
422
|
+
:ipv6_private ]
|
423
|
+
when :multicast, :multi, :multiemission
|
424
|
+
r_args = [ :ipv4_multicast,
|
425
|
+
:ipv6_multicast ]
|
426
|
+
when :reserved, :example
|
427
|
+
r_args = [ :ipv4_example ]
|
428
|
+
when :strange, :unusual, :nonpublic, :unpublic
|
429
|
+
r_args = [ :local,
|
430
|
+
:auto,
|
431
|
+
:private,
|
432
|
+
:reserved,
|
433
|
+
:multicast ]
|
434
|
+
else
|
435
|
+
raise ArgumentError, "Provided symbol is unknown: #{obj.to_s}"
|
436
|
+
end
|
437
|
+
|
438
|
+
unless r_args.nil?
|
439
|
+
r_args.push :include_origins if include_origins
|
440
|
+
return to_cidrs(*r_args)
|
441
|
+
end
|
442
|
+
|
443
|
+
# strange types here
|
444
|
+
if obj.is_a?(Array)
|
445
|
+
return obj.map do |addr|
|
446
|
+
r = NetAddr::CIDR.create(addr)
|
447
|
+
r.tag[:Originator] = addr if include_origins
|
448
|
+
r
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
# URI or something that responds to host method - fetch string
|
454
|
+
obj = obj.host if obj.respond_to?(:host)
|
455
|
+
|
456
|
+
# objects of external classes
|
457
|
+
case obj.class.name.to_sym
|
458
|
+
when :IPAddr # IPAddr - fetch IP/mask string
|
459
|
+
obj = obj.native.inspect.split[1].chomp('>')[5..-1]
|
460
|
+
when :IPAddrList # IPAddrList - pass array to parse
|
461
|
+
return include_origins ? to_cidrs(obj.to_a, :include_origins) : to_cidrs(obj.to_a)
|
462
|
+
end
|
463
|
+
|
464
|
+
# string or similar - immediate generation
|
465
|
+
if obj.respond_to?(:to_s)
|
466
|
+
hostmask = ""
|
467
|
+
obj = obj.to_s
|
468
|
+
# URI
|
469
|
+
if obj =~ /^[^:]+:\/\/(.*)/
|
470
|
+
obj = $1.split('/').first
|
471
|
+
# IP in URI
|
472
|
+
if obj =~ /^\[([^\]]+)\]/
|
473
|
+
obj = $1
|
474
|
+
else
|
475
|
+
obj = obj.split(':').first
|
476
|
+
end
|
477
|
+
# host(s) and a mask
|
478
|
+
elsif obj =~ /^([^\/]+)(\/((\d{1,2}$)|(\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b$)))/
|
479
|
+
obj = $1
|
480
|
+
hostmask = $2
|
481
|
+
end
|
482
|
+
begin
|
483
|
+
ipa = obj.split('%').first.to_s
|
484
|
+
r = NetAddr::CIDR.create(ipa + hostmask)
|
485
|
+
rescue NetAddr::ValidationError
|
486
|
+
begin
|
487
|
+
addresses = Resolv::getaddresses(obj)
|
488
|
+
rescue NoMethodError # unhandled error
|
489
|
+
raise Resolv::ResolvError, "not connected or network error"
|
490
|
+
end
|
491
|
+
addresses.map! do |addr|
|
492
|
+
begin
|
493
|
+
r = NetAddr::CIDR.create(addr.split('%').first + hostmask)
|
494
|
+
r.tag[:Originator] = ori_obj
|
495
|
+
r
|
496
|
+
rescue ArgumentError
|
497
|
+
nil
|
498
|
+
end
|
499
|
+
end
|
500
|
+
addresses.flatten!
|
501
|
+
addresses.compact!
|
502
|
+
return addresses
|
503
|
+
end
|
504
|
+
r.tag[:Originator] = ori_obj
|
505
|
+
return [r]
|
506
|
+
end
|
507
|
+
|
508
|
+
# should never happend
|
509
|
+
r = obj.is_a?(NetAddr::CIDR) ? obj.dup : NetAddr::CIDR.create(obj.to_s)
|
510
|
+
r.tag[:Originator] = ori_obj
|
511
|
+
return [r]
|
512
|
+
end
|
513
|
+
|
514
|
+
# This method calls IPAccess.to_cidrs
|
515
|
+
# and returns first obtained entry containing
|
516
|
+
# single IP address with mask (NetAddr::CIDR).
|
517
|
+
|
518
|
+
def self.to_cidr(*addresses)
|
519
|
+
r = self.to_cidrs(*addresses)
|
520
|
+
return r.respond_to?(:first) ? first : r
|
521
|
+
end
|
522
|
+
|
523
|
+
end
|