ipaccess 1.2.0 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -13
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.yardopts +2 -0
  5. data/ChangeLog +66 -0
  6. data/Manifest.txt +5 -10
  7. data/README.md +2 -2
  8. data/Rakefile +1 -1
  9. data/docs/HISTORY +11 -0
  10. data/docs/TODO +1 -1
  11. data/docs/yard-tpl/default/fulldoc/html/css/common.css +5 -0
  12. data/examples/open-uri.rb +14 -0
  13. data/examples/telnet.rb +1 -1
  14. data/ipaccess.gemspec +62 -0
  15. data/lib/ipaccess.rb +2 -566
  16. data/lib/ipaccess/arm_sockets.rb +0 -1
  17. data/lib/ipaccess/core.rb +523 -0
  18. data/lib/ipaccess/ghost_doc/ghost_doc.rb +1 -1
  19. data/lib/ipaccess/ghost_doc/ghost_doc_acl.rdoc +54 -0
  20. data/lib/ipaccess/ghost_doc/ghost_doc_net_ftp.rb +35 -19
  21. data/lib/ipaccess/ghost_doc/ghost_doc_net_http.rb +34 -18
  22. data/lib/ipaccess/ghost_doc/ghost_doc_net_smtp.rb +35 -19
  23. data/lib/ipaccess/ghost_doc/ghost_doc_net_telnet.rb +35 -19
  24. data/lib/ipaccess/ghost_doc/ghost_doc_patched_usage.rdoc +65 -0
  25. data/lib/ipaccess/ghost_doc/ghost_doc_sockets.rb +353 -125
  26. data/lib/ipaccess/ip_access_check.rb +2 -2
  27. data/lib/ipaccess/ip_access_errors.rb +2 -2
  28. data/lib/ipaccess/ip_access_list.rb +3 -3
  29. data/lib/ipaccess/patches/generic.rb +150 -183
  30. data/lib/ipaccess/patches/net_ftp.rb +1 -2
  31. data/lib/ipaccess/patches/net_http.rb +10 -14
  32. data/lib/ipaccess/patches/net_imap.rb +1 -2
  33. data/lib/ipaccess/patches/net_pop.rb +2 -4
  34. data/lib/ipaccess/patches/net_smtp.rb +2 -4
  35. data/lib/ipaccess/patches/net_telnet.rb +1 -2
  36. data/lib/ipaccess/patches/sockets.rb +67 -69
  37. data/lib/ipaccess/socket.rb +0 -17
  38. metadata +70 -100
  39. metadata.gz.sig +0 -0
  40. data/lib/ipaccess/ghost_doc/ghost_doc_acl.rb +0 -54
  41. data/lib/ipaccess/ghost_doc/ghost_doc_p_blacklist.rb +0 -36
  42. data/lib/ipaccess/ghost_doc/ghost_doc_p_blacklist_e.rb +0 -7
  43. data/lib/ipaccess/ghost_doc/ghost_doc_p_unblacklist.rb +0 -36
  44. data/lib/ipaccess/ghost_doc/ghost_doc_p_unblacklist_e.rb +0 -7
  45. data/lib/ipaccess/ghost_doc/ghost_doc_p_unwhitelist.rb +0 -36
  46. data/lib/ipaccess/ghost_doc/ghost_doc_p_unwhitelist_e.rb +0 -7
  47. data/lib/ipaccess/ghost_doc/ghost_doc_p_whitelist.rb +0 -36
  48. data/lib/ipaccess/ghost_doc/ghost_doc_p_whitelist_e.rb +0 -7
  49. data/lib/ipaccess/ghost_doc/ghost_doc_patched_usage.rb +0 -64
@@ -33,4 +33,3 @@ IPAccess.arm UDPSocket
33
33
  IPAccess.arm TCPSocket
34
34
  IPAccess.arm TCPServer
35
35
  IPAccess.arm SOCKSSocket if Object.const_defined?(:SOCKSSocket)
36
-
@@ -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