001: // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS;
004:
005: import java.io.*;
006: import java.util.*;
007: import org.xbill.DNS.utils.*;
008:
009: /**
010: * Transaction Signature - this record is automatically generated by the
011: * resolver. TSIG records provide transaction security between the
012: * sender and receiver of a message, using a shared key.
013: * @see Resolver
014: * @see TSIG
015: *
016: * @author Brian Wellington
017: */
018:
019: public class TSIGRecord extends Record {
020:
021: private Name alg;
022: private Date timeSigned;
023: private int fudge;
024: private byte[] signature;
025: private int originalID;
026: private int error;
027: private byte[] other;
028:
029: TSIGRecord() {
030: }
031:
032: Record getObject() {
033: return new TSIGRecord();
034: }
035:
036: /**
037: * Creates a TSIG Record from the given data. This is normally called by
038: * the TSIG class
039: * @param alg The shared key's algorithm
040: * @param timeSigned The time that this record was generated
041: * @param fudge The fudge factor for time - if the time that the message is
042: * received is not in the range [now - fudge, now + fudge], the signature
043: * fails
044: * @param signature The signature
045: * @param originalID The message ID at the time of its generation
046: * @param error The extended error field. Should be 0 in queries.
047: * @param other The other data field. Currently used only in BADTIME
048: * responses.
049: * @see TSIG
050: */
051: public TSIGRecord(Name name, int dclass, long ttl, Name alg,
052: Date timeSigned, int fudge, byte[] signature,
053: int originalID, int error, byte other[]) {
054: super (name, Type.TSIG, dclass, ttl);
055: this .alg = checkName("alg", alg);
056: this .timeSigned = timeSigned;
057: this .fudge = checkU16("fudge", fudge);
058: this .signature = signature;
059: this .originalID = checkU16("originalID", originalID);
060: this .error = checkU16("error", error);
061: this .other = other;
062: }
063:
064: void rrFromWire(DNSInput in) throws IOException {
065: alg = new Name(in);
066:
067: long timeHigh = in.readU16();
068: long timeLow = in.readU32();
069: long time = (timeHigh << 32) + timeLow;
070: timeSigned = new Date(time * 1000);
071: fudge = in.readU16();
072:
073: int sigLen = in.readU16();
074: signature = in.readByteArray(sigLen);
075:
076: originalID = in.readU16();
077: error = in.readU16();
078:
079: int otherLen = in.readU16();
080: if (otherLen > 0)
081: other = in.readByteArray(otherLen);
082: else
083: other = null;
084: }
085:
086: void rdataFromString(Tokenizer st, Name origin) throws IOException {
087: throw st.exception("no text format defined for TSIG");
088: }
089:
090: /** Converts rdata to a String */
091: String rrToString() {
092: StringBuffer sb = new StringBuffer();
093: sb.append(alg);
094: sb.append(" ");
095: if (Options.check("multiline"))
096: sb.append("(\n\t");
097:
098: sb.append(timeSigned.getTime() / 1000);
099: sb.append(" ");
100: sb.append(fudge);
101: sb.append(" ");
102: sb.append(signature.length);
103: if (Options.check("multiline")) {
104: sb.append("\n");
105: sb.append(base64.formatString(signature, 64, "\t", false));
106: } else {
107: sb.append(" ");
108: sb.append(base64.toString(signature));
109: }
110: sb.append(" ");
111: sb.append(Rcode.TSIGstring(error));
112: sb.append(" ");
113: if (other == null)
114: sb.append(0);
115: else {
116: sb.append(other.length);
117: if (Options.check("multiline"))
118: sb.append("\n\n\n\t");
119: else
120: sb.append(" ");
121: if (error == Rcode.BADTIME) {
122: if (other.length != 6) {
123: sb.append("<invalid BADTIME other data>");
124: } else {
125: long time = ((long) (other[0] & 0xFF) << 40)
126: + ((long) (other[1] & 0xFF) << 32)
127: + ((other[2] & 0xFF) << 24)
128: + ((other[3] & 0xFF) << 16)
129: + ((other[4] & 0xFF) << 8)
130: + ((other[5] & 0xFF));
131: sb.append("<server time: ");
132: sb.append(new Date(time * 1000));
133: sb.append(">");
134: }
135: } else {
136: sb.append("<");
137: sb.append(base64.toString(other));
138: sb.append(">");
139: }
140: }
141: if (Options.check("multiline"))
142: sb.append(" )");
143: return sb.toString();
144: }
145:
146: /** Returns the shared key's algorithm */
147: public Name getAlgorithm() {
148: return alg;
149: }
150:
151: /** Returns the time that this record was generated */
152: public Date getTimeSigned() {
153: return timeSigned;
154: }
155:
156: /** Returns the time fudge factor */
157: public int getFudge() {
158: return fudge;
159: }
160:
161: /** Returns the signature */
162: public byte[] getSignature() {
163: return signature;
164: }
165:
166: /** Returns the original message ID */
167: public int getOriginalID() {
168: return originalID;
169: }
170:
171: /** Returns the extended error */
172: public int getError() {
173: return error;
174: }
175:
176: /** Returns the other data */
177: public byte[] getOther() {
178: return other;
179: }
180:
181: void rrToWire(DNSOutput out, Compression c, boolean canonical) {
182: alg.toWire(out, null, canonical);
183:
184: long time = timeSigned.getTime() / 1000;
185: int timeHigh = (int) (time >> 32);
186: long timeLow = (time & 0xFFFFFFFFL);
187: out.writeU16(timeHigh);
188: out.writeU32(timeLow);
189: out.writeU16(fudge);
190:
191: out.writeU16(signature.length);
192: out.writeByteArray(signature);
193:
194: out.writeU16(originalID);
195: out.writeU16(error);
196:
197: if (other != null) {
198: out.writeU16(other.length);
199: out.writeByteArray(other);
200: } else
201: out.writeU16(0);
202: }
203:
204: }
|