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
18package org.apache.harmony.xnet.provider.jsse;
19
20/**
21 * This class encapsulates the functionality of Alert Protocol.
22 * Constant values are taken according to the TLS v1 specification
23 * (http://www.ietf.org/rfc/rfc2246.txt), p 7.2.
24 */
25public class AlertProtocol {
26
27    // ------------------------ AlertLevel codes --------------------------
28    /**
29     * Defines the severity of alert as warning
30     */
31    protected static final byte WARNING = 1;
32    /**
33     * Defines the severity of alert as fatal
34     */
35    protected static final byte FATAL = 2;
36
37    // --------------------- AlertDescription codes -----------------------
38    /**
39     * Defines the description code of the close_notify alert
40     */
41    protected static final byte CLOSE_NOTIFY = 0;
42    /**
43     * Defines the description code of the unexpected_message alert
44     */
45    protected static final byte UNEXPECTED_MESSAGE = 10;
46    /**
47     * Defines the description code of the bad_record_mac alert
48     */
49    protected static final byte BAD_RECORD_MAC = 20;
50    /**
51     * Defines the description code of the decryption_failed alert
52     */
53    protected static final byte DECRYPTION_FAILED = 21;
54    /**
55     * Defines the description code of the record_overflow alert
56     */
57    protected static final byte RECORD_OVERFLOW = 22;
58    /**
59     * Defines the description code of the decompression_failure alert
60     */
61    protected static final byte DECOMPRESSION_FAILURE = 30;
62    /**
63     * Defines the description code of the handshake_failure alert
64     */
65    protected static final byte HANDSHAKE_FAILURE = 40;
66    /**
67     * Defines the description code of the bad_certificate alert
68     */
69    protected static final byte BAD_CERTIFICATE = 42;
70    /**
71     * Defines the description code of the unsupported_certificate alert
72     */
73    protected static final byte UNSUPPORTED_CERTIFICATE = 43;
74    /**
75     * Defines the description code of the certificate_revoked alert
76     */
77    protected static final byte CERTIFICATE_REVOKED = 44;
78    /**
79     * Defines the description code of the certificate_expired alert
80     */
81    protected static final byte CERTIFICATE_EXPIRED = 45;
82    /**
83     * Defines the description code of the certificate_unknown alert
84     */
85    protected static final byte CERTIFICATE_UNKNOWN = 46;
86    /**
87     * Defines the description code of the illegal_parameter alert
88     */
89    protected static final byte ILLEGAL_PARAMETER = 47;
90    /**
91     * Defines the description code of the unknown_ca alert
92     */
93    protected static final byte UNKNOWN_CA = 48;
94    /**
95     * Defines the description code of the access_denied alert
96     */
97    protected static final byte ACCESS_DENIED = 49;
98    /**
99     * Defines the description code of the decode_error alert
100     */
101    protected static final byte DECODE_ERROR = 50;
102    /**
103     * Defines the description code of the decrypt_error alert
104     */
105    protected static final byte DECRYPT_ERROR = 51;
106    /**
107     * Defines the description code of the export_restriction alert
108     */
109    protected static final byte EXPORT_RESTRICTION = 60;
110    /**
111     * Defines the description code of the protocol_version alert
112     */
113    protected static final byte PROTOCOL_VERSION = 70;
114    /**
115     * Defines the description code of the insufficient_security alert
116     */
117    protected static final byte INSUFFICIENT_SECURITY = 71;
118    /**
119     * Defines the description code of the internal_error alert
120     */
121    protected static final byte INTERNAL_ERROR = 80;
122    /**
123     * Defines the description code of the user_canceled alert
124     */
125    protected static final byte USER_CANCELED = 90;
126    /**
127     * Defines the description code of the no_renegotiation alert
128     */
129    protected static final byte NO_RENEGOTIATION = 100;
130    // holds level and description codes
131    private final byte[] alert = new byte[2];
132    // record protocol to be used to wrap the alerts
133    private SSLRecordProtocol recordProtocol;
134
135    private Logger.Stream logger = Logger.getStream("alert");
136
137    /**
138     * Creates the instance of AlertProtocol.
139     * Note that class is not ready to work without providing of
140     * record protocol
141     * @see #setRecordProtocol
142     */
143    protected AlertProtocol() {}
144
145    /**
146     * Sets up the record protocol to be used by this allert protocol.
147     */
148    protected void setRecordProtocol(SSLRecordProtocol recordProtocol) {
149        this.recordProtocol = recordProtocol;
150    }
151
152    /**
153     * Reports an alert to be sent/received by transport.
154     * This method is usually called during processing
155     * of the income TSL record: if it contains alert message from another
156     * peer, or if warning alert occured during the processing of the
157     * message and this warning should be sent to another peer.
158     * @param   level:  alert level code
159     * @param   description: alert description code
160     * @return
161     */
162    protected void alert(byte level, byte description) {
163        if (logger != null) {
164            logger.println("Alert.alert: "+level+" "+description);
165        }
166        this.alert[0] = level;
167        this.alert[1] = description;
168    }
169
170    /**
171     * Returns the description code of alert or -100 if there
172     * is no alert.
173     */
174    protected byte getDescriptionCode() {
175        return (alert[0] != 0) ? alert[1] : -100;
176    }
177
178    /**
179     * Resets the protocol to be in "no alert" state.
180     * This method shoud be called after processing of the reported alert.
181     */
182    protected void setProcessed() {
183        // free the info about alert
184        if (logger != null) {
185            logger.println("Alert.setProcessed");
186        }
187        this.alert[0] = 0;
188    }
189
190    /**
191     * Checks if any alert has occured.
192     */
193    protected boolean hasAlert() {
194        return (alert[0] != 0);
195    }
196
197    /**
198     * Checks if occured alert is fatal alert.
199     */
200    protected boolean isFatalAlert() {
201        return (alert[0] == 2);
202    }
203
204    /**
205     * Returns the string representation of occured alert.
206     * If no alert has occured null is returned.
207     */
208    protected String getAlertDescription() {
209        switch (alert[1]) {
210        case CLOSE_NOTIFY:
211            return "close_notify";
212        case UNEXPECTED_MESSAGE:
213            return "unexpected_message";
214        case BAD_RECORD_MAC:
215            return "bad_record_mac";
216        case DECRYPTION_FAILED:
217            return "decryption_failed";
218        case RECORD_OVERFLOW:
219            return "record_overflow";
220        case DECOMPRESSION_FAILURE:
221            return "decompression_failure";
222        case HANDSHAKE_FAILURE:
223            return "handshake_failure";
224        case BAD_CERTIFICATE:
225            return "bad_certificate";
226        case UNSUPPORTED_CERTIFICATE:
227            return "unsupported_certificate";
228        case CERTIFICATE_REVOKED:
229            return "certificate_revoked";
230        case CERTIFICATE_EXPIRED:
231            return "certificate_expired";
232        case CERTIFICATE_UNKNOWN:
233            return "certificate_unknown";
234        case ILLEGAL_PARAMETER:
235            return "illegal_parameter";
236        case UNKNOWN_CA:
237            return "unknown_ca";
238        case ACCESS_DENIED:
239            return "access_denied";
240        case DECODE_ERROR:
241            return "decode_error";
242        case DECRYPT_ERROR:
243            return "decrypt_error";
244        case EXPORT_RESTRICTION:
245            return "export_restriction";
246        case PROTOCOL_VERSION:
247            return "protocol_version";
248        case INSUFFICIENT_SECURITY:
249            return "insufficient_security";
250        case INTERNAL_ERROR:
251            return "internal_error";
252        case USER_CANCELED:
253            return "user_canceled";
254        case NO_RENEGOTIATION:
255            return "no_renegotiation";
256        }
257        return null;
258    }
259
260    /**
261     * Returns the record with reported alert message.
262     * The returned array of bytes is ready to be sent to another peer.
263     * Note, that this method does not automatically set the state of alert
264     * protocol in "no alert" state, so after wrapping the method setProcessed
265     * should be called.
266     */
267    protected byte[] wrap() {
268        byte[] res = recordProtocol.wrap(ContentType.ALERT, alert, 0, 2);
269        return res;
270    }
271
272    /**
273     * Shutdown the protocol. It will be impossible to use the instance
274     * after the calling of this method.
275     */
276    protected void shutdown() {
277        alert[0] = 0;
278        alert[1] = 0;
279        recordProtocol = null;
280    }
281}
282
283