Commit 836f9960 authored by Lutz Jänicke's avatar Lutz Jänicke
Browse files

New Option SSL_OP_CIPHER_SERVER_PREFERENCE allows TLS/SSLv3 server to override

the clients choice; in SSLv2 the client uses the server's preferences.
parent 1613c4d3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3,6 +3,12 @@

 Changes between 0.9.6 and 0.9.7  [xx XXX 2000]

  *) New option SSL_OP_CIPHER_SERVER_PREFERENCE allows the server to override
     the clients preferred ciphersuites and rather use its own preferences.
     Should help to work around M$ SGC (Server Gated Cryptography) bug in
     Internet Explorer by ensuring unchanged hash method during stepup.
     [Lutz Jaenicke]

  *) Make mkdef.pl recognise all DECLARE_ASN1 macros, change rijndael
     to aes and add a new 'exist' option to print out symbols that don't
     appear to exist.
+3 −0
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ static void sc_usage(void)
	BIO_printf(bio_err," -tls1         - just use TLSv1\n");
	BIO_printf(bio_err," -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
	BIO_printf(bio_err," -bugs         - Switch on all SSL implementation bug workarounds\n");
	BIO_printf(bio_err," -serverpref   - Use server's cipher preferences (only SSLv2)\n");
	BIO_printf(bio_err," -cipher       - preferred cipher to use, use the 'openssl ciphers'\n");
	BIO_printf(bio_err,"                 command to see what is available\n");
	BIO_printf(bio_err," -engine id    - Initialise and use the specified engine\n");
@@ -311,6 +312,8 @@ int MAIN(int argc, char **argv)
			off|=SSL_OP_NO_SSLv3;
		else if (strcmp(*argv,"-no_ssl2") == 0)
			off|=SSL_OP_NO_SSLv2;
		else if (strcmp(*argv,"-serverpref") == 0)
			off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
		else if	(strcmp(*argv,"-cipher") == 0)
			{
			if (--argc < 1) goto bad;
+3 −0
Original line number Diff line number Diff line
@@ -231,6 +231,7 @@ static void sv_usage(void)
	BIO_printf(bio_err," -CAfile arg   - PEM format file of CA's\n");
	BIO_printf(bio_err," -nocert       - Don't use any certificates (Anon-DH)\n");
	BIO_printf(bio_err," -cipher arg   - play with 'openssl ciphers' to see what goes here\n");
	BIO_printf(bio_err," -serverpref   - Use server's cipher preferences\n");
	BIO_printf(bio_err," -quiet        - No server output\n");
	BIO_printf(bio_err," -no_tmp_rsa   - Do not generate a tmp RSA key\n");
	BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
@@ -508,6 +509,8 @@ int MAIN(int argc, char *argv[])
			if (--argc < 1) goto bad;
			CApath= *(++argv);
			}
		else if	(strcmp(*argv,"-serverpref") == 0)
			{ off|=SSL_OP_CIPHER_SERVER_PREFERENCE; }
		else if	(strcmp(*argv,"-cipher") == 0)
			{
			if (--argc < 1) goto bad;
+24 −8
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ static int get_server_hello(SSL *s)
	unsigned char *buf;
	unsigned char *p;
	int i,j;
	STACK_OF(SSL_CIPHER) *sk=NULL,*cl;
	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;

	buf=(unsigned char *)s->init_buf->data;
	p=buf;
@@ -414,27 +414,43 @@ static int get_server_hello(SSL *s)
		sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);

		/* get the array of ciphers we will accept */
		cl=ssl_get_ciphers_by_id(s);
		cl=SSL_get_ciphers(s);
		sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);

		/*
		 * If server preference flag set, choose the first
		 * (highest priority) cipher the server sends, otherwise
		 * client preference has priority.
		 */
		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
		    prio = sk;
		    allow = cl;
		    }
		else
		    {
		    prio = cl;
		    allow = sk;
		    }
		/* In theory we could have ciphers sent back that we
		 * don't want to use but that does not matter since we
		 * will check against the list we originally sent and
		 * for performance reasons we should not bother to match
		 * the two lists up just to check. */
		for (i=0; i<sk_SSL_CIPHER_num(cl); i++)
		for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
			{
			if (sk_SSL_CIPHER_find(sk,
					       sk_SSL_CIPHER_value(cl,i)) >= 0)
			if (sk_SSL_CIPHER_find(allow,
					     sk_SSL_CIPHER_value(prio,i)) >= 0)
				break;
			}

		if (i >= sk_SSL_CIPHER_num(cl))
		if (i >= sk_SSL_CIPHER_num(prio))
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
			return(-1);
			}
		s->session->cipher=sk_SSL_CIPHER_value(cl,i);
		s->session->cipher=sk_SSL_CIPHER_value(prio,i);


		if (s->session->peer != NULL) /* can't happen*/
+23 −6
Original line number Diff line number Diff line
@@ -450,6 +450,7 @@ static int get_client_hello(SSL *s)
	unsigned char *p;
	STACK_OF(SSL_CIPHER) *cs; /* a stack of SSL_CIPHERS */
	STACK_OF(SSL_CIPHER) *cl; /* the ones we want to use */
	STACK_OF(SSL_CIPHER) *prio, *allow;
	int z;

	/* This is a bit of a hack to check for the correct packet
@@ -555,21 +556,37 @@ static int get_client_hello(SSL *s)
			&s->session->ciphers);
		if (cs == NULL) goto mem_err;

		cl=ssl_get_ciphers_by_id(s);
		cl=SSL_get_ciphers(s);

		for (z=0; z<sk_SSL_CIPHER_num(cs); z++)
		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
			if (sk_SSL_CIPHER_find(cl,sk_SSL_CIPHER_value(cs,z)) < 0)
		    prio=sk_SSL_CIPHER_dup(cl);
		    if (prio == NULL) goto mem_err;
		    allow = cs;
		    }
		else
		    {
		    prio = cs;
		    allow = cl;
		    }
		for (z=0; z<sk_SSL_CIPHER_num(prio); z++)
			{
				sk_SSL_CIPHER_delete(cs,z);
			if (sk_SSL_CIPHER_find(allow,sk_SSL_CIPHER_value(prio,z)) < 0)
				{
				sk_SSL_CIPHER_delete(prio,z);
				z--;
				}
			}

		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
		    sk_SSL_CIPHER_free(s->session->ciphers);
		    s->session->ciphers = prio;
		    }
		/* s->session->ciphers should now have a list of
		 * ciphers that are on both the client and server.
		 * This list is ordered by the order the client sent
		 * the ciphers.
		 * the ciphers or in the order of the server's preference
		 * if SSL_OP_CIPHER_SERVER_PREFERENCE was set.
		 */
		}
	p+=s->s2->tmp.cipher_spec_length;
Loading