src/share/classes/com/sun/jndi/dns/ResourceRecord.java

Print this page
rev 9296 : Detect compression loops in the JNDI DNS client
   1 /*
   2  * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  67         null, null, null, null, null,
  68         null, null, null, "AAAA", null,
  69         null, null, null, "SRV", null,
  70         "NAPTR"
  71     };
  72 
  73     /*
  74      * Resource record class codes
  75      */
  76     static final int CLASS_INTERNET = 1;
  77     static final int CLASS_HESIOD   = 2;
  78     static final int QCLASS_STAR    = 255;      // query class "*"
  79 
  80     /*
  81      * Mapping from resource record type codes to class name strings.
  82      */
  83     static final String rrClassNames[] = {
  84         null, "IN", null, null, "HS"
  85     };
  86 





  87 
  88     byte[] msg;                 // DNS message
  89     int msgLen;                 // msg size (in octets)
  90     boolean qSection;           // true if this RR is part of question section
  91                                 // and therefore has no ttl or rdata
  92     int offset;                 // offset of RR w/in msg
  93     int rrlen;                  // number of octets in encoded RR
  94     DnsName name;               // name field of RR, including root label
  95     int rrtype;                 // type field of RR
  96     String rrtypeName;          // name of of rrtype
  97     int rrclass;                // class field of RR
  98     String rrclassName;         // name of rrclass
  99     int ttl = 0;                // ttl field of RR
 100     int rdlen = 0;              // number of octets of rdata
 101     Object rdata = null;        // rdata -- most are String, unknown are byte[]
 102 
 103 
 104     /*
 105      * Constructs a new ResourceRecord.  The encoded data of the DNS
 106      * message is contained in msg; data for this RR begins at msg[offset].


 222         long diff = s2 - s1;
 223         if (diff == 0) {
 224             return 0;
 225         } else if ((diff > 0 &&  diff <= 0x7FFFFFFF) ||
 226                    (diff < 0 && -diff >  0x7FFFFFFF)) {
 227             return -1;
 228         } else {
 229             return 1;
 230         }
 231     }
 232 
 233 
 234     /*
 235      * Decodes the binary format of the RR.
 236      * May throw ArrayIndexOutOfBoundsException given corrupt data.
 237      */
 238     private void decode(boolean decodeRdata) throws InvalidNameException {
 239         int pos = offset;       // index of next unread octet
 240 
 241         name = new DnsName();                           // NAME
 242         pos = decodeName(pos, name);
 243 
 244         rrtype = getUShort(pos);                        // TYPE
 245         rrtypeName = (rrtype < rrTypeNames.length)
 246             ? rrTypeNames[rrtype]
 247             : null;
 248         if (rrtypeName == null) {
 249             rrtypeName = Integer.toString(rrtype);
 250         }
 251         pos += 2;
 252 
 253         rrclass = getUShort(pos);                       // CLASS
 254         rrclassName = (rrclass < rrClassNames.length)
 255             ? rrClassNames[rrclass]
 256             : null;
 257         if (rrclassName == null) {
 258             rrclassName = Integer.toString(rrclass);
 259         }
 260         pos += 2;
 261 
 262         if (!qSection) {


 301      * Returns the 4-byte signed value at msg[pos].  The high
 302      * order byte comes first.
 303      */
 304     private int getInt(int pos) {
 305         return ((getUShort(pos) << 16) | getUShort(pos + 2));
 306     }
 307 
 308     /*
 309      * Returns the 4-byte unsigned value at msg[pos].  The high
 310      * order byte comes first.
 311      */
 312     private long getUInt(int pos) {
 313         return (getInt(pos) & 0xffffffffL);
 314     }
 315 
 316     /*
 317      * Returns the name encoded at msg[pos], including the root label.
 318      */
 319     private DnsName decodeName(int pos) throws InvalidNameException {
 320         DnsName n = new DnsName();
 321         decodeName(pos, n);
 322         return n;
 323     }
 324 
 325     /*
 326      * Prepends to "n" the domain name encoded at msg[pos], including the root
 327      * label.  Returns the index into "msg" following the name.
 328      */
 329     private int decodeName(int pos, DnsName n) throws InvalidNameException {




 330         if (msg[pos] == 0) {                            // end of name
 331             n.add(0, "");
 332             return (pos + 1);
 333         } else if ((msg[pos] & 0xC0) != 0) {            // name compression
 334             decodeName(getUShort(pos) & 0x3FFF, n);
 335             return (pos + 2);
 336         } else {                                        // append a label
 337             int len = msg[pos++];
 338             try {
 339                 n.add(0, new String(msg, pos, len, "ISO-8859-1"));
 340             } catch (java.io.UnsupportedEncodingException e) {
 341                 // assert false : "ISO-Latin-1 charset unavailable";
 342             }
 343             return decodeName(pos + len, n);
 344         }
 345     }
 346 
 347     /*
 348      * Returns the rdata encoded at msg[pos].  The format is dependent
 349      * on the rrtype and rrclass values, which have already been set.
 350      * The length of the encoded data is rdlen, which has already been
 351      * set.
 352      * The rdata of records with unknown type/class combinations is
 353      * returned in a newly-allocated byte array.
 354      */
 355     private Object decodeRdata(int pos) throws InvalidNameException {
 356         if (rrclass == CLASS_INTERNET) {
 357             switch (rrtype) {
 358             case TYPE_A:
 359                 return decodeA(pos);
 360             case TYPE_AAAA:
 361                 return decodeAAAA(pos);
 362             case TYPE_CNAME:
 363             case TYPE_NS:


 381         byte[] rd = new byte[rdlen];
 382         System.arraycopy(msg, pos, rd, 0, rdlen);
 383         return rd;
 384     }
 385 
 386     /*
 387      * Returns the rdata of an MX record that is encoded at msg[pos].
 388      */
 389     private String decodeMx(int pos) throws InvalidNameException {
 390         int preference = getUShort(pos);
 391         pos += 2;
 392         DnsName name = decodeName(pos);
 393         return (preference + " " + name);
 394     }
 395 
 396     /*
 397      * Returns the rdata of an SOA record that is encoded at msg[pos].
 398      */
 399     private String decodeSoa(int pos) throws InvalidNameException {
 400         DnsName mname = new DnsName();
 401         pos = decodeName(pos, mname);
 402         DnsName rname = new DnsName();
 403         pos = decodeName(pos, rname);
 404 
 405         long serial = getUInt(pos);
 406         pos += 4;
 407         long refresh = getUInt(pos);
 408         pos += 4;
 409         long retry = getUInt(pos);
 410         pos += 4;
 411         long expire = getUInt(pos);
 412         pos += 4;
 413         long minimum = getUInt(pos);    // now used as negative TTL
 414         pos += 4;
 415 
 416         return (mname + " " + rname + " " + serial + " " +
 417                 refresh + " " + retry + " " + expire + " " + minimum);
 418     }
 419 
 420     /*
 421      * Returns the rdata of an SRV record that is encoded at msg[pos].
 422      * See RFC 2782.
 423      */


   1 /*
   2  * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  67         null, null, null, null, null,
  68         null, null, null, "AAAA", null,
  69         null, null, null, "SRV", null,
  70         "NAPTR"
  71     };
  72 
  73     /*
  74      * Resource record class codes
  75      */
  76     static final int CLASS_INTERNET = 1;
  77     static final int CLASS_HESIOD   = 2;
  78     static final int QCLASS_STAR    = 255;      // query class "*"
  79 
  80     /*
  81      * Mapping from resource record type codes to class name strings.
  82      */
  83     static final String rrClassNames[] = {
  84         null, "IN", null, null, "HS"
  85     };
  86 
  87     /*
  88      * Maximum number of compression references in labels.
  89      * Used to detect compression loops.
  90      */
  91     private static final int MAXIMUM_COMPRESSION_REFERENCES = 16;
  92 
  93     byte[] msg;                 // DNS message
  94     int msgLen;                 // msg size (in octets)
  95     boolean qSection;           // true if this RR is part of question section
  96                                 // and therefore has no ttl or rdata
  97     int offset;                 // offset of RR w/in msg
  98     int rrlen;                  // number of octets in encoded RR
  99     DnsName name;               // name field of RR, including root label
 100     int rrtype;                 // type field of RR
 101     String rrtypeName;          // name of of rrtype
 102     int rrclass;                // class field of RR
 103     String rrclassName;         // name of rrclass
 104     int ttl = 0;                // ttl field of RR
 105     int rdlen = 0;              // number of octets of rdata
 106     Object rdata = null;        // rdata -- most are String, unknown are byte[]
 107 
 108 
 109     /*
 110      * Constructs a new ResourceRecord.  The encoded data of the DNS
 111      * message is contained in msg; data for this RR begins at msg[offset].


 227         long diff = s2 - s1;
 228         if (diff == 0) {
 229             return 0;
 230         } else if ((diff > 0 &&  diff <= 0x7FFFFFFF) ||
 231                    (diff < 0 && -diff >  0x7FFFFFFF)) {
 232             return -1;
 233         } else {
 234             return 1;
 235         }
 236     }
 237 
 238 
 239     /*
 240      * Decodes the binary format of the RR.
 241      * May throw ArrayIndexOutOfBoundsException given corrupt data.
 242      */
 243     private void decode(boolean decodeRdata) throws InvalidNameException {
 244         int pos = offset;       // index of next unread octet
 245 
 246         name = new DnsName();                           // NAME
 247         pos = decodeName(pos, name, 0);
 248 
 249         rrtype = getUShort(pos);                        // TYPE
 250         rrtypeName = (rrtype < rrTypeNames.length)
 251             ? rrTypeNames[rrtype]
 252             : null;
 253         if (rrtypeName == null) {
 254             rrtypeName = Integer.toString(rrtype);
 255         }
 256         pos += 2;
 257 
 258         rrclass = getUShort(pos);                       // CLASS
 259         rrclassName = (rrclass < rrClassNames.length)
 260             ? rrClassNames[rrclass]
 261             : null;
 262         if (rrclassName == null) {
 263             rrclassName = Integer.toString(rrclass);
 264         }
 265         pos += 2;
 266 
 267         if (!qSection) {


 306      * Returns the 4-byte signed value at msg[pos].  The high
 307      * order byte comes first.
 308      */
 309     private int getInt(int pos) {
 310         return ((getUShort(pos) << 16) | getUShort(pos + 2));
 311     }
 312 
 313     /*
 314      * Returns the 4-byte unsigned value at msg[pos].  The high
 315      * order byte comes first.
 316      */
 317     private long getUInt(int pos) {
 318         return (getInt(pos) & 0xffffffffL);
 319     }
 320 
 321     /*
 322      * Returns the name encoded at msg[pos], including the root label.
 323      */
 324     private DnsName decodeName(int pos) throws InvalidNameException {
 325         DnsName n = new DnsName();
 326         decodeName(pos, n, 0);
 327         return n;
 328     }
 329 
 330     /*
 331      * Prepends to "n" the domain name encoded at msg[pos], including the root
 332      * label.  Returns the index into "msg" following the name.
 333      */
 334     private int decodeName(int pos, DnsName n, int level)
 335         throws InvalidNameException {
 336         if (level > MAXIMUM_COMPRESSION_REFERENCES) {
 337             throw new InvalidNameException("Too many compression references");
 338         }
 339         if (msg[pos] == 0) {                            // end of name
 340             n.add(0, "");
 341             return (pos + 1);
 342         } else if ((msg[pos] & 0xC0) != 0) {            // name compression
 343             decodeName(getUShort(pos) & 0x3FFF, n, level + 1);
 344             return (pos + 2);
 345         } else {                                        // append a label
 346             int len = msg[pos++];
 347             try {
 348                 n.add(0, new String(msg, pos, len, "ISO-8859-1"));
 349             } catch (java.io.UnsupportedEncodingException e) {
 350                 // assert false : "ISO-Latin-1 charset unavailable";
 351             }
 352             return decodeName(pos + len, n, level);
 353         }
 354     }
 355 
 356     /*
 357      * Returns the rdata encoded at msg[pos].  The format is dependent
 358      * on the rrtype and rrclass values, which have already been set.
 359      * The length of the encoded data is rdlen, which has already been
 360      * set.
 361      * The rdata of records with unknown type/class combinations is
 362      * returned in a newly-allocated byte array.
 363      */
 364     private Object decodeRdata(int pos) throws InvalidNameException {
 365         if (rrclass == CLASS_INTERNET) {
 366             switch (rrtype) {
 367             case TYPE_A:
 368                 return decodeA(pos);
 369             case TYPE_AAAA:
 370                 return decodeAAAA(pos);
 371             case TYPE_CNAME:
 372             case TYPE_NS:


 390         byte[] rd = new byte[rdlen];
 391         System.arraycopy(msg, pos, rd, 0, rdlen);
 392         return rd;
 393     }
 394 
 395     /*
 396      * Returns the rdata of an MX record that is encoded at msg[pos].
 397      */
 398     private String decodeMx(int pos) throws InvalidNameException {
 399         int preference = getUShort(pos);
 400         pos += 2;
 401         DnsName name = decodeName(pos);
 402         return (preference + " " + name);
 403     }
 404 
 405     /*
 406      * Returns the rdata of an SOA record that is encoded at msg[pos].
 407      */
 408     private String decodeSoa(int pos) throws InvalidNameException {
 409         DnsName mname = new DnsName();
 410         pos = decodeName(pos, mname, 0);
 411         DnsName rname = new DnsName();
 412         pos = decodeName(pos, rname, 0);
 413 
 414         long serial = getUInt(pos);
 415         pos += 4;
 416         long refresh = getUInt(pos);
 417         pos += 4;
 418         long retry = getUInt(pos);
 419         pos += 4;
 420         long expire = getUInt(pos);
 421         pos += 4;
 422         long minimum = getUInt(pos);    // now used as negative TTL
 423         pos += 4;
 424 
 425         return (mname + " " + rname + " " + serial + " " +
 426                 refresh + " " + retry + " " + expire + " " + minimum);
 427     }
 428 
 429     /*
 430      * Returns the rdata of an SRV record that is encoded at msg[pos].
 431      * See RFC 2782.
 432      */