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.java.security.x509.X500DistinguishedName;
  42: import gnu.javax.net.ssl.provider.Extension.Value;
  43: 
  44: import java.io.PrintWriter;
  45: import java.io.StringWriter;
  46: import java.nio.ByteBuffer;
  47: import java.nio.ByteOrder;
  48: import java.util.Iterator;
  49: import java.util.NoSuchElementException;
  50: 
  51: import javax.security.auth.x500.X500Principal;
  52: 
  53: /**
  54:  * The trusted authorities hello extension.
  55:  * 
  56:  * <pre>
  57: struct {
  58:   TrustedAuthority trusted_authorities_list&lt;0..2^16-1&gt;;
  59: } TrustedAuthorities;
  60: 
  61: struct {
  62:   IdentifierType identifier_type;
  63:   select (identifier_type) {
  64:     case pre_agreed: struct {};
  65:     case key_sha1_hash: SHA1Hash;
  66:     case x509_name: DistinguishedName;
  67:     case cert_sha1_hash: SHA1Hash;
  68:   } identifier;
  69: } TrustedAuthority;
  70: 
  71: enum {
  72:   pre_agreed(0), key_sha1_hash(1), x509_name(2),
  73:   cert_sha1_hash(3), (255)
  74: } IdentifierType;
  75: 
  76: opaque DistinguishedName&lt;1..2^16-1&gt;;</pre>
  77:  * 
  78:  * @author csm
  79:  */
  80: public class TrustedAuthorities extends Value
  81:   implements Iterable<TrustedAuthorities.TrustedAuthority>
  82: {
  83:   private final ByteBuffer buffer;
  84: 
  85:   public TrustedAuthorities(final ByteBuffer buffer)
  86:   {
  87:     this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
  88:   }
  89:   
  90:   // XXX really implement Builder.
  91:   
  92:   public int length()
  93:   {
  94:     return 2 + (buffer.getShort(0) & 0xFFFF);
  95:   }
  96:   
  97:   public ByteBuffer buffer()
  98:   {
  99:     return (ByteBuffer) buffer.duplicate().limit(length());
 100:   }
 101:   
 102:   public int size()
 103:   {
 104:     int len = buffer.getShort(0) & 0xFFFF;
 105:     int n = 0;
 106:     for (int i = 2; i < len; i++)
 107:       {
 108:         TrustedAuthority auth =
 109:           new TrustedAuthority((ByteBuffer) buffer.duplicate().position(i));
 110:         i += auth.length();
 111:         n++;
 112:       }
 113:     return n;
 114:   }
 115: 
 116:   public TrustedAuthority get(final int index)
 117:   {
 118:     int len = buffer.getShort(0) & 0xFFFF;
 119:     int n = 0;
 120:     int i = 2;
 121:     while (i < len && n <= index)
 122:       {
 123:         TrustedAuthority auth =
 124:           new TrustedAuthority((ByteBuffer) buffer.duplicate().position(i));
 125:         if (n == index)
 126:           return auth;
 127:         i += auth.length();
 128:         n++;
 129:       }
 130:     throw new IndexOutOfBoundsException();
 131:   }
 132:   
 133:   public String toString()
 134:   {
 135:     return toString(null);
 136:   }
 137:   
 138:   public String toString(String prefix)
 139:   {
 140:     StringWriter str = new StringWriter();
 141:     PrintWriter out = new PrintWriter(str);
 142:     if (prefix != null) out.print(prefix);
 143:     out.println("struct {");
 144:     String subprefix = "  ";
 145:     if (prefix != null)
 146:       subprefix = prefix + subprefix;
 147:     for(TrustedAuthority ta : this)
 148:       out.println(ta);
 149:     if (prefix != null) out.print(prefix);
 150:     out.print("} TrustedAuthorities;");
 151:     return str.toString();
 152:   }
 153:   
 154:   public Iterator<TrustedAuthority> iterator()
 155:   {
 156:     return new AuthoritiesIterator();
 157:   }
 158:   
 159:   public class AuthoritiesIterator implements Iterator<TrustedAuthority>
 160:   {
 161:     private int index;
 162:     
 163:     public AuthoritiesIterator()
 164:     {
 165:       index = 0;
 166:     }
 167:     
 168:     public TrustedAuthority next() throws NoSuchElementException
 169:     {
 170:       try
 171:         {
 172:           return get(index++);
 173:         }
 174:       catch (IndexOutOfBoundsException ioobe)
 175:         {
 176:           throw new NoSuchElementException();
 177:         }
 178:     }
 179:     
 180:     public boolean hasNext()
 181:     {
 182:       return index < size();
 183:     }
 184:     
 185:     public void remove()
 186:     {
 187:       throw new UnsupportedOperationException();
 188:     }
 189:   }
 190: 
 191:   public static class TrustedAuthority implements Constructed
 192:   {
 193:     private final ByteBuffer buffer;
 194:     
 195:     public TrustedAuthority(final ByteBuffer buffer)
 196:     {
 197:       this.buffer = buffer;
 198:     }
 199:     
 200:     public int length()
 201:     {
 202:       switch (type().getValue())
 203:       {
 204:         case 0: return 1;
 205:         case 1:
 206:         case 3: return 21;
 207:         case 2: return 3 + (buffer.getShort(1) & 0xFFFF);
 208:       }
 209:       throw new IllegalArgumentException("unknown authority type");
 210:     }
 211:     
 212:     public byte[] sha1Hash()
 213:     {
 214:       IdentifierType t = type();
 215:       if (t != IdentifierType.CERT_SHA1_HASH
 216:           && t != IdentifierType.KEY_SHA1_HASH)
 217:         throw new IllegalArgumentException(t + " does not have a hash value");
 218:       byte[] b = new byte[20];
 219:       ((ByteBuffer) buffer.duplicate().position(1)).get(b);
 220:       return b;
 221:     }
 222:     
 223:     public X500Principal name()
 224:     {
 225:       int len = buffer.getShort(1) & 0xFFFF;
 226:       byte[] b = new byte[len];
 227:       ((ByteBuffer) buffer.duplicate().position(3)).get(b);
 228:       return new X500Principal(b);
 229:     }
 230:     
 231:     public IdentifierType type()
 232:     {
 233:       switch (buffer.get(0))
 234:       {
 235:         case 0: return IdentifierType.PRE_AGREED;
 236:         case 1: return IdentifierType.KEY_SHA1_HASH;
 237:         case 2: return IdentifierType.X509_NAME;
 238:         case 3: return IdentifierType.CERT_SHA1_HASH;
 239:       }
 240:       
 241:       throw new IllegalArgumentException("invalid IdentifierType");
 242:     }
 243:     
 244:     public String toString()
 245:     {
 246:       return toString(null);
 247:     }
 248:     
 249:     public String toString(String prefix)
 250:     {
 251:       StringWriter str = new StringWriter();
 252:       PrintWriter out = new PrintWriter(str);
 253:       if (prefix != null) out.print(prefix);
 254:       out.println("struct {");
 255:       if (prefix != null) out.print(prefix);
 256:       out.print("  identifier_type = ");
 257:       out.print(type());
 258:       out.println(";");
 259:       switch (type().getValue())
 260:       {
 261:         case 0: break;
 262:         case 1:
 263:         case 3:
 264:           if (prefix != null) out.print(prefix);
 265:           out.print("  sha1_hash = ");
 266:           out.print(Util.toHexString(sha1Hash(), ':'));
 267:           out.println(";");
 268:           break;
 269:           
 270:         case 2:
 271:           if (prefix != null) out.print(prefix);
 272:           out.print("  name = ");
 273:           out.print(name());
 274:           out.println(";");
 275:       }
 276:       if (prefix != null) out.print(prefix);
 277:       out.print("} TrustedAuthority;");
 278:       return str.toString();
 279:     }
 280:   }
 281:   
 282:   public static enum IdentifierType
 283:   {
 284:     PRE_AGREED (0), KEY_SHA1_HASH (1), X509_NAME (2), CERT_SHA1_HASH (3);
 285:     
 286:     private final int value;
 287:     
 288:     private IdentifierType(final int value)
 289:     {
 290:       this.value = value;
 291:     }
 292:     
 293:     public int getValue()
 294:     {
 295:       return value;
 296:     }
 297:   }
 298: }