resolv 0.7.0 → 0.7.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 +4 -4
- data/lib/resolv.rb +101 -13
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 38de4f14ddb183350d35593550caa34f9694644fb9d2fc79bd275d92d17ee338
|
|
4
|
+
data.tar.gz: 00d4977e89fb7cd8ec4a772c481d63e49fd4441b90c7ec5be42a79294ab3da19
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 175ca63aa1f82ebabc499bbcd8eedf17c33ff220c439187a1c5778ca2e74926d15651a720c0bb5f615a698747252d8f9cd82c5db5fb25d28a4d1e63cb696acf1
|
|
7
|
+
data.tar.gz: 8789721febc5b7a96a8bcfdc51dd503afefa648a6d7057e6951b77d1fb514c613e35524ef9680e4ef6d4ad49e310a0fa2d1e92a972eae0e8f23969519c7db1d9
|
data/lib/resolv.rb
CHANGED
|
@@ -35,7 +35,7 @@ require 'rbconfig'
|
|
|
35
35
|
class Resolv
|
|
36
36
|
|
|
37
37
|
# The version string
|
|
38
|
-
VERSION = "0.7.
|
|
38
|
+
VERSION = "0.7.2"
|
|
39
39
|
|
|
40
40
|
##
|
|
41
41
|
# Looks up the first IP address for +name+.
|
|
@@ -487,13 +487,18 @@ class Resolv
|
|
|
487
487
|
# * Resolv::DNS::Resource::IN::A
|
|
488
488
|
# * Resolv::DNS::Resource::IN::AAAA
|
|
489
489
|
# * Resolv::DNS::Resource::IN::ANY
|
|
490
|
+
# * Resolv::DNS::Resource::IN::CAA
|
|
490
491
|
# * Resolv::DNS::Resource::IN::CNAME
|
|
491
492
|
# * Resolv::DNS::Resource::IN::HINFO
|
|
493
|
+
# * Resolv::DNS::Resource::IN::HTTPS
|
|
494
|
+
# * Resolv::DNS::Resource::IN::LOC
|
|
492
495
|
# * Resolv::DNS::Resource::IN::MINFO
|
|
493
496
|
# * Resolv::DNS::Resource::IN::MX
|
|
494
497
|
# * Resolv::DNS::Resource::IN::NS
|
|
495
498
|
# * Resolv::DNS::Resource::IN::PTR
|
|
496
499
|
# * Resolv::DNS::Resource::IN::SOA
|
|
500
|
+
# * Resolv::DNS::Resource::IN::SRV
|
|
501
|
+
# * Resolv::DNS::Resource::IN::SVCB
|
|
497
502
|
# * Resolv::DNS::Resource::IN::TXT
|
|
498
503
|
# * Resolv::DNS::Resource::IN::WKS
|
|
499
504
|
#
|
|
@@ -721,7 +726,8 @@ class Resolv
|
|
|
721
726
|
begin
|
|
722
727
|
reply, from = recv_reply(select_result[0])
|
|
723
728
|
rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
|
|
724
|
-
Errno::ECONNRESET # Windows
|
|
729
|
+
Errno::ECONNRESET, # Windows
|
|
730
|
+
EOFError
|
|
725
731
|
# No name server running on the server?
|
|
726
732
|
# Don't wait anymore.
|
|
727
733
|
raise ResolvTimeout
|
|
@@ -930,8 +936,11 @@ class Resolv
|
|
|
930
936
|
end
|
|
931
937
|
|
|
932
938
|
def recv_reply(readable_socks)
|
|
933
|
-
|
|
939
|
+
len_data = readable_socks[0].read(2)
|
|
940
|
+
raise EOFError if len_data.nil? || len_data.bytesize != 2
|
|
941
|
+
len = len_data.unpack('n')[0]
|
|
934
942
|
reply = @socks[0].read(len)
|
|
943
|
+
raise EOFError if reply.nil? || reply.bytesize != len
|
|
935
944
|
return reply, nil
|
|
936
945
|
end
|
|
937
946
|
|
|
@@ -1244,6 +1253,13 @@ class Resolv
|
|
|
1244
1253
|
|
|
1245
1254
|
class Str # :nodoc:
|
|
1246
1255
|
def initialize(string)
|
|
1256
|
+
# A label is limited to 63 octets. [RFC 1035 2.3.4] Checking it here
|
|
1257
|
+
# makes it an invariant of the object: every label, however it was
|
|
1258
|
+
# built, fits in its length octet and cannot wrap it. Callers turn
|
|
1259
|
+
# this into the error their own contract promises.
|
|
1260
|
+
if string.bytesize > 63
|
|
1261
|
+
raise ArgumentError, "DNS label is too long (#{string.bytesize} bytes, max 63): #{string.inspect}"
|
|
1262
|
+
end
|
|
1247
1263
|
@string = string
|
|
1248
1264
|
# case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
|
|
1249
1265
|
# This assumes @string is given in ASCII compatible encoding.
|
|
@@ -1289,7 +1305,26 @@ class Resolv
|
|
|
1289
1305
|
when Name
|
|
1290
1306
|
return arg
|
|
1291
1307
|
when String
|
|
1292
|
-
|
|
1308
|
+
# A hostname is runtime data rather than a programming mistake, so
|
|
1309
|
+
# both size limits surface as ResolvError to stay rescuable alongside
|
|
1310
|
+
# the rest of name resolution. The type check below is a caller
|
|
1311
|
+
# mistake and keeps raising ArgumentError.
|
|
1312
|
+
begin
|
|
1313
|
+
labels = Label.split(arg)
|
|
1314
|
+
rescue ArgumentError => e
|
|
1315
|
+
raise ResolvError.new(e.message)
|
|
1316
|
+
end
|
|
1317
|
+
# Label::Str enforces the per-label limit. Only the total is knowable
|
|
1318
|
+
# here, and it counts the encoded form, so size starts at 1 for the
|
|
1319
|
+
# root label's terminating zero octet. [RFC 1035 2.3.4, 3.1]
|
|
1320
|
+
size = 1
|
|
1321
|
+
labels.each do |label|
|
|
1322
|
+
size += 1 + label.string.bytesize
|
|
1323
|
+
if size > 255
|
|
1324
|
+
raise ResolvError.new("DNS name is too long (#{size} octets, max 255): #{arg.inspect}")
|
|
1325
|
+
end
|
|
1326
|
+
end
|
|
1327
|
+
return Name.new(labels, /\.\z/ =~ arg ? true : false)
|
|
1293
1328
|
else
|
|
1294
1329
|
raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
|
|
1295
1330
|
end
|
|
@@ -1411,12 +1446,24 @@ class Resolv
|
|
|
1411
1446
|
@rd == other.rd &&
|
|
1412
1447
|
@ra == other.ra &&
|
|
1413
1448
|
@rcode == other.rcode &&
|
|
1414
|
-
|
|
1449
|
+
question_equal?(other.question) &&
|
|
1415
1450
|
@answer == other.answer &&
|
|
1416
1451
|
@authority == other.authority &&
|
|
1417
1452
|
@additional == other.additional
|
|
1418
1453
|
end
|
|
1419
1454
|
|
|
1455
|
+
# A question holds the resource class itself, and decoding creates a fresh
|
|
1456
|
+
# class for each unknown type, so the classes cannot be compared by
|
|
1457
|
+
# identity alone.
|
|
1458
|
+
private def question_equal?(other_question) # :nodoc:
|
|
1459
|
+
return false unless @question.length == other_question.length
|
|
1460
|
+
@question.zip(other_question) {|(name, typeclass), (o_name, o_typeclass)|
|
|
1461
|
+
return false unless name == o_name &&
|
|
1462
|
+
Resource::Generic.type_class_equal?(typeclass, o_typeclass)
|
|
1463
|
+
}
|
|
1464
|
+
return true
|
|
1465
|
+
end
|
|
1466
|
+
|
|
1420
1467
|
def add_question(name, typeclass)
|
|
1421
1468
|
@question << [Name.create(name), typeclass]
|
|
1422
1469
|
end
|
|
@@ -1523,8 +1570,15 @@ class Resolv
|
|
|
1523
1570
|
end
|
|
1524
1571
|
|
|
1525
1572
|
def put_string(d)
|
|
1526
|
-
|
|
1527
|
-
|
|
1573
|
+
s = d.to_s
|
|
1574
|
+
# A character-string is prefixed by a single length octet, so it can
|
|
1575
|
+
# hold at most 255 octets. [RFC 1035 3.3] Reject anything longer to
|
|
1576
|
+
# avoid silently truncating the length to its low 8 bits (mod 256).
|
|
1577
|
+
if s.bytesize > 255
|
|
1578
|
+
raise ArgumentError, "character-string is too long (#{s.bytesize} bytes, max 255): #{s.inspect}"
|
|
1579
|
+
end
|
|
1580
|
+
self.put_pack("C", s.bytesize)
|
|
1581
|
+
@data << s
|
|
1528
1582
|
end
|
|
1529
1583
|
|
|
1530
1584
|
def put_string_list(ds)
|
|
@@ -1554,7 +1608,17 @@ class Resolv
|
|
|
1554
1608
|
end
|
|
1555
1609
|
|
|
1556
1610
|
def put_label(d)
|
|
1557
|
-
|
|
1611
|
+
s = d.to_s
|
|
1612
|
+
# Label::Str applies this limit when a label is built, so what is left
|
|
1613
|
+
# for here is a raw string handed straight to put_labels. The two ways
|
|
1614
|
+
# an over-long label goes wrong differ: 64 to 255 octets write a length
|
|
1615
|
+
# octet in the reserved or compression pointer range, and 256 or more
|
|
1616
|
+
# wrap it mod 256. Either way the encoded name stops being the name the
|
|
1617
|
+
# caller asked for. [RFC 1035 2.3.4, 4.1.4]
|
|
1618
|
+
if s.bytesize > 63
|
|
1619
|
+
raise ArgumentError, "DNS label is too long (#{s.bytesize} bytes, max 63): #{s.inspect}"
|
|
1620
|
+
end
|
|
1621
|
+
self.put_string(s)
|
|
1558
1622
|
end
|
|
1559
1623
|
end
|
|
1560
1624
|
|
|
@@ -1680,7 +1744,9 @@ class Resolv
|
|
|
1680
1744
|
prev_index = @index
|
|
1681
1745
|
save_index = nil
|
|
1682
1746
|
d = []
|
|
1683
|
-
size
|
|
1747
|
+
# size counts the encoded form, so it starts at 1 for the root
|
|
1748
|
+
# label's terminating zero octet. [RFC 1035 3.1]
|
|
1749
|
+
size = 1
|
|
1684
1750
|
while true
|
|
1685
1751
|
raise DecodeError.new("limit exceeded") if @limit <= @index
|
|
1686
1752
|
case @data.getbyte(@index)
|
|
@@ -1711,6 +1777,11 @@ class Resolv
|
|
|
1711
1777
|
|
|
1712
1778
|
def get_label
|
|
1713
1779
|
return Label::Str.new(self.get_string)
|
|
1780
|
+
rescue ArgumentError => e
|
|
1781
|
+
# A length octet of 64..191 is reserved rather than a label length,
|
|
1782
|
+
# but this decoder used to read it as one. [RFC 1035 4.1.4] Report it
|
|
1783
|
+
# the way the rest of a malformed message is reported.
|
|
1784
|
+
raise DecodeError.new(e.message)
|
|
1714
1785
|
end
|
|
1715
1786
|
|
|
1716
1787
|
def get_question
|
|
@@ -1898,8 +1969,9 @@ class Resolv
|
|
|
1898
1969
|
key_name = :"key#{key_number}"
|
|
1899
1970
|
c.const_set(:KeyName, key_name)
|
|
1900
1971
|
c.const_set(:KeyNumber, key_number)
|
|
1901
|
-
|
|
1902
|
-
|
|
1972
|
+
# Not registered in a constant or in ClassHash. ClassHash creates a
|
|
1973
|
+
# class for every unknown SvcParamKey, so registering them
|
|
1974
|
+
# permanently would let a malicious response exhaust memory.
|
|
1903
1975
|
return c
|
|
1904
1976
|
end
|
|
1905
1977
|
end
|
|
@@ -2206,12 +2278,28 @@ class Resolv
|
|
|
2206
2278
|
return self.new(msg.get_bytes)
|
|
2207
2279
|
end
|
|
2208
2280
|
|
|
2281
|
+
# create makes a fresh class for each decoded resource, so the type and
|
|
2282
|
+
# class values have to be compared instead of the class itself.
|
|
2283
|
+
def self.type_class_equal?(klass, other) # :nodoc:
|
|
2284
|
+
return true if klass.equal?(other)
|
|
2285
|
+
Generic > klass && Generic > other &&
|
|
2286
|
+
klass::TypeValue == other::TypeValue &&
|
|
2287
|
+
klass::ClassValue == other::ClassValue
|
|
2288
|
+
end
|
|
2289
|
+
|
|
2290
|
+
def ==(other) # :nodoc:
|
|
2291
|
+
return other.is_a?(Generic) &&
|
|
2292
|
+
Generic.type_class_equal?(self.class, other.class) &&
|
|
2293
|
+
@data == other.data
|
|
2294
|
+
end
|
|
2295
|
+
|
|
2209
2296
|
def self.create(type_value, class_value) # :nodoc:
|
|
2210
2297
|
c = Class.new(Generic)
|
|
2211
2298
|
c.const_set(:TypeValue, type_value)
|
|
2212
2299
|
c.const_set(:ClassValue, class_value)
|
|
2213
|
-
|
|
2214
|
-
|
|
2300
|
+
# Not registered in a constant or in ClassHash. get_class creates a
|
|
2301
|
+
# class for every unknown (type, class) pair, so registering them
|
|
2302
|
+
# permanently would let a malicious response exhaust memory.
|
|
2215
2303
|
return c
|
|
2216
2304
|
end
|
|
2217
2305
|
end
|