summaryrefslogtreecommitdiffstats
path: root/crypto/src/main/java/org/conscrypt/AlertProtocol.java
blob: 0330e79acaa84c90f7423e17e3534f0cf6f78071 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.conscrypt;

/**
 * This class encapsulates the functionality of Alert Protocol.
 * Constant values are taken according to the TLS v1 specification
 * (http://www.ietf.org/rfc/rfc2246.txt), p 7.2.
 */
public class AlertProtocol {

    // ------------------------ AlertLevel codes --------------------------
    /**
     * Defines the severity of alert as warning
     */
    protected static final byte WARNING = 1;
    /**
     * Defines the severity of alert as fatal
     */
    protected static final byte FATAL = 2;

    // --------------------- AlertDescription codes -----------------------
    /**
     * Defines the description code of the close_notify alert
     */
    protected static final byte CLOSE_NOTIFY = 0;
    /**
     * Defines the description code of the unexpected_message alert
     */
    protected static final byte UNEXPECTED_MESSAGE = 10;
    /**
     * Defines the description code of the bad_record_mac alert
     */
    protected static final byte BAD_RECORD_MAC = 20;
    /**
     * Defines the description code of the decryption_failed alert
     */
    protected static final byte DECRYPTION_FAILED = 21;
    /**
     * Defines the description code of the record_overflow alert
     */
    protected static final byte RECORD_OVERFLOW = 22;
    /**
     * Defines the description code of the decompression_failure alert
     */
    protected static final byte DECOMPRESSION_FAILURE = 30;
    /**
     * Defines the description code of the handshake_failure alert
     */
    protected static final byte HANDSHAKE_FAILURE = 40;
    /**
     * Defines the description code of the bad_certificate alert
     */
    protected static final byte BAD_CERTIFICATE = 42;
    /**
     * Defines the description code of the unsupported_certificate alert
     */
    protected static final byte UNSUPPORTED_CERTIFICATE = 43;
    /**
     * Defines the description code of the certificate_revoked alert
     */
    protected static final byte CERTIFICATE_REVOKED = 44;
    /**
     * Defines the description code of the certificate_expired alert
     */
    protected static final byte CERTIFICATE_EXPIRED = 45;
    /**
     * Defines the description code of the certificate_unknown alert
     */
    protected static final byte CERTIFICATE_UNKNOWN = 46;
    /**
     * Defines the description code of the illegal_parameter alert
     */
    protected static final byte ILLEGAL_PARAMETER = 47;
    /**
     * Defines the description code of the unknown_ca alert
     */
    protected static final byte UNKNOWN_CA = 48;
    /**
     * Defines the description code of the access_denied alert
     */
    protected static final byte ACCESS_DENIED = 49;
    /**
     * Defines the description code of the decode_error alert
     */
    protected static final byte DECODE_ERROR = 50;
    /**
     * Defines the description code of the decrypt_error alert
     */
    protected static final byte DECRYPT_ERROR = 51;
    /**
     * Defines the description code of the export_restriction alert
     */
    protected static final byte EXPORT_RESTRICTION = 60;
    /**
     * Defines the description code of the protocol_version alert
     */
    protected static final byte PROTOCOL_VERSION = 70;
    /**
     * Defines the description code of the insufficient_security alert
     */
    protected static final byte INSUFFICIENT_SECURITY = 71;
    /**
     * Defines the description code of the internal_error alert
     */
    protected static final byte INTERNAL_ERROR = 80;
    /**
     * Defines the description code of the user_canceled alert
     */
    protected static final byte USER_CANCELED = 90;
    /**
     * Defines the description code of the no_renegotiation alert
     */
    protected static final byte NO_RENEGOTIATION = 100;
    // holds level and description codes
    private final byte[] alert = new byte[2];
    // record protocol to be used to wrap the alerts
    private SSLRecordProtocol recordProtocol;

    private Logger.Stream logger = Logger.getStream("alert");

    /**
     * Creates the instance of AlertProtocol.
     * Note that class is not ready to work without providing of
     * record protocol
     * @see #setRecordProtocol
     */
    protected AlertProtocol() {}

    /**
     * Sets up the record protocol to be used by this allert protocol.
     */
    protected void setRecordProtocol(SSLRecordProtocol recordProtocol) {
        this.recordProtocol = recordProtocol;
    }

    /**
     * Reports an alert to be sent/received by transport.
     * This method is usually called during processing
     * of the income TSL record: if it contains alert message from another
     * peer, or if warning alert occured during the processing of the
     * message and this warning should be sent to another peer.
     * @param level alert level code
     * @param description alert description code
     */
    protected void alert(byte level, byte description) {
        if (logger != null) {
            logger.println("Alert.alert: "+level+" "+description);
        }
        this.alert[0] = level;
        this.alert[1] = description;
    }

    /**
     * Returns the description code of alert or -100 if there
     * is no alert.
     */
    protected byte getDescriptionCode() {
        return (alert[0] != 0) ? alert[1] : -100;
    }

    /**
     * Resets the protocol to be in "no alert" state.
     * This method shoud be called after processing of the reported alert.
     */
    protected void setProcessed() {
        // free the info about alert
        if (logger != null) {
            logger.println("Alert.setProcessed");
        }
        this.alert[0] = 0;
    }

    /**
     * Checks if any alert has occured.
     */
    protected boolean hasAlert() {
        return (alert[0] != 0);
    }

    /**
     * Checks if occured alert is fatal alert.
     */
    protected boolean isFatalAlert() {
        return (alert[0] == 2);
    }

    /**
     * Returns the string representation of occured alert.
     * If no alert has occured null is returned.
     */
    protected String getAlertDescription() {
        switch (alert[1]) {
        case CLOSE_NOTIFY:
            return "close_notify";
        case UNEXPECTED_MESSAGE:
            return "unexpected_message";
        case BAD_RECORD_MAC:
            return "bad_record_mac";
        case DECRYPTION_FAILED:
            return "decryption_failed";
        case RECORD_OVERFLOW:
            return "record_overflow";
        case DECOMPRESSION_FAILURE:
            return "decompression_failure";
        case HANDSHAKE_FAILURE:
            return "handshake_failure";
        case BAD_CERTIFICATE:
            return "bad_certificate";
        case UNSUPPORTED_CERTIFICATE:
            return "unsupported_certificate";
        case CERTIFICATE_REVOKED:
            return "certificate_revoked";
        case CERTIFICATE_EXPIRED:
            return "certificate_expired";
        case CERTIFICATE_UNKNOWN:
            return "certificate_unknown";
        case ILLEGAL_PARAMETER:
            return "illegal_parameter";
        case UNKNOWN_CA:
            return "unknown_ca";
        case ACCESS_DENIED:
            return "access_denied";
        case DECODE_ERROR:
            return "decode_error";
        case DECRYPT_ERROR:
            return "decrypt_error";
        case EXPORT_RESTRICTION:
            return "export_restriction";
        case PROTOCOL_VERSION:
            return "protocol_version";
        case INSUFFICIENT_SECURITY:
            return "insufficient_security";
        case INTERNAL_ERROR:
            return "internal_error";
        case USER_CANCELED:
            return "user_canceled";
        case NO_RENEGOTIATION:
            return "no_renegotiation";
        }
        return null;
    }

    /**
     * Returns the record with reported alert message.
     * The returned array of bytes is ready to be sent to another peer.
     * Note, that this method does not automatically set the state of alert
     * protocol in "no alert" state, so after wrapping the method setProcessed
     * should be called.
     */
    protected byte[] wrap() {
        byte[] res = recordProtocol.wrap(ContentType.ALERT, alert, 0, 2);
        return res;
    }

    /**
     * Shutdown the protocol. It will be impossible to use the instance
     * after the calling of this method.
     */
    protected void shutdown() {
        alert[0] = 0;
        alert[1] = 0;
        recordProtocol = null;
    }
}