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