#include "ssl.h"
#ifndef _SSLALERT_H_
#include "sslalert.h"
#endif
#ifndef _SSLALLOC_H_
#include "sslalloc.h"
#endif
#ifndef _SSLCTX_H_
#include "sslctx.h"
#endif
#ifndef _SSLSESS_H_
#include "sslsess.h"
#endif
#ifndef _SSL_DEBUG_H_
#include "sslDebug.h"
#endif
#include <assert.h>
SSLErr
SSLProcessAlert(SSLRecord rec, SSLContext *ctx)
{ SSLErr err = SSLNoErr;
AlertLevel level;
AlertDescription desc;
uint8 *progress;
uint32 remaining;
if (rec.contents.length % 2 != 0)
{ ERR(err = SSLFatalSessionAlert(alert_illegal_parameter, ctx));
if (!err)
ERR(err = SSLProtocolErr);
return err;
}
progress = rec.contents.data;
remaining = rec.contents.length;
while (remaining > 0)
{ level = (AlertLevel)*progress++;
desc = (AlertDescription)*progress++;
remaining -= 2;
if (level == alert_fatal)
{
SSLDeleteSessionData(ctx);
dprintf1("***Fatal alert %d received", desc);
return SSLFatalAlert;
}
switch (desc)
{ case alert_unexpected_message:
case alert_bad_record_mac:
case alert_decompression_failure:
case alert_handshake_failure:
case alert_illegal_parameter:
SSLDeleteSessionData(ctx);
err = SSLFatalAlert;
break;
case alert_close_notify:
ERR(SSLClose(ctx));
err = SSLNoErr;
break;
case alert_no_certificate:
if (ctx->state == HandshakeClientCertificate)
if (ERR(err = SSLAdvanceHandshake(SSL_certificate, ctx)) != 0)
return err;
break;
case alert_bad_certificate:
case alert_unsupported_certificate:
case alert_certificate_revoked:
case alert_certificate_expired:
case alert_certificate_unknown:
err = SSLNoErr;
break;
default:
break;
}
}
return err;
}
SSLErr
SSLSendAlert(AlertLevel level, AlertDescription desc, SSLContext *ctx)
{ SSLRecord rec;
SSLErr err;
CASSERT((ctx->negProtocolVersion != SSL_Version_2_0));
if ((err = SSLEncodeAlert(&rec, level, desc, ctx)) != 0)
return err;
assert(ctx->sslTslCalls != NULL);
if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
return err;
if ((err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
return err;
return SSLNoErr;
}
SSLErr
SSLEncodeAlert(SSLRecord *rec, AlertLevel level, AlertDescription desc, SSLContext *ctx)
{ SSLErr err;
rec->contentType = SSL_alert;
CASSERT((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->sysCtx)) != 0)
return err;
rec->contents.data[0] = level;
rec->contents.data[1] = desc;
return SSLNoErr;
}
SSLErr
SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
{ SSLErr err1, err2;
if(desc != alert_close_notify) {
errorLog1("SSLFatalSessionAlert: desc %d\n", desc);
}
SSLChangeHdskState(ctx, SSLErrorClose);
err1 = SSLDeleteSessionData(ctx);
err2 = SSLSendAlert(alert_fatal, desc, ctx);
return err1 != 0 ? err1 : err2;
}