Home | History | Annotate | Download | only in DNS
      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