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 }