Source code: gnu/javax/net/ssl/provider/Alert.java
1 /* Alert.java -- SSL Alert message.
2 Copyright (C) 2006 Free Software Foundation, Inc.
3
4 This file is a part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package gnu.javax.net.ssl.provider;
40
41 import java.io.EOFException;
42 import java.io.InputStream;
43 import java.io.IOException;
44 import java.io.OutputStream;
45
46 /**
47 * An alert message in the SSL protocol. Alerts are sent both as warnings
48 * which may allow execution to continue, or they may be fatal, which will
49 * halt this session. An alert object is composed of two enums -- the level,
50 * which indicates the seriousness of the alert, and the description, which
51 * indicates the reason for the alert.
52 *
53 * <pre>
54 * struct {
55 * AlertLevel level;
56 * AlertDescription description;
57 * }
58 * </pre>
59 */
60 final class Alert implements Constructed
61 {
62
63 // Fields.
64 // -------------------------------------------------------------------------
65
66 /** The alert level enumerated. */
67 private final Level level;
68
69 /** The alert description enumerated. */
70 private final Description description;
71
72 // Constructor.
73 // -------------------------------------------------------------------------
74
75 Alert(Level level, Description description)
76 {
77 this.level = level;
78 this.description = description;
79 }
80
81 // Class method.
82 // -------------------------------------------------------------------------
83
84 static Alert read(InputStream in) throws IOException
85 {
86 Level level = Level.read(in);
87 Description desc = Description.read(in);
88 return new Alert(level, desc);
89 }
90
91 static Alert forName(String name)
92 {
93 if (name == null)
94 {
95 return new Alert(Level.FATAL, Description.INTERNAL_ERROR);
96 }
97 Description desc = Description.INTERNAL_ERROR;
98 if (name.equals("close_notify"))
99 {
100 desc = Description.CLOSE_NOTIFY;
101 }
102 else if (name.equals("unexpected_message"))
103 {
104 desc = Description.UNEXPECTED_MESSAGE;
105 }
106 else if (name.equals("bad_record_mac"))
107 {
108 desc = Description.BAD_RECORD_MAC;
109 }
110 else if (name.equals("DECRYPTION_FAILED"))
111 {
112 desc = Description.DECRYPTION_FAILED;
113 }
114 else if (name.equals("record_overflow"))
115 {
116 desc = Description.RECORD_OVERFLOW;
117 }
118 else if (name.equals("decompression_failure"))
119 {
120 desc = Description.DECOMPRESSION_FAILURE;
121 }
122 else if (name.equals("handshake_failure"))
123 {
124 desc = Description.HANDSHAKE_FAILURE;
125 }
126 else if (name.equals("no_certificate"))
127 {
128 desc = Description.NO_CERTIFICATE;
129 }
130 else if (name.equals("bad_certificate"))
131 {
132 desc = Description.BAD_CERTIFICATE;
133 }
134 else if (name.equals("unsupported_certificate"))
135 {
136 desc = Description.UNSUPPORTED_CERTIFICATE;
137 }
138 else if (name.equals("certificate_revoked"))
139 {
140 desc = Description.CERTIFICATE_REVOKED;
141 }
142 else if (name.equals("certificate_expired"))
143 {
144 desc = Description.CERTIFICATE_EXPIRED;
145 }
146 else if (name.equals("certificate_unknown"))
147 {
148 desc = Description.CERTIFICATE_UNKNOWN;
149 }
150 else if (name.equals("illegal_parameter"))
151 {
152 desc = Description.ILLEGAL_PARAMETER;
153 }
154 else if (name.equals("unknown_ca"))
155 {
156 desc = Description.UNKNOWN_CA;
157 }
158 else if (name.equals("access_denied"))
159 {
160 desc = Description.ACCESS_DENIED;
161 }
162 else if (name.equals("decode_error"))
163 {
164 desc = Description.DECODE_ERROR;
165 }
166 else if (name.equals("decrypt_error"))
167 {
168 desc = Description.DECRYPT_ERROR;
169 }
170 else if (name.equals("export_restriction"))
171 {
172 desc = Description.EXPORT_RESTRICTION;
173 }
174 else if (name.equals("protocol_version"))
175 {
176 desc = Description.PROTOCOL_VERSION;
177 }
178 else if (name.equals("insufficient_security"))
179 {
180 desc = Description.INSUFFICIENT_SECURITY;
181 }
182 else if (name.equals("internal_error"))
183 {
184 desc = Description.INTERNAL_ERROR;
185 }
186 else if (name.equals("user_canceled"))
187 {
188 desc = Description.USER_CANCELED;
189 }
190 else if (name.equals("no_renegotiation"))
191 {
192 desc = Description.NO_RENEGOTIATION;
193 }
194 else if (name.equals("unsupported_extension"))
195 {
196 desc = Description.UNSUPPORTED_EXTENSION;
197 }
198 else if (name.equals("certificate_unobtainable"))
199 {
200 desc = Description.CERTIFICATE_UNOBTAINABLE;
201 }
202 else if (name.equals("unrecognized_name"))
203 {
204 desc = Description.UNRECOGNIZED_NAME;
205 }
206 else if (name.equals("bad_certificate_status_response"))
207 {
208 desc = Description.BAD_CERTIFICATE_STATUS_RESPONSE;
209 }
210 else if (name.equals("bad_certificate_hash_value"))
211 {
212 desc = Description.BAD_CERTIFICATE_HASH_VALUE;
213 }
214 else if (name.equals("unknown_srp_username"))
215 {
216 desc = Description.UNKNOWN_SRP_USERNAME;
217 }
218 else if (name.equals("missing_srp_username"))
219 {
220 desc = Description.MISSING_SRP_USERNAME;
221 }
222 return new Alert(Level.FATAL, desc);
223 }
224
225 // Instance methods.
226 // -------------------------------------------------------------------------
227
228 public void write(OutputStream out) throws IOException
229 {
230 out.write((byte) level.getValue());
231 out.write((byte) description.getValue());
232 }
233
234 byte[] getEncoded()
235 {
236 return new byte[] { (byte) level.getValue(),
237 (byte) description.getValue() };
238 }
239
240 Level getLevel()
241 {
242 return level;
243 }
244
245 Description getDescription()
246 {
247 return description;
248 }
249
250 public String toString()
251 {
252 String nl = System.getProperty("line.separator");
253 return "struct {" + nl +
254 " level = " + level + ";" + nl +
255 " description = " + description + ";" + nl +
256 "} Alert;" + nl;
257 }
258
259 // Inner classes.
260 // -------------------------------------------------------------------------
261
262 /**
263 * The level enumeration.
264 *
265 * <pre>
266 * enum { warning(1), fatal(2), (255) } AlertLevel;
267 * </pre>
268 */
269 static final class Level implements Enumerated
270 {
271
272 // Constants and fields.
273 // -----------------------------------------------------------------------
274
275 static final Level WARNING = new Level(1), FATAL = new Level(2);
276
277 private final int value;
278
279 // Constructor.
280 // -----------------------------------------------------------------------
281
282 private Level(int value)
283 {
284 this.value = value;
285 }
286
287 // Class method.
288 // -----------------------------------------------------------------------
289
290 static Level read(InputStream in) throws IOException
291 {
292 int i = in.read();
293 if (i == -1)
294 {
295 throw new EOFException("unexpected end of stream");
296 }
297 switch (i & 0xFF)
298 {
299 case 1: return WARNING;
300 case 2: return FATAL;
301 default: return new Level(i);
302 }
303 }
304
305 // Instance methods.
306 // -----------------------------------------------------------------------
307
308 public byte[] getEncoded()
309 {
310 return new byte[] { (byte) value };
311 }
312
313 public int getValue()
314 {
315 return value;
316 }
317
318 public String toString()
319 {
320 switch (value)
321 {
322 case 1: return "warning";
323 case 2: return "fatal";
324 default: return "unknown(" + value + ")";
325 }
326 }
327 }
328
329 /**
330 * The description enumeration.
331 */
332 static final class Description implements Enumerated
333 {
334
335 // Constants and fields.
336 // -----------------------------------------------------------------------
337
338 static final Description
339 CLOSE_NOTIFY = new Description( 0),
340 UNEXPECTED_MESSAGE = new Description( 10),
341 BAD_RECORD_MAC = new Description( 20),
342 DECRYPTION_FAILED = new Description( 21),
343 RECORD_OVERFLOW = new Description( 22),
344 DECOMPRESSION_FAILURE = new Description( 30),
345 HANDSHAKE_FAILURE = new Description( 40),
346 NO_CERTIFICATE = new Description( 41),
347 BAD_CERTIFICATE = new Description( 42),
348 UNSUPPORTED_CERTIFICATE = new Description( 43),
349 CERTIFICATE_REVOKED = new Description( 44),
350 CERTIFICATE_EXPIRED = new Description( 45),
351 CERTIFICATE_UNKNOWN = new Description( 46),
352 ILLEGAL_PARAMETER = new Description( 47),
353 UNKNOWN_CA = new Description( 48),
354 ACCESS_DENIED = new Description( 49),
355 DECODE_ERROR = new Description( 50),
356 DECRYPT_ERROR = new Description( 51),
357 EXPORT_RESTRICTION = new Description( 60),
358 PROTOCOL_VERSION = new Description( 70),
359 INSUFFICIENT_SECURITY = new Description( 71),
360 INTERNAL_ERROR = new Description( 80),
361 USER_CANCELED = new Description( 90),
362 NO_RENEGOTIATION = new Description(100),
363 UNSUPPORTED_EXTENSION = new Description(110),
364 CERTIFICATE_UNOBTAINABLE = new Description(111),
365 UNRECOGNIZED_NAME = new Description(112),
366 BAD_CERTIFICATE_STATUS_RESPONSE = new Description(113),
367 BAD_CERTIFICATE_HASH_VALUE = new Description(114),
368 UNKNOWN_SRP_USERNAME = new Description(120),
369 MISSING_SRP_USERNAME = new Description(121);
370
371 private final int value;
372
373 // Constructor.
374 // -----------------------------------------------------------------------
375
376 private Description(int value)
377 {
378 this.value = value;
379 }
380
381 // Class method.
382 // -----------------------------------------------------------------------
383
384 static Description read(InputStream in) throws IOException
385 {
386 int i = in.read();
387 if (i == -1)
388 {
389 throw new EOFException("unexpected end of input stream");
390 }
391 switch (i)
392 {
393 case 0: return CLOSE_NOTIFY;
394 case 10: return UNEXPECTED_MESSAGE;
395 case 20: return BAD_RECORD_MAC;
396 case 21: return DECRYPTION_FAILED;
397 case 22: return RECORD_OVERFLOW;
398 case 30: return DECOMPRESSION_FAILURE;
399 case 40: return HANDSHAKE_FAILURE;
400 case 41: return NO_CERTIFICATE;
401 case 42: return BAD_CERTIFICATE;
402 case 43: return UNSUPPORTED_CERTIFICATE;
403 case 44: return CERTIFICATE_REVOKED;
404 case 45: return CERTIFICATE_EXPIRED;
405 case 46: return CERTIFICATE_UNKNOWN;
406 case 47: return ILLEGAL_PARAMETER;
407 case 48: return UNKNOWN_CA;
408 case 49: return ACCESS_DENIED;
409 case 50: return DECODE_ERROR;
410 case 51: return DECRYPT_ERROR;
411 case 60: return EXPORT_RESTRICTION;
412 case 70: return PROTOCOL_VERSION;
413 case 71: return INSUFFICIENT_SECURITY;
414 case 80: return INTERNAL_ERROR;
415 case 90: return USER_CANCELED;
416 case 100: return NO_RENEGOTIATION;
417 case 120: return UNKNOWN_SRP_USERNAME;
418 case 121: return MISSING_SRP_USERNAME;
419 default: return new Description(i);
420 }
421 }
422
423 // Instance methods.
424 // -----------------------------------------------------------------------
425
426 public byte[] getEncoded()
427 {
428 return new byte[] { (byte) value };
429 }
430
431 public int getValue()
432 {
433 return value;
434 }
435
436 public String toString()
437 {
438 switch (value)
439 {
440 case 0: return "close_notify";
441 case 10: return "unexpected_message";
442 case 20: return "bad_record_mac";
443 case 21: return "decryption_failed";
444 case 22: return "record_overflow";
445 case 30: return "decompression_failure";
446 case 40: return "handshake_failure";
447 case 42: return "bad_certificate";
448 case 43: return "unsupported_certificate";
449 case 44: return "certificate_revoked";
450 case 45: return "certificate_expired";
451 case 46: return "certificate_unknown";
452 case 47: return "illegal_parameter";
453 case 48: return "unknown_ca";
454 case 49: return "access_denied";
455 case 50: return "decode_error";
456 case 51: return "decrypt_error";
457 case 60: return "export_restriction";
458 case 70: return "protocol_version";
459 case 71: return "insufficient_security";
460 case 80: return "internal_error";
461 case 90: return "user_canceled";
462 case 100: return "no_renegotiation";
463 case 110: return "unsupported_extension";
464 case 111: return "certificate_unobtainable";
465 case 112: return "unrecognized_name";
466 case 113: return "bad_certificate_status_response";
467 case 114: return "bad_certificate_hash_value";
468 case 120: return "unknown_srp_username";
469 case 121: return "missing_srp_username";
470 default: return "unknown(" + value + ")";
471 }
472 }
473 }
474 }