]> git.saurik.com Git - apple/security.git/blame - SecureTransport/sslAlertMessage.cpp
Security-176.tar.gz
[apple/security.git] / SecureTransport / sslAlertMessage.cpp
CommitLineData
5a719ac8
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19/* *********************************************************************
20 File: sslAlertMessage.cpp - SSL3 Alert protocol
21 ****************************************************************** */
22
23#include "ssl.h"
24#include "sslAlertMessage.h"
25#include "sslMemory.h"
26#include "sslContext.h"
27#include "sslSession.h"
28#include "sslDebug.h"
df0e469f 29#include "sslUtils.h"
5a719ac8
A
30
31#include <assert.h>
32
33#ifdef NDEBUG
34#define SSLLogAlertMsg(msg,sent)
35#else
36static void SSLLogAlertMsg(AlertDescription msg, bool sent);
37#endif
38
df0e469f
A
39static OSStatus SSLEncodeAlert(
40 SSLRecord &rec,
41 AlertLevel level,
42 AlertDescription desc,
43 SSLContext *ctx);
44
45/*
46 * If a peer sends us any kind of a bad cert alert, we may need to adjust
47 * ctx->clientCertState accordingly.
48 */
49static void
50SSLDetectCertRejected(
51 SSLContext *ctx,
52 AlertDescription desc)
53{
54 if(ctx->protocolSide == SSL_ServerSide) {
55 return;
56 }
57 if(ctx->clientCertState != kSSLClientCertSent) {
58 return;
59 }
60 switch(desc) {
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;
68 break;
69 default:
70 break;
71 }
72}
73
5a719ac8
A
74OSStatus
75SSLProcessAlert(SSLRecord rec, SSLContext *ctx)
76{ OSStatus err = noErr;
77 AlertLevel level;
78 AlertDescription desc;
79 uint8 *charPtr;
80 uint32 remaining;
81
82 if (rec.contents.length % 2 != 0)
83 {
84 err = SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx);
85 if (!err) {
86 err = errSSLProtocol;
87 }
88 return err;
89 }
90
91 charPtr = rec.contents.data;
92 remaining = rec.contents.length;
df0e469f
A
93 bool fatal = false;
94
5a719ac8
A
95 while (remaining > 0)
96 { level = (AlertLevel)*charPtr++;
97 desc = (AlertDescription)*charPtr++;
df0e469f 98 sslHdskMsgDebug("alert msg recieved level %d desc %d",
5a719ac8
A
99 (int)level, (int)desc);
100 remaining -= 2;
101 SSLLogAlertMsg(desc, false);
102
df0e469f
A
103 if (level == SSL_AlertLevelFatal) {
104 /* explicit fatal errror */
105 fatal = true;
106 sslHdskMsgDebug("***Fatal alert %d received\n", desc);
5a719ac8 107 }
df0e469f
A
108 SSLDetectCertRejected(ctx, desc);
109
110 switch (desc) {
111 /* A number of these are fatal by implication */
112 case SSL_AlertUnexpectedMsg:
113 err = errSSLPeerUnexpectedMsg;
114 fatal = true;
115 break;
5a719ac8 116 case SSL_AlertBadRecordMac:
df0e469f
A
117 err = errSSLPeerBadRecordMac;
118 fatal = true;
119 break;
120 case SSL_AlertDecryptionFail:
121 err = errSSLPeerDecryptionFail;
122 fatal = true;
123 break;
124 case SSL_AlertRecordOverflow:
125 err = errSSLPeerRecordOverflow;
126 fatal = true;
127 break;
5a719ac8 128 case SSL_AlertDecompressFail:
df0e469f
A
129 err = errSSLPeerDecompressFail;
130 fatal = true;
131 break;
5a719ac8 132 case SSL_AlertHandshakeFail:
df0e469f
A
133 err = errSSLPeerHandshakeFail;
134 fatal = true;
135 break;
5a719ac8 136 case SSL_AlertIllegalParam:
df0e469f
A
137 err = errSSLIllegalParam;
138 fatal = true;
139 break;
140 case SSL_AlertBadCert:
141 err = errSSLPeerBadCert;
142 break;
143 case SSL_AlertUnsupportedCert:
144 err = errSSLPeerUnsupportedCert;
145 break;
146 case SSL_AlertCertRevoked:
147 err = errSSLPeerCertRevoked;
148 break;
149 case SSL_AlertCertExpired:
150 err = errSSLPeerCertExpired;
151 break;
152 case SSL_AlertCertUnknown:
153 err = errSSLPeerCertUnknown;
154 break;
155 case SSL_AlertUnknownCA:
156 err = errSSLPeerUnknownCA;
157 break;
158 case SSL_AlertAccessDenied:
159 err = errSSLPeerAccessDenied;
160 break;
161 case SSL_AlertDecodeError:
162 err = errSSLPeerDecodeError;
163 break;
164 case SSL_AlertDecryptError:
165 err = errSSLPeerDecryptError;
166 break;
167 case SSL_AlertExportRestriction:
168 err = errSSLPeerExportRestriction;
169 break;
170 case SSL_AlertProtocolVersion:
171 err = errSSLPeerProtocolVersion;
172 break;
173 case SSL_AlertInsufficientSecurity:
174 err = errSSLPeerInsufficientSecurity;
175 break;
176 case SSL_AlertInternalError:
177 err = errSSLPeerInternalError;
178 break;
179 case SSL_AlertUserCancelled:
180 err = errSSLPeerUserCancelled;
5a719ac8 181 break;
df0e469f
A
182 case SSL_AlertNoRenegotiation:
183 err = errSSLPeerNoRenegotiation;
184 break;
185 /* unusual cases.... */
5a719ac8 186 case SSL_AlertCloseNotify:
df0e469f 187 /* the clean "we're done" case */
5a719ac8
A
188 SSLClose(ctx);
189 err = noErr;
190 break;
191 case SSL_AlertNoCert:
192 if((ctx->state == SSL_HdskStateClientCert) &&
193 (ctx->protocolSide == SSL_ServerSide) &&
194 (ctx->clientAuth != kAlwaysAuthenticate)) {
195 /*
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.
205 */
206 if ((err = SSLAdvanceHandshake(SSL_HdskCert,
207 ctx)) != 0) {
208 return err;
209 }
210 }
211 break;
5a719ac8 212 default:
df0e469f
A
213 /* Unknown alert, ignore if not fatal */
214 if(level == SSL_AlertLevelFatal) {
215 err = errSSLFatalAlert;
216 }
217 else {
218 err = noErr;
219 }
5a719ac8
A
220 break;
221 }
df0e469f
A
222 if(fatal) {
223 /* don't bother processing any more */
224 break;
225 }
5a719ac8 226 }
df0e469f
A
227 if(fatal) {
228 SSLDeleteSessionData(ctx);
229 }
5a719ac8
A
230 return err;
231}
232
233OSStatus
234SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
235{ SSLRecord rec;
236 OSStatus err;
237
df0e469f
A
238 switch(ctx->negProtocolVersion) {
239 case SSL_Version_Undetermined:
240 /* Too early in negotiation to send an alert */
241 return noErr;
242 case SSL_Version_2_0:
243 /* shouldn't be here */
244 assert(0);
245 return errSSLInternal;
246 default:
247 break;
248 }
249 if(ctx->sentFatalAlert) {
250 /* no more alerts allowed */
251 return noErr;
252 }
5a719ac8
A
253 if ((err = SSLEncodeAlert(rec, level, desc, ctx)) != 0)
254 return err;
255 assert(ctx->sslTslCalls != NULL);
256 SSLLogAlertMsg(desc, true);
257 if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
258 return err;
259 if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0)
260 return err;
df0e469f
A
261 if(desc == SSL_AlertCloseNotify) {
262 /* no more alerts allowed */
263 ctx->sentFatalAlert = true;
264 }
5a719ac8
A
265 return noErr;
266}
267
df0e469f 268static OSStatus
5a719ac8
A
269SSLEncodeAlert(SSLRecord &rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
270{ OSStatus err;
271
df0e469f
A
272 rec.protocolVersion = ctx->negProtocolVersion;
273 rec.contentType = SSL_RecordTypeAlert;
5a719ac8
A
274 rec.contents.length = 2;
275 if ((err = SSLAllocBuffer(rec.contents, 2, ctx)) != 0)
276 return err;
277 rec.contents.data[0] = level;
278 rec.contents.data[1] = desc;
279
280 return noErr;
281}
282
283OSStatus
284SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
285{ OSStatus err1, err2;
286
287 if(desc != SSL_AlertCloseNotify) {
df0e469f 288 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
5a719ac8
A
289 }
290 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
291
df0e469f
A
292 if(ctx->negProtocolVersion < TLS_Version_1_0) {
293 /* translate to SSL3 if necessary */
294 switch(desc) {
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;
306 break;
307 case SSL_AlertUnknownCA:
308 desc = SSL_AlertUnsupportedCert;
309 break;
310 case SSL_AlertInternalError:
311 desc = SSL_AlertCloseNotify;
312 break;
313 default:
314 /* send as is */
315 break;
316 }
317 }
5a719ac8
A
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);
321
322 /* Second, send the alert */
323 err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);
324
df0e469f
A
325 ctx->sentFatalAlert = true;
326
5a719ac8
A
327 /* If they both returned errors, arbitrarily return the first */
328 return err1 != 0 ? err1 : err2;
329}
330
331#ifndef NDEBUG
332
333/* log alert messages */
334
335static char *alertMsgToStr(AlertDescription msg)
336{
337 static char badStr[100];
338
339 switch(msg) {
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";
362
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";
377
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";
390
391 default:
392 sprintf(badStr, "Unknown state (%d(d)", msg);
393 return badStr;
394 }
395}
396
397static void SSLLogAlertMsg(AlertDescription msg, bool sent)
398{
399 sslHdskMsgDebug("---%s alert msg %s",
400 alertMsgToStr(msg), (sent ? "sent" : "recv"));
401}
402
403#endif /* NDEBUG */