-#if ENABLE_DTLS
- if(ctx->isDTLS)
- head+=8;
-#endif
-
- if (!ctx->partialReadBuffer.data || ctx->partialReadBuffer.length < head)
- { if (ctx->partialReadBuffer.data)
- if ((err = SSLFreeBuffer(&ctx->partialReadBuffer, ctx)) != 0)
- { SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
- return err;
- }
- if ((err = SSLAllocBuffer(&ctx->partialReadBuffer,
- DEFAULT_BUFFER_SIZE, ctx)) != 0)
- { SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
- return err;
- }
- }
-
- if (ctx->negProtocolVersion == SSL_Version_Undetermined) {
- if (ctx->amountRead < 1)
- { readData.length = 1 - ctx->amountRead;
- readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
- len = readData.length;
- err = sslIoRead(readData, &len, ctx);
- if(err != 0)
- { if (err == errSSLWouldBlock) {
- ctx->amountRead += len;
- return err;
- }
- else {
- /* abort */
- err = errSSLClosedAbort;
- if((ctx->protocolSide == kSSLClientSide) &&
- (ctx->amountRead == 0) &&
- (len == 0)) {
- /*
- * Detect "server refused to even try to negotiate"
- * error, when the server drops the connection before
- * sending a single byte.
- */
- switch(ctx->state) {
- case SSL_HdskStateServerHello:
- case SSL_HdskStateServerHelloUnknownVersion:
- sslHdskStateDebug("Server dropped initial connection\n");
- err = errSSLConnectionRefused;
- break;
- default:
- break;
- }
- }
- SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
- return err;
- }
- }
- ctx->amountRead += len;
- }
- }
-
- if (ctx->amountRead < head)
- { readData.length = head - ctx->amountRead;
- readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
- len = readData.length;
- err = sslIoRead(readData, &len, ctx);
- if(err != 0)
- {
- switch(err) {
- case errSSLWouldBlock:
- ctx->amountRead += len;
- break;
- #if SSL_ALLOW_UNNOTICED_DISCONNECT
- case errSSLClosedGraceful:
- /* legal if we're on record boundary and we've gotten past
- * the handshake */
- if((ctx->amountRead == 0) && /* nothing pending */
- (len == 0) && /* nothing new */
- (ctx->state == SSL_HdskStateClientReady)) { /* handshake done */
- /*
- * This means that the server has disconnected without
- * sending a closure alert notice. This is technically
- * illegal per the SSL3 spec, but about half of the
- * servers out there do it, so we report it as a separate
- * error which most clients - including (currently)
- * URLAccess - ignore by treating it the same as
- * a errSSLClosedGraceful error. Paranoid
- * clients can detect it and handle it however they
- * want to.
- */
- SSLChangeHdskState(ctx, SSL_HdskStateNoNotifyClose);
- err = errSSLClosedNoNotify;
- break;
- }
- else {
- /* illegal disconnect */
- err = errSSLClosedAbort;
- /* and drop thru to default: fatal alert */
- }
- #endif /* SSL_ALLOW_UNNOTICED_DISCONNECT */
- default:
- SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
- break;
- }
- return err;
- }
- ctx->amountRead += len;
- }
-
- assert(ctx->amountRead >= head);
-
- charPtr = ctx->partialReadBuffer.data;
- rec->contentType = *charPtr++;
- if (rec->contentType < SSL_RecordTypeV3_Smallest ||
- rec->contentType > SSL_RecordTypeV3_Largest)
- return errSSLProtocol;
-
- rec->protocolVersion = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2);
- charPtr += 2;
-
-#if ENABLE_DTLS
- if(rec->protocolVersion == DTLS_Version_1_0)
- {
- sslUint64 seqNum;
- SSLDecodeUInt64(charPtr, 8, &seqNum);
- charPtr += 8;
- sslLogRecordIo("Read DTLS Record %08x_%08x (seq is: %08x_%08x)",
- seqNum.high, seqNum.low,
- ctx->readCipher.sequenceNum.high,ctx->readCipher.sequenceNum.low);
-
- /* if the epoch of the record is different of current read cipher, just drop it */
- if((seqNum.high>>8)!=(ctx->readCipher.sequenceNum.high>>8)) {
- skipit=1;
- } else {
- ctx->readCipher.sequenceNum.high=seqNum.high;
- ctx->readCipher.sequenceNum.low=seqNum.low;
- }
- }
-#endif
-
- contentLen = SSLDecodeInt(charPtr, 2);
- charPtr += 2;
- if (contentLen > (16384 + 2048)) /* Maximum legal length of an
- * SSLCipherText payload */
- { SSLFatalSessionAlert(SSL_AlertRecordOverflow, ctx);
- return errSSLProtocol;
+static OSStatus errorTranslate(int recordErr)
+{
+ switch(recordErr) {
+ case errSecSuccess:
+ return errSecSuccess;
+ case errSSLRecordInternal:
+ return errSSLInternal;
+ case errSSLRecordWouldBlock:
+ return errSSLWouldBlock;
+ case errSSLRecordProtocol:
+ return errSSLProtocol;
+ case errSSLRecordNegotiation:
+ return errSSLNegotiation;
+ case errSSLRecordClosedAbort:
+ return errSSLClosedAbort;
+ case errSSLRecordConnectionRefused:
+ return errSSLConnectionRefused;
+ case errSSLRecordDecryptionFail:
+ return errSSLDecryptionFail;
+ case errSSLRecordBadRecordMac:
+ return errSSLBadRecordMac;
+ case errSSLRecordRecordOverflow:
+ return errSSLRecordOverflow;
+ case errSSLRecordUnexpectedRecord:
+ return errSSLUnexpectedRecord;
+ default:
+ sslErrorLog("unknown error code returned in sslErrorTranslate: %d\n", recordErr);
+ return recordErr;