Class: Net::DNS::RR::TSIG

Inherits:
Net::DNS::RR show all
Defined in:
lib/Net/DNS/RR/TSIG.rb

Overview

NAME

Net::DNS::RR::TSIG - DNS TSIG resource record

DESCRIPTION

Class for DNS Transaction Signature (TSIG) resource records.

BUGS

This code is still under development. Use with caution on production systems.

The time_signed and other_data fields should be 48-bit unsigned integers (RFC 2845, Sections 2.3 and 4.5.2). The current implementation ignores the upper 16 bits; this will cause problems for times later than 19 Jan 2038 03:14:07 UTC.

The only builtin algorithm currently supported is HMAC-MD5.SIG-ALG.REG.INT. You can use other algorithms by supplying an appropriate sign_func.

COPYRIGHT

Copyright © 2002 Michael Fuhr.

Portions Copyright © 2002-2004 Chris Reinhardt.

All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.

ACKNOWLEDGMENT

Most of the code in the Net::DNS::RR::TSIG module was contributed by Chris Turbeville.

Support for external signing functions was added by Andrew Tridgell.

SEE ALSO

Net::DNS, Net::DNS::Resolver, Net::DNS::Packet, Net::DNS::Header, Net::DNS::Question, Net::DNS::RR, RFC 2845

Constant Summary collapse

DEFAULT_ALGORITHM =
"HMAC-MD5.SIG-ALG.REG.INT"
DEFAULT_FUDGE =
300

Constants inherited from Net::DNS::RR

RRS

Instance Attribute Summary collapse

Attributes inherited from Net::DNS::RR

#name, #rdata, #rdlength, #rrclass, #ttl, #type

Instance Method Summary collapse

Methods inherited from Net::DNS::RR

#_canonicalRdata, #_canonicaldata, _get_subclass, _name2wire, #_name2wire, build_regex, create, #create_rrsort_func, #data, #get_rrsort_func, #init, #init_rrsort_func, #inspect, new_from_data, new_from_hash, new_from_string, #set_rrsort_func

Instance Attribute Details

#algorithmObject

Gets or sets the domain name that specifies the name of the algorithm. The only algorithm currently supported is HMAC-MD5.SIG-ALG.REG.INT.

rr.algorithm=(algorithm_name)
print "algorithm = ", rr.algorithm, "\n"


74
75
76
# File 'lib/Net/DNS/RR/TSIG.rb', line 74

def algorithm
  @algorithm
end

#errorObject



248
249
250
251
252
253
254
255
256
257
# File 'lib/Net/DNS/RR/TSIG.rb', line 248

def error
  rcode=0
  error = @error
  
  if (error!=nil)
    rcode = Net::DNS::Rcodesbyval[error] || error
  end
  
  return rcode
end

#fudgeObject

Gets or sets the original message ID.

rr.original_id(12345)
print "original ID = ", rr.original_id, "\n"


94
95
96
# File 'lib/Net/DNS/RR/TSIG.rb', line 94

def fudge
  @fudge
end

#keyObject

Returns the value of attribute key.



148
149
150
# File 'lib/Net/DNS/RR/TSIG.rb', line 148

def key
  @key
end

#macObject



263
264
265
266
# File 'lib/Net/DNS/RR/TSIG.rb', line 263

def mac
  mac = @mac.unpack("H*") if @mac!=nil;
  return mac;
end

#mac_sizeObject



259
260
261
# File 'lib/Net/DNS/RR/TSIG.rb', line 259

def mac_size
  return (@mac!=nil ? @mac : "").length
end

#original_idObject

Gets or sets the original message ID.

rr.original_id(12345)
print "original ID = ", rr.original_id, "\n"


117
118
119
# File 'lib/Net/DNS/RR/TSIG.rb', line 117

def original_id
  @original_id
end

#other_dataObject

Returns the Other Data. This field should be empty unless the error is BADTIME, in which case it will contain the server’s time as the number of seconds since 1 Jan 1970 00:00:00 UTC.

print "other data = ", rr.other_data, "\n"


139
140
141
# File 'lib/Net/DNS/RR/TSIG.rb', line 139

def other_data
  @other_data
end

#other_lenObject

Returns the length of the Other Data. Should be zero unless the error is BADTIME.

print "other len = ", rr.other_len, "\n"


131
132
133
# File 'lib/Net/DNS/RR/TSIG.rb', line 131

def other_len
  @other_len
end

#sign_funcObject

This sets the signing function to be used for this TSIG record.

The default signing function is HMAC-MD5.

tsig.sign_func=(Proc.new {|key, data| return some_digest_algorithm(key, data)})


147
148
149
# File 'lib/Net/DNS/RR/TSIG.rb', line 147

def sign_func
  @sign_func
end

#time_signedObject

Gets or sets the signing time as the number of seconds since 1 Jan 1970 00:00:00 UTC.

The default signing time is the current time.

rr.time_signed=(time)
print "time signed = ", rr.time_signed, "\n"


84
85
86
# File 'lib/Net/DNS/RR/TSIG.rb', line 84

def time_signed
  @time_signed
end

Instance Method Details

#init_defaultsObject



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/Net/DNS/RR/TSIG.rb', line 219

def init_defaults
  @algorithm   = DEFAULT_ALGORITHM
  @time_signed = Time.now.to_i
  @fudge       = DEFAULT_FUDGE
  @mac_size    = 0
  @mac         = ""
  @original_id = 0
  @error       = 0
  @other_len   = 0
  @other_data  = nil
  @sign_func   = lambda { |key, data|
    # a signing function for the HMAC-MD5 algorithm. This can be overridden using
    # the sign_func element
    key.gsub!(/ /,"")
    key = Base64::decode64(key)
    
#            OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new("md5"), key, data) 
    OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new("md5"), key, data) 
    
    #            hmac = Digest::HMAC_MD5.new(key)
    #            hmac.add(data)
    
    #           hmac.digest
  }
  
  # RFC 2845 Section 2.3
  @rrclass = "ANY"
end

#new_from_data(data, offset) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/Net/DNS/RR/TSIG.rb', line 187

def new_from_data(data, offset)
  if (@rdlength > 0)
    @algorithm, offset = Net::DNS::Packet.dn_expand(data, offset)
    
    time_high, time_low = data.unpack("\@#{offset} nN")
    self.time_signed = time_low	# bug
    offset += Net::DNS::INT16SZ + Net::DNS::INT32SZ
    
    @fudge, @mac_size = data.unpack("\@$offset nn")
    offset += Net::DNS::INT16SZ + Net::DNS::INT16SZ
    
    @mac = data[offset, @mac_size]
    offset += @mac_size
    
    @original_id, @error, @other_len = data.unpack("\@#{offset} nnn")
    offset += Net::DNS::INT16SZ * 3
    
    odata = data[offset, @other_len]
    odata_high, odata_low = odata.unpack("nN")
    @other_data = odata_low
  end
end

#new_from_hash(values) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/Net/DNS/RR/TSIG.rb', line 150

def new_from_hash(values)
  init_defaults
  if (values.has_key?:key)
    @key = values[:key]
  end
  if (values.has_key?:fudge)
    @fudge = values[:fudge]
  end
  if (values.has_key?:algorithm)
    @algorithm = values[:algorithm]
  end
  if (values.has_key?:mac_size)
    @mac_size = values[:mac_size]
  end
  if (values.has_key?:mac)
    @mac = values[:mac]
  end
  if (values.has_key?:other_len)
    @other_len = values[:other_len]
  end
  if (values.has_key?:other_data)
    @other_data = values[:other_data]
  end
  if (values.has_key?:original_id)
    @original_id = values[:original_id]
  end
  if (values.has_key?:error)
    @error = values[:error]
  end
  if (values.has_key?:sign_func)
    @sign_func = values[:sign_func]
  end
  if (values.has_key?:time_signed)
    @time_signed = values[:time_signed]
  end
end

#new_from_string(string) ⇒ Object



210
211
212
213
214
215
216
217
# File 'lib/Net/DNS/RR/TSIG.rb', line 210

def new_from_string(string)
  
  if (string!=nil && (string =~ /^(.*)$/))
    @key     = $1
  end
  
  init_defaults
end

#rdatastrObject



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/Net/DNS/RR/TSIG.rb', line 268

def rdatastr
  error = @error
  error = "UNDEFINED" unless error!=nil
  
  rdatastr=""
  
  if (@algorithm!=nil)
    rdatastr = "#{@algorithm}. #{error}";
    if (@other_len > 0 && @other_data!=nil)
      rdatastr += " #{@other_data}"
    end
  else
    rdatastr = ""
  end
  
  return rdatastr
end

#rr_rdata(packet, offset) ⇒ Object



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/Net/DNS/RR/TSIG.rb', line 330

def rr_rdata(packet, offset)
  rdata = ""
  
  if (@key != nil)
    # form the data to be signed
    sigdata = sig_data(packet)
    
    # and call the signing function
    @mac = @sign_func.call(@key, sigdata)
    @mac_size = @mac.length
    
    # construct the signed TSIG record
    packet.compnames = Hash.new
    rdata += packet.dn_comp(@algorithm, 0)
    
    rdata += [0, @time_signed].pack("nN")	# bug
    rdata += [@fudge, @mac_size].pack("nn")
    rdata += @mac
    
    rdata += [packet.header.id,@error,@other_len].pack("nnn")
    
    rdata += [0, @other_data].pack("nN") if @other_data!=nil
  end
  
  return rdata
end

#sig_data(packet) ⇒ Object

Returns the packet packed according to RFC2845 in a form for signing. This is only needed if you want to supply an external signing function, such as is needed for TSIG-GSS.

sigdata = tsig.sig_data(packet)


292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/Net/DNS/RR/TSIG.rb', line 292

def sig_data(packet)
  # return the data that needs to be signed/verified. This is useful for
  # external TSIG verification routines
  newpacket = packet.clone
  sigdata = ""
  
  newpacket.additional = []
  newpacket.header = packet.header.clone
  newpacket.additional = packet.additional.map {|i| i}
  newpacket.additional.shift
  newpacket.header.arcount-=1
  newpacket.compnames = Hash.new
  
  # Add the request MAC if present (used to validate responses).
  sigdata += [@request_mac].pack("H*") if @request_mac
  
  sigdata += newpacket.data
  
  # Don't compress the record (key) name.
  tmppacket = Net::DNS::Packet.new
  sigdata += tmppacket.dn_comp(@name.downcase, 0)
  
  sigdata += [Net::DNS.classesbyname(@rrclass.upcase())].pack("n")
  sigdata += [@ttl].pack("N")
  
  # Don't compress the algorithm name.
  tmppacket.compnames = Hash.new
  sigdata += tmppacket.dn_comp(@algorithm.downcase, 0)
  
  sigdata += [0, @time_signed].pack("nN")	# bug
  sigdata += [@fudge].pack("n")
  sigdata += [@error, @other_len].pack("nn")
  
  sigdata += [0, @other_data].pack("nN") if @other_data!=nil
  
  return sigdata
end