1 /**
2 * TLS Alert Message
3 * 
4 * Copyright:
5 * (C) 2004-2006,2011,2012,2015 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.tls.alert;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_TLS):
15 
16 import memutils.vector;
17 import botan.utils.exceptn;
18 import botan.utils.types;
19 import std.conv : to;
20 
21 alias ushort TLSAlertType;
22 /**
23 * SSL/TLS TLSAlert Message
24 */
25 struct TLSAlert
26 {
27 public:
28     /**
29     * Type codes for TLS alerts
30     */
31     enum : TLSAlertType {
32         CLOSE_NOTIFY                        = 0,
33         UNEXPECTED_MESSAGE                  = 10,
34         BAD_RECORD_MAC                      = 20,
35         DECRYPTION_FAILED                   = 21,
36         RECORD_OVERFLOW                     = 22,
37         DECOMPRESSION_FAILURE               = 30,
38         HANDSHAKE_FAILURE                   = 40,
39         NO_CERTIFICATE                      = 41, // SSLv3 only
40         BAD_CERTIFICATE                     = 42,
41         UNSUPPORTED_CERTIFICATE             = 43,
42         CERTIFICATE_REVOKED                 = 44,
43         CERTIFICATE_EXPIRED                 = 45,
44         CERTIFICATE_UNKNOWN                 = 46,
45         ILLEGAL_PARAMETER                   = 47,
46         UNKNOWN_CA                          = 48,
47         ACCESS_DENIED                       = 49,
48         DECODE_ERROR                        = 50,
49         DECRYPT_ERROR                       = 51,
50         EXPORT_RESTRICTION                  = 60,
51         PROTOCOL_VERSION                    = 70,
52         INSUFFICIENT_SECURITY               = 71,
53         INTERNAL_ERROR                      = 80,
54         INAPPROPRIATE_FALLBACK              = 86,
55         USER_CANCELED                       = 90,
56         NO_RENEGOTIATION                    = 100,
57         UNSUPPORTED_EXTENSION               = 110,
58         CERTIFICATE_UNOBTAINABLE            = 111,
59         UNRECOGNIZED_NAME                   = 112,
60         BAD_CERTIFICATE_STATUS_RESPONSE     = 113,
61         BAD_CERTIFICATE_HASH_VALUE          = 114,
62         UNKNOWN_PSK_IDENTITY                = 115,
63         NO_APPLICATION_PROTOCOL                = 120, // RFC 7301
64 
65         // pseudo alert values
66         NULL_ALERT                          = 256,
67         HEARTBEAT_PAYLOAD                   = 257
68     }
69 
70     /**
71     * Returns: true iff this alert is non-empty
72     */
73     bool isValid() const { return (m_type_code != NULL_ALERT); }
74 
75     /**
76     * Returns: if this alert is a fatal one or not
77     */
78     bool isFatal() const { return m_fatal; }
79 
80     /**
81     * Returns: type of alert
82     */
83     TLSAlertType type() const { return m_type_code; }
84 
85     /**
86     * Returns: type of alert
87     */
88     string typeString() const
89     {
90         final switch(type())
91         {
92             case CLOSE_NOTIFY:
93                 return "close_notify";
94             case UNEXPECTED_MESSAGE:
95                 return "unexpected_message";
96             case BAD_RECORD_MAC:
97                 return "bad_record_mac";
98             case DECRYPTION_FAILED:
99                 return "decryption_failed";
100             case RECORD_OVERFLOW:
101                 return "record_overflow";
102             case DECOMPRESSION_FAILURE:
103                 return "decompression_failure";
104             case HANDSHAKE_FAILURE:
105                 return "handshake_failure";
106             case NO_CERTIFICATE:
107                 return "no_certificate";
108             case BAD_CERTIFICATE:
109                 return "bad_certificate";
110             case UNSUPPORTED_CERTIFICATE:
111                 return "unsupported_certificate";
112             case CERTIFICATE_REVOKED:
113                 return "certificate_revoked";
114             case CERTIFICATE_EXPIRED:
115                 return "certificate_expired";
116             case CERTIFICATE_UNKNOWN:
117                 return "certificate_unknown";
118             case ILLEGAL_PARAMETER:
119                 return "illegal_parameter";
120             case UNKNOWN_CA:
121                 return "unknown_ca";
122             case ACCESS_DENIED:
123                 return "access_denied";
124             case DECODE_ERROR:
125                 return "decode_error";
126             case DECRYPT_ERROR:
127                 return "decrypt_error";
128             case EXPORT_RESTRICTION:
129                 return "export_restriction";
130             case PROTOCOL_VERSION:
131                 return "protocol_version";
132             case INSUFFICIENT_SECURITY:
133                 return "insufficient_security";
134             case INTERNAL_ERROR:
135                 return "internal_error";
136             case INAPPROPRIATE_FALLBACK:
137                 return "inappropriate_fallback";
138             case USER_CANCELED:
139                 return "user_canceled";
140             case NO_RENEGOTIATION:
141                 return "no_renegotiation";
142                 
143             case UNSUPPORTED_EXTENSION:
144                 return "unsupported_extension";
145             case CERTIFICATE_UNOBTAINABLE:
146                 return "certificate_unobtainable";
147             case UNRECOGNIZED_NAME:
148                 return "unrecognized_name";
149             case BAD_CERTIFICATE_STATUS_RESPONSE:
150                 return "bad_certificate_status_response";
151             case BAD_CERTIFICATE_HASH_VALUE:
152                 return "bad_certificate_hash_value";
153             case UNKNOWN_PSK_IDENTITY:
154                 return "unknown_psk_identity";
155             case NO_APPLICATION_PROTOCOL:
156                 return "no_application_protocol";
157             case NULL_ALERT:
158                 return "none";
159                 
160             case HEARTBEAT_PAYLOAD:
161                 return "heartbeat_payload";
162         }
163 
164     }
165 
166     /**
167     * Serialize an alert
168     */
169     Vector!ubyte serialize() const
170     {
171         return Vector!ubyte([
172             cast(ubyte)(isFatal() ? 2 : 1),
173             cast(ubyte)(type())
174         ]);
175     }
176 
177     /**
178     * Deserialize an TLSAlert message
179     * Params:
180     *  buf = the serialized alert
181     */
182     this(const ref SecureVector!ubyte buf)
183     {
184         if (buf.length != 2)
185             throw new DecodingError("TLSAlert: Bad size " ~ to!string(buf.length) ~ " for alert message");
186         
187         if (buf[0] == 1)          m_fatal = false;
188         else if (buf[0] == 2)     m_fatal = true;
189         else
190             throw new DecodingError("TLSAlert: Bad code for alert level");
191         
192         const ubyte dc = buf[1];
193         
194         m_type_code = cast(TLSAlertType)(dc);
195     }
196 
197     /**
198     * Create a new TLSAlert
199     * Params:
200     *  type_code = the type of alert
201     *  fatal = specifies if this is a fatal alert
202     */
203     this(TLSAlertType type_code = NULL_ALERT, bool fatal = false)
204     {
205         m_fatal = fatal;
206         m_type_code = type_code;
207     }
208 
209 private:
210     bool m_fatal;
211     TLSAlertType m_type_code;
212 }