- s2n(0,d);
-
- if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
- ch_len=SSL2_CHALLENGE_LENGTH;
- else
- ch_len=SSL2_MAX_CHALLENGE_LENGTH;
-
- /* write out sslv2 challenge */
- if (SSL3_RANDOM_SIZE < ch_len)
- i=SSL3_RANDOM_SIZE;
- else
- i=ch_len;
- s2n(i,d);
- memset(&(s->s3->client_random[0]),0,SSL3_RANDOM_SIZE);
- RAND_bytes(&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
- memcpy(p,&(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
- p+=i;
-
- i= p- &(buf[2]);
- buf[0]=((i>>8)&0xff)|0x80;
- buf[1]=(i&0xff);
-
- s->state=SSL23_ST_CW_CLNT_HELLO_B;
- /* number of bytes to write */
- s->init_num=i+2;
- s->init_off=0;
-
- ssl3_finish_mac(s,&(buf[2]),i);
- }
-
- /* SSL3_ST_CW_CLNT_HELLO_B */
- return(ssl23_write_bytes(s));
- }
-
-static int ssl23_get_server_hello(s)
-SSL *s;
- {
- char buf[8];
- unsigned char *p;
- int i,ch_len;
- int n;
-
- n=ssl23_read_bytes(s,7);
-
- if (n != 7) return(n);
- p=s->packet;
-
- memcpy(buf,p,n);
-
- if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) &&
- (p[5] == 0x00) && (p[6] == 0x02))
- {
- /* we are talking sslv2 */
- /* we need to clean up the SSLv3 setup and put in the
- * sslv2 stuff. */
-
- if (s->options & SSL_OP_NO_SSLv2)
- {
- SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
- goto err;
- }
- if (s->s2 == NULL)
- {
- if (!ssl2_new(s))
- goto err;
- }
- else
- ssl2_clear(s);
-
- if (s->options & SSL_OP_NETSCAPE_CHALLENGE_BUG)
- ch_len=SSL2_CHALLENGE_LENGTH;
- else
- ch_len=SSL2_MAX_CHALLENGE_LENGTH;
-
- /* write out sslv2 challenge */
- i=(SSL3_RANDOM_SIZE < ch_len)
- ?SSL3_RANDOM_SIZE:ch_len;
- s->s2->challenge_length=i;
- memcpy(s->s2->challenge,
- &(s->s3->client_random[SSL3_RANDOM_SIZE-i]),i);
-
- if (s->s3 != NULL) ssl3_free(s);
-
- if (!BUF_MEM_grow(s->init_buf,
- SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER))
- {
- SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,ERR_R_BUF_LIB);
- goto err;
- }
-
- s->state=SSL2_ST_GET_SERVER_HELLO_A;
- s->s2->ssl2_rollback=1;
-
- /* setup the 5 bytes we have read so we get them from
- * the sslv2 buffer */
- s->rstate=SSL_ST_READ_HEADER;
- s->packet_length=n;
- s->packet= &(s->s2->rbuf[0]);
- memcpy(s->packet,buf,n);
- s->s2->rbuf_left=n;
- s->s2->rbuf_offs=0;
-
- /* we have already written one */
- s->s2->write_sequence=1;
-
- s->method=SSLv2_client_method();
- s->handshake_func=s->method->ssl_connect;
- }
- else if ((p[0] == SSL3_RT_HANDSHAKE) &&
- (p[1] == SSL3_VERSION_MAJOR) &&
- ((p[2] == SSL3_VERSION_MINOR) ||
- (p[2] == TLS1_VERSION_MINOR)) &&
- (p[5] == SSL3_MT_SERVER_HELLO))
- {
- /* we have sslv3 or tls1 */
-
- if (!ssl_init_wbio_buffer(s,1)) goto err;
-
- /* we are in this state */
- s->state=SSL3_ST_CR_SRVR_HELLO_A;
-
- /* put the 5 bytes we have read into the input buffer
- * for SSLv3 */
- s->rstate=SSL_ST_READ_HEADER;
- s->packet_length=n;
- s->packet= &(s->s3->rbuf.buf[0]);
- memcpy(s->packet,buf,n);
- s->s3->rbuf.left=n;
- s->s3->rbuf.offset=0;
-
- if ((p[2] == SSL3_VERSION_MINOR) &&
- !(s->options & SSL_OP_NO_SSLv3))
- {
- s->version=SSL3_VERSION;
- s->method=SSLv3_client_method();
- }
- else if ((p[2] == TLS1_VERSION_MINOR) &&
- !(s->options & SSL_OP_NO_TLSv1))
- {
- s->version=TLS1_VERSION;
- s->method=TLSv1_client_method();
- }
- else
- {
- SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
- goto err;
- }
-
- s->handshake_func=s->method->ssl_connect;
- }
- else if ((p[0] == SSL3_RT_ALERT) &&
- (p[1] == SSL3_VERSION_MAJOR) &&
- ((p[2] == SSL3_VERSION_MINOR) ||
- (p[2] == TLS1_VERSION_MINOR)) &&
- (p[3] == 0) &&
- (p[4] == 2))
- {
- void (*cb)()=NULL;
- int j;
-
- /* An alert */
- if (s->info_callback != NULL)
- cb=s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb=s->ctx->info_callback;
-
- i=p[5];
- if (cb != NULL)
- {
- j=(i<<8)|p[6];
- cb(s,SSL_CB_READ_ALERT,j);
- }
-
- s->rwstate=SSL_NOTHING;
- SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,1000+p[6]);
- goto err;
- }
- else
- {
- SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNKNOWN_PROTOCOL);
- goto err;
- }
- s->init_num=0;
-
- /* Since, if we are sending a ssl23 client hello, we are not
- * reusing a session-id */
- if (!ssl_get_new_session(s,0))
- goto err;
-
- s->first_packet=1;
- return(SSL_connect(s));
-err:
- return(-1);
- }