401 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			401 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| Index: crypto/openssl/crypto/asn1/a_object.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/crypto/asn1/a_object.c	(revision 270128)
 | |
| +++ crypto/openssl/crypto/asn1/a_object.c	(working copy)
 | |
| @@ -285,17 +285,29 @@ err:
 | |
|  		ASN1_OBJECT_free(ret);
 | |
|  	return(NULL);
 | |
|  }
 | |
| +
 | |
|  ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
 | |
|  	     long len)
 | |
|  	{
 | |
|  	ASN1_OBJECT *ret=NULL;
 | |
|  	const unsigned char *p;
 | |
| -	int i;
 | |
| -	/* Sanity check OID encoding: can't have leading 0x80 in
 | |
| -	 * subidentifiers, see: X.690 8.19.2
 | |
| +	int i, length;
 | |
| +
 | |
| +	/* Sanity check OID encoding.
 | |
| +	 * Need at least one content octet.
 | |
| +	 * MSB must be clear in the last octet.
 | |
| +	 * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
 | |
|  	 */
 | |
| -	for (i = 0, p = *pp; i < len; i++, p++)
 | |
| +	if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
 | |
| +	    p[len - 1] & 0x80)
 | |
|  		{
 | |
| +		ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
 | |
| +		return NULL;
 | |
| +		}
 | |
| +	/* Now 0 < len <= INT_MAX, so the cast is safe. */
 | |
| +	length = (int)len;
 | |
| +	for (i = 0; i < length; i++, p++)
 | |
| +		{
 | |
|  		if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
 | |
|  			{
 | |
|  			ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
 | |
| @@ -313,20 +325,20 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, cons
 | |
|  	else	ret=(*a);
 | |
|  
 | |
|  	p= *pp;
 | |
| -	if ((ret->data == NULL) || (ret->length < len))
 | |
| +	if ((ret->data == NULL) || (ret->length < length))
 | |
|  		{
 | |
|  		if (ret->data != NULL) OPENSSL_free(ret->data);
 | |
| -		ret->data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1);
 | |
| +		ret->data=(unsigned char *)OPENSSL_malloc(length);
 | |
|  		ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 | |
|  		if (ret->data == NULL)
 | |
|  			{ i=ERR_R_MALLOC_FAILURE; goto err; }
 | |
|  		}
 | |
| -	memcpy(ret->data,p,(int)len);
 | |
| -	ret->length=(int)len;
 | |
| +	memcpy(ret->data,p,length);
 | |
| +	ret->length=length;
 | |
|  	ret->sn=NULL;
 | |
|  	ret->ln=NULL;
 | |
|  	/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
 | |
| -	p+=len;
 | |
| +	p+=length;
 | |
|  
 | |
|  	if (a != NULL) (*a)=ret;
 | |
|  	*pp=p;
 | |
| Index: crypto/openssl/crypto/objects/obj_dat.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/crypto/objects/obj_dat.c	(revision 270128)
 | |
| +++ crypto/openssl/crypto/objects/obj_dat.c	(working copy)
 | |
| @@ -444,12 +444,13 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
 | |
|  	unsigned char *p;
 | |
|  	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 | |
|  
 | |
| -	if ((a == NULL) || (a->data == NULL)) {
 | |
| -		buf[0]='\0';
 | |
| +	/* Ensure that, at every state, |buf| is NUL-terminated. */
 | |
| +	if (buf && buf_len > 0)
 | |
| +		buf[0] = '\0';
 | |
| +
 | |
| +	if ((a == NULL) || (a->data == NULL))
 | |
|  		return(0);
 | |
| -	}
 | |
|  
 | |
| -
 | |
|  	if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
 | |
|  		{
 | |
|  		const char *s;
 | |
| @@ -527,9 +528,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
 | |
|  				i=(int)(l/40);
 | |
|  				l-=(long)(i*40);
 | |
|  				}
 | |
| -			if (buf && (buf_len > 0))
 | |
| +			if (buf && (buf_len > 1))
 | |
|  				{
 | |
|  				*buf++ = i + '0';
 | |
| +				*buf = '\0';
 | |
|  				buf_len--;
 | |
|  				}
 | |
|  			n++;
 | |
| @@ -544,9 +546,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1
 | |
|  			i = strlen(bndec);
 | |
|  			if (buf)
 | |
|  				{
 | |
| -				if (buf_len > 0)
 | |
| +				if (buf_len > 1)
 | |
|  					{
 | |
|  					*buf++ = '.';
 | |
| +					*buf = '\0';
 | |
|  					buf_len--;
 | |
|  					}
 | |
|  				BUF_strlcpy(buf,bndec,buf_len);
 | |
| @@ -786,4 +789,3 @@ err:
 | |
|  	OPENSSL_free(buf);
 | |
|  	return(ok);
 | |
|  	}
 | |
| -
 | |
| Index: crypto/openssl/ssl/d1_both.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/ssl/d1_both.c	(revision 270128)
 | |
| +++ crypto/openssl/ssl/d1_both.c	(working copy)
 | |
| @@ -580,30 +580,33 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max,
 | |
|  		return 0;
 | |
|  	}
 | |
|  
 | |
| +/* dtls1_max_handshake_message_len returns the maximum number of bytes
 | |
| + * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but may
 | |
| + * be greater if the maximum certificate list size requires it. */
 | |
| +static unsigned long dtls1_max_handshake_message_len(const SSL *s)
 | |
| +	{
 | |
| +	unsigned long max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
 | |
| +	if (max_len < (unsigned long)s->max_cert_list)
 | |
| +		return s->max_cert_list;
 | |
| +	return max_len;
 | |
| +	}
 | |
|  
 | |
|  static int
 | |
| -dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok)
 | |
| +dtls1_reassemble_fragment(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
 | |
|  	{
 | |
|  	hm_fragment *frag = NULL;
 | |
|  	pitem *item = NULL;
 | |
|  	int i = -1, is_complete;
 | |
|  	PQ_64BIT seq64;
 | |
| -	unsigned long frag_len = msg_hdr->frag_len, max_len;
 | |
| +	unsigned long frag_len = msg_hdr->frag_len;
 | |
|  
 | |
| -	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
 | |
| +	if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len ||
 | |
| +	    msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
 | |
|  		goto err;
 | |
|  
 | |
| -	/* Determine maximum allowed message size. Depends on (user set)
 | |
| -	 * maximum certificate length, but 16k is minimum.
 | |
| -	 */
 | |
| -	if (DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH < s->max_cert_list)
 | |
| -		max_len = s->max_cert_list;
 | |
| -	else
 | |
| -		max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
 | |
| +	if (frag_len == 0)
 | |
| +		return DTLS1_HM_FRAGMENT_RETRY;
 | |
|  
 | |
| -	if ((msg_hdr->frag_off+frag_len) > max_len)
 | |
| -		goto err;
 | |
| -
 | |
|  	/* Try to find item in queue */
 | |
|  	pq_64bit_init(&seq64);
 | |
|  	pq_64bit_assign_word(&seq64, msg_hdr->seq);
 | |
| @@ -632,7 +635,8 @@ static int
 | |
|  
 | |
|  
 | |
|  	/* If message is already reassembled, this must be a
 | |
| -	 * retransmit and can be dropped.
 | |
| +	 * retransmit and can be dropped. In this case item != NULL and so frag
 | |
| +	 * does not need to be freed.
 | |
|  	 */
 | |
|  	if (frag->reassembly == NULL)
 | |
|  		{
 | |
| @@ -652,7 +656,9 @@ static int
 | |
|  	/* read the body of the fragment (header has already been read */
 | |
|  	i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 | |
|  		frag->fragment + msg_hdr->frag_off,frag_len,0);
 | |
| -	if (i<=0 || (unsigned long)i!=frag_len)
 | |
| +	if ((unsigned long)i!=frag_len)
 | |
| +		i=-1;
 | |
| +	if (i<=0)
 | |
|  		goto err;
 | |
|  
 | |
|  	RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
 | |
| @@ -680,14 +686,18 @@ static int
 | |
|  			i = -1;
 | |
|  			}
 | |
|  
 | |
| -		pqueue_insert(s->d1->buffered_messages, item);
 | |
| +		item = pqueue_insert(s->d1->buffered_messages, item);
 | |
| +		/* pqueue_insert fails iff a duplicate item is inserted.
 | |
| +		 * However, |item| cannot be a duplicate. If it were,
 | |
| +		 * |pqueue_find|, above, would have returned it and control
 | |
| +		 * would never have reached this branch. */
 | |
| +		OPENSSL_assert(item != NULL);
 | |
|  		}
 | |
|  
 | |
|  	return DTLS1_HM_FRAGMENT_RETRY;
 | |
|  
 | |
|  err:
 | |
| -	if (frag != NULL) dtls1_hm_fragment_free(frag);
 | |
| -	if (item != NULL) OPENSSL_free(item);
 | |
| +	if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
 | |
|  	*ok = 0;
 | |
|  	return i;
 | |
|  	}
 | |
| @@ -694,7 +704,7 @@ err:
 | |
|  
 | |
|  
 | |
|  static int
 | |
| -dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
 | |
| +dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st* msg_hdr, int *ok)
 | |
|  {
 | |
|  	int i=-1;
 | |
|  	hm_fragment *frag = NULL;
 | |
| @@ -714,7 +724,7 @@ static int
 | |
|  	/* If we already have an entry and this one is a fragment,
 | |
|  	 * don't discard it and rather try to reassemble it.
 | |
|  	 */
 | |
| -	if (item != NULL && frag_len < msg_hdr->msg_len)
 | |
| +	if (item != NULL && frag_len != msg_hdr->msg_len)
 | |
|  		item = NULL;
 | |
|  
 | |
|  	/* Discard the message if sequence number was already there, is
 | |
| @@ -739,9 +749,12 @@ static int
 | |
|  		}
 | |
|  	else
 | |
|  		{
 | |
| -		if (frag_len && frag_len < msg_hdr->msg_len)
 | |
| +		if (frag_len != msg_hdr->msg_len)
 | |
|  			return dtls1_reassemble_fragment(s, msg_hdr, ok);
 | |
|  
 | |
| +		if (frag_len > dtls1_max_handshake_message_len(s))
 | |
| +			goto err;
 | |
| +
 | |
|  		frag = dtls1_hm_fragment_new(frag_len, 0);
 | |
|  		if ( frag == NULL)
 | |
|  			goto err;
 | |
| @@ -753,7 +766,9 @@ static int
 | |
|  			/* read the body of the fragment (header has already been read) */
 | |
|  			i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 | |
|  				frag->fragment,frag_len,0);
 | |
| -			if (i<=0 || (unsigned long)i!=frag_len)
 | |
| +			if ((unsigned long)i!=frag_len)
 | |
| +				i = -1;
 | |
| +			if (i<=0)
 | |
|  				goto err;
 | |
|  			}
 | |
|  
 | |
| @@ -765,14 +780,21 @@ static int
 | |
|  		if ( item == NULL)
 | |
|  			goto err;
 | |
|  
 | |
| -		pqueue_insert(s->d1->buffered_messages, item);
 | |
| +		item = pqueue_insert(s->d1->buffered_messages, item);
 | |
| +		/* pqueue_insert fails iff a duplicate item is inserted.
 | |
| +		 * However, |item| cannot be a duplicate. If it were,
 | |
| +		 * |pqueue_find|, above, would have returned it. Then, either
 | |
| +		 * |frag_len| != |msg_hdr->msg_len| in which case |item| is set
 | |
| +		 * to NULL and it will have been processed with
 | |
| +		 * |dtls1_reassemble_fragment|, above, or the record will have
 | |
| +		 * been discarded. */
 | |
| +		OPENSSL_assert(item != NULL);
 | |
|  		}
 | |
|  
 | |
|  	return DTLS1_HM_FRAGMENT_RETRY;
 | |
|  
 | |
|  err:
 | |
| -	if ( frag != NULL) dtls1_hm_fragment_free(frag);
 | |
| -	if ( item != NULL) OPENSSL_free(item);
 | |
| +	if (frag != NULL && item == NULL) dtls1_hm_fragment_free(frag);
 | |
|  	*ok = 0;
 | |
|  	return i;
 | |
|  	}
 | |
| Index: crypto/openssl/ssl/d1_clnt.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/ssl/d1_clnt.c	(revision 270128)
 | |
| +++ crypto/openssl/ssl/d1_clnt.c	(working copy)
 | |
| @@ -796,6 +796,13 @@ int dtls1_send_client_key_exchange(SSL *s)
 | |
|  			RSA *rsa;
 | |
|  			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 | |
|  
 | |
| +			if (s->session->sess_cert == NULL)
 | |
| +				{
 | |
| +				/* We should always have a server certificate with SSL_kRSA. */
 | |
| +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 | |
| +				goto err;
 | |
| +				}
 | |
| +
 | |
|  			if (s->session->sess_cert->peer_rsa_tmp != NULL)
 | |
|  				rsa=s->session->sess_cert->peer_rsa_tmp;
 | |
|  			else
 | |
| @@ -986,6 +993,13 @@ int dtls1_send_client_key_exchange(SSL *s)
 | |
|  			{
 | |
|  			DH *dh_srvr,*dh_clnt;
 | |
|  
 | |
| +			if (s->session->sess_cert == NULL)
 | |
| +				{
 | |
| +				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
 | |
| +				SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
 | |
| +				goto err;
 | |
| +				}
 | |
| +
 | |
|  			if (s->session->sess_cert->peer_dh_tmp != NULL)
 | |
|  				dh_srvr=s->session->sess_cert->peer_dh_tmp;
 | |
|  			else
 | |
| @@ -1226,5 +1240,3 @@ int dtls1_send_client_certificate(SSL *s)
 | |
|  	/* SSL3_ST_CW_CERT_D */
 | |
|  	return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
 | |
|  	}
 | |
| -
 | |
| -
 | |
| Index: crypto/openssl/ssl/s23_srvr.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/ssl/s23_srvr.c	(revision 270128)
 | |
| +++ crypto/openssl/ssl/s23_srvr.c	(working copy)
 | |
| @@ -328,16 +328,12 @@ int ssl23_get_client_hello(SSL *s)
 | |
|  			 * Client Hello message, this would be difficult, and we'd have
 | |
|  			 * to read more records to find out.
 | |
|  			 * No known SSL 3.0 client fragments ClientHello like this,
 | |
| -			 * so we simply assume TLS 1.0 to avoid protocol version downgrade
 | |
| -			 * attacks. */
 | |
| +			 * so we simply reject such connections to avoid
 | |
| +			 * protocol version downgrade attacks. */
 | |
|  			if (p[3] == 0 && p[4] < 6)
 | |
|  				{
 | |
| -#if 0
 | |
|  				SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_SMALL);
 | |
|  				goto err;
 | |
| -#else
 | |
| -				v[1] = TLS1_VERSION_MINOR;
 | |
| -#endif
 | |
|  				}
 | |
|  			/* if major version number > 3 set minor to a value
 | |
|  			 * which will use the highest version 3 we support.
 | |
| @@ -344,7 +340,7 @@ int ssl23_get_client_hello(SSL *s)
 | |
|  			 * If TLS 2.0 ever appears we will need to revise
 | |
|  			 * this....
 | |
|  			 */
 | |
| -			else if (p[9] > SSL3_VERSION_MAJOR)
 | |
| +			if (p[9] > SSL3_VERSION_MAJOR)
 | |
|  				v[1]=0xff;
 | |
|  			else
 | |
|  				v[1]=p[10]; /* minor version according to client_version */
 | |
| @@ -412,6 +408,18 @@ int ssl23_get_client_hello(SSL *s)
 | |
|  		v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
 | |
|  		v[1] = p[4];
 | |
|  
 | |
| +		/* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
 | |
| +		 * header is sent directly on the wire, not wrapped as a TLS
 | |
| +		 * record. It's format is:
 | |
| +		 * Byte  Content
 | |
| +		 * 0-1   msg_length
 | |
| +		 * 2     msg_type
 | |
| +		 * 3-4   version
 | |
| +		 * 5-6   cipher_spec_length
 | |
| +		 * 7-8   session_id_length
 | |
| +		 * 9-10  challenge_length
 | |
| +		 * ...   ...
 | |
| +		 */
 | |
|  		n=((p[0]&0x7f)<<8)|p[1];
 | |
|  		if (n > (1024*4))
 | |
|  			{
 | |
| @@ -418,8 +426,16 @@ int ssl23_get_client_hello(SSL *s)
 | |
|  			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
 | |
|  			goto err;
 | |
|  			}
 | |
| +		if (n < 9)
 | |
| +			{
 | |
| +			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
 | |
| +			goto err;
 | |
| +			}
 | |
|  
 | |
|  		j=ssl23_read_bytes(s,n+2);
 | |
| +		/* We previously read 11 bytes, so if j > 0, we must have
 | |
| +		 * j == n+2 == s->packet_length. We have at least 11 valid
 | |
| +		 * packet bytes. */
 | |
|  		if (j <= 0) return(j);
 | |
|  
 | |
|  		ssl3_finish_mac(s, s->packet+2, s->packet_length-2);
 | |
| Index: crypto/openssl/ssl/s3_clnt.c
 | |
| ===================================================================
 | |
| --- crypto/openssl/ssl/s3_clnt.c	(revision 270128)
 | |
| +++ crypto/openssl/ssl/s3_clnt.c	(working copy)
 | |
| @@ -1913,6 +1913,13 @@ int ssl3_send_client_key_exchange(SSL *s)
 | |
|  			RSA *rsa;
 | |
|  			unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 | |
|  
 | |
| +			if (s->session->sess_cert == NULL)
 | |
| +				{
 | |
| +				/* We should always have a server certificate with SSL_kRSA. */
 | |
| +				SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
 | |
| +				goto err;
 | |
| +				}
 | |
| +
 | |
|  			if (s->session->sess_cert->peer_rsa_tmp != NULL)
 | |
|  				rsa=s->session->sess_cert->peer_rsa_tmp;
 | |
|  			else
 |