static OSStatus SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx);
static OSStatus SSLHandshakeProceed(SSLContext *ctx);
+static OSStatus SSLSendAlert(SSLContext *ctx, tls_alert_level_t level, tls_alert_t description);
OSStatus
SSLWrite(
err = errSSLClosedGraceful;
goto abort;
case SSL_HdskStateErrorClose:
+ case SSL_HdskStateOutOfBandError:
err = errSSLClosedAbort;
goto abort;
case SSL_HdskStateReady:
err = errSSLClosedGraceful;
goto abort;
case SSL_HdskStateErrorClose:
+ case SSL_HdskStateOutOfBandError:
err = errSSLClosedAbort;
goto abort;
case SSL_HdskStateNoNotifyClose:
return errSecParam;
}
- if (ctx->state == SSL_HdskStateGracefulClose)
- return errSSLClosedGraceful;
- if (ctx->state == SSL_HdskStateErrorClose)
- return errSSLClosedAbort;
- if (ctx->state == SSL_HdskStatePending)
- return errSecBadReq;
+ switch (ctx->state) {
+ case SSL_HdskStateGracefulClose:
+ return errSSLClosedGraceful;
+ case SSL_HdskStateErrorClose:
+ case SSL_HdskStateOutOfBandError:
+ return errSSLClosedAbort;
+ case SSL_HdskStatePending:
+ return errSecBadReq;
+ default:
+ break;
+ }
/* If we are the client, we start the negotiation */
if(ctx->protocolSide == kSSLClientSide) {
if(ctx == NULL) {
return errSecParam;
}
- if (ctx->state == SSL_HdskStateGracefulClose)
- return errSSLClosedGraceful;
- if (ctx->state == SSL_HdskStateErrorClose)
- return errSSLClosedAbort;
+
+ switch (ctx->state) {
+ case SSL_HdskStateGracefulClose:
+ return errSSLClosedGraceful;
+ case SSL_HdskStateErrorClose:
+ return errSSLClosedAbort;
+ default:
+ break;
+ }
if(ctx->isDTLS && ctx->timeout_deadline) {
CFAbsoluteTime current = CFAbsoluteTimeGetCurrent();
SSLChangeHdskState(ctx, SSL_HdskStatePending);
}
+ /* If an out-of-band error occurred, handle it here and then terminate
+ the connection as needed. */
+ if (ctx->state == SSL_HdskStateOutOfBandError) {
+ bool shouldClose = true;
+ switch (ctx->outOfBandError) {
+ case errSecCertificateExpired:
+ SSLSendAlert(ctx, tls_handshake_alert_level_fatal, tls_handshake_alert_CertExpired);
+ break;
+ case errSecCertificateRevoked:
+ SSLSendAlert(ctx, tls_handshake_alert_level_fatal, tls_handshake_alert_CertRevoked);
+ break;
+ default:
+ shouldClose = false;
+ break;
+ }
+
+ if (shouldClose) {
+ return SSLClose(ctx);
+ }
+ }
+
do {
err = SSLHandshakeProceed(ctx);
if((err != 0) && (err != errSSLUnexpectedRecord))
err = SSLServiceWriteQueue(ctx);
SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose);
- if (err == errSecIO)
+ if (err == errSecIO)
err = errSecSuccess; /* Ignore errors related to closed streams */
return err;
}
+static OSStatus
+SSLSendAlert(SSLContext *ctx, tls_alert_level_t alertLevel, tls_alert_t alert)
+{
+ sslHdskStateDebug("SSLSendAlert");
+ if (ctx == NULL) {
+ return errSecParam;
+ }
+
+ return tls_handshake_send_alert(ctx->hdsk, alertLevel, alert);
+}
+
+OSStatus
+SSLSetError(SSLContext *ctx, OSStatus error)
+{
+ ctx->state = SSL_HdskStateOutOfBandError;
+ ctx->outOfBandError = error;
+ return errSecSuccess;
+}
+
/*
* Determine how much data the client can be guaranteed to
* obtain via SSLRead() without blocking or causing any low-level