sslAlertMessage.c
1 /* 2 * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 /* 25 * sslAlertMessage.c - SSL3 Alert protocol 26 */ 27 28 #include "tls_handshake_priv.h" 29 #include "sslAlertMessage.h" 30 #include "sslHandshake.h" 31 #include "sslHandshake_priv.h" 32 #include "sslMemory.h" 33 #include "sslSession.h" 34 #include "sslDebug.h" 35 #include "sslUtils.h" 36 37 #include <assert.h> 38 39 #if !SSL_DEBUG 40 #define SSLLogAlertMsg(msg,sent) 41 #else 42 static void SSLLogAlertMsg(AlertDescription msg, bool sent); 43 #endif 44 45 static int SSLEncodeAlert( 46 tls_buffer *rec, 47 AlertLevel level, 48 AlertDescription desc, 49 tls_handshake_t ctx); 50 51 /* 52 * If a peer sends us any kind of a bad cert alert, we may need to adjust 53 * ctx->clientCertState accordingly. 54 */ 55 static void 56 SSLDetectCertRejected( 57 tls_handshake_t ctx, 58 AlertDescription desc) 59 { 60 if(ctx->isServer) { 61 return; 62 } 63 if(ctx->clientCertState != kSSLClientCertSent) { 64 return; 65 } 66 switch(desc) { 67 case SSL_AlertBadCert: 68 case SSL_AlertUnsupportedCert: 69 case SSL_AlertCertRevoked: 70 case SSL_AlertCertExpired: 71 case SSL_AlertCertUnknown: 72 case SSL_AlertUnknownCA: 73 ctx->clientCertState = kSSLClientCertRejected; 74 break; 75 default: 76 break; 77 } 78 } 79 80 int 81 SSLProcessAlert(tls_buffer rec, tls_handshake_t ctx) 82 { int err = errSSLSuccess; 83 AlertLevel level; 84 AlertDescription desc; 85 uint8_t *charPtr; 86 size_t remaining; 87 88 if (rec.length % 2 != 0) 89 { 90 err = SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx); 91 if (!err) { 92 err = errSSLProtocol; 93 } 94 return err; 95 } 96 97 charPtr = rec.data; 98 remaining = rec.length; 99 bool fatal = false; 100 101 while (remaining > 0) 102 { level = (AlertLevel)*charPtr++; 103 desc = (AlertDescription)*charPtr++; 104 sslHdskMsgDebug("alert msg received level %d desc %d", 105 (int)level, (int)desc); 106 remaining -= 2; 107 SSLLogAlertMsg(desc, false); 108 109 if (level == SSL_AlertLevelFatal) { 110 /* explicit fatal errror */ 111 fatal = true; 112 sslErrorLog("***Fatal alert %d received\n", desc); 113 } 114 SSLDetectCertRejected(ctx, desc); 115 116 switch (desc) { 117 /* A number of these are fatal by implication */ 118 case SSL_AlertUnexpectedMsg: 119 err = errSSLPeerUnexpectedMsg; 120 fatal = true; 121 break; 122 case SSL_AlertBadRecordMac: 123 err = errSSLPeerBadRecordMac; 124 fatal = true; 125 break; 126 case SSL_AlertDecryptionFail_RESERVED: 127 err = errSSLPeerDecryptionFail; 128 fatal = true; 129 break; 130 case SSL_AlertRecordOverflow: 131 err = errSSLPeerRecordOverflow; 132 fatal = true; 133 break; 134 case SSL_AlertDecompressFail: 135 err = errSSLPeerDecompressFail; 136 fatal = true; 137 break; 138 case SSL_AlertHandshakeFail: 139 err = errSSLPeerHandshakeFail; 140 fatal = true; 141 break; 142 case SSL_AlertIllegalParam: 143 err = errSSLIllegalParam; 144 fatal = true; 145 break; 146 case SSL_AlertBadCert: 147 err = errSSLPeerBadCert; 148 break; 149 case SSL_AlertUnsupportedCert: 150 err = errSSLPeerUnsupportedCert; 151 break; 152 case SSL_AlertCertRevoked: 153 err = errSSLPeerCertRevoked; 154 break; 155 case SSL_AlertCertExpired: 156 err = errSSLPeerCertExpired; 157 break; 158 case SSL_AlertCertUnknown: 159 err = errSSLPeerCertUnknown; 160 break; 161 case SSL_AlertUnknownCA: 162 err = errSSLPeerUnknownCA; 163 break; 164 case SSL_AlertAccessDenied: 165 err = errSSLPeerAccessDenied; 166 break; 167 case SSL_AlertDecodeError: 168 err = errSSLPeerDecodeError; 169 break; 170 case SSL_AlertDecryptError: 171 err = errSSLPeerDecryptError; 172 break; 173 case SSL_AlertExportRestriction_RESERVED: 174 err = errSSLPeerExportRestriction; 175 break; 176 case SSL_AlertProtocolVersion: 177 err = errSSLPeerProtocolVersion; 178 break; 179 case SSL_AlertInsufficientSecurity: 180 err = errSSLPeerInsufficientSecurity; 181 break; 182 case SSL_AlertInternalError: 183 err = errSSLPeerInternalError; 184 break; 185 case SSL_AlertUserCancelled: 186 err = errSSLPeerUserCancelled; 187 break; 188 case SSL_AlertNoRenegotiation: 189 err = errSSLPeerNoRenegotiation; 190 break; 191 /* unusual cases.... */ 192 case SSL_AlertCloseNotify: 193 /* the clean "we're done" case */ 194 tls_handshake_close(ctx); 195 err = errSSLClosedGraceful; 196 break; 197 case SSL_AlertNoCert_RESERVED: 198 if((ctx->state == SSL_HdskStateClientCert) && 199 (ctx->isServer)) { 200 /* 201 * Advance to 202 * state ClientKeyExchange by pretending we 203 * just got an empty client cert msg. 204 */ 205 if ((err = SSLAdvanceHandshake(SSL_HdskCert, 206 ctx)) != 0) { 207 return err; 208 } 209 } 210 break; 211 case SSL_AlertUnsupportedExtension: 212 err = errSSLFatalAlert; 213 fatal = true; 214 break; 215 216 default: 217 /* Unknown alert, ignore if not fatal */ 218 if(level == SSL_AlertLevelFatal) { 219 err = errSSLFatalAlert; 220 } 221 else { 222 err = errSSLSuccess; 223 } 224 break; 225 } 226 if(fatal) { 227 /* don't bother processing any more */ 228 break; 229 } 230 } 231 if(fatal) { 232 SSLDeleteSessionData(ctx); 233 } 234 return err; 235 } 236 237 int 238 SSLSendAlert(AlertLevel level, AlertDescription desc, tls_handshake_t ctx) 239 { 240 tls_buffer rec; 241 int err; 242 243 switch(ctx->negProtocolVersion) { 244 case tls_protocol_version_Undertermined: 245 /* Too early in negotiation to send an alert */ 246 return errSSLSuccess; 247 default: 248 break; 249 } 250 if(ctx->sentFatalAlert) { 251 /* no more alerts allowed */ 252 return errSSLSuccess; 253 } 254 if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0) 255 return err; 256 SSLLogAlertMsg(desc, true); 257 err = ctx->callbacks->write(ctx->callback_ctx, rec, tls_record_type_Alert); 258 SSLFreeBuffer(&rec); 259 if(desc == SSL_AlertCloseNotify) { 260 /* no more alerts allowed */ 261 ctx->sentFatalAlert = true; 262 } 263 return err; 264 } 265 266 static int 267 SSLEncodeAlert(tls_buffer *rec, AlertLevel level, AlertDescription desc, tls_handshake_t ctx) 268 { int err; 269 270 rec->length = 2; 271 if ((err = SSLAllocBuffer(rec, 2))) 272 return err; 273 rec->data[0] = level; 274 rec->data[1] = desc; 275 276 return errSSLSuccess; 277 } 278 279 int 280 SSLFatalSessionAlert(AlertDescription desc, tls_handshake_t ctx) 281 { int err1, err2; 282 283 if(desc != SSL_AlertCloseNotify) { 284 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc); 285 } 286 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); 287 288 if(ctx->negProtocolVersion < tls_protocol_version_TLS_1_0) { 289 /* translate to SSL3 if necessary */ 290 switch(desc) { 291 //case SSL_AlertDecryptionFail_RESERVED: 292 case SSL_AlertRecordOverflow: 293 case SSL_AlertAccessDenied: 294 case SSL_AlertDecodeError: 295 case SSL_AlertDecryptError: 296 //case SSL_AlertExportRestriction_RESERVED: 297 case SSL_AlertProtocolVersion: 298 case SSL_AlertInsufficientSecurity: 299 case SSL_AlertUserCancelled: 300 case SSL_AlertNoRenegotiation: 301 desc = SSL_AlertHandshakeFail; 302 break; 303 case SSL_AlertUnknownCA: 304 desc = SSL_AlertUnsupportedCert; 305 break; 306 case SSL_AlertInternalError: 307 desc = SSL_AlertCloseNotify; 308 break; 309 default: 310 /* send as is */ 311 break; 312 } 313 } 314 /* Make session unresumable; I'm not stopping if I get an error, 315 because I'd like to attempt to send the alert anyway */ 316 err1 = SSLDeleteSessionData(ctx); 317 318 /* Second, send the alert */ 319 err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx); 320 321 ctx->sentFatalAlert = true; 322 323 /* If they both returned errors, arbitrarily return the first */ 324 return err1 != 0 ? err1 : err2; 325 } 326 327 #if SSL_DEBUG 328 329 /* log alert messages */ 330 static char *alertMsgToStr(AlertDescription msg) 331 { 332 static char badStr[100]; 333 334 switch(msg) { 335 case SSL_AlertCloseNotify: 336 return "SSL_AlertCloseNotify"; 337 case SSL_AlertUnexpectedMsg: 338 return "SSL_AlertUnexpectedMsg"; 339 case SSL_AlertBadRecordMac: 340 return "SSL_AlertBadRecordMac"; 341 case SSL_AlertDecryptionFail_RESERVED: 342 return "SSL_AlertDecryptionFail"; 343 case SSL_AlertRecordOverflow: 344 return "SSL_AlertRecordOverflow"; 345 case SSL_AlertDecompressFail: 346 return "SSL_AlertDecompressFail"; 347 case SSL_AlertHandshakeFail: 348 return "SSL_AlertHandshakeFail"; 349 case SSL_AlertNoCert_RESERVED: 350 return "SSL_AlertNoCert"; 351 case SSL_AlertBadCert: 352 return "SSL_AlertBadCert"; 353 case SSL_AlertUnsupportedCert: 354 return "SSL_AlertUnsupportedCert"; 355 case SSL_AlertCertRevoked: 356 return "SSL_AlertCertRevoked"; 357 358 case SSL_AlertCertExpired: 359 return "SSL_AlertCertExpired"; 360 case SSL_AlertCertUnknown: 361 return "SSL_AlertCertUnknown"; 362 case SSL_AlertIllegalParam: 363 return "SSL_AlertIllegalParam"; 364 case SSL_AlertUnknownCA: 365 return "SSL_AlertUnknownCA"; 366 case SSL_AlertAccessDenied: 367 return "SSL_AlertAccessDenied"; 368 case SSL_AlertDecodeError: 369 return "SSL_AlertDecodeError"; 370 case SSL_AlertDecryptError: 371 return "SSL_AlertDecryptError"; 372 373 case SSL_AlertExportRestriction_RESERVED: 374 return "SSL_AlertExportRestriction"; 375 case SSL_AlertProtocolVersion: 376 return "SSL_AlertProtocolVersion"; 377 case SSL_AlertInsufficientSecurity: 378 return "SSL_AlertInsufficientSecurity"; 379 case SSL_AlertInternalError: 380 return "SSL_AlertInternalError"; 381 case SSL_AlertUserCancelled: 382 return "SSL_AlertUserCancelled"; 383 case SSL_AlertNoRenegotiation: 384 return "SSL_AlertNoRenegotiation"; 385 386 default: 387 sprintf(badStr, "Unknown state (%d)", msg); 388 return badStr; 389 } 390 } 391 392 static void SSLLogAlertMsg(AlertDescription msg, bool sent) 393 { 394 sslHdskMsgDebug("---%s alert msg %s", 395 alertMsgToStr(msg), (sent ? "sent" : "recv")); 396 } 397 398 #endif /* SSL_DEBUG */