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