sslAlertMessage.cpp [plain text]
#include "ssl.h"
#include "sslAlertMessage.h"
#include "sslMemory.h"
#include "sslContext.h"
#include "sslSession.h"
#include "sslDebug.h"
#include <assert.h>
#ifdef NDEBUG
#define SSLLogAlertMsg(msg,sent)
#else
static void SSLLogAlertMsg(AlertDescription msg, bool sent);
#endif
OSStatus
SSLProcessAlert(SSLRecord rec, SSLContext *ctx)
{ OSStatus err = noErr;
AlertLevel level;
AlertDescription desc;
uint8 *charPtr;
uint32 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;
while (remaining > 0)
{ level = (AlertLevel)*charPtr++;
desc = (AlertDescription)*charPtr++;
sslHdskMsgDebug("alert msg recieved level %d desc %d\n",
(int)level, (int)desc);
remaining -= 2;
SSLLogAlertMsg(desc, false);
if (level == SSL_AlertLevelFatal)
{
SSLDeleteSessionData(ctx);
sslErrorLog("***Fatal alert %d received\n", desc);
return errSSLFatalAlert;
}
switch (desc)
{ case SSL_AlertUnexpectedMsg:
case SSL_AlertBadRecordMac:
case SSL_AlertDecompressFail:
case SSL_AlertHandshakeFail:
case SSL_AlertIllegalParam:
SSLDeleteSessionData(ctx);
err = errSSLFatalAlert;
break;
case SSL_AlertCloseNotify:
SSLClose(ctx);
err = noErr;
break;
case SSL_AlertNoCert:
if((ctx->state == SSL_HdskStateClientCert) &&
(ctx->protocolSide == SSL_ServerSide) &&
(ctx->clientAuth != kAlwaysAuthenticate)) {
if ((err = SSLAdvanceHandshake(SSL_HdskCert,
ctx)) != 0) {
return err;
}
}
break;
case SSL_AlertBadCert:
case SSL_AlertUnsupportedCert:
case SSL_AlertCertRevoked:
case SSL_AlertCertExpired:
case SSL_AlertCertUnknown:
err = noErr;
break;
default:
break;
}
}
return err;
}
OSStatus
SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
{ SSLRecord rec;
OSStatus err;
assert((ctx->negProtocolVersion != SSL_Version_2_0));
if ((err = SSLEncodeAlert(rec, level, desc, ctx)) != 0)
return err;
assert(ctx->sslTslCalls != NULL);
SSLLogAlertMsg(desc, true);
if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
return err;
if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0)
return err;
return noErr;
}
OSStatus
SSLEncodeAlert(SSLRecord &rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
{ OSStatus err;
rec.contentType = SSL_RecordTypeAlert;
assert((ctx->negProtocolVersion != SSL_Version_2_0));
if(ctx->negProtocolVersion == SSL_Version_Undetermined) {
rec.protocolVersion = ctx->maxProtocolVersion;
}
else {
rec.protocolVersion = ctx->negProtocolVersion;
}
rec.contents.length = 2;
if ((err = SSLAllocBuffer(rec.contents, 2, ctx)) != 0)
return err;
rec.contents.data[0] = level;
rec.contents.data[1] = desc;
return noErr;
}
OSStatus
SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
{ OSStatus err1, err2;
if(desc != SSL_AlertCloseNotify) {
sslErrorLog("SSLFatalSessionAlert: desc %d\n", desc);
}
SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
err1 = SSLDeleteSessionData(ctx);
err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);
return err1 != 0 ? err1 : err2;
}
#ifndef NDEBUG
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:
return "SSL_AlertDecryptionFail";
case SSL_AlertRecordOverflow:
return "SSL_AlertRecordOverflow";
case SSL_AlertDecompressFail:
return "SSL_AlertDecompressFail";
case SSL_AlertHandshakeFail:
return "SSL_AlertHandshakeFail";
case SSL_AlertNoCert:
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:
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