]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslAlertMessage.cpp
Security-179.tar.gz
[apple/security.git] / SecureTransport / sslAlertMessage.cpp
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"
29 #include "sslUtils.h"
30
31 #include <assert.h>
32
33 #ifdef NDEBUG
34 #define SSLLogAlertMsg(msg,sent)
35 #else
36 static void SSLLogAlertMsg(AlertDescription msg, bool sent);
37 #endif
38
39 static 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 */
49 static void
50 SSLDetectCertRejected(
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
74 OSStatus
75 SSLProcessAlert(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;
93 bool fatal = false;
94
95 while (remaining > 0)
96 { level = (AlertLevel)*charPtr++;
97 desc = (AlertDescription)*charPtr++;
98 sslHdskMsgDebug("alert msg recieved level %d desc %d",
99 (int)level, (int)desc);
100 remaining -= 2;
101 SSLLogAlertMsg(desc, false);
102
103 if (level == SSL_AlertLevelFatal) {
104 /* explicit fatal errror */
105 fatal = true;
106 sslHdskMsgDebug("***Fatal alert %d received\n", desc);
107 }
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;
116 case SSL_AlertBadRecordMac:
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;
128 case SSL_AlertDecompressFail:
129 err = errSSLPeerDecompressFail;
130 fatal = true;
131 break;
132 case SSL_AlertHandshakeFail:
133 err = errSSLPeerHandshakeFail;
134 fatal = true;
135 break;
136 case SSL_AlertIllegalParam:
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;
181 break;
182 case SSL_AlertNoRenegotiation:
183 err = errSSLPeerNoRenegotiation;
184 break;
185 /* unusual cases.... */
186 case SSL_AlertCloseNotify:
187 /* the clean "we're done" case */
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;
212 default:
213 /* Unknown alert, ignore if not fatal */
214 if(level == SSL_AlertLevelFatal) {
215 err = errSSLFatalAlert;
216 }
217 else {
218 err = noErr;
219 }
220 break;
221 }
222 if(fatal) {
223 /* don't bother processing any more */
224 break;
225 }
226 }
227 if(fatal) {
228 SSLDeleteSessionData(ctx);
229 }
230 return err;
231 }
232
233 OSStatus
234 SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
235 { SSLRecord rec;
236 OSStatus err;
237
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 }
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;
261 if(desc == SSL_AlertCloseNotify) {
262 /* no more alerts allowed */
263 ctx->sentFatalAlert = true;
264 }
265 return noErr;
266 }
267
268 static OSStatus
269 SSLEncodeAlert(SSLRecord &rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
270 { OSStatus err;
271
272 rec.protocolVersion = ctx->negProtocolVersion;
273 rec.contentType = SSL_RecordTypeAlert;
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
283 OSStatus
284 SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
285 { OSStatus err1, err2;
286
287 if(desc != SSL_AlertCloseNotify) {
288 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
289 }
290 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
291
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 }
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
325 ctx->sentFatalAlert = true;
326
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
335 static 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
397 static void SSLLogAlertMsg(AlertDescription msg, bool sent)
398 {
399 sslHdskMsgDebug("---%s alert msg %s",
400 alertMsgToStr(msg), (sent ? "sent" : "recv"));
401 }
402
403 #endif /* NDEBUG */