]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/sslAlertMessage.c
Security-55471.14.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 = errSecSuccess;
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 sslErrorLog("***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 = errSecSuccess;
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 = errSecSuccess;
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 errSecSuccess;
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 errSecSuccess;
262 }
263 if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0)
264 return err;
265 SSLLogAlertMsg(desc, true);
266 if ((err = SSLWriteRecord(rec, ctx)) != 0)
267 return err;
268 if ((err = SSLFreeBuffer(&rec.contents)))
269 return err;
270 if(desc == SSL_AlertCloseNotify) {
271 /* no more alerts allowed */
272 ctx->sentFatalAlert = true;
273 }
274 return errSecSuccess;
275 }
276
277 static OSStatus
278 SSLEncodeAlert(SSLRecord *rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
279 { OSStatus err;
280
281 rec->protocolVersion = ctx->negProtocolVersion;
282 rec->contentType = SSL_RecordTypeAlert;
283 rec->contents.length = 2;
284 if ((err = SSLAllocBuffer(&rec->contents, 2)))
285 return err;
286 rec->contents.data[0] = level;
287 rec->contents.data[1] = desc;
288
289 return errSecSuccess;
290 }
291
292 OSStatus
293 SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
294 { OSStatus err1, err2;
295
296 if(desc != SSL_AlertCloseNotify) {
297 sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
298 }
299 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
300
301 if(ctx->negProtocolVersion < TLS_Version_1_0) {
302 /* translate to SSL3 if necessary */
303 switch(desc) {
304 //case SSL_AlertDecryptionFail_RESERVED:
305 case SSL_AlertRecordOverflow:
306 case SSL_AlertAccessDenied:
307 case SSL_AlertDecodeError:
308 case SSL_AlertDecryptError:
309 //case SSL_AlertExportRestriction_RESERVED:
310 case SSL_AlertProtocolVersion:
311 case SSL_AlertInsufficientSecurity:
312 case SSL_AlertUserCancelled:
313 case SSL_AlertNoRenegotiation:
314 desc = SSL_AlertHandshakeFail;
315 break;
316 case SSL_AlertUnknownCA:
317 desc = SSL_AlertUnsupportedCert;
318 break;
319 case SSL_AlertInternalError:
320 desc = SSL_AlertCloseNotify;
321 break;
322 default:
323 /* send as is */
324 break;
325 }
326 }
327 /* Make session unresumable; I'm not stopping if I get an error,
328 because I'd like to attempt to send the alert anyway */
329 err1 = SSLDeleteSessionData(ctx);
330
331 /* Second, send the alert */
332 err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);
333
334 ctx->sentFatalAlert = true;
335
336 /* If they both returned errors, arbitrarily return the first */
337 return err1 != 0 ? err1 : err2;
338 }
339
340 #ifndef NDEBUG
341
342 /* log alert messages */
343
344 static char *alertMsgToStr(AlertDescription msg)
345 {
346 static char badStr[100];
347
348 switch(msg) {
349 case SSL_AlertCloseNotify:
350 return "SSL_AlertCloseNotify";
351 case SSL_AlertUnexpectedMsg:
352 return "SSL_AlertUnexpectedMsg";
353 case SSL_AlertBadRecordMac:
354 return "SSL_AlertBadRecordMac";
355 case SSL_AlertDecryptionFail_RESERVED:
356 return "SSL_AlertDecryptionFail";
357 case SSL_AlertRecordOverflow:
358 return "SSL_AlertRecordOverflow";
359 case SSL_AlertDecompressFail:
360 return "SSL_AlertDecompressFail";
361 case SSL_AlertHandshakeFail:
362 return "SSL_AlertHandshakeFail";
363 case SSL_AlertNoCert_RESERVED:
364 return "SSL_AlertNoCert";
365 case SSL_AlertBadCert:
366 return "SSL_AlertBadCert";
367 case SSL_AlertUnsupportedCert:
368 return "SSL_AlertUnsupportedCert";
369 case SSL_AlertCertRevoked:
370 return "SSL_AlertCertRevoked";
371
372 case SSL_AlertCertExpired:
373 return "SSL_AlertCertExpired";
374 case SSL_AlertCertUnknown:
375 return "SSL_AlertCertUnknown";
376 case SSL_AlertIllegalParam:
377 return "SSL_AlertIllegalParam";
378 case SSL_AlertUnknownCA:
379 return "SSL_AlertUnknownCA";
380 case SSL_AlertAccessDenied:
381 return "SSL_AlertAccessDenied";
382 case SSL_AlertDecodeError:
383 return "SSL_AlertDecodeError";
384 case SSL_AlertDecryptError:
385 return "SSL_AlertDecryptError";
386
387 case SSL_AlertExportRestriction_RESERVED:
388 return "SSL_AlertExportRestriction";
389 case SSL_AlertProtocolVersion:
390 return "SSL_AlertProtocolVersion";
391 case SSL_AlertInsufficientSecurity:
392 return "SSL_AlertInsufficientSecurity";
393 case SSL_AlertInternalError:
394 return "SSL_AlertInternalError";
395 case SSL_AlertUserCancelled:
396 return "SSL_AlertUserCancelled";
397 case SSL_AlertNoRenegotiation:
398 return "SSL_AlertNoRenegotiation";
399
400 default:
401 sprintf(badStr, "Unknown state (%d(d)", msg);
402 return badStr;
403 }
404 }
405
406 static void SSLLogAlertMsg(AlertDescription msg, bool sent)
407 {
408 sslHdskMsgDebug("---%s alert msg %s",
409 alertMsgToStr(msg), (sent ? "sent" : "recv"));
410 }
411
412 #endif /* NDEBUG */