1 # Copyright (C) 2010 Nominum, Inc.
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 class HIP(dns
.rdata
.Rdata
):
27 @ivar hit: the host identity tag
29 @ivar algorithm: the public key cryptographic algorithm
31 @ivar key: the public key
33 @ivar servers: the rendezvous servers
34 @type servers: list of dns.name.Name objects
37 __slots__
= ['hit', 'algorithm', 'key', 'servers']
39 def __init__(self
, rdclass
, rdtype
, hit
, algorithm
, key
, servers
):
40 super(HIP
, self
).__init
__(rdclass
, rdtype
)
42 self
.algorithm
= algorithm
44 self
.servers
= servers
46 def to_text(self
, origin
=None, relativize
=True, **kw
):
47 hit
= self
.hit
.encode('hex-codec')
48 key
= self
.key
.encode('base64-codec').replace('\n', '')
51 for server
in self
.servers
:
52 servers
.append(str(server
.choose_relativity(origin
, relativize
)))
54 text
+= (' ' + ' '.join(servers
))
55 return '%u %s %s%s' % (self
.algorithm
, hit
, key
, text
)
57 def from_text(cls
, rdclass
, rdtype
, tok
, origin
= None, relativize
= True):
58 algorithm
= tok
.get_uint8()
59 hit
= tok
.get_string().decode('hex-codec')
61 raise dns
.exception
.SyntaxError("HIT too long")
62 key
= tok
.get_string().decode('base64-codec')
66 if token
.is_eol_or_eof():
68 server
= dns
.name
.from_text(token
.value
, origin
)
69 server
.choose_relativity(origin
, relativize
)
70 servers
.append(server
)
71 return cls(rdclass
, rdtype
, hit
, algorithm
, key
, servers
)
73 from_text
= classmethod(from_text
)
75 def to_wire(self
, file, compress
= None, origin
= None):
78 file.write(struct
.pack("!BBH", lh
, self
.algorithm
, lk
))
81 for server
in self
.servers
:
82 server
.to_wire(file, None, origin
)
84 def from_wire(cls
, rdclass
, rdtype
, wire
, current
, rdlen
, origin
= None):
85 (lh
, algorithm
, lk
) = struct
.unpack('!BBH',
86 wire
[current
: current
+ 4])
89 hit
= wire
[current
: current
+ lh
]
92 key
= wire
[current
: current
+ lk
]
97 (server
, cused
) = dns
.name
.from_wire(wire
[: current
+ rdlen
],
101 if not origin
is None:
102 server
= server
.relativize(origin
)
103 servers
.append(server
)
104 return cls(rdclass
, rdtype
, hit
, algorithm
, key
, servers
)
106 from_wire
= classmethod(from_wire
)
108 def choose_relativity(self
, origin
= None, relativize
= True):
110 for server
in self
.servers
:
111 server
= server
.choose_relativity(origin
, relativize
)
112 servers
.append(server
)
113 self
.servers
= servers
115 def _cmp(self
, other
):
116 b1
= cStringIO
.StringIO()
119 b1
.write(struct
.pack("!BBH", lh
, self
.algorithm
, lk
))
122 b2
= cStringIO
.StringIO()
125 b2
.write(struct
.pack("!BBH", lh
, other
.algorithm
, lk
))
128 v
= cmp(b1
.getvalue(), b2
.getvalue())
131 ls
= len(self
.servers
)
132 lo
= len(other
.servers
)
136 v
= cmp(self
.servers
[i
], other
.servers
[i
])