~ubuntu-branches/ubuntu/trusty/zonecheck/trusty-proposed

« back to all changes in this revision

Viewing changes to test/generic.rb

  • Committer: Bazaar Package Importer
  • Author(s): Stephane Bortzmeyer
  • Date: 2004-03-10 14:08:05 UTC
  • Revision ID: james.westby@ubuntu.com-20040310140805-ij55fso1e23bk8ye
Tags: upstream-2.0.3
ImportĀ upstreamĀ versionĀ 2.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# ZCTEST 1.0
 
2
# $Id: generic.rb,v 1.26 2003/12/01 09:45:15 sdalu Exp $
 
3
 
 
4
 
5
# CONTACT     : zonecheck@nic.fr
 
6
# AUTHOR      : Stephane D'Alu <sdalu@nic.fr>
 
7
#
 
8
# CREATED     : 2002/08/02 13:58:17
 
9
# REVISION    : $Revision: 1.26 $ 
 
10
# DATE        : $Date: 2003/12/01 09:45:15 $
 
11
#
 
12
# CONTRIBUTORS: (see also CREDITS file)
 
13
#
 
14
#
 
15
# LICENSE     : GPL v2 (or MIT/X11-like after agreement)
 
16
# COPYRIGHT   : AFNIC (c) 2003
 
17
#
 
18
# This file is part of ZoneCheck.
 
19
#
 
20
# ZoneCheck is free software; you can redistribute it and/or modify it
 
21
# under the terms of the GNU General Public License as published by
 
22
# the Free Software Foundation; either version 2 of the License, or
 
23
# (at your option) any later version.
 
24
 
25
# ZoneCheck is distributed in the hope that it will be useful, but
 
26
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
27
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
28
# General Public License for more details.
 
29
#
 
30
# You should have received a copy of the GNU General Public License
 
31
# along with ZoneCheck; if not, write to the Free Software Foundation,
 
32
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
33
#
 
34
 
 
35
require 'framework'
 
36
 
 
37
module CheckGeneric
 
38
    ##
 
39
    ## Check syntax validity of the domain name
 
40
    ##
 
41
    class DomainNameSyntax < Test
 
42
        with_msgcat 'test/generic.%s'
 
43
 
 
44
        #-- Checks --------------------------------------------------
 
45
        # DESC: A domainname should only contains A-Z a-Z 0-9 '-' '.'
 
46
        def chk_dn_sntx
 
47
            @domain.name.to_s =~ /^[A-Za-z0-9\-\.]+$/
 
48
        end
 
49
 
 
50
        # DESC: A domainname should not countain a double hyphen
 
51
        def chk_dn_dbl_hyph
 
52
            ! (@domain.name.to_s =~ /--/)
 
53
        end
 
54
 
 
55
        # DESC: A domainname should not start or end with an hyphen
 
56
        def chk_dn_orp_hyph
 
57
            ! (@domain.name.to_s =~ /(^|\.)-|-(\.|$)/)
 
58
        end
 
59
    end
 
60
 
 
61
 
 
62
 
 
63
    ##
 
64
    ## Check basic absurdity with the nameserver IP addresses
 
65
    ##
 
66
    class ServerAddress < Test
 
67
        with_msgcat 'test/generic.%s'
 
68
 
 
69
        #-- Initialization ------------------------------------------
 
70
        def initialize(*args)
 
71
            super(*args)
 
72
            @cache.create(:ip, :by_subnet)
 
73
        end
 
74
 
 
75
        #-- Shortcuts -----------------------------------------------
 
76
        def ip
 
77
            @cache.use(:ip) {
 
78
                ip = @domain.ns.collect { |ns, ips| ips }
 
79
                ip.flatten!
 
80
                ip
 
81
            }
 
82
        end
 
83
 
 
84
        def ns_from_ip(ip)
 
85
            @domain.ns.each { |ns, ips|
 
86
                return ns if ips.include?(ip)
 
87
            }
 
88
            nil
 
89
        end
 
90
 
 
91
        def by_subnet
 
92
            @cache.use(:by_subnet) {
 
93
                nethosts = {}
 
94
                ip.each { |i| 
 
95
                    net = case i                     # decide of subnet size:
 
96
                          when Address::IPv4 then i.prefix(28) # /28 for IPv4
 
97
                          when Address::IPv6 then i.prefix(64) # /64 for IPv6
 
98
                          end
 
99
                    nethosts[net] = [ ] unless nethosts.has_key?(net)
 
100
                    nethosts[net] << i
 
101
                }
 
102
                nethosts
 
103
            }
 
104
        end
 
105
 
 
106
        #-- Checks --------------------------------------------------
 
107
        # DESC: Addresses should be distincts
 
108
        def chk_ip_distinct
 
109
            # Ok all addresses are distincts
 
110
            return true if ip == ip.uniq
 
111
            
 
112
            # Create data for failure handling
 
113
            hosts = {}
 
114
            @domain.ns.each { |ns, ips|
 
115
                ips.each { |i| 
 
116
                    hosts[i] = [ ] unless hosts.has_key?(i)
 
117
                    hosts[i] << ns
 
118
                }
 
119
            }
 
120
            hosts.delete_if { |k, v| v.size < 2 }
 
121
            hosts.each { |k, v| # Got at least 1 entry as ip != ip.uniq
 
122
                return { 'ip' => k, 'ns' => v.join(', ') }
 
123
            }
 
124
        end
 
125
 
 
126
        # DESC: Addresses should avoid belonging to the same network
 
127
        def chk_ip_same_net
 
128
            # Only keep list of hosts on same subnet
 
129
            same_net = by_subnet.dup.delete_if { |k, v| v.size < 2 }
 
130
                
 
131
            # Ok all hosts are on different subnets
 
132
            return true if same_net.empty?
 
133
 
 
134
            # Create output data for failure
 
135
            subnetlist = []
 
136
            same_net.each { |k, v|
 
137
                hlist   = (v.collect { |i| ns = ns_from_ip(i) }).join(', ')
 
138
                prefix = case k
 
139
                         when Address::IPv4 then 28
 
140
                         when Address::IPv6 then 64
 
141
                         end
 
142
                subnetlist << "#{k}/#{prefix} (#{hlist})"
 
143
            }
 
144
            return { 'subnets' => subnetlist.join(', ') }
 
145
        end
 
146
 
 
147
        # DESC: Addresses should avoid belonging ALL to the same network
 
148
        # WARN: Test is wrong in case of IPv4 and IPv6
 
149
        def chk_ip_all_same_net
 
150
            # Ok not all hosts are on the same subnet
 
151
            return true unless ((by_subnet.size           == 1) && 
 
152
                                (by_subnet.values[0].size >  1))
 
153
 
 
154
            # Create output data for failure
 
155
            subnet = by_subnet.keys[0]
 
156
            prefix = case subnet
 
157
                     when Address::IPv4 then 28
 
158
                     when Address::IPv6 then 64
 
159
                     end
 
160
            return { 'subnet' => "#{subnet}/#{prefix}" }
 
161
        end
 
162
 
 
163
        # DESC: Addresses should avoid belonging ALL to the same AS
 
164
        def chk_all_same_asn
 
165
            asn = ip.collect { |addr|
 
166
                aname = NResolv::DNS::Name::create(addr.to_dnsform +
 
167
                                                   '.asn.routeviews.org.')
 
168
                txtres = @cm[nil].txt(aname, NResolv::DNS::Resource::IN::TXT)
 
169
                txtres[0].txtdata[0]
 
170
            }
 
171
            asn.uniq!
 
172
            asn.size > 1 ? true : { 'asn' => asn[0] }
 
173
        end
 
174
    end
 
175
 
 
176
 
 
177
    ##
 
178
    ## Check for nameserver!
 
179
    ##
 
180
    class NameServers < Test
 
181
        with_msgcat 'test/generic.%s'
 
182
 
 
183
        #-- Checks --------------------------------------------------
 
184
        # DESC: A domain should have a nameserver!
 
185
        def chk_one_ns
 
186
            @domain.ns.length >= 1
 
187
        end
 
188
 
 
189
        # DESC: A domain should have at least 2 nameservers
 
190
        def chk_several_ns
 
191
            @domain.ns.length >= 2
 
192
        end
 
193
    end
 
194
 
 
195
 
 
196
    ##
 
197
    ##
 
198
    ##
 
199
    class Delegation < Test
 
200
        with_msgcat 'test/generic.%s'
 
201
 
 
202
        #-- Initialisation ------------------------------------------
 
203
        def initialize(*args)
 
204
            super(*args)
 
205
            @querysize = const('delegation_query_size').to_i
 
206
        end
 
207
 
 
208
        #-- Checks --------------------------------------------------
 
209
        def chk_delegation_udp512
 
210
            dummyttl    = 3600
 
211
            msg         = NResolv::DNS::Message::Answer::new
 
212
            msg.question.add(NResolv::DNS::Name::Root, 
 
213
                             NResolv::DNS::Resource::IN::NS)
 
214
            @domain.ns.each { |ns, ips|
 
215
                msg.authority.add(@domain.name, 
 
216
                                  NResolv::DNS::Resource::IN::NS::new(ns),
 
217
                                  dummyttl) 
 
218
            }
 
219
            excess = (msg.to_wire.size + @querysize-1) - 512
 
220
 
 
221
            return true if excess <= 0
 
222
            { 'excess' => excess }
 
223
        end
 
224
 
 
225
        def chk_delegation_udp512_additional
 
226
            dummyttl    = 3600
 
227
            msg         = NResolv::DNS::Message::Answer::new
 
228
            msg.question.add(NResolv::DNS::Name::Root, 
 
229
                             NResolv::DNS::Resource::IN::NS)
 
230
            @domain.ns.each { |ns, ips|
 
231
                msg.answer.add(@domain.name, 
 
232
                               NResolv::DNS::Resource::IN::NS::new(ns),
 
233
                               dummyttl)
 
234
 
 
235
                if ns.in_domain?(@domain.name)
 
236
                    ips.each { |ip|
 
237
                        msg.additional.add(ns, ip.to_dnsressource, dummyttl) }
 
238
                end
 
239
            }
 
240
 
 
241
            excess = (msg.to_wire.size + @querysize-1) - 512
 
242
 
 
243
            return true if excess <= 0
 
244
            { 'excess' => excess }
 
245
        end
 
246
    end
 
247
end