2 * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * sslAlertMessage.c - SSL3 Alert protocol
29 #include "sslAlertMessage.h"
30 #include "sslMemory.h"
31 #include "sslContext.h"
32 #include "sslSession.h"
39 #define SSLLogAlertMsg(msg,sent)
41 static void SSLLogAlertMsg(AlertDescription msg
, bool sent
);
44 static OSStatus
SSLEncodeAlert(
47 AlertDescription desc
,
51 * If a peer sends us any kind of a bad cert alert, we may need to adjust
52 * ctx->clientCertState accordingly.
55 SSLDetectCertRejected(
57 AlertDescription desc
)
59 if(ctx
->protocolSide
== kSSLServerSide
) {
62 if(ctx
->clientCertState
!= kSSLClientCertSent
) {
66 case SSL_AlertBadCert
:
67 case SSL_AlertUnsupportedCert
:
68 case SSL_AlertCertRevoked
:
69 case SSL_AlertCertExpired
:
70 case SSL_AlertCertUnknown
:
71 case SSL_AlertUnknownCA
:
72 ctx
->clientCertState
= kSSLClientCertRejected
;
80 SSLProcessAlert(SSLRecord rec
, SSLContext
*ctx
)
81 { OSStatus err
= noErr
;
83 AlertDescription desc
;
87 if (rec
.contents
.length
% 2 != 0)
89 err
= SSLFatalSessionAlert(SSL_AlertIllegalParam
, ctx
);
96 charPtr
= rec
.contents
.data
;
97 remaining
= rec
.contents
.length
;
100 while (remaining
> 0)
101 { level
= (AlertLevel
)*charPtr
++;
102 desc
= (AlertDescription
)*charPtr
++;
103 sslHdskMsgDebug("alert msg received level %d desc %d",
104 (int)level
, (int)desc
);
106 SSLLogAlertMsg(desc
, false);
108 if (level
== SSL_AlertLevelFatal
) {
109 /* explicit fatal errror */
111 sslHdskMsgDebug("***Fatal alert %d received\n", desc
);
113 SSLDetectCertRejected(ctx
, desc
);
116 /* A number of these are fatal by implication */
117 case SSL_AlertUnexpectedMsg
:
118 err
= errSSLPeerUnexpectedMsg
;
121 case SSL_AlertBadRecordMac
:
122 err
= errSSLPeerBadRecordMac
;
125 case SSL_AlertDecryptionFail_RESERVED
:
126 err
= errSSLPeerDecryptionFail
;
129 case SSL_AlertRecordOverflow
:
130 err
= errSSLPeerRecordOverflow
;
133 case SSL_AlertDecompressFail
:
134 err
= errSSLPeerDecompressFail
;
137 case SSL_AlertHandshakeFail
:
138 err
= errSSLPeerHandshakeFail
;
141 case SSL_AlertIllegalParam
:
142 err
= errSSLIllegalParam
;
145 case SSL_AlertBadCert
:
146 err
= errSSLPeerBadCert
;
148 case SSL_AlertUnsupportedCert
:
149 err
= errSSLPeerUnsupportedCert
;
151 case SSL_AlertCertRevoked
:
152 err
= errSSLPeerCertRevoked
;
154 case SSL_AlertCertExpired
:
155 err
= errSSLPeerCertExpired
;
157 case SSL_AlertCertUnknown
:
158 err
= errSSLPeerCertUnknown
;
160 case SSL_AlertUnknownCA
:
161 err
= errSSLPeerUnknownCA
;
163 case SSL_AlertAccessDenied
:
164 err
= errSSLPeerAccessDenied
;
166 case SSL_AlertDecodeError
:
167 err
= errSSLPeerDecodeError
;
169 case SSL_AlertDecryptError
:
170 err
= errSSLPeerDecryptError
;
172 case SSL_AlertExportRestriction_RESERVED
:
173 err
= errSSLPeerExportRestriction
;
175 case SSL_AlertProtocolVersion
:
176 err
= errSSLPeerProtocolVersion
;
178 case SSL_AlertInsufficientSecurity
:
179 err
= errSSLPeerInsufficientSecurity
;
181 case SSL_AlertInternalError
:
182 err
= errSSLPeerInternalError
;
184 case SSL_AlertUserCancelled
:
185 err
= errSSLPeerUserCancelled
;
187 case SSL_AlertNoRenegotiation
:
188 err
= errSSLPeerNoRenegotiation
;
190 /* unusual cases.... */
191 case SSL_AlertCloseNotify
:
192 /* the clean "we're done" case */
196 case SSL_AlertNoCert_RESERVED
:
197 if((ctx
->state
== SSL_HdskStateClientCert
) &&
198 (ctx
->protocolSide
== kSSLServerSide
) &&
199 (ctx
->clientAuth
!= kAlwaysAuthenticate
)) {
201 * Tolerate this unless we're configured to
202 * *require* a client cert. If a client cert is
203 * required, we'll catch the error at the next
204 * handshake msg we receive - which will probably
205 * be a client key exchange msg, which is illegal
206 * when we're in state SSL_HdskStateClientCert.
207 * If the client cert is optional, advance to
208 * state ClientKeyExchange by pretending we
209 * just got a client cert msg.
211 if ((err
= SSLAdvanceHandshake(SSL_HdskCert
,
217 case SSL_AlertUnsupportedExtension
:
218 err
= errSSLFatalAlert
;
223 /* Unknown alert, ignore if not fatal */
224 if(level
== SSL_AlertLevelFatal
) {
225 err
= errSSLFatalAlert
;
233 /* don't bother processing any more */
238 SSLDeleteSessionData(ctx
);
244 SSLSendAlert(AlertLevel level
, AlertDescription desc
, SSLContext
*ctx
)
248 switch(ctx
->negProtocolVersion
) {
249 case SSL_Version_Undetermined
:
250 /* Too early in negotiation to send an alert */
252 case SSL_Version_2_0
:
253 /* shouldn't be here */
255 return errSSLInternal
;
259 if(ctx
->sentFatalAlert
) {
260 /* no more alerts allowed */
263 if ((err
= SSLEncodeAlert(&rec
, level
, desc
, ctx
)) != 0)
265 assert(ctx
->sslTslCalls
!= NULL
);
266 SSLLogAlertMsg(desc
, true);
267 if ((err
= ctx
->sslTslCalls
->writeRecord(rec
, ctx
)) != 0)
269 if ((err
= SSLFreeBuffer(&rec
.contents
, ctx
)) != 0)
271 if(desc
== SSL_AlertCloseNotify
) {
272 /* no more alerts allowed */
273 ctx
->sentFatalAlert
= true;
279 SSLEncodeAlert(SSLRecord
*rec
, AlertLevel level
, AlertDescription desc
, SSLContext
*ctx
)
282 rec
->protocolVersion
= ctx
->negProtocolVersion
;
283 rec
->contentType
= SSL_RecordTypeAlert
;
284 rec
->contents
.length
= 2;
285 if ((err
= SSLAllocBuffer(&rec
->contents
, 2, ctx
)) != 0)
287 rec
->contents
.data
[0] = level
;
288 rec
->contents
.data
[1] = desc
;
294 SSLFatalSessionAlert(AlertDescription desc
, SSLContext
*ctx
)
295 { OSStatus err1
, err2
;
297 if(desc
!= SSL_AlertCloseNotify
) {
298 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc
);
300 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
302 if(ctx
->negProtocolVersion
< TLS_Version_1_0
) {
303 /* translate to SSL3 if necessary */
305 //case SSL_AlertDecryptionFail_RESERVED:
306 case SSL_AlertRecordOverflow
:
307 case SSL_AlertAccessDenied
:
308 case SSL_AlertDecodeError
:
309 case SSL_AlertDecryptError
:
310 //case SSL_AlertExportRestriction_RESERVED:
311 case SSL_AlertProtocolVersion
:
312 case SSL_AlertInsufficientSecurity
:
313 case SSL_AlertUserCancelled
:
314 case SSL_AlertNoRenegotiation
:
315 desc
= SSL_AlertHandshakeFail
;
317 case SSL_AlertUnknownCA
:
318 desc
= SSL_AlertUnsupportedCert
;
320 case SSL_AlertInternalError
:
321 desc
= SSL_AlertCloseNotify
;
328 /* Make session unresumable; I'm not stopping if I get an error,
329 because I'd like to attempt to send the alert anyway */
330 err1
= SSLDeleteSessionData(ctx
);
332 /* Second, send the alert */
333 err2
= SSLSendAlert(SSL_AlertLevelFatal
, desc
, ctx
);
335 ctx
->sentFatalAlert
= true;
337 /* If they both returned errors, arbitrarily return the first */
338 return err1
!= 0 ? err1
: err2
;
343 /* log alert messages */
345 static char *alertMsgToStr(AlertDescription msg
)
347 static char badStr
[100];
350 case SSL_AlertCloseNotify
:
351 return "SSL_AlertCloseNotify";
352 case SSL_AlertUnexpectedMsg
:
353 return "SSL_AlertUnexpectedMsg";
354 case SSL_AlertBadRecordMac
:
355 return "SSL_AlertBadRecordMac";
356 case SSL_AlertDecryptionFail_RESERVED
:
357 return "SSL_AlertDecryptionFail";
358 case SSL_AlertRecordOverflow
:
359 return "SSL_AlertRecordOverflow";
360 case SSL_AlertDecompressFail
:
361 return "SSL_AlertDecompressFail";
362 case SSL_AlertHandshakeFail
:
363 return "SSL_AlertHandshakeFail";
364 case SSL_AlertNoCert_RESERVED
:
365 return "SSL_AlertNoCert";
366 case SSL_AlertBadCert
:
367 return "SSL_AlertBadCert";
368 case SSL_AlertUnsupportedCert
:
369 return "SSL_AlertUnsupportedCert";
370 case SSL_AlertCertRevoked
:
371 return "SSL_AlertCertRevoked";
373 case SSL_AlertCertExpired
:
374 return "SSL_AlertCertExpired";
375 case SSL_AlertCertUnknown
:
376 return "SSL_AlertCertUnknown";
377 case SSL_AlertIllegalParam
:
378 return "SSL_AlertIllegalParam";
379 case SSL_AlertUnknownCA
:
380 return "SSL_AlertUnknownCA";
381 case SSL_AlertAccessDenied
:
382 return "SSL_AlertAccessDenied";
383 case SSL_AlertDecodeError
:
384 return "SSL_AlertDecodeError";
385 case SSL_AlertDecryptError
:
386 return "SSL_AlertDecryptError";
388 case SSL_AlertExportRestriction_RESERVED
:
389 return "SSL_AlertExportRestriction";
390 case SSL_AlertProtocolVersion
:
391 return "SSL_AlertProtocolVersion";
392 case SSL_AlertInsufficientSecurity
:
393 return "SSL_AlertInsufficientSecurity";
394 case SSL_AlertInternalError
:
395 return "SSL_AlertInternalError";
396 case SSL_AlertUserCancelled
:
397 return "SSL_AlertUserCancelled";
398 case SSL_AlertNoRenegotiation
:
399 return "SSL_AlertNoRenegotiation";
402 sprintf(badStr
, "Unknown state (%d(d)", msg
);
407 static void SSLLogAlertMsg(AlertDescription msg
, bool sent
)
409 sslHdskMsgDebug("---%s alert msg %s",
410 alertMsgToStr(msg
), (sent
? "sent" : "recv"));