2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
19 /* *********************************************************************
20 File: sslAlertMessage.cpp - SSL3 Alert protocol
21 ****************************************************************** */
24 #include "sslAlertMessage.h"
25 #include "sslMemory.h"
26 #include "sslContext.h"
27 #include "sslSession.h"
34 #define SSLLogAlertMsg(msg,sent)
36 static void SSLLogAlertMsg(AlertDescription msg
, bool sent
);
39 static OSStatus
SSLEncodeAlert(
42 AlertDescription desc
,
46 * If a peer sends us any kind of a bad cert alert, we may need to adjust
47 * ctx->clientCertState accordingly.
50 SSLDetectCertRejected(
52 AlertDescription desc
)
54 if(ctx
->protocolSide
== SSL_ServerSide
) {
57 if(ctx
->clientCertState
!= kSSLClientCertSent
) {
61 case SSL_AlertBadCert
:
62 case SSL_AlertUnsupportedCert
:
63 case SSL_AlertCertRevoked
:
64 case SSL_AlertCertExpired
:
65 case SSL_AlertCertUnknown
:
66 case SSL_AlertUnknownCA
:
67 ctx
->clientCertState
= kSSLClientCertRejected
;
75 SSLProcessAlert(SSLRecord rec
, SSLContext
*ctx
)
76 { OSStatus err
= noErr
;
78 AlertDescription desc
;
82 if (rec
.contents
.length
% 2 != 0)
84 err
= SSLFatalSessionAlert(SSL_AlertIllegalParam
, ctx
);
91 charPtr
= rec
.contents
.data
;
92 remaining
= rec
.contents
.length
;
96 { level
= (AlertLevel
)*charPtr
++;
97 desc
= (AlertDescription
)*charPtr
++;
98 sslHdskMsgDebug("alert msg recieved level %d desc %d",
99 (int)level
, (int)desc
);
101 SSLLogAlertMsg(desc
, false);
103 if (level
== SSL_AlertLevelFatal
) {
104 /* explicit fatal errror */
106 sslHdskMsgDebug("***Fatal alert %d received\n", desc
);
108 SSLDetectCertRejected(ctx
, desc
);
111 /* A number of these are fatal by implication */
112 case SSL_AlertUnexpectedMsg
:
113 err
= errSSLPeerUnexpectedMsg
;
116 case SSL_AlertBadRecordMac
:
117 err
= errSSLPeerBadRecordMac
;
120 case SSL_AlertDecryptionFail
:
121 err
= errSSLPeerDecryptionFail
;
124 case SSL_AlertRecordOverflow
:
125 err
= errSSLPeerRecordOverflow
;
128 case SSL_AlertDecompressFail
:
129 err
= errSSLPeerDecompressFail
;
132 case SSL_AlertHandshakeFail
:
133 err
= errSSLPeerHandshakeFail
;
136 case SSL_AlertIllegalParam
:
137 err
= errSSLIllegalParam
;
140 case SSL_AlertBadCert
:
141 err
= errSSLPeerBadCert
;
143 case SSL_AlertUnsupportedCert
:
144 err
= errSSLPeerUnsupportedCert
;
146 case SSL_AlertCertRevoked
:
147 err
= errSSLPeerCertRevoked
;
149 case SSL_AlertCertExpired
:
150 err
= errSSLPeerCertExpired
;
152 case SSL_AlertCertUnknown
:
153 err
= errSSLPeerCertUnknown
;
155 case SSL_AlertUnknownCA
:
156 err
= errSSLPeerUnknownCA
;
158 case SSL_AlertAccessDenied
:
159 err
= errSSLPeerAccessDenied
;
161 case SSL_AlertDecodeError
:
162 err
= errSSLPeerDecodeError
;
164 case SSL_AlertDecryptError
:
165 err
= errSSLPeerDecryptError
;
167 case SSL_AlertExportRestriction
:
168 err
= errSSLPeerExportRestriction
;
170 case SSL_AlertProtocolVersion
:
171 err
= errSSLPeerProtocolVersion
;
173 case SSL_AlertInsufficientSecurity
:
174 err
= errSSLPeerInsufficientSecurity
;
176 case SSL_AlertInternalError
:
177 err
= errSSLPeerInternalError
;
179 case SSL_AlertUserCancelled
:
180 err
= errSSLPeerUserCancelled
;
182 case SSL_AlertNoRenegotiation
:
183 err
= errSSLPeerNoRenegotiation
;
185 /* unusual cases.... */
186 case SSL_AlertCloseNotify
:
187 /* the clean "we're done" case */
191 case SSL_AlertNoCert
:
192 if((ctx
->state
== SSL_HdskStateClientCert
) &&
193 (ctx
->protocolSide
== SSL_ServerSide
) &&
194 (ctx
->clientAuth
!= kAlwaysAuthenticate
)) {
196 * Tolerate this unless we're configured to
197 * *require* a client cert. If a client cert is
198 * required, we'll catch the error at the next
199 * handshake msg we receive - which will probably
200 * be a client key exchange msg, which is illegal
201 * when we're in state SSL_HdskStateClientCert.
202 * If the client cert is optional, advance to
203 * state ClientKeyExchange by pretending we
204 * just got a client cert msg.
206 if ((err
= SSLAdvanceHandshake(SSL_HdskCert
,
213 /* Unknown alert, ignore if not fatal */
214 if(level
== SSL_AlertLevelFatal
) {
215 err
= errSSLFatalAlert
;
223 /* don't bother processing any more */
228 SSLDeleteSessionData(ctx
);
234 SSLSendAlert(AlertLevel level
, AlertDescription desc
, SSLContext
*ctx
)
238 switch(ctx
->negProtocolVersion
) {
239 case SSL_Version_Undetermined
:
240 /* Too early in negotiation to send an alert */
242 case SSL_Version_2_0
:
243 /* shouldn't be here */
245 return errSSLInternal
;
249 if(ctx
->sentFatalAlert
) {
250 /* no more alerts allowed */
253 if ((err
= SSLEncodeAlert(rec
, level
, desc
, ctx
)) != 0)
255 assert(ctx
->sslTslCalls
!= NULL
);
256 SSLLogAlertMsg(desc
, true);
257 if ((err
= ctx
->sslTslCalls
->writeRecord(rec
, ctx
)) != 0)
259 if ((err
= SSLFreeBuffer(rec
.contents
, ctx
)) != 0)
261 if(desc
== SSL_AlertCloseNotify
) {
262 /* no more alerts allowed */
263 ctx
->sentFatalAlert
= true;
269 SSLEncodeAlert(SSLRecord
&rec
, AlertLevel level
, AlertDescription desc
, SSLContext
*ctx
)
272 rec
.protocolVersion
= ctx
->negProtocolVersion
;
273 rec
.contentType
= SSL_RecordTypeAlert
;
274 rec
.contents
.length
= 2;
275 if ((err
= SSLAllocBuffer(rec
.contents
, 2, ctx
)) != 0)
277 rec
.contents
.data
[0] = level
;
278 rec
.contents
.data
[1] = desc
;
284 SSLFatalSessionAlert(AlertDescription desc
, SSLContext
*ctx
)
285 { OSStatus err1
, err2
;
287 if(desc
!= SSL_AlertCloseNotify
) {
288 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc
);
290 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
292 if(ctx
->negProtocolVersion
< TLS_Version_1_0
) {
293 /* translate to SSL3 if necessary */
295 case SSL_AlertDecryptionFail
:
296 case SSL_AlertRecordOverflow
:
297 case SSL_AlertAccessDenied
:
298 case SSL_AlertDecodeError
:
299 case SSL_AlertDecryptError
:
300 case SSL_AlertExportRestriction
:
301 case SSL_AlertProtocolVersion
:
302 case SSL_AlertInsufficientSecurity
:
303 case SSL_AlertUserCancelled
:
304 case SSL_AlertNoRenegotiation
:
305 desc
= SSL_AlertHandshakeFail
;
307 case SSL_AlertUnknownCA
:
308 desc
= SSL_AlertUnsupportedCert
;
310 case SSL_AlertInternalError
:
311 desc
= SSL_AlertCloseNotify
;
318 /* Make session unresumable; I'm not stopping if I get an error,
319 because I'd like to attempt to send the alert anyway */
320 err1
= SSLDeleteSessionData(ctx
);
322 /* Second, send the alert */
323 err2
= SSLSendAlert(SSL_AlertLevelFatal
, desc
, ctx
);
325 ctx
->sentFatalAlert
= true;
327 /* If they both returned errors, arbitrarily return the first */
328 return err1
!= 0 ? err1
: err2
;
333 /* log alert messages */
335 static char *alertMsgToStr(AlertDescription msg
)
337 static char badStr
[100];
340 case SSL_AlertCloseNotify
:
341 return "SSL_AlertCloseNotify";
342 case SSL_AlertUnexpectedMsg
:
343 return "SSL_AlertUnexpectedMsg";
344 case SSL_AlertBadRecordMac
:
345 return "SSL_AlertBadRecordMac";
346 case SSL_AlertDecryptionFail
:
347 return "SSL_AlertDecryptionFail";
348 case SSL_AlertRecordOverflow
:
349 return "SSL_AlertRecordOverflow";
350 case SSL_AlertDecompressFail
:
351 return "SSL_AlertDecompressFail";
352 case SSL_AlertHandshakeFail
:
353 return "SSL_AlertHandshakeFail";
354 case SSL_AlertNoCert
:
355 return "SSL_AlertNoCert";
356 case SSL_AlertBadCert
:
357 return "SSL_AlertBadCert";
358 case SSL_AlertUnsupportedCert
:
359 return "SSL_AlertUnsupportedCert";
360 case SSL_AlertCertRevoked
:
361 return "SSL_AlertCertRevoked";
363 case SSL_AlertCertExpired
:
364 return "SSL_AlertCertExpired";
365 case SSL_AlertCertUnknown
:
366 return "SSL_AlertCertUnknown";
367 case SSL_AlertIllegalParam
:
368 return "SSL_AlertIllegalParam";
369 case SSL_AlertUnknownCA
:
370 return "SSL_AlertUnknownCA";
371 case SSL_AlertAccessDenied
:
372 return "SSL_AlertAccessDenied";
373 case SSL_AlertDecodeError
:
374 return "SSL_AlertDecodeError";
375 case SSL_AlertDecryptError
:
376 return "SSL_AlertDecryptError";
378 case SSL_AlertExportRestriction
:
379 return "SSL_AlertExportRestriction";
380 case SSL_AlertProtocolVersion
:
381 return "SSL_AlertProtocolVersion";
382 case SSL_AlertInsufficientSecurity
:
383 return "SSL_AlertInsufficientSecurity";
384 case SSL_AlertInternalError
:
385 return "SSL_AlertInternalError";
386 case SSL_AlertUserCancelled
:
387 return "SSL_AlertUserCancelled";
388 case SSL_AlertNoRenegotiation
:
389 return "SSL_AlertNoRenegotiation";
392 sprintf(badStr
, "Unknown state (%d(d)", msg
);
397 static void SSLLogAlertMsg(AlertDescription msg
, bool sent
)
399 sslHdskMsgDebug("---%s alert msg %s",
400 alertMsgToStr(msg
), (sent
? "sent" : "recv"));