Source for gnu.javax.net.ssl.provider.TrustedAuthorities

   1: /* TrustedAuthorities.java
   2:    Copyright (C) 2006  Free Software Foundation, Inc.
   3: 
   4: This file is a part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2 of the License, or (at
   9: your option) any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; if not, write to the Free Software
  18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  19: USA
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version.  */
  37: 
  38: 
  39: package gnu.javax.net.ssl.provider;
  40: 
  41: import gnu.javax.net.ssl.provider.Extension.Value;
  42: 
  43: import java.io.PrintWriter;
  44: import java.io.StringWriter;
  45: import java.nio.ByteBuffer;
  46: import java.nio.ByteOrder;
  47: import java.util.Iterator;
  48: import java.util.NoSuchElementException;
  49: 
  50: import javax.security.auth.x500.X500Principal;
  51: 
  52: /**
  53:  * The trusted authorities hello extension.
  54:  *
  55:  * <pre>
  56: struct {
  57:   TrustedAuthority trusted_authorities_list&lt;0..2^16-1&gt;;
  58: } TrustedAuthorities;
  59: 
  60: struct {
  61:   IdentifierType identifier_type;
  62:   select (identifier_type) {
  63:     case pre_agreed: struct {};
  64:     case key_sha1_hash: SHA1Hash;
  65:     case x509_name: DistinguishedName;
  66:     case cert_sha1_hash: SHA1Hash;
  67:   } identifier;
  68: } TrustedAuthority;
  69: 
  70: enum {
  71:   pre_agreed(0), key_sha1_hash(1), x509_name(2),
  72:   cert_sha1_hash(3), (255)
  73: } IdentifierType;
  74: 
  75: opaque DistinguishedName&lt;1..2^16-1&gt;;</pre>
  76:  *
  77:  * @author csm
  78:  */
  79: public class TrustedAuthorities extends Value
  80:   implements Iterable<TrustedAuthorities.TrustedAuthority>
  81: {
  82:   private final ByteBuffer buffer;
  83: 
  84:   public TrustedAuthorities(final ByteBuffer buffer)
  85:   {
  86:     this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
  87:   }
  88: 
  89:   // XXX really implement Builder.
  90: 
  91:   public int length()
  92:   {
  93:     return 2 + (buffer.getShort(0) & 0xFFFF);
  94:   }
  95: 
  96:   public ByteBuffer buffer()
  97:   {
  98:     return (ByteBuffer) buffer.duplicate().limit(length());
  99:   }
 100: 
 101:   public int size()
 102:   {
 103:     int len = buffer.getShort(0) & 0xFFFF;
 104:     int n = 0;
 105:     for (int i = 2; i < len; i++)
 106:       {
 107:         TrustedAuthority auth =
 108:           new TrustedAuthority((ByteBuffer) buffer.duplicate().position(i));
 109:         i += auth.length();
 110:         n++;
 111:       }
 112:     return n;
 113:   }
 114: 
 115:   public TrustedAuthority get(final int index)
 116:   {
 117:     int len = buffer.getShort(0) & 0xFFFF;
 118:     int n = 0;
 119:     int i = 2;
 120:     while (i < len && n <= index)
 121:       {
 122:         TrustedAuthority auth =
 123:           new TrustedAuthority((ByteBuffer) buffer.duplicate().position(i));
 124:         if (n == index)
 125:           return auth;
 126:         i += auth.length();
 127:         n++;
 128:       }
 129:     throw new IndexOutOfBoundsException();
 130:   }
 131: 
 132:   public String toString()
 133:   {
 134:     return toString(null);
 135:   }
 136: 
 137:   public String toString(String prefix)
 138:   {
 139:     StringWriter str = new StringWriter();
 140:     PrintWriter out = new PrintWriter(str);
 141:     if (prefix != null) out.print(prefix);
 142:     out.println("struct {");
 143:     String subprefix = "  ";
 144:     if (prefix != null)
 145:       subprefix = prefix + subprefix;
 146:     for(TrustedAuthority ta : this)
 147:       out.println(ta);
 148:     if (prefix != null) out.print(prefix);
 149:     out.print("} TrustedAuthorities;");
 150:     return str.toString();
 151:   }
 152: 
 153:   public Iterator<TrustedAuthority> iterator()
 154:   {
 155:     return new AuthoritiesIterator();
 156:   }
 157: 
 158:   public class AuthoritiesIterator implements Iterator<TrustedAuthority>
 159:   {
 160:     private int index;
 161: 
 162:     public AuthoritiesIterator()
 163:     {
 164:       index = 0;
 165:     }
 166: 
 167:     public TrustedAuthority next() throws NoSuchElementException
 168:     {
 169:       try
 170:         {
 171:           return get(index++);
 172:         }
 173:       catch (IndexOutOfBoundsException ioobe)
 174:         {
 175:           throw new NoSuchElementException();
 176:         }
 177:     }
 178: 
 179:     public boolean hasNext()
 180:     {
 181:       return index < size();
 182:     }
 183: 
 184:     public void remove()
 185:     {
 186:       throw new UnsupportedOperationException();
 187:     }
 188:   }
 189: 
 190:   public static class TrustedAuthority implements Constructed
 191:   {
 192:     private final ByteBuffer buffer;
 193: 
 194:     public TrustedAuthority(final ByteBuffer buffer)
 195:     {
 196:       this.buffer = buffer;
 197:     }
 198: 
 199:     public int length()
 200:     {
 201:       switch (type().getValue())
 202:       {
 203:         case 0: return 1;
 204:         case 1:
 205:         case 3: return 21;
 206:         case 2: return 3 + (buffer.getShort(1) & 0xFFFF);
 207:       }
 208:       throw new IllegalArgumentException("unknown authority type");
 209:     }
 210: 
 211:     public byte[] sha1Hash()
 212:     {
 213:       IdentifierType t = type();
 214:       if (t != IdentifierType.CERT_SHA1_HASH
 215:           && t != IdentifierType.KEY_SHA1_HASH)
 216:         throw new IllegalArgumentException(t + " does not have a hash value");
 217:       byte[] b = new byte[20];
 218:       ((ByteBuffer) buffer.duplicate().position(1)).get(b);
 219:       return b;
 220:     }
 221: 
 222:     public X500Principal name()
 223:     {
 224:       int len = buffer.getShort(1) & 0xFFFF;
 225:       byte[] b = new byte[len];
 226:       ((ByteBuffer) buffer.duplicate().position(3)).get(b);
 227:       return new X500Principal(b);
 228:     }
 229: 
 230:     public IdentifierType type()
 231:     {
 232:       switch (buffer.get(0))
 233:       {
 234:         case 0: return IdentifierType.PRE_AGREED;
 235:         case 1: return IdentifierType.KEY_SHA1_HASH;
 236:         case 2: return IdentifierType.X509_NAME;
 237:         case 3: return IdentifierType.CERT_SHA1_HASH;
 238:       }
 239: 
 240:       throw new IllegalArgumentException("invalid IdentifierType");
 241:     }
 242: 
 243:     public String toString()
 244:     {
 245:       return toString(null);
 246:     }
 247: 
 248:     public String toString(String prefix)
 249:     {
 250:       StringWriter str = new StringWriter();
 251:       PrintWriter out = new PrintWriter(str);
 252:       if (prefix != null) out.print(prefix);
 253:       out.println("struct {");
 254:       if (prefix != null) out.print(prefix);
 255:       out.print("  identifier_type = ");
 256:       out.print(type());
 257:       out.println(";");
 258:       switch (type().getValue())
 259:       {
 260:         case 0: break;
 261:         case 1:
 262:         case 3:
 263:           if (prefix != null) out.print(prefix);
 264:           out.print("  sha1_hash = ");
 265:           out.print(Util.toHexString(sha1Hash(), ':'));
 266:           out.println(";");
 267:           break;
 268: 
 269:         case 2:
 270:           if (prefix != null) out.print(prefix);
 271:           out.print("  name = ");
 272:           out.print(name());
 273:           out.println(";");
 274:       }
 275:       if (prefix != null) out.print(prefix);
 276:       out.print("} TrustedAuthority;");
 277:       return str.toString();
 278:     }
 279:   }
 280: 
 281:   public static enum IdentifierType
 282:   {
 283:     PRE_AGREED (0), KEY_SHA1_HASH (1), X509_NAME (2), CERT_SHA1_HASH (3);
 284: 
 285:     private final int value;
 286: 
 287:     private IdentifierType(final int value)
 288:     {
 289:       this.value = value;
 290:     }
 291: 
 292:     public int getValue()
 293:     {
 294:       return value;
 295:     }
 296:   }
 297: }