- {
- BUF_MEM *buf;
- unsigned long Time=(unsigned long)time(NULL);
- void (*cb)(const SSL *ssl,int type,int val)=NULL;
- long num1;
- unsigned long alg_k;
- int ret= -1;
- int new_state,state,skip=0;
-
- 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_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
- return(-1);
- }
-
- for (;;)
- {
- state=s->state;
-
- switch (s->state)
- {
- case SSL_ST_RENEGOTIATE:
- s->new_session=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:
-
- s->server=1;
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
-
- if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00))
- {
- SSLerr(SSL_F_DTLS1_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;
-
- 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
- {
- /* 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;
- }
-
- if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
- s->d1->send_cookie = 1;
- else
- s->d1->send_cookie = 0;
-
- break;
-
- case SSL3_ST_SW_HELLO_REQ_A:
- case SSL3_ST_SW_HELLO_REQ_B:
-
- s->shutdown=0;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
- ret=dtls1_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;
- ret=ssl3_get_client_hello(s);
- if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
- s->new_session = 2;
-
- if (s->d1->send_cookie)
- s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
- else
- s->state = SSL3_ST_SW_SRVR_HELLO_A;
-
- s->init_num=0;
- break;
-
- case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
- case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
-
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
- ret = dtls1_send_hello_verify_request(s);
- if ( ret <= 0) goto end;
- s->d1->send_cookie = 0;
- s->state=SSL3_ST_SW_FLUSH;
- s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
-
- /* HelloVerifyRequest resets Finished MAC */
- ssl3_init_finished_mac(s);
- break;
-
- case SSL3_ST_SW_SRVR_HELLO_A:
- case SSL3_ST_SW_SRVR_HELLO_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
- ret=dtls1_send_server_hello(s);
- if (ret <= 0) goto end;
-
- if (s->hit)
- s->state=SSL3_ST_SW_CHANGE_A;
- 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 */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
- {
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
- ret=dtls1_send_server_certificate(s);
- if (ret <= 0) goto end;
- }
- else
- skip=1;
- s->state=SSL3_ST_SW_KEY_EXCH_A;
- 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 or
- * RSA but we have a sign only certificate */
- if (s->s3->tmp.use_rsa_tmp
- || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
- || ((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)
- )
- )
- )
- )
- {
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
- ret=dtls1_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))
- {
- /* no cert request */
- skip=1;
- s->s3->tmp.cert_request=0;
- s->state=SSL3_ST_SW_SRVR_DONE_A;
- }
- else
- {
- s->s3->tmp.cert_request=1;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
- ret=dtls1_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;