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 }