]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslAlertMessage.cpp
Security-54.1.3.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
30 #include <assert.h>
31
32 #ifdef NDEBUG
33 #define SSLLogAlertMsg(msg,sent)
34 #else
35 static void SSLLogAlertMsg(AlertDescription msg, bool sent);
36 #endif
37
38 OSStatus
39 SSLProcessAlert(SSLRecord rec, SSLContext *ctx)
40 { OSStatus err = noErr;
41 AlertLevel level;
42 AlertDescription desc;
43 uint8 *charPtr;
44 uint32 remaining;
45
46 if (rec.contents.length % 2 != 0)
47 {
48 err = SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx);
49 if (!err) {
50 err = errSSLProtocol;
51 }
52 return err;
53 }
54
55 charPtr = rec.contents.data;
56 remaining = rec.contents.length;
57 while (remaining > 0)
58 { level = (AlertLevel)*charPtr++;
59 desc = (AlertDescription)*charPtr++;
60 sslHdskMsgDebug("alert msg recieved level %d desc %d\n",
61 (int)level, (int)desc);
62 remaining -= 2;
63 SSLLogAlertMsg(desc, false);
64
65 /*
66 * Ignore sessionID-related failures here;
67 * the important thing is the alert.
68 */
69 if (level == SSL_AlertLevelFatal)
70 {
71 SSLDeleteSessionData(ctx);
72 sslErrorLog("***Fatal alert %d received\n", desc);
73 return errSSLFatalAlert;
74 }
75
76 switch (desc)
77 { case SSL_AlertUnexpectedMsg:
78 case SSL_AlertBadRecordMac:
79 case SSL_AlertDecompressFail:
80 case SSL_AlertHandshakeFail:
81 case SSL_AlertIllegalParam:
82 /* These must always be fatal; if we got here, the level is warning;
83 * die anyway
84 */
85 SSLDeleteSessionData(ctx);
86 err = errSSLFatalAlert;
87 break;
88 case SSL_AlertCloseNotify:
89 SSLClose(ctx);
90 err = noErr;
91 break;
92 case SSL_AlertNoCert:
93 if((ctx->state == SSL_HdskStateClientCert) &&
94 (ctx->protocolSide == SSL_ServerSide) &&
95 (ctx->clientAuth != kAlwaysAuthenticate)) {
96 /*
97 * Tolerate this unless we're configured to
98 * *require* a client cert. If a client cert is
99 * required, we'll catch the error at the next
100 * handshake msg we receive - which will probably
101 * be a client key exchange msg, which is illegal
102 * when we're in state SSL_HdskStateClientCert.
103 * If the client cert is optional, advance to
104 * state ClientKeyExchange by pretending we
105 * just got a client cert msg.
106 */
107 if ((err = SSLAdvanceHandshake(SSL_HdskCert,
108 ctx)) != 0) {
109 return err;
110 }
111 }
112 break;
113 case SSL_AlertBadCert:
114 case SSL_AlertUnsupportedCert:
115 case SSL_AlertCertRevoked:
116 case SSL_AlertCertExpired:
117 case SSL_AlertCertUnknown:
118 err = noErr;
119 break;
120 default:
121 /* Unknown alert, but not fatal; ignore it */
122 break;
123 }
124 }
125
126 return err;
127 }
128
129 OSStatus
130 SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
131 { SSLRecord rec;
132 OSStatus err;
133
134 assert((ctx->negProtocolVersion != SSL_Version_2_0));
135
136 if ((err = SSLEncodeAlert(rec, level, desc, ctx)) != 0)
137 return err;
138 assert(ctx->sslTslCalls != NULL);
139 SSLLogAlertMsg(desc, true);
140 if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
141 return err;
142 if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0)
143 return err;
144
145 return noErr;
146 }
147
148 OSStatus
149 SSLEncodeAlert(SSLRecord &rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
150 { OSStatus err;
151
152 rec.contentType = SSL_RecordTypeAlert;
153 assert((ctx->negProtocolVersion != SSL_Version_2_0));
154 if(ctx->negProtocolVersion == SSL_Version_Undetermined) {
155 /* error while negotiating */
156 rec.protocolVersion = ctx->maxProtocolVersion;
157 }
158 else {
159 rec.protocolVersion = ctx->negProtocolVersion;
160 }
161 rec.contents.length = 2;
162 if ((err = SSLAllocBuffer(rec.contents, 2, ctx)) != 0)
163 return err;
164 rec.contents.data[0] = level;
165 rec.contents.data[1] = desc;
166
167 return noErr;
168 }
169
170 OSStatus
171 SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
172 { OSStatus err1, err2;
173
174 if(desc != SSL_AlertCloseNotify) {
175 sslErrorLog("SSLFatalSessionAlert: desc %d\n", desc);
176 }
177 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
178
179 /* Make session unresumable; I'm not stopping if I get an error,
180 because I'd like to attempt to send the alert anyway */
181 err1 = SSLDeleteSessionData(ctx);
182
183 /* Second, send the alert */
184 err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);
185
186 /* If they both returned errors, arbitrarily return the first */
187 return err1 != 0 ? err1 : err2;
188 }
189
190 #ifndef NDEBUG
191
192 /* log alert messages */
193
194 static char *alertMsgToStr(AlertDescription msg)
195 {
196 static char badStr[100];
197
198 switch(msg) {
199 case SSL_AlertCloseNotify:
200 return "SSL_AlertCloseNotify";
201 case SSL_AlertUnexpectedMsg:
202 return "SSL_AlertUnexpectedMsg";
203 case SSL_AlertBadRecordMac:
204 return "SSL_AlertBadRecordMac";
205 case SSL_AlertDecryptionFail:
206 return "SSL_AlertDecryptionFail";
207 case SSL_AlertRecordOverflow:
208 return "SSL_AlertRecordOverflow";
209 case SSL_AlertDecompressFail:
210 return "SSL_AlertDecompressFail";
211 case SSL_AlertHandshakeFail:
212 return "SSL_AlertHandshakeFail";
213 case SSL_AlertNoCert:
214 return "SSL_AlertNoCert";
215 case SSL_AlertBadCert:
216 return "SSL_AlertBadCert";
217 case SSL_AlertUnsupportedCert:
218 return "SSL_AlertUnsupportedCert";
219 case SSL_AlertCertRevoked:
220 return "SSL_AlertCertRevoked";
221
222 case SSL_AlertCertExpired:
223 return "SSL_AlertCertExpired";
224 case SSL_AlertCertUnknown:
225 return "SSL_AlertCertUnknown";
226 case SSL_AlertIllegalParam:
227 return "SSL_AlertIllegalParam";
228 case SSL_AlertUnknownCA:
229 return "SSL_AlertUnknownCA";
230 case SSL_AlertAccessDenied:
231 return "SSL_AlertAccessDenied";
232 case SSL_AlertDecodeError:
233 return "SSL_AlertDecodeError";
234 case SSL_AlertDecryptError:
235 return "SSL_AlertDecryptError";
236
237 case SSL_AlertExportRestriction:
238 return "SSL_AlertExportRestriction";
239 case SSL_AlertProtocolVersion:
240 return "SSL_AlertProtocolVersion";
241 case SSL_AlertInsufficientSecurity:
242 return "SSL_AlertInsufficientSecurity";
243 case SSL_AlertInternalError:
244 return "SSL_AlertInternalError";
245 case SSL_AlertUserCancelled:
246 return "SSL_AlertUserCancelled";
247 case SSL_AlertNoRenegotiation:
248 return "SSL_AlertNoRenegotiation";
249
250 default:
251 sprintf(badStr, "Unknown state (%d(d)", msg);
252 return badStr;
253 }
254 }
255
256 static void SSLLogAlertMsg(AlertDescription msg, bool sent)
257 {
258 sslHdskMsgDebug("---%s alert msg %s",
259 alertMsgToStr(msg), (sent ? "sent" : "recv"));
260 }
261
262 #endif /* NDEBUG */