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 * 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         BAD_CERTIFICATE                     = 42,
40         UNSUPPORTED_CERTIFICATE             = 43,
41         CERTIFICATE_REVOKED                 = 44,
42         CERTIFICATE_EXPIRED                 = 45,
43         CERTIFICATE_UNKNOWN                 = 46,
44         ILLEGAL_PARAMETER                   = 47,
45         UNKNOWN_CA                          = 48,
46         ACCESS_DENIED                       = 49,
47         DECODE_ERROR                        = 50,
48         DECRYPT_ERROR                       = 51,
49         EXPORT_RESTRICTION                  = 60,
50         PROTOCOL_VERSION                    = 70,
51         INSUFFICIENT_SECURITY               = 71,
52         INTERNAL_ERROR                      = 80,
53         INAPPROPRIATE_FALLBACK              = 86,
54         USER_CANCELED                       = 90,
55         NO_RENEGOTIATION                    = 100,
56         UNSUPPORTED_EXTENSION               = 110,
57         CERTIFICATE_UNOBTAINABLE            = 111,
58         UNRECOGNIZED_NAME                   = 112,
59         BAD_CERTIFICATE_STATUS_RESPONSE     = 113,
60         BAD_CERTIFICATE_HASH_VALUE          = 114,
61         UNKNOWN_PSK_IDENTITY                = 115,
62         NO_APPLICATION_PROTOCOL                = 120, // RFC 7301
63 
64         // pseudo alert values
65         NULL_ALERT                          = 256,
66         HEARTBEAT_PAYLOAD                   = 257
67     }
68 
69     /**
70     * Returns: true iff this alert is non-empty
71     */
72     bool isValid() const { return (m_type_code != NULL_ALERT); }
73 
74     /**
75     * Returns: if this alert is a fatal one or not
76     */
77     bool isFatal() const { return m_fatal; }
78 
79     /**
80     * Returns: type of alert
81     */
82     TLSAlertType type() const { return m_type_code; }
83 
84     /**
85     * Returns: type of alert
86     */
87     string typeString() const
88     {
89         final switch(type())
90         {
91             case CLOSE_NOTIFY:
92                 return "close_notify";
93             case UNEXPECTED_MESSAGE:
94                 return "unexpected_message";
95             case BAD_RECORD_MAC:
96                 return "bad_record_mac";
97             case DECRYPTION_FAILED:
98                 return "decryption_failed";
99             case RECORD_OVERFLOW:
100                 return "record_overflow";
101             case DECOMPRESSION_FAILURE:
102                 return "decompression_failure";
103             case HANDSHAKE_FAILURE:
104                 return "handshake_failure";
105             case BAD_CERTIFICATE:
106                 return "bad_certificate";
107             case UNSUPPORTED_CERTIFICATE:
108                 return "unsupported_certificate";
109             case CERTIFICATE_REVOKED:
110                 return "certificate_revoked";
111             case CERTIFICATE_EXPIRED:
112                 return "certificate_expired";
113             case CERTIFICATE_UNKNOWN:
114                 return "certificate_unknown";
115             case ILLEGAL_PARAMETER:
116                 return "illegal_parameter";
117             case UNKNOWN_CA:
118                 return "unknown_ca";
119             case ACCESS_DENIED:
120                 return "access_denied";
121             case DECODE_ERROR:
122                 return "decode_error";
123             case DECRYPT_ERROR:
124                 return "decrypt_error";
125             case EXPORT_RESTRICTION:
126                 return "export_restriction";
127             case PROTOCOL_VERSION:
128                 return "protocol_version";
129             case INSUFFICIENT_SECURITY:
130                 return "insufficient_security";
131             case INTERNAL_ERROR:
132                 return "internal_error";
133             case INAPPROPRIATE_FALLBACK:
134                 return "inappropriate_fallback";
135             case USER_CANCELED:
136                 return "user_canceled";
137             case NO_RENEGOTIATION:
138                 return "no_renegotiation";
139                 
140             case UNSUPPORTED_EXTENSION:
141                 return "unsupported_extension";
142             case CERTIFICATE_UNOBTAINABLE:
143                 return "certificate_unobtainable";
144             case UNRECOGNIZED_NAME:
145                 return "unrecognized_name";
146             case BAD_CERTIFICATE_STATUS_RESPONSE:
147                 return "bad_certificate_status_response";
148             case BAD_CERTIFICATE_HASH_VALUE:
149                 return "bad_certificate_hash_value";
150             case UNKNOWN_PSK_IDENTITY:
151                 return "unknown_psk_identity";
152             case NO_APPLICATION_PROTOCOL:
153                 return "no_application_protocol";
154             case NULL_ALERT:
155                 return "none";
156                 
157             case HEARTBEAT_PAYLOAD:
158                 return "heartbeat_payload";
159         }
160 
161     }
162 
163     /**
164     * Serialize an alert
165     */
166     Vector!ubyte serialize() const
167     {
168         return Vector!ubyte([
169             cast(ubyte)(isFatal() ? 2 : 1),
170             cast(ubyte)(type())
171         ]);
172     }
173 
174     /**
175     * Deserialize an TLSAlert message
176     * Params:
177     *  buf = the serialized alert
178     */
179     this(const ref SecureVector!ubyte buf)
180     {
181         if (buf.length != 2)
182             throw new DecodingError("TLSAlert: Bad size " ~ to!string(buf.length) ~ " for alert message");
183         
184         if (buf[0] == 1)          m_fatal = false;
185         else if (buf[0] == 2)     m_fatal = true;
186         else
187             throw new DecodingError("TLSAlert: Bad code for alert level");
188         
189         const ubyte dc = buf[1];
190         
191         m_type_code = cast(TLSAlertType)(dc);
192     }
193 
194     /**
195     * Create a new TLSAlert
196     * Params:
197     *  type_code = the type of alert
198     *  fatal = specifies if this is a fatal alert
199     */
200     this(TLSAlertType type_code, bool fatal = false)
201     {
202         m_fatal = fatal;
203         m_type_code = type_code;
204     }
205 
206 private:
207     bool m_fatal;
208     TLSAlertType m_type_code;
209 }