#include #include "ssl_locl.h" #include #include #include #include #include //#define DEBUG static const SSL_METHOD *spp_get_server_method(int ver); static const SSL_METHOD *spp_get_server_method(int ver) { if (ver == SPP_VERSION) return SPP_server_method(); return NULL; } IMPLEMENT_spp_meth_func(SPP_VERSION, SPP_server_method, spp_accept, ssl_undefined_function, spp_get_server_method) int spp_accept(SSL *s) { BUF_MEM *buf; SPP_PROXY *proxy=NULL; unsigned long alg_k,Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1,i; int new_state,state,skip=0; /* Matteo -- START */ struct timeval currTime; // keep current time struct timeval prevTime; // keep previous time (to compute time passed) struct timeval originTime; // keep previous time (to compute time passed) /* Matteo -- END*/ RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); clear_sys_error(); if (s->info_callback != NULL) cb=s->info_callback; else if (s->ctx->info_callback != NULL) cb=s->ctx->info_callback; /* init things to blank */ s->in_handshake++; if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); if (s->cert == NULL) { SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_NO_CERTIFICATE_SET); return(-1); } #ifndef OPENSSL_NO_HEARTBEATS /* If we're awaiting a HeartbeatResponse, pretend we * already got and don't await it anymore, because * Heartbeats don't make sense during handshakes anyway. */ if (s->tlsext_hb_pending) { s->tlsext_hb_pending = 0; s->tlsext_hb_seq++; } #endif for (;;) { state=s->state; switch (s->state) { case SSL_ST_RENEGOTIATE: s->renegotiate=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: case SSL_ST_ACCEPT: case SSL_ST_BEFORE|SSL_ST_ACCEPT: case SSL_ST_OK|SSL_ST_ACCEPT: // Initialize timers gettimeofday(&currTime, NULL); gettimeofday(&prevTime, NULL); gettimeofday(&originTime, NULL); // Log #ifdef DEBUG log_time("Before state\n", &currTime, &prevTime, &originTime); #endif s->server=1; s->proxy = 0; s->proxy_id = 2; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); if ((s->version>>8) != 6) { SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); return -1; } s->type=SSL_ST_ACCEPT; if (s->init_buf == NULL) { if ((buf=BUF_MEM_new()) == NULL) { ret= -1; goto end; } if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH)) { ret= -1; goto end; } s->init_buf=buf; } if (!ssl3_setup_buffers(s)) { ret= -1; goto end; } s->init_num=0; s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE; if (s->state != SSL_ST_RENEGOTIATE) { /* Ok, we now need to push on a buffering BIO so that * the output is sent in a way that TCP likes :-) */ if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; } ssl3_init_finished_mac(s); s->state=SSL3_ST_SR_CLNT_HELLO_A; s->ctx->stats.sess_accept++; } else if (!s->s3->send_connection_binding && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { /* Server attempting to renegotiate with * client that doesn't support secure * renegotiation. */ SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); ret = -1; goto end; } else { /* s->state == SSL_ST_RENEGOTIATE, * we will just send a HelloRequest */ s->ctx->stats.sess_accept_renegotiate++; s->state=SSL3_ST_SW_HELLO_REQ_A; } break; case SSL3_ST_SW_HELLO_REQ_A: case SSL3_ST_SW_HELLO_REQ_B: s->shutdown=0; #ifdef DEBUG log_time("Sending hello request\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; ssl3_init_finished_mac(s); break; case SSL3_ST_SW_HELLO_REQ_C: s->state=SSL_ST_OK; break; case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: s->shutdown=0; if (s->rwstate != SSL_X509_LOOKUP) { ret=ssl3_get_client_hello(s); #ifdef DEBUG log_time("Received client hello\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; if (!spp_generate_slice_keys(s)) goto end; } /* #ifndef OPENSSL_NO_SRP { int al; if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) < 0) { // callback indicates firther work to be done s->rwstate=SSL_X509_LOOKUP; goto end; } if (ret != SSL_ERROR_NONE) { ssl3_send_alert(s,SSL3_AL_FATAL,al); // This is not really an error but the only means to // for a client to detect whether srp is supported. if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY) SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT); ret = SSL_TLSEXT_ERR_ALERT_FATAL; ret= -1; goto end; } } #endif */ s->renegotiate = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; break; case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: #ifdef DEBUG log_time("Sending server hello\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_server_hello(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->hit) { if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else s->state=SSL3_ST_SW_CHANGE_A; } #else if (s->hit) s->state=SSL3_ST_SW_CHANGE_A; #endif else s->state=SSL3_ST_SW_CERT_A; s->init_num=0; break; case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH, */ /* normal PSK or KRB5 or SRP */ if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aKRB5|SSL_aSRP)) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { #ifdef DEBUG log_time("Sending certificate\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_status_expected) s->state=SSL3_ST_SW_CERT_STATUS_A; else s->state=SSL3_ST_SW_KEY_EXCH_A; } else { skip = 1; s->state=SSL3_ST_SW_KEY_EXCH_A; } #else } else skip=1; s->state=SSL3_ST_SW_KEY_EXCH_A; #endif s->init_num=0; break; case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* clear this, it may get reset by * send_server_key_exchange */ if ((s->options & SSL_OP_EPHEMERAL_RSA) #ifndef OPENSSL_NO_KRB5 && !(alg_k & SSL_kKRB5) #endif /* OPENSSL_NO_KRB5 */ ) /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key * even when forbidden by protocol specs * (handshake may fail as clients are not required to * be able to handle this) */ s->s3->tmp.use_rsa_tmp=1; else s->s3->tmp.use_rsa_tmp=0; /* only send if a DH key exchange, fortezza or * RSA but we have a sign only certificate * * PSK: may send PSK identity hints * * For ECC ciphersuites, we send a serverKeyExchange * message only if the cipher suite is either * ECDH-anon or ECDHE. In other cases, the * server certificate contains the server's * public key for key exchange. */ if (s->s3->tmp.use_rsa_tmp /* PSK: send ServerKeyExchange if PSK identity * hint if provided */ #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif #ifndef OPENSSL_NO_SRP /* SRP: send ServerKeyExchange */ || (alg_k & SSL_kSRP) #endif || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH)) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) ) ) ) ) { #ifdef DEBUG log_time("Sending server key exchange\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; } else skip=1; s->state=SSL3_ST_SW_CERT_REQ_A; s->init_num=0; break; case SSL3_ST_SW_CERT_REQ_A: case SSL3_ST_SW_CERT_REQ_B: if (/* don't request cert unless asked for it: */ !(s->verify_mode & SSL_VERIFY_PEER) || /* if SSL_VERIFY_CLIENT_ONCE is set, * don't request cert during re-negotiation: */ ((s->session->peer != NULL) && (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || /* never request cert in anonymous ciphersuites * (see section "Certificate request" in SSL 3 drafts * and in RFC 2246): */ ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && /* ... except when the application insists on verification * (against the specs, but s3_clnt.c accepts this for SSL 3) */ !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* never request cert in Kerberos ciphersuites */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) || /* don't request certificate for SRP auth */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) /* With normal PSK Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { /* no cert request */ skip=1; s->s3->tmp.cert_request=0; s->state=SSL3_ST_SW_SRVR_DONE_A; if (s->s3->handshake_buffer) if (!ssl3_digest_cached_records(s)) return -1; } else { s->s3->tmp.cert_request=1; #ifdef DEBUG log_time("Sending certificate request\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; #else s->state=SSL3_ST_SW_FLUSH; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; #endif s->init_num=0; } break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: #ifdef DEBUG log_time("Sending server done\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_server_done(s); #ifdef DEBUG log_time("Sent server done\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; s->state=SSL3_ST_SW_FLUSH; s->init_num=0; break; case SSL3_ST_SW_FLUSH: /* This code originally checked to see if * any data was pending using BIO_CTRL_INFO * and then flushed. This caused problems * as documented in PR#1939. The proposed * fix doesn't completely resolve this issue * as buggy implementations of BIO_CTRL_PENDING * still exist. So instead we just flush * unconditionally. */ s->rwstate=SSL_WRITING; if (BIO_flush(s->wbio) <= 0) { ret= -1; goto end; } s->rwstate=SSL_NOTHING; s->state=s->s3->tmp.next_state; break; case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: /* Check for second client hello (MS SGC) */ #ifdef DEBUG log_time("Checking for second client hello\n", &currTime, &prevTime, &originTime); #endif ret = ssl3_check_client_hello(s); #ifdef DEBUG log_time("Checked for second client hello\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; if (ret == 2) s->state = SSL3_ST_SR_CLNT_HELLO_C; else { if (s->s3->tmp.cert_request) { #ifdef DEBUG log_time("Receiving required client certificate\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_get_client_certificate(s); if (ret <= 0) goto end; } proxy = spp_get_next_proxy(s, proxy, 0); if (proxy == NULL) { s->state=SSL3_ST_SR_KEY_EXCH_A; } else { s->state=SPP_ST_CR_PRXY_CERT_A; } s->init_num=0; } break; case SPP_ST_CR_PRXY_CERT_A: case SPP_ST_CR_PRXY_CERT_B: #ifdef DEBUG log_time("Waiting for proxy certificate\n", &currTime, &prevTime, &originTime); #endif ret=spp_get_proxy_certificate(s, proxy); #ifdef DEBUG log_time("Received proxy certificate\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; s->state=SPP_ST_CR_PRXY_KEY_EXCH_A; s->init_num=0; break; /* Receive the hello messages from the proxies now. */ case SPP_ST_CR_PRXY_KEY_EXCH_A: case SPP_ST_CR_PRXY_KEY_EXCH_B: ret=spp_get_proxy_key_exchange(s, proxy); #ifdef DEBUG log_time("Received proxy key exchange\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; s->state=SPP_ST_CR_PRXY_DONE_A; s->init_num=0; break; case SPP_ST_CR_PRXY_DONE_A: case SPP_ST_CR_PRXY_DONE_B: ret=spp_get_proxy_done(s, proxy); #ifdef DEBUG log_time("Received proxy done\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; proxy = spp_get_next_proxy(s, proxy, 0); if (proxy == NULL) { s->state=SSL3_ST_SR_KEY_EXCH_A; } else { /* Go back and read the next proxy */ s->state=SPP_ST_CR_PRXY_CERT_A; } s->init_num=0; break; case SSL3_ST_SR_KEY_EXCH_A: case SSL3_ST_SR_KEY_EXCH_B: #ifdef DEBUG log_time("Receiving client key exchange\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_get_client_key_exchange(s); #ifdef DEBUG log_time("Received client key exchange\n", &currTime, &prevTime, &originTime); #endif if (ret <= 0) goto end; if (ret == 2) { /* For the ECDH ciphersuites when * the client sends its ECDH pub key in * a certificate, the CertificateVerify * message is not sent. * Also for GOST ciphersuites when * the client uses its key from the certificate * for key exchange. */ s->state = SPP_ST_CR_PRXY_MAT_A; s->init_num = 0; } else if (TLS1_get_version(s) >= TLS1_2_VERSION) { s->state=SPP_ST_CR_PRXY_MAT_A; s->init_num=0; if (!s->session->peer) break; /* For TLS v1.2 freeze the handshake buffer * at this point and digest cached records. */ if (!s->s3->handshake_buffer) { SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR); return -1; } s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; if (!ssl3_digest_cached_records(s)) return -1; } else { int offset=0; int dgst_num; s->state=SPP_ST_CR_PRXY_MAT_A; s->init_num=0; /* We need to get hashes here so if there is * a client cert, it can be verified * FIXME - digest processing for CertificateVerify * should be generalized. But it is next step */ if (s->s3->handshake_buffer) if (!ssl3_digest_cached_records(s)) return -1; for (dgst_num=0; dgst_nums3->handshake_dgst[dgst_num]) { int dgst_size; s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset])); dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]); if (dgst_size < 0) { ret = -1; goto end; } offset+=dgst_size; } } break; /* Send the proxy key material. */ case SPP_ST_CW_PRXY_MAT_A: case SPP_ST_CW_PRXY_MAT_B: #ifdef DEBUG log_time("Sending proxy key material\n", &currTime, &prevTime, &originTime); #endif for (i = 0; i < s->proxies_len; i++) { ret=spp_send_proxy_key_material(s, s->proxies[i]); if (ret <= 0) goto end; s->state = SPP_ST_CW_PRXY_MAT_A; s->init_num=0; } ret=spp_send_end_key_material_server(s); #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_ticket_expected) s->state=SSL3_ST_SW_SESSION_TICKET_A; else #endif s->state=SSL3_ST_SW_CHANGE_A; //s->s3->change_cipher_spec=0; s->init_num=0; break; case SPP_ST_CR_PRXY_MAT_A: case SPP_ST_CR_PRXY_MAT_B: #ifdef DEBUG log_time("Receiving proxy key material\n", &currTime, &prevTime, &originTime); #endif for (i = s->proxies_len-1; i >= 0; i--) { ret=spp_get_proxy_key_material(s, s->proxies[i]); if (ret <= 0) goto end; s->state = SPP_ST_CR_PRXY_MAT_A; s->init_num=0; } ret=spp_get_end_key_material_server(s); if (ret <= 0) goto end; #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->state=SSL3_ST_SR_FINISHED_A; #else if (s->s3->next_proto_neg_seen) s->state=SSL3_ST_SR_NEXT_PROTO_A; else s->state=SSL3_ST_SR_FINISHED_A; #endif s->s3->change_cipher_spec=0; s->init_num=0; break; case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: #ifdef DEBUG log_time("Receiving cert verify\n", &currTime, &prevTime, &originTime); #endif s->s3->flags |= SSL3_FLAGS_CCS_OK; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->state=SSL3_ST_SR_FINISHED_A; #else if (s->s3->next_proto_neg_seen) s->state=SSL3_ST_SR_NEXT_PROTO_A; else s->state=SSL3_ST_SR_FINISHED_A; #endif s->init_num=0; break; #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) case SSL3_ST_SR_NEXT_PROTO_A: case SSL3_ST_SR_NEXT_PROTO_B: #ifdef DEBUG log_time("Receiving next proto\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_get_next_proto(s); if (ret <= 0) goto end; s->init_num = 0; s->state=SSL3_ST_SR_FINISHED_A; break; #endif case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: #ifdef DEBUG log_time("Receiving client finished\n", &currTime, &prevTime, &originTime); #endif s->s3->flags |= SSL3_FLAGS_CCS_OK; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret <= 0) goto end; if (s->hit) s->state=SSL_ST_OK; s->state=SPP_ST_CW_PRXY_MAT_A; s->init_num=0; break; #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: #ifdef DEBUG log_time("Sending session ticket\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; break; case SSL3_ST_SW_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: #ifdef DEBUG log_time("Sending cert status\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_cert_status(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_KEY_EXCH_A; s->init_num=0; break; #endif case SSL3_ST_SW_CHANGE_A: case SSL3_ST_SW_CHANGE_B: s->session->cipher=s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret= -1; goto end; } #ifdef DEBUG log_time("Sending change cipher state\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FINISHED_A; s->init_num=0; if (!s->method->ssl3_enc->change_cipher_state(s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret= -1; goto end; } break; case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: #ifdef DEBUG log_time("Sending server finished\n", &currTime, &prevTime, &originTime); #endif ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) { #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; #else if (s->s3->next_proto_neg_seen) { s->s3->flags |= SSL3_FLAGS_CCS_OK; s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A; } else s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; #endif } else s->s3->tmp.next_state=SSL_ST_OK; s->init_num=0; // Store the values for end-to-end integrity checking if (spp_init_integrity_st(s) <= 0) goto end; /* Setup the slices now that we have the necessary state. */ ret = spp_init_slices_st(s, SSL3_CHANGE_CIPHER_SERVER_WRITE); if (ret <= 0) goto end; ret = spp_init_slices_st(s, SSL3_CHANGE_CIPHER_SERVER_READ); if (ret <= 0) goto end; break; case SSL_ST_OK: #ifdef DEBUG log_time("Handshake OK\n", &currTime, &prevTime, &originTime); #endif /* clean a few things up */ ssl3_cleanup_key_block(s); BUF_MEM_free(s->init_buf); s->init_buf=NULL; /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num=0; if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; /* s->server=1; */ s->handshake_func=spp_accept; if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); } ret = 1; goto end; /* break; */ default: SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_UNKNOWN_STATE); ret= -1; goto end; /* break; */ } if (!s->s3->tmp.reuse_message && !skip) { if (s->debug) { if ((ret=BIO_flush(s->wbio)) <= 0) goto end; } if ((cb != NULL) && (s->state != state)) { new_state=s->state; s->state=state; cb(s,SSL_CB_ACCEPT_LOOP,1); s->state=new_state; } } skip=0; } end: #ifdef DEBUG log_time("Handshake end\n", &currTime, &prevTime, &originTime); #endif /* BIO_flush(s->wbio); */ s->in_handshake--; if (cb != NULL) cb(s,SSL_CB_ACCEPT_EXIT,ret); return(ret); }