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 java.io.IOException;
     21 import java.security.cert.X509Certificate;
     22 import java.util.ArrayList;
     23 import javax.security.auth.x500.X500Principal;
     24 import libcore.io.Streams;
     25 
     26 /**
     27  *
     28  * Represents certificate request message
     29  * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.4.
     30  * Certificate request</a>
     31  */
     32 public class CertificateRequest extends Message {
     33 
     34     /**
     35      * Requested certificate types
     36      */
     37     final byte[] certificate_types;
     38 
     39     /**
     40      * Certificate authorities
     41      */
     42     final X500Principal[] certificate_authorities;
     43 
     44     /**
     45      * Requested certificate types as Strings
     46      * ("RSA", "DSA", "DH_RSA" or "DH_DSA")
     47      */
     48     private String[] types;
     49 
     50     /**
     51      * Encoded form of certificate authorities
     52      */
     53     private byte[][] encoded_principals;
     54 
     55     /**
     56      * Creates outbound message
     57      *
     58      * @param certificate_types
     59      * @param accepted - array of certificate authority certificates
     60      */
     61     public CertificateRequest(byte[] certificate_types,
     62                               X509Certificate[] accepted) {
     63 
     64         if (accepted == null) {
     65             fatalAlert(AlertProtocol.INTERNAL_ERROR,
     66                     "CertificateRequest: array of certificate authority certificates is null");
     67         }
     68         this.certificate_types = certificate_types;
     69 
     70         int totalPrincipalsLength = 0;
     71         certificate_authorities = new X500Principal[accepted.length];
     72         encoded_principals = new byte[accepted.length][];
     73         for (int i = 0; i < accepted.length; i++) {
     74             certificate_authorities[i] = accepted[i].getIssuerX500Principal();
     75             encoded_principals[i] = certificate_authorities[i].getEncoded();
     76             totalPrincipalsLength += encoded_principals[i].length + 2;
     77         }
     78 
     79         length = 3 + certificate_types.length + totalPrincipalsLength;
     80     }
     81 
     82     /**
     83      * Creates inbound message
     84      *
     85      * @param in
     86      * @param length
     87      * @throws IOException
     88      */
     89     public CertificateRequest(HandshakeIODataStream in, int length) throws IOException {
     90         int size = in.readUint8();
     91         certificate_types = new byte[size];
     92         Streams.readFully(in, certificate_types);
     93         size = in.readUint16();
     94         int totalPrincipalsLength = 0;
     95         int principalLength = 0;
     96         ArrayList<X500Principal> principals = new ArrayList<X500Principal>();
     97         while (totalPrincipalsLength < size) {
     98             principalLength = in.readUint16(); // encoded X500Principal size
     99             principals.add(new X500Principal(in));
    100             totalPrincipalsLength += 2;
    101             totalPrincipalsLength += principalLength;
    102         }
    103         certificate_authorities = principals.toArray(new X500Principal[principals.size()]);
    104         this.length = 3 + certificate_types.length + totalPrincipalsLength;
    105         if (this.length != length) {
    106             fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR: incorrect CertificateRequest");
    107         }
    108     }
    109 
    110     /**
    111      * Sends message
    112      *
    113      * @param out
    114      */
    115     @Override
    116     public void send(HandshakeIODataStream out) {
    117 
    118         out.writeUint8(certificate_types.length);
    119         for (int i = 0; i < certificate_types.length; i++) {
    120             out.write(certificate_types[i]);
    121         }
    122         int authoritiesLength = 0;
    123         for (int i = 0; i < certificate_authorities.length; i++) {
    124             authoritiesLength += encoded_principals[i].length +2;
    125         }
    126         out.writeUint16(authoritiesLength);
    127         for (int i = 0; i < certificate_authorities.length; i++) {
    128             out.writeUint16(encoded_principals[i].length);
    129             out.write(encoded_principals[i]);
    130         }
    131     }
    132 
    133     /**
    134      * Returns message type
    135      *
    136      * @return
    137      */
    138     @Override
    139     public int getType() {
    140         return Handshake.CERTIFICATE_REQUEST;
    141     }
    142 
    143     /**
    144      * Returns requested certificate types as array of strings
    145      */
    146     public String[] getTypesAsString() {
    147         if (types == null) {
    148             types = new String[certificate_types.length];
    149             for (int i = 0; i < types.length; i++) {
    150                 String type = CipherSuite.getClientKeyType(certificate_types[i]);
    151                 if (type == null) {
    152                     fatalAlert(AlertProtocol.DECODE_ERROR,
    153                             "DECODE ERROR: incorrect CertificateRequest");
    154                 }
    155                 types[i] = type;
    156             }
    157         }
    158         return types;
    159     }
    160 
    161 }
    162