1 // Copyright (c) 1999-2004 Brian Wellington (bwelling (at) xbill.org) 2 3 package org.xbill.DNS; 4 5 import java.io.*; 6 import java.util.*; 7 import 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 19 public class TSIGRecord extends Record { 20 21 private static final long serialVersionUID = -88820909016649306L; 22 23 private Name alg; 24 private Date timeSigned; 25 private int fudge; 26 private byte [] signature; 27 private int originalID; 28 private int error; 29 private byte [] other; 30 31 TSIGRecord() {} 32 33 Record 34 getObject() { 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 */ 53 public 54 TSIGRecord(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 68 void 69 rrFromWire(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 91 void 92 rdataFromString(Tokenizer st, Name origin) throws IOException { 93 throw st.exception("no text format defined for TSIG"); 94 } 95 96 /** Converts rdata to a String */ 97 String 98 rrToString() { 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 */ 154 public Name 155 getAlgorithm() { 156 return alg; 157 } 158 159 /** Returns the time that this record was generated */ 160 public Date 161 getTimeSigned() { 162 return timeSigned; 163 } 164 165 /** Returns the time fudge factor */ 166 public int 167 getFudge() { 168 return fudge; 169 } 170 171 /** Returns the signature */ 172 public byte [] 173 getSignature() { 174 return signature; 175 } 176 177 /** Returns the original message ID */ 178 public int 179 getOriginalID() { 180 return originalID; 181 } 182 183 /** Returns the extended error */ 184 public int 185 getError() { 186 return error; 187 } 188 189 /** Returns the other data */ 190 public byte [] 191 getOther() { 192 return other; 193 } 194 195 void 196 rrToWire(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