+ is_v2_record = RECORD_LAYER_is_sslv2_record(&s->rlayer);
+
+ PACKET_null_init(&cookie);
+ /* First lets get s->client_version set correctly */
+ if (is_v2_record) {
+ unsigned int version;
+ unsigned int mt;
+ /*-
+ * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
+ * header is sent directly on the wire, not wrapped as a TLS
+ * record. Our record layer just processes the message length and passes
+ * the rest right through. Its format is:
+ * Byte Content
+ * 0-1 msg_length - decoded by the record layer
+ * 2 msg_type - s->init_msg points here
+ * 3-4 version
+ * 5-6 cipher_spec_length
+ * 7-8 session_id_length
+ * 9-10 challenge_length
+ * ... ...
+ */
+
+ if (!PACKET_get_1(&pkt, &mt)
+ || mt != SSL2_MT_CLIENT_HELLO) {
+ /*
+ * Should never happen. We should have tested this in the record
+ * layer in order to have determined that this is a SSLv2 record
+ * in the first place
+ */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!PACKET_get_net_2(&pkt, &version)) {
+ /* No protocol version supplied! */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ if (version == 0x0002) {
+ /* This is real SSLv2. We don't support it. */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ } else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
+ /* SSLv3/TLS */
+ s->client_version = version;
+ } else {
+ /* No idea what protocol this is */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ } else {
+ /*
+ * use version from inside client hello, not from record header (may
+ * differ: see RFC 2246, Appendix E, second paragraph)
+ */
+ if(!PACKET_get_net_2(&pkt, (unsigned int *)&s->client_version)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ }
+
+ /* Do SSL/TLS version negotiation if applicable */
+ if (!SSL_IS_DTLS(s)) {
+ if (s->version != TLS_ANY_VERSION) {
+ if (s->client_version >= s->version) {
+ protverr = 0;
+ }
+ } else if (s->client_version >= SSL3_VERSION) {
+ switch(s->client_version) {
+ default:
+ case TLS1_2_VERSION:
+ if(!(s->options & SSL_OP_NO_TLSv1_2)) {
+ s->version = TLS1_2_VERSION;
+ s->method = TLSv1_2_server_method();
+ protverr = 0;
+ break;
+ }
+ /* Deliberately fall through */
+ case TLS1_1_VERSION:
+ if(!(s->options & SSL_OP_NO_TLSv1_1)) {
+ s->version = TLS1_1_VERSION;
+ s->method = TLSv1_1_server_method();
+ protverr = 0;
+ break;
+ }
+ /* Deliberately fall through */
+ case TLS1_VERSION:
+ if(!(s->options & SSL_OP_NO_TLSv1)) {
+ s->version = TLS1_VERSION;
+ s->method = TLSv1_server_method();
+ protverr = 0;
+ break;
+ }
+ /* Deliberately fall through */
+ case SSL3_VERSION:
+#ifndef OPENSSL_NO_SSL3
+ if(!(s->options & SSL_OP_NO_SSLv3)) {
+ s->version = SSL3_VERSION;
+ s->method = SSLv3_server_method();
+ protverr = 0;
+ break;
+ }
+#else
+ break;
+#endif
+ }
+ }
+ } else if (s->client_version <= s->version
+ || s->method->version == DTLS_ANY_VERSION) {
+ /*
+ * For DTLS we just check versions are potentially compatible. Version
+ * negotiation comes later.
+ */
+ protverr = 0;
+ }
+
+ if (protverr) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ if ((!s->enc_write_ctx && !s->write_hash)) {