ssl3con.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,928 行 · 第 1/5 页
C
1,928 行
/* ssl_ReleaseSpecReadLock(ss); */ PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength)); if (rv != SECSuccess) { rv = SECFailure; ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); } return rv;}/* Process the plain text before sending it. * Returns the number of bytes of plaintext that were succesfully sent * plus the number of bytes of plaintext that were copied into the * output (write) buffer. * Returns SECFailure on a hard IO error, memory error, or crypto error. * Does NOT return SECWouldBlock. */static PRInt32ssl3_SendRecord( sslSocket * ss, SSL3ContentType type, const SSL3Opaque * buf, PRInt32 bytes, PRInt32 flags){ ssl3CipherSpec * cwSpec; sslBuffer * write = &ss->sec->writeBuf; const ssl3BulkCipherDef * cipher_def; SECStatus rv; PRUint32 bufSize = 0; PRInt32 sent = 0; PRInt32 cipherBytes = -1; PRBool isBlocking = ssl_SocketIsBlocking(ss); PRBool ssl3WasNull = PR_FALSE; SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s bytes=%d", SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), bytes)); PRINT_BUF(3, (ss, "Send record (plain text)", buf, bytes)); PORT_Assert( ssl_HaveXmitBufLock(ss) ); if (ss->ssl3 == NULL) { /* This can happen on a server if the very first incoming record ** looks like a defective ssl3 record (e.g. too long), and we're ** trying to send an alert. */ ssl3WasNull = PR_TRUE; PR_ASSERT(type == content_alert); rv = ssl3_InitState(ss); if (rv != SECSuccess) { return SECFailure; /* ssl3_InitState has set the error code. */ } } while (bytes > 0) { PRInt32 count; PRUint32 contentLen; PRUint32 fragLen; PRUint32 macLen; contentLen = PR_MIN(bytes, MAX_FRAGMENT_LENGTH); if (write->space < contentLen + SSL3_BUFFER_FUDGE) { rv = sslBuffer_Grow(write, contentLen + SSL3_BUFFER_FUDGE); if (rv != SECSuccess) { SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes", SSL_GETPID(), ss->fd, contentLen + SSL3_BUFFER_FUDGE)); return SECFailure; /* sslBuffer_Grow set a memory error code. */ } } /* This variable records * the actual size of the buffer we allocated above. Some * algorithms (FORTEZZA) will expand the number of bytes it needs to * send data. If we only supply the output buffer with the same number * of bytes as the input buffer, we will fail. */ bufSize = contentLen + SSL3_BUFFER_FUDGE; /* * null compression is easy to do */ PORT_Memcpy(write->buf + SSL3_RECORD_HEADER_LENGTH, buf, contentLen); buf += contentLen; bytes -= contentLen; PORT_Assert( bytes >= 0 ); ssl_GetSpecReadLock(ss); /********************************/ cwSpec = ss->ssl3->cwSpec; cipher_def = cwSpec->cipher_def; /* * Add the MAC */ rv = ssl3_ComputeRecordMAC( cwSpec, (ss->sec->isServer) ? cwSpec->server.write_mac_context : cwSpec->client.write_mac_context, type, cwSpec->version, cwSpec->write_seq_num, write->buf + SSL3_RECORD_HEADER_LENGTH, contentLen, write->buf + contentLen + SSL3_RECORD_HEADER_LENGTH, &macLen); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); goto spec_locked_loser; } fragLen = contentLen + macLen; /* needs to be encrypted */ PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024); /* * Pad the text (if we're doing a block cipher) * then Encrypt it */ if (cipher_def->type == type_block) { int padding_length; int i; unsigned char * pBuf; /* Assume blockSize is a power of two */ padding_length = cipher_def->block_size - 1 - ((fragLen) & (cipher_def->block_size - 1)); fragLen += padding_length + 1; PORT_Assert((fragLen % cipher_def->block_size) == 0); /* Pad according to TLS rules (also acceptable to SSL3). */ pBuf = &write->buf[fragLen + SSL3_RECORD_HEADER_LENGTH - 1]; for (i = padding_length + 1; i > 0; --i) { *pBuf-- = padding_length; } } rv = cwSpec->encode( cwSpec->encodeContext, write->buf + SSL3_RECORD_HEADER_LENGTH, &cipherBytes, bufSize, write->buf + SSL3_RECORD_HEADER_LENGTH, fragLen); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_ENCRYPTION_FAILURE);spec_locked_loser: ssl_ReleaseSpecReadLock(ss); return SECFailure; } PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024); /* * XXX should we zero out our copy of the buffer after compressing * and encryption ?? */ ssl3_BumpSequenceNumber(&cwSpec->write_seq_num); ssl_ReleaseSpecReadLock(ss); /************************************/ /* PORT_Assert(fragLen == cipherBytes); */ write->len = cipherBytes + SSL3_RECORD_HEADER_LENGTH; write->buf[0] = type; write->buf[1] = MSB(cwSpec->version); write->buf[2] = LSB(cwSpec->version); write->buf[3] = MSB(cipherBytes); write->buf[4] = LSB(cipherBytes); PRINT_BUF(50, (ss, "send (encrypted) record data:", write->buf, write->len)); /* If there's still some previously saved ciphertext, * or the caller doesn't want us to send the data yet, * then add all our new ciphertext to the amount previously saved. */ if ((ss->pendingBuf.len > 0) || (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { rv = ssl_SaveWriteData(ss, &ss->pendingBuf, write->buf, write->len); if (rv != SECSuccess) { /* presumably a memory error, SEC_ERROR_NO_MEMORY */ return SECFailure; } write->len = 0; /* All cipher text is saved away. */ if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { count = ssl_SendSavedWriteData(ss, &ss->pendingBuf, &ssl_DefSend); if (count < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) { ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE); return SECFailure; } } } else if (write->len > 0) { count = ssl_DefSend(ss, write->buf, write->len, flags & ~ssl_SEND_FLAG_MASK); if (count < 0) { if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE); return (sent > 0) ? sent : SECFailure; } /* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */ count = 0; } /* now take all the remaining unsent newly-generated ciphertext and * append it to the buffer of previously unsent ciphertext. */ if ((unsigned)count < write->len) { rv = ssl_SaveWriteData(ss, &ss->pendingBuf, write->buf + (unsigned)count, write->len - (unsigned)count); if (rv != SECSuccess) { /* presumably a memory error, SEC_ERROR_NO_MEMORY */ return SECFailure; } } write->len = 0; } sent += contentLen; if ((flags & ssl_SEND_FLAG_NO_BUFFER) && (isBlocking || (ss->pendingBuf.len > 0))) { break; } } return sent;}/* Attempt to send the content of "in" in an SSL application_data record. * Returns "len" or SECFailure, never SECWouldBlock, nor SECSuccess. */intssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, PRInt32 len, PRInt32 flags){ PRInt32 sent = 0; PORT_Assert( ssl_HaveXmitBufLock(ss) ); while (len > 0) { PRInt32 count; if (sent > 0) { ssl_ReleaseXmitBufLock(ss); PR_Sleep(PR_INTERVAL_NO_WAIT); /* PR_Yield(); */ ssl_GetXmitBufLock(ss); } count = ssl3_SendRecord(ss, content_application_data, in, len, flags | ssl_SEND_FLAG_NO_BUFFER); if (count < 0) { return (sent > 0) ? sent : count; /* error code set by ssl3_SendRecord */ } sent += count; len -= count; in += count; } return sent;}/* Attempt to send the content of sendBuf buffer in an SSL handshake record. * This function returns SECSuccess or SECFailure, never SECWouldBlock. * It used to always set sendBuf.len to 0, even when returning SECFailure. * Now it does not. * * Called from SSL3_SendAlert(), ssl3_SendChangeCipherSpecs(), * ssl3_AppendHandshake(), ssl3_SendClientHello(), * ssl3_SendHelloRequest(), ssl3_SendServerHelloDone(), * ssl3_SendFinished(), */static SECStatusssl3_FlushHandshake(sslSocket *ss, PRInt32 flags){ PRInt32 rv; sslConnectInfo *ci; PORT_Assert(ss->sec != NULL); PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert( ssl_HaveXmitBufLock(ss) ); ci = &ss->sec->ci; if (!ci->sendBuf.buf || !ci->sendBuf.len) return SECSuccess; rv = ssl3_SendRecord(ss, content_handshake, ci->sendBuf.buf, ci->sendBuf.len, flags); if (rv < 0) { return (SECStatus)rv; /* error code set by ssl3_SendRecord */ } ci->sendBuf.len = 0; return SECSuccess;}/* * Called from ssl3_HandleAlert and from ssl3_HandleCertificates when * the remote client sends a negative response to our certificate request. * Returns SECFailure if the application has required client auth. * SECSuccess otherwise. */static SECStatusssl3_HandleNoCertificate(sslSocket *ss){ if (ss->sec->peerCert != NULL) { if (ss->sec->peerKey != NULL) { SECKEY_DestroyPublicKey(ss->sec->peerKey); ss->sec->peerKey = NULL; } CERT_DestroyCertificate(ss->sec->peerCert); ss->sec->peerCert = NULL; } /* If the server has required client-auth blindly but doesn't * actually look at the certificate it won't know that no * certificate was presented so we shutdown the socket to ensure * an error. We only do this if we aren't connected because * if we're redoing the handshake we know the server is paying * attention to the certificate. */ if ((ss->requireCertificate == 1) || (!ss->connected && (ss->requireCertificate > 1))) { PRFileDesc * lower; ss->sec->uncache(ss->sec->ci.sid); SSL3_SendAlert(ss, alert_fatal, bad_certificate); lower = ss->fd->lower; lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH); PORT_SetError(SSL_ERROR_NO_CERTIFICATE); return SECFailure; } return SECSuccess;}/************************************************************************ * Alerts *//*** Acquires both handshake and XmitBuf locks.** Called from: ssl3_IllegalParameter <-** ssl3_HandshakeFailure <-** ssl3_HandleAlert <- ssl3_HandleRecord.** ssl3_HandleChangeCipherSpecs <- ssl3_HandleRecord** ssl3_ConsumeHandshakeVariable <-** ssl3_HandleHelloRequest <-** ssl3_HandleServerHello <-** ssl3_HandleServerKeyExchange <-** ssl3_HandleCertificateRequest <-** ssl3_HandleServerHelloDone <-** ssl3_HandleClientHello <-** ssl3_HandleV2ClientHello <-** ssl3_HandleCertificateVerify <-** ssl3_HandleFortezzaClientKeyExchange <-** ssl3_HandleClientKeyExchange <-** ssl3_HandleCertificate <-** ssl3_HandleFinished <-** ssl3_HandleHandshakeMessage <-** ssl3_HandleRecord <-***/SECStatusSSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc){ uint8 bytes[2]; SECStatus rv; SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d", SSL_GETPID(), ss->fd, level, desc)); bytes[0] = level; bytes[1] = desc; ssl_GetSSL3HandshakeLock(ss); if (level == alert_fatal) { if (ss->sec->ci.sid) { ss->sec->uncache(ss->sec->ci.sid); } } ssl_GetXmitBufLock(ss); rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); if (rv == SECSuccess) { PRInt32 sent; sent = ssl3_SendRecord(ss, content_alert, bytes, 2, 0); rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; } ssl_ReleaseXmitBufLock(ss); ssl_ReleaseSSL3HandshakeLock(ss); return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */}/* * Send illegal_parameter alert. Set generic error number. */static SECStatusssl3_IllegalParameter(sslSocket *ss)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?