]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/sslAlertMessage.c
Security-55179.1.tar.gz
[apple/security.git] / libsecurity_ssl / lib / 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 "ssl.h"
29 #include "sslAlertMessage.h"
30 #include "sslMemory.h"
31 #include "sslContext.h"
32 #include "sslSession.h"
33 #include "sslDebug.h"
34 #include "sslUtils.h"
35
36 #include <assert.h>
37
38 #ifdef NDEBUG
39 #define SSLLogAlertMsg(msg,sent)
40 #else
41 static void SSLLogAlertMsg(AlertDescription msg, bool sent);
42 #endif
43
44 static OSStatus SSLEncodeAlert(
45 SSLRecord *rec,
46 AlertLevel level,
47 AlertDescription desc,
48 SSLContext *ctx);
49
50 /*
51 * If a peer sends us any kind of a bad cert alert, we may need to adjust
52 * ctx->clientCertState accordingly.
53 */
54 static void
55 SSLDetectCertRejected(
56 SSLContext *ctx,
57 AlertDescription desc)
58 {
59 if(ctx->protocolSide == kSSLServerSide) {
60 return;
61 }
62 if(ctx->clientCertState != kSSLClientCertSent) {
63 return;
64 }
65 switch(desc) {
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;
73 break;
74 default:
75 break;
76 }
77 }
78
79 OSStatus
80 SSLProcessAlert(SSLRecord rec, SSLContext *ctx)
81 { OSStatus err = noErr;
82 AlertLevel level;
83 AlertDescription desc;
84 uint8_t *charPtr;
85 size_t remaining;
86
87 if (rec.contents.length % 2 != 0)
88 {
89 err = SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx);
90 if (!err) {
91 err = errSSLProtocol;
92 }
93 return err;
94 }
95
96 charPtr = rec.contents.data;
97 remaining = rec.contents.length;
98 bool fatal = false;
99
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);
105 remaining -= 2;
106 SSLLogAlertMsg(desc, false);
107
108 if (level == SSL_AlertLevelFatal) {
109 /* explicit fatal errror */
110 fatal = true;
111 sslHdskMsgDebug("***Fatal alert %d received\n", desc);
112 }
113 SSLDetectCertRejected(ctx, desc);
114
115 switch (desc) {
116 /* A number of these are fatal by implication */
117 case SSL_AlertUnexpectedMsg:
118 err = errSSLPeerUnexpectedMsg;
119 fatal = true;
120 break;
121 case SSL_AlertBadRecordMac:
122 err = errSSLPeerBadRecordMac;
123 fatal = true;
124 break;
125 case SSL_AlertDecryptionFail_RESERVED:
126 err = errSSLPeerDecryptionFail;
127 fatal = true;
128 break;
129 case SSL_AlertRecordOverflow:
130 err = errSSLPeerRecordOverflow;
131 fatal = true;
132 break;
133 case SSL_AlertDecompressFail:
134 err = errSSLPeerDecompressFail;
135 fatal = true;
136 break;
137 case SSL_AlertHandshakeFail:
138 err = errSSLPeerHandshakeFail;
139 fatal = true;
140 break;
141 case SSL_AlertIllegalParam:
142 err = errSSLIllegalParam;
143 fatal = true;
144 break;
145 case SSL_AlertBadCert:
146 err = errSSLPeerBadCert;
147 break;
148 case SSL_AlertUnsupportedCert:
149 err = errSSLPeerUnsupportedCert;
150 break;
151 case SSL_AlertCertRevoked:
152 err = errSSLPeerCertRevoked;
153 break;
154 case SSL_AlertCertExpired:
155 err = errSSLPeerCertExpired;
156 break;
157 case SSL_AlertCertUnknown:
158 err = errSSLPeerCertUnknown;
159 break;
160 case SSL_AlertUnknownCA:
161 err = errSSLPeerUnknownCA;
162 break;
163 case SSL_AlertAccessDenied:
164 err = errSSLPeerAccessDenied;
165 break;
166 case SSL_AlertDecodeError:
167 err = errSSLPeerDecodeError;
168 break;
169 case SSL_AlertDecryptError:
170 err = errSSLPeerDecryptError;
171 break;
172 case SSL_AlertExportRestriction_RESERVED:
173 err = errSSLPeerExportRestriction;
174 break;
175 case SSL_AlertProtocolVersion:
176 err = errSSLPeerProtocolVersion;
177 break;
178 case SSL_AlertInsufficientSecurity:
179 err = errSSLPeerInsufficientSecurity;
180 break;
181 case SSL_AlertInternalError:
182 err = errSSLPeerInternalError;
183 break;
184 case SSL_AlertUserCancelled:
185 err = errSSLPeerUserCancelled;
186 break;
187 case SSL_AlertNoRenegotiation:
188 err = errSSLPeerNoRenegotiation;
189 break;
190 /* unusual cases.... */
191 case SSL_AlertCloseNotify:
192 /* the clean "we're done" case */
193 SSLClose(ctx);
194 err = noErr;
195 break;
196 case SSL_AlertNoCert_RESERVED:
197 if((ctx->state == SSL_HdskStateClientCert) &&
198 (ctx->protocolSide == kSSLServerSide) &&
199 (ctx->clientAuth != kAlwaysAuthenticate)) {
200 /*
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.
210 */
211 if ((err = SSLAdvanceHandshake(SSL_HdskCert,
212 ctx)) != 0) {
213 return err;
214 }
215 }
216 break;
217 case SSL_AlertUnsupportedExtension:
218 err = errSSLFatalAlert;
219 fatal = true;
220 break;
221
222 default:
223 /* Unknown alert, ignore if not fatal */
224 if(level == SSL_AlertLevelFatal) {
225 err = errSSLFatalAlert;
226 }
227 else {
228 err = noErr;
229 }
230 break;
231 }
232 if(fatal) {
233 /* don't bother processing any more */
234 break;
235 }
236 }
237 if(fatal) {
238 SSLDeleteSessionData(ctx);
239 }
240 return err;
241 }
242
243 OSStatus
244 SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
245 { SSLRecord rec;
246 OSStatus err;
247
248 switch(ctx->negProtocolVersion) {
249 case SSL_Version_Undetermined:
250 /* Too early in negotiation to send an alert */
251 return noErr;
252 case SSL_Version_2_0:
253 /* shouldn't be here */
254 assert(0);
255 return errSSLInternal;
256 default:
257 break;
258 }
259 if(ctx->sentFatalAlert) {
260 /* no more alerts allowed */
261 return noErr;
262 }
263 if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0)
264 return err;
265 assert(ctx->sslTslCalls != NULL);
266 SSLLogAlertMsg(desc, true);
267 if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
268 return err;
269 if ((err = SSLFreeBuffer(&rec.contents, ctx)) != 0)
270 return err;
271 if(desc == SSL_AlertCloseNotify) {
272 /* no more alerts allowed */
273 ctx->sentFatalAlert = true;
274 }
275 return noErr;
276 }
277
278 static OSStatus
279 SSLEncodeAlert(SSLRecord *rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
280 { OSStatus err;
281
282 rec->protocolVersion = ctx->negProtocolVersion;
283 rec->contentType = SSL_RecordTypeAlert;
284 rec->contents.length = 2;
285 if ((err = SSLAllocBuffer(&rec->contents, 2, ctx)) != 0)
286 return err;
287 rec->contents.data[0] = level;
288 rec->contents.data[1] = desc;
289
290 return noErr;
291 }
292
293 OSStatus
294 SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
295 { OSStatus err1, err2;
296
297 if(desc != SSL_AlertCloseNotify) {
298 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
299 }
300 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
301
302 if(ctx->negProtocolVersion < TLS_Version_1_0) {
303 /* translate to SSL3 if necessary */
304 switch(desc) {
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;
316 break;
317 case SSL_AlertUnknownCA:
318 desc = SSL_AlertUnsupportedCert;
319 break;
320 case SSL_AlertInternalError:
321 desc = SSL_AlertCloseNotify;
322 break;
323 default:
324 /* send as is */
325 break;
326 }
327 }
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);
331
332 /* Second, send the alert */
333 err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);
334
335 ctx->sentFatalAlert = true;
336
337 /* If they both returned errors, arbitrarily return the first */
338 return err1 != 0 ? err1 : err2;
339 }
340
341 #ifndef NDEBUG
342
343 /* log alert messages */
344
345 static char *alertMsgToStr(AlertDescription msg)
346 {
347 static char badStr[100];
348
349 switch(msg) {
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";
372
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";
387
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";
400
401 default:
402 sprintf(badStr, "Unknown state (%d(d)", msg);
403 return badStr;
404 }
405 }
406
407 static void SSLLogAlertMsg(AlertDescription msg, bool sent)
408 {
409 sslHdskMsgDebug("---%s alert msg %s",
410 alertMsgToStr(msg), (sent ? "sent" : "recv"));
411 }
412
413 #endif /* NDEBUG */