001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Boris Kuznetsov
020: * @version $Revision$
021: */package org.apache.harmony.xnet.provider.jsse;
022:
023: import org.apache.harmony.xnet.provider.jsse.Message;
024: import org.apache.harmony.xnet.provider.jsse.Handshake;
025: import org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream;
026: import org.apache.harmony.xnet.provider.jsse.AlertProtocol;
027:
028: import java.io.IOException;
029: import java.security.cert.X509Certificate;
030: import java.util.Vector;
031:
032: import javax.security.auth.x500.X500Principal;
033:
034: /**
035: *
036: * Represents certificate request message
037: * @see TLS 1.0 spec., 7.4.4. Certificate request
038: * (http://www.ietf.org/rfc/rfc2246.txt)
039: */
040: public class CertificateRequest extends Message {
041:
042: /**
043: * Client certificate types as defined in
044: * TLS 1.0 spec., 7.4.4. Certificate request
045: */
046: public static final byte RSA_SIGN = 1;
047: public static final byte DSS_SIGN = 2;
048: public static final byte RSA_FIXED_DH = 3;
049: public static final byte DSS_FIXED_DH = 4;
050:
051: /**
052: * Requested certificate types
053: */
054: final byte[] certificate_types;
055:
056: /**
057: * Certificate authorities
058: */
059: X500Principal[] certificate_authorities;
060:
061: //Requested certificate types as Strings
062: // ("RSA", "DSA", "DH_RSA" or "DH_DSA")
063: private String[] types;
064:
065: // Encoded form of certificate authorities
066: private byte[][] encoded_principals;
067:
068: /**
069: * Creates outbound message
070: *
071: * @param certificate_types
072: * @param accepted - array of certificate authority certificates
073: */
074: public CertificateRequest(byte[] certificate_types,
075: X509Certificate[] accepted) {
076:
077: if (accepted == null) {
078: fatalAlert(AlertProtocol.INTERNAL_ERROR,
079: "CertificateRequest: array of certificate authority certificates is null");
080: }
081: this .certificate_types = certificate_types;
082:
083: int totalPrincipalsLength = 0;
084: certificate_authorities = new X500Principal[accepted.length];
085: encoded_principals = new byte[accepted.length][];
086: for (int i = 0; i < accepted.length; i++) {
087: certificate_authorities[i] = accepted[i]
088: .getIssuerX500Principal();
089: encoded_principals[i] = certificate_authorities[i]
090: .getEncoded();
091: totalPrincipalsLength += encoded_principals[i].length + 2;
092: }
093:
094: length = 3 + certificate_types.length + totalPrincipalsLength;
095: }
096:
097: /**
098: * Creates inbound message
099: *
100: * @param in
101: * @param length
102: * @throws IOException
103: */
104: public CertificateRequest(HandshakeIODataStream in, int length)
105: throws IOException {
106: int size = in.readUint8();
107: certificate_types = new byte[size];
108: in.read(certificate_types, 0, size);
109: size = in.readUint16();
110: certificate_authorities = new X500Principal[size];
111: int totalPrincipalsLength = 0;
112: int principalLength = 0;
113: Vector principals = new Vector();
114: while (totalPrincipalsLength < size) {
115: principalLength = in.readUint16(); // encoded X500Principal size
116: principals.add(new X500Principal(in));
117: totalPrincipalsLength += 2;
118: totalPrincipalsLength += principalLength;
119: }
120: certificate_authorities = new X500Principal[principals.size()];
121: for (int i = 0; i < certificate_authorities.length; i++) {
122: certificate_authorities[i] = (X500Principal) principals
123: .elementAt(i);
124: }
125: this .length = 3 + certificate_types.length
126: + totalPrincipalsLength;
127: if (this .length != length) {
128: fatalAlert(AlertProtocol.DECODE_ERROR,
129: "DECODE ERROR: incorrect CertificateRequest");
130: }
131:
132: }
133:
134: /**
135: * Sends message
136: *
137: * @param out
138: */
139: public void send(HandshakeIODataStream out) {
140:
141: out.writeUint8(certificate_types.length);
142: for (int i = 0; i < certificate_types.length; i++) {
143: out.write(certificate_types[i]);
144: }
145: int authoritiesLength = 0;
146: for (int i = 0; i < certificate_authorities.length; i++) {
147: authoritiesLength += encoded_principals[i].length + 2;
148: }
149: out.writeUint16(authoritiesLength);
150: for (int i = 0; i < certificate_authorities.length; i++) {
151: out.writeUint16(encoded_principals[i].length);
152: out.write(encoded_principals[i]);
153: }
154: }
155:
156: /**
157: * Returns message type
158: *
159: * @return
160: */
161: public int getType() {
162: return Handshake.CERTIFICATE_REQUEST;
163: }
164:
165: /**
166: * Returns requested certificate types as array of strings
167: */
168: public String[] getTypesAsString() {
169: if (types == null) {
170: types = new String[certificate_types.length];
171: for (int i = 0; i < types.length; i++) {
172: switch (certificate_types[i]) {
173: case 1:
174: types[i] = "RSA";
175: break;
176: case 2:
177: types[i] = "DSA";
178: break;
179: case 3:
180: types[i] = "DH_RSA";
181: break;
182: case 4:
183: types[i] = "DH_DSA";
184: break;
185: default:
186: fatalAlert(AlertProtocol.DECODE_ERROR,
187: "DECODE ERROR: incorrect CertificateRequest");
188: }
189: }
190: }
191: return types;
192: }
193:
194: }
|