TSIGRecord.java revision d7955ce24d294fb2014c59d11fca184471056f44
1// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS;
4
5import java.io.*;
6import java.util.*;
7import org.xbill.DNS.utils.*;
8
9/**
10 * Transaction Signature - this record is automatically generated by the
11 * resolver.  TSIG records provide transaction security between the
12 * sender and receiver of a message, using a shared key.
13 * @see Resolver
14 * @see TSIG
15 *
16 * @author Brian Wellington
17 */
18
19public class TSIGRecord extends Record {
20
21private static final long serialVersionUID = -88820909016649306L;
22
23private Name alg;
24private Date timeSigned;
25private int fudge;
26private byte [] signature;
27private int originalID;
28private int error;
29private byte [] other;
30
31TSIGRecord() {}
32
33Record
34getObject() {
35	return new TSIGRecord();
36}
37
38/**
39 * Creates a TSIG Record from the given data.  This is normally called by
40 * the TSIG class
41 * @param alg The shared key's algorithm
42 * @param timeSigned The time that this record was generated
43 * @param fudge The fudge factor for time - if the time that the message is
44 * received is not in the range [now - fudge, now + fudge], the signature
45 * fails
46 * @param signature The signature
47 * @param originalID The message ID at the time of its generation
48 * @param error The extended error field.  Should be 0 in queries.
49 * @param other The other data field.  Currently used only in BADTIME
50 * responses.
51 * @see TSIG
52 */
53public
54TSIGRecord(Name name, int dclass, long ttl, Name alg, Date timeSigned,
55	   int fudge, byte [] signature, int originalID, int error,
56	   byte other[])
57{
58	super(name, Type.TSIG, dclass, ttl);
59	this.alg = checkName("alg", alg);
60	this.timeSigned = timeSigned;
61	this.fudge = checkU16("fudge", fudge);
62	this.signature = signature;
63	this.originalID = checkU16("originalID", originalID);
64	this.error = checkU16("error", error);
65	this.other = other;
66}
67
68void
69rrFromWire(DNSInput in) throws IOException {
70	alg = new Name(in);
71
72	long timeHigh = in.readU16();
73	long timeLow = in.readU32();
74	long time = (timeHigh << 32) + timeLow;
75	timeSigned = new Date(time * 1000);
76	fudge = in.readU16();
77
78	int sigLen = in.readU16();
79	signature = in.readByteArray(sigLen);
80
81	originalID = in.readU16();
82	error = in.readU16();
83
84	int otherLen = in.readU16();
85	if (otherLen > 0)
86		other = in.readByteArray(otherLen);
87	else
88		other = null;
89}
90
91void
92rdataFromString(Tokenizer st, Name origin) throws IOException {
93	throw st.exception("no text format defined for TSIG");
94}
95
96/** Converts rdata to a String */
97String
98rrToString() {
99	StringBuffer sb = new StringBuffer();
100	sb.append(alg);
101	sb.append(" ");
102	if (Options.check("multiline"))
103		sb.append("(\n\t");
104
105	sb.append (timeSigned.getTime() / 1000);
106	sb.append (" ");
107	sb.append (fudge);
108	sb.append (" ");
109	sb.append (signature.length);
110	if (Options.check("multiline")) {
111		sb.append ("\n");
112		sb.append (base64.formatString(signature, 64, "\t", false));
113	} else {
114		sb.append (" ");
115		sb.append (base64.toString(signature));
116	}
117	sb.append (" ");
118	sb.append (Rcode.TSIGstring(error));
119	sb.append (" ");
120	if (other == null)
121		sb.append (0);
122	else {
123		sb.append (other.length);
124		if (Options.check("multiline"))
125			sb.append("\n\n\n\t");
126		else
127			sb.append(" ");
128		if (error == Rcode.BADTIME) {
129			if (other.length != 6) {
130				sb.append("<invalid BADTIME other data>");
131			} else {
132				long time = ((long)(other[0] & 0xFF) << 40) +
133					    ((long)(other[1] & 0xFF) << 32) +
134					    ((other[2] & 0xFF) << 24) +
135					    ((other[3] & 0xFF) << 16) +
136					    ((other[4] & 0xFF) << 8) +
137					    ((other[5] & 0xFF)     );
138				sb.append("<server time: ");
139				sb.append(new Date(time * 1000));
140				sb.append(">");
141			}
142		} else {
143			sb.append("<");
144			sb.append(base64.toString(other));
145			sb.append(">");
146		}
147	}
148	if (Options.check("multiline"))
149		sb.append(" )");
150	return sb.toString();
151}
152
153/** Returns the shared key's algorithm */
154public Name
155getAlgorithm() {
156	return alg;
157}
158
159/** Returns the time that this record was generated */
160public Date
161getTimeSigned() {
162	return timeSigned;
163}
164
165/** Returns the time fudge factor */
166public int
167getFudge() {
168	return fudge;
169}
170
171/** Returns the signature */
172public byte []
173getSignature() {
174	return signature;
175}
176
177/** Returns the original message ID */
178public int
179getOriginalID() {
180	return originalID;
181}
182
183/** Returns the extended error */
184public int
185getError() {
186	return error;
187}
188
189/** Returns the other data */
190public byte []
191getOther() {
192	return other;
193}
194
195void
196rrToWire(DNSOutput out, Compression c, boolean canonical) {
197	alg.toWire(out, null, canonical);
198
199	long time = timeSigned.getTime() / 1000;
200	int timeHigh = (int) (time >> 32);
201	long timeLow = (time & 0xFFFFFFFFL);
202	out.writeU16(timeHigh);
203	out.writeU32(timeLow);
204	out.writeU16(fudge);
205
206	out.writeU16(signature.length);
207	out.writeByteArray(signature);
208
209	out.writeU16(originalID);
210	out.writeU16(error);
211
212	if (other != null) {
213		out.writeU16(other.length);
214		out.writeByteArray(other);
215	}
216	else
217		out.writeU16(0);
218}
219
220}
221