+++ /dev/null
-/*
- * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * sslAlertMessage.c - SSL3 Alert protocol
- */
-
-#include "ssl.h"
-#include "sslAlertMessage.h"
-#include "sslMemory.h"
-#include "sslContext.h"
-#include "sslSession.h"
-#include "sslDebug.h"
-#include "sslUtils.h"
-
-#include <assert.h>
-
-#ifdef NDEBUG
-#define SSLLogAlertMsg(msg,sent)
-#else
-static void SSLLogAlertMsg(AlertDescription msg, bool sent);
-#endif
-
-static OSStatus SSLEncodeAlert(
- SSLRecord *rec,
- AlertLevel level,
- AlertDescription desc,
- SSLContext *ctx);
-
-/*
- * If a peer sends us any kind of a bad cert alert, we may need to adjust
- * ctx->clientCertState accordingly.
- */
-static void
-SSLDetectCertRejected(
- SSLContext *ctx,
- AlertDescription desc)
-{
- if(ctx->protocolSide == kSSLServerSide) {
- return;
- }
- if(ctx->clientCertState != kSSLClientCertSent) {
- return;
- }
- switch(desc) {
- case SSL_AlertBadCert:
- case SSL_AlertUnsupportedCert:
- case SSL_AlertCertRevoked:
- case SSL_AlertCertExpired:
- case SSL_AlertCertUnknown:
- case SSL_AlertUnknownCA:
- ctx->clientCertState = kSSLClientCertRejected;
- break;
- default:
- break;
- }
-}
-
-OSStatus
-SSLProcessAlert(SSLRecord rec, SSLContext *ctx)
-{ OSStatus err = errSecSuccess;
- AlertLevel level;
- AlertDescription desc;
- uint8_t *charPtr;
- size_t remaining;
-
- if (rec.contents.length % 2 != 0)
- {
- err = SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx);
- if (!err) {
- err = errSSLProtocol;
- }
- return err;
- }
-
- charPtr = rec.contents.data;
- remaining = rec.contents.length;
- bool fatal = false;
-
- while (remaining > 0)
- { level = (AlertLevel)*charPtr++;
- desc = (AlertDescription)*charPtr++;
- sslHdskMsgDebug("alert msg received level %d desc %d",
- (int)level, (int)desc);
- remaining -= 2;
- SSLLogAlertMsg(desc, false);
-
- if (level == SSL_AlertLevelFatal) {
- /* explicit fatal errror */
- fatal = true;
- sslErrorLog("***Fatal alert %d received\n", desc);
- }
- SSLDetectCertRejected(ctx, desc);
-
- switch (desc) {
- /* A number of these are fatal by implication */
- case SSL_AlertUnexpectedMsg:
- err = errSSLPeerUnexpectedMsg;
- fatal = true;
- break;
- case SSL_AlertBadRecordMac:
- err = errSSLPeerBadRecordMac;
- fatal = true;
- break;
- case SSL_AlertDecryptionFail_RESERVED:
- err = errSSLPeerDecryptionFail;
- fatal = true;
- break;
- case SSL_AlertRecordOverflow:
- err = errSSLPeerRecordOverflow;
- fatal = true;
- break;
- case SSL_AlertDecompressFail:
- err = errSSLPeerDecompressFail;
- fatal = true;
- break;
- case SSL_AlertHandshakeFail:
- err = errSSLPeerHandshakeFail;
- fatal = true;
- break;
- case SSL_AlertIllegalParam:
- err = errSSLIllegalParam;
- fatal = true;
- break;
- case SSL_AlertBadCert:
- err = errSSLPeerBadCert;
- break;
- case SSL_AlertUnsupportedCert:
- err = errSSLPeerUnsupportedCert;
- break;
- case SSL_AlertCertRevoked:
- err = errSSLPeerCertRevoked;
- break;
- case SSL_AlertCertExpired:
- err = errSSLPeerCertExpired;
- break;
- case SSL_AlertCertUnknown:
- err = errSSLPeerCertUnknown;
- break;
- case SSL_AlertUnknownCA:
- err = errSSLPeerUnknownCA;
- break;
- case SSL_AlertAccessDenied:
- err = errSSLPeerAccessDenied;
- break;
- case SSL_AlertDecodeError:
- err = errSSLPeerDecodeError;
- break;
- case SSL_AlertDecryptError:
- err = errSSLPeerDecryptError;
- break;
- case SSL_AlertExportRestriction_RESERVED:
- err = errSSLPeerExportRestriction;
- break;
- case SSL_AlertProtocolVersion:
- err = errSSLPeerProtocolVersion;
- break;
- case SSL_AlertInsufficientSecurity:
- err = errSSLPeerInsufficientSecurity;
- break;
- case SSL_AlertInternalError:
- err = errSSLPeerInternalError;
- break;
- case SSL_AlertUserCancelled:
- err = errSSLPeerUserCancelled;
- break;
- case SSL_AlertNoRenegotiation:
- err = errSSLPeerNoRenegotiation;
- break;
- /* unusual cases.... */
- case SSL_AlertCloseNotify:
- /* the clean "we're done" case */
- SSLClose(ctx);
- err = errSecSuccess;
- break;
- case SSL_AlertNoCert_RESERVED:
- if((ctx->state == SSL_HdskStateClientCert) &&
- (ctx->protocolSide == kSSLServerSide) &&
- (ctx->clientAuth != kAlwaysAuthenticate)) {
- /*
- * Tolerate this unless we're configured to
- * *require* a client cert. If a client cert is
- * required, we'll catch the error at the next
- * handshake msg we receive - which will probably
- * be a client key exchange msg, which is illegal
- * when we're in state SSL_HdskStateClientCert.
- * If the client cert is optional, advance to
- * state ClientKeyExchange by pretending we
- * just got a client cert msg.
- */
- if ((err = SSLAdvanceHandshake(SSL_HdskCert,
- ctx)) != 0) {
- return err;
- }
- }
- break;
- case SSL_AlertUnsupportedExtension:
- err = errSSLFatalAlert;
- fatal = true;
- break;
-
- default:
- /* Unknown alert, ignore if not fatal */
- if(level == SSL_AlertLevelFatal) {
- err = errSSLFatalAlert;
- }
- else {
- err = errSecSuccess;
- }
- break;
- }
- if(fatal) {
- /* don't bother processing any more */
- break;
- }
- }
- if(fatal) {
- SSLDeleteSessionData(ctx);
- }
- return err;
-}
-
-OSStatus
-SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
-{ SSLRecord rec;
- OSStatus err;
-
- switch(ctx->negProtocolVersion) {
- case SSL_Version_Undetermined:
- /* Too early in negotiation to send an alert */
- return errSecSuccess;
- case SSL_Version_2_0:
- /* shouldn't be here */
- assert(0);
- return errSSLInternal;
- default:
- break;
- }
- if(ctx->sentFatalAlert) {
- /* no more alerts allowed */
- return errSecSuccess;
- }
- if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0)
- return err;
- SSLLogAlertMsg(desc, true);
- if ((err = SSLWriteRecord(rec, ctx)) != 0)
- return err;
- if ((err = SSLFreeBuffer(&rec.contents)))
- return err;
- if(desc == SSL_AlertCloseNotify) {
- /* no more alerts allowed */
- ctx->sentFatalAlert = true;
- }
- return errSecSuccess;
-}
-
-static OSStatus
-SSLEncodeAlert(SSLRecord *rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
-{ OSStatus err;
-
- rec->protocolVersion = ctx->negProtocolVersion;
- rec->contentType = SSL_RecordTypeAlert;
- rec->contents.length = 2;
- if ((err = SSLAllocBuffer(&rec->contents, 2)))
- return err;
- rec->contents.data[0] = level;
- rec->contents.data[1] = desc;
-
- return errSecSuccess;
-}
-
-OSStatus
-SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
-{ OSStatus err1, err2;
-
- if(desc != SSL_AlertCloseNotify) {
- sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
- }
- SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
-
- if(ctx->negProtocolVersion < TLS_Version_1_0) {
- /* translate to SSL3 if necessary */
- switch(desc) {
- //case SSL_AlertDecryptionFail_RESERVED:
- case SSL_AlertRecordOverflow:
- case SSL_AlertAccessDenied:
- case SSL_AlertDecodeError:
- case SSL_AlertDecryptError:
- //case SSL_AlertExportRestriction_RESERVED:
- case SSL_AlertProtocolVersion:
- case SSL_AlertInsufficientSecurity:
- case SSL_AlertUserCancelled:
- case SSL_AlertNoRenegotiation:
- desc = SSL_AlertHandshakeFail;
- break;
- case SSL_AlertUnknownCA:
- desc = SSL_AlertUnsupportedCert;
- break;
- case SSL_AlertInternalError:
- desc = SSL_AlertCloseNotify;
- break;
- default:
- /* send as is */
- break;
- }
- }
- /* Make session unresumable; I'm not stopping if I get an error,
- because I'd like to attempt to send the alert anyway */
- err1 = SSLDeleteSessionData(ctx);
-
- /* Second, send the alert */
- err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);
-
- ctx->sentFatalAlert = true;
-
- /* If they both returned errors, arbitrarily return the first */
- return err1 != 0 ? err1 : err2;
-}
-
-#ifndef NDEBUG
-
-/* log alert messages */
-
-static char *alertMsgToStr(AlertDescription msg)
-{
- static char badStr[100];
-
- switch(msg) {
- case SSL_AlertCloseNotify:
- return "SSL_AlertCloseNotify";
- case SSL_AlertUnexpectedMsg:
- return "SSL_AlertUnexpectedMsg";
- case SSL_AlertBadRecordMac:
- return "SSL_AlertBadRecordMac";
- case SSL_AlertDecryptionFail_RESERVED:
- return "SSL_AlertDecryptionFail";
- case SSL_AlertRecordOverflow:
- return "SSL_AlertRecordOverflow";
- case SSL_AlertDecompressFail:
- return "SSL_AlertDecompressFail";
- case SSL_AlertHandshakeFail:
- return "SSL_AlertHandshakeFail";
- case SSL_AlertNoCert_RESERVED:
- return "SSL_AlertNoCert";
- case SSL_AlertBadCert:
- return "SSL_AlertBadCert";
- case SSL_AlertUnsupportedCert:
- return "SSL_AlertUnsupportedCert";
- case SSL_AlertCertRevoked:
- return "SSL_AlertCertRevoked";
-
- case SSL_AlertCertExpired:
- return "SSL_AlertCertExpired";
- case SSL_AlertCertUnknown:
- return "SSL_AlertCertUnknown";
- case SSL_AlertIllegalParam:
- return "SSL_AlertIllegalParam";
- case SSL_AlertUnknownCA:
- return "SSL_AlertUnknownCA";
- case SSL_AlertAccessDenied:
- return "SSL_AlertAccessDenied";
- case SSL_AlertDecodeError:
- return "SSL_AlertDecodeError";
- case SSL_AlertDecryptError:
- return "SSL_AlertDecryptError";
-
- case SSL_AlertExportRestriction_RESERVED:
- return "SSL_AlertExportRestriction";
- case SSL_AlertProtocolVersion:
- return "SSL_AlertProtocolVersion";
- case SSL_AlertInsufficientSecurity:
- return "SSL_AlertInsufficientSecurity";
- case SSL_AlertInternalError:
- return "SSL_AlertInternalError";
- case SSL_AlertUserCancelled:
- return "SSL_AlertUserCancelled";
- case SSL_AlertNoRenegotiation:
- return "SSL_AlertNoRenegotiation";
-
- default:
- sprintf(badStr, "Unknown state (%d(d)", msg);
- return badStr;
- }
-}
-
-static void SSLLogAlertMsg(AlertDescription msg, bool sent)
-{
- sslHdskMsgDebug("---%s alert msg %s",
- alertMsgToStr(msg), (sent ? "sent" : "recv"));
-}
-
-#endif /* NDEBUG */