Home | History | Annotate | Download | only in jsse
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.xnet.provider.jsse;
     19 
     20 import org.apache.harmony.xnet.provider.jsse.Message;
     21 import org.apache.harmony.xnet.provider.jsse.Handshake;
     22 import org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream;
     23 import org.apache.harmony.xnet.provider.jsse.AlertProtocol;
     24 
     25 import java.io.IOException;
     26 import java.security.cert.X509Certificate;
     27 import java.util.Vector;
     28 
     29 import javax.security.auth.x500.X500Principal;
     30 
     31 /**
     32  *
     33  * Represents certificate request message
     34  * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.4.
     35  * Certificate request</a>
     36  */
     37 public class CertificateRequest extends Message {
     38 
     39     /**
     40      * Client certificate types as defined in
     41      * TLS 1.0 spec., 7.4.4. Certificate request
     42      */
     43     public static final byte RSA_SIGN = 1;
     44     public static final byte DSS_SIGN = 2;
     45     public static final byte RSA_FIXED_DH = 3;
     46     public static final byte DSS_FIXED_DH = 4;
     47 
     48     /**
     49      * Requested certificate types
     50      */
     51     final byte[] certificate_types;
     52 
     53     /**
     54      * Certificate authorities
     55      */
     56     X500Principal[] certificate_authorities;
     57 
     58     //Requested certificate types as Strings
     59     // ("RSA", "DSA", "DH_RSA" or "DH_DSA")
     60     private String[] types;
     61 
     62     // Encoded form of certificate authorities
     63     private byte[][] encoded_principals;
     64 
     65     /**
     66      * Creates outbound message
     67      *
     68      * @param certificate_types
     69      * @param accepted - array of certificate authority certificates
     70      */
     71     public CertificateRequest(byte[] certificate_types,
     72             X509Certificate[] accepted) {
     73 
     74         if (accepted == null) {
     75             fatalAlert(AlertProtocol.INTERNAL_ERROR,
     76                     "CertificateRequest: array of certificate authority certificates is null");
     77         }
     78         this.certificate_types = certificate_types;
     79 
     80         int totalPrincipalsLength = 0;
     81         certificate_authorities = new X500Principal[accepted.length];
     82         encoded_principals = new byte[accepted.length][];
     83         for (int i = 0; i < accepted.length; i++) {
     84             certificate_authorities[i] = accepted[i].getIssuerX500Principal();
     85             encoded_principals[i] = certificate_authorities[i].getEncoded();
     86             totalPrincipalsLength += encoded_principals[i].length + 2;
     87         }
     88 
     89         length = 3 + certificate_types.length + totalPrincipalsLength;
     90     }
     91 
     92     /**
     93      * Creates inbound message
     94      *
     95      * @param in
     96      * @param length
     97      * @throws IOException
     98      */
     99     public CertificateRequest(HandshakeIODataStream in, int length)
    100             throws IOException {
    101         int size = in.readUint8();
    102         certificate_types = new byte[size];
    103         in.read(certificate_types, 0, size);
    104         size = in.readUint16();
    105         certificate_authorities = new X500Principal[size];
    106         int totalPrincipalsLength = 0;
    107         int principalLength = 0;
    108         Vector<X500Principal> principals = new Vector<X500Principal>();
    109         while (totalPrincipalsLength < size) {
    110             principalLength = in.readUint16(); // encoded X500Principal size
    111             principals.add(new X500Principal(in));
    112             totalPrincipalsLength += 2;
    113             totalPrincipalsLength += principalLength;
    114         }
    115         certificate_authorities = new X500Principal[principals.size()];
    116         for (int i = 0; i < certificate_authorities.length; i++) {
    117             certificate_authorities[i] = principals.elementAt(i);
    118         }
    119         this.length = 3 + certificate_types.length + totalPrincipalsLength;
    120         if (this.length != length) {
    121             fatalAlert(AlertProtocol.DECODE_ERROR,
    122                     "DECODE ERROR: incorrect CertificateRequest");
    123         }
    124 
    125     }
    126 
    127     /**
    128      * Sends message
    129      *
    130      * @param out
    131      */
    132     @Override
    133     public void send(HandshakeIODataStream out) {
    134 
    135         out.writeUint8(certificate_types.length);
    136         for (int i = 0; i < certificate_types.length; i++) {
    137             out.write(certificate_types[i]);
    138         }
    139         int authoritiesLength = 0;
    140         for (int i = 0; i < certificate_authorities.length; i++) {
    141             authoritiesLength += encoded_principals[i].length +2;
    142         }
    143         out.writeUint16(authoritiesLength);
    144         for (int i = 0; i < certificate_authorities.length; i++) {
    145             out.writeUint16(encoded_principals[i].length);
    146             out.write(encoded_principals[i]);
    147         }
    148     }
    149 
    150     /**
    151      * Returns message type
    152      *
    153      * @return
    154      */
    155     @Override
    156     public int getType() {
    157         return Handshake.CERTIFICATE_REQUEST;
    158     }
    159 
    160     /**
    161      * Returns requested certificate types as array of strings
    162      */
    163     public String[] getTypesAsString() {
    164         if (types == null) {
    165             types = new String[certificate_types.length];
    166             for (int i = 0; i < types.length; i++) {
    167                 switch (certificate_types[i]) {
    168                 case 1:
    169                     types[i] = "RSA";
    170                     break;
    171                 case 2:
    172                     types[i] = "DSA";
    173                     break;
    174                 case 3:
    175                     types[i] = "DH_RSA";
    176                     break;
    177                 case 4:
    178                     types[i] = "DH_DSA";
    179                     break;
    180                 default:
    181                     fatalAlert(AlertProtocol.DECODE_ERROR,
    182                             "DECODE ERROR: incorrect CertificateRequest");
    183                 }
    184             }
    185         }
    186         return types;
    187     }
    188 
    189 }
    190