New option no-ssl3-method which removes SSLv3_*method

When no-ssl3 is set only make SSLv3 disabled by default. Retain -ssl3
options for s_client/s_server/ssltest.

When no-ssl3-method is set SSLv3_*method() is removed and all -ssl3
options.

We should document this somewhere, e.g. wiki, FAQ or manual page.
Reviewed-by: Emilia Käsper <emilia@openssl.org>
diff --git a/Configure b/Configure
index 1369f59..708594a 100755
--- a/Configure
+++ b/Configure
@@ -854,6 +854,11 @@
 					{
 					$disabled{"tls1"} = "option(tls)"
 					}
+				elsif ($1 eq "ssl3-method")
+					{
+					$disabled{"ssl3-method"} = "option(ssl)";
+					$disabled{"ssl3"} = "option(ssl)";
+					}
 				else
 					{
 					$disabled{$1} = "option";
diff --git a/apps/s_client.c b/apps/s_client.c
index a6f972a..e4281c6 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -336,7 +336,9 @@
 	BIO_printf(bio_err," -srp_strength int - minimal mength in bits for N (default %d).\n",SRP_MINIMAL_N);
 #endif
 	BIO_printf(bio_err," -ssl2         - just use SSLv2\n");
+#ifndef OPENSSL_NO_SSL3_METHOD
 	BIO_printf(bio_err," -ssl3         - just use SSLv3\n");
+#endif
 	BIO_printf(bio_err," -tls1_2       - just use TLSv1.2\n");
 	BIO_printf(bio_err," -tls1_1       - just use TLSv1.1\n");
 	BIO_printf(bio_err," -tls1         - just use TLSv1\n");
@@ -914,7 +916,7 @@
 		else if	(strcmp(*argv,"-ssl2") == 0)
 			meth=SSLv2_client_method();
 #endif
-#ifndef OPENSSL_NO_SSL3
+#ifndef OPENSSL_NO_SSL3_METHOD
 		else if	(strcmp(*argv,"-ssl3") == 0)
 			meth=SSLv3_client_method();
 #endif
diff --git a/apps/s_server.c b/apps/s_server.c
index 1e15281..c9764e9 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -509,7 +509,9 @@
 	BIO_printf(bio_err," -srpuserseed string - A seed string for a default user salt.\n");
 #endif
 	BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
+#ifndef OPENSSL_NO_SSL3_METHOD
 	BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
+#endif
 	BIO_printf(bio_err," -tls1_2       - Just talk TLSv1.2\n");
 	BIO_printf(bio_err," -tls1_1       - Just talk TLSv1.1\n");
 	BIO_printf(bio_err," -tls1         - Just talk TLSv1\n");
@@ -1408,7 +1410,7 @@
 		else if	(strcmp(*argv,"-ssl2") == 0)
 			{ meth=SSLv2_server_method(); }
 #endif
-#ifndef OPENSSL_NO_SSL3
+#ifndef OPENSSL_NO_SSL3_METHOD
 		else if	(strcmp(*argv,"-ssl3") == 0)
 			{ meth=SSLv3_server_method(); }
 #endif
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 68c00c5..c84c662 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -167,9 +167,9 @@
 #include <openssl/engine.h>
 #endif
 
-static const SSL_METHOD *ssl3_get_client_method(int ver);
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
 
+#ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_client_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
@@ -182,6 +182,7 @@
 			ssl_undefined_function,
 			ssl3_connect,
 			ssl3_get_client_method)
+#endif
 
 int ssl3_connect(SSL *s)
 	{
diff --git a/ssl/s3_meth.c b/ssl/s3_meth.c
index cdddb17..4dec703 100644
--- a/ssl/s3_meth.c
+++ b/ssl/s3_meth.c
@@ -60,7 +60,7 @@
 #include <openssl/objects.h>
 #include "ssl_locl.h"
 
-static const SSL_METHOD *ssl3_get_method(int ver);
+#ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_method(int ver)
 	{
 	if (ver == SSL3_VERSION)
@@ -73,5 +73,4 @@
 			 ssl3_accept,
 			 ssl3_connect,
 			 ssl3_get_method)
-
-
+#endif
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index b553326..876a245 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -170,6 +170,7 @@
 #endif
 #include <openssl/md5.h>
 
+#ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_server_method(int ver);
 
 static const SSL_METHOD *ssl3_get_server_method(int ver)
@@ -180,6 +181,12 @@
 		return(NULL);
 	}
 
+IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
+			ssl3_accept,
+			ssl_undefined_function,
+			ssl3_get_server_method)
+#endif
+
 #ifndef OPENSSL_NO_SRP
 static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
 	{
@@ -206,11 +213,6 @@
 	}
 #endif
 
-IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
-			ssl3_accept,
-			ssl_undefined_function,
-			ssl3_get_server_method)
-
 int ssl3_accept(SSL *s)
 	{
 	BUF_MEM *buf;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 681dec9..beb00a0 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2235,9 +2235,11 @@
 const SSL_METHOD *SSLv2_client_method(void);	/* SSLv2 */
 #endif
 
+#ifndef OPENSSL_NO_SSL3_METHOD
 const SSL_METHOD *SSLv3_method(void);		/* SSLv3 */
 const SSL_METHOD *SSLv3_server_method(void);	/* SSLv3 */
 const SSL_METHOD *SSLv3_client_method(void);	/* SSLv3 */
+#endif
 
 const SSL_METHOD *SSLv23_method(void);	/* SSLv3 but can rollback to v2 */
 const SSL_METHOD *SSLv23_server_method(void);	/* SSLv3 but can rollback to v2 */
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index 028f852..4f2f477 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -776,7 +776,7 @@
 #ifndef OPENSSL_NO_SSL2
 	fprintf(stderr," -ssl2         - use SSLv2\n");
 #endif
-#ifndef OPENSSL_NO_SSL3
+#ifndef OPENSSL_NO_SSL3_METHOD
 	fprintf(stderr," -ssl3         - use SSLv3\n");
 #endif
 #ifndef OPENSSL_NO_TLS1
@@ -1180,7 +1180,7 @@
 			}
 		else if	(strcmp(*argv,"-ssl3") == 0)
 			{
-#ifdef OPENSSL_NO_SSL3
+#ifdef OPENSSL_NO_SSL3_METHOD
 			no_protocol = 1;
 #endif
 			ssl3 = 1;
diff --git a/util/mk1mf.pl b/util/mk1mf.pl
index 73523ef..0fcadcb 100755
--- a/util/mk1mf.pl
+++ b/util/mk1mf.pl
@@ -1388,12 +1388,17 @@
 	return($ret);
 	}
 
+# Options picked up from the OPTIONS line in the top level Makefile
+# generated by Configure.
+
 sub read_options
 	{
 	# Many options are handled in a similar way. In particular
 	# no-xxx sets zero or more scalars to 1.
-	# Process these using a hash containing the option name and
-	# reference to the scalars to set.
+	# Process these using the %valid_options hash containing the option
+	# name and reference to the scalars to set. In some cases the option
+	# needs no special handling and can be ignored: this is done by
+	# setting the value to 0.
 
 	my %valid_options = (
 		"no-rc2" => \$no_rc2,
@@ -1427,6 +1432,7 @@
 		"gaswin" => \$gaswin,
 		"no-ssl2" => \$no_ssl2,
 		"no-ssl3" => \$no_ssl3,
+		"no-ssl3-method" => 0,
 		"no-tlsext" => \$no_tlsext,
 		"no-srp" => \$no_srp,
 		"no-cms" => \$no_cms,
diff --git a/util/mkdef.pl b/util/mkdef.pl
index 0f42504..460d565 100755
--- a/util/mkdef.pl
+++ b/util/mkdef.pl
@@ -108,6 +108,8 @@
 			 "CAPIENG",
 			 # SSL v2
 			 "SSL2",
+			 # SSL v3 method
+			 "SSL3_METHOD",
 			 # JPAKE
 			 "JPAKE",
 			 # NEXTPROTONEG
@@ -144,7 +146,7 @@
 my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng;
 my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc; 
 my $no_nextprotoneg; my $no_sctp; my $no_srtp; my $no_ssl_trace;
-my $no_unit_test;
+my $no_unit_test; my $no_ssl3_method;
 
 my $fips;
 
@@ -239,6 +241,7 @@
  	elsif (/^no-ec-nistp224-64-gcc-128$/)	{ $no_nistp_gcc=1; }
 	elsif (/^no-nextprotoneg$/)	{ $no_nextprotoneg=1; }
 	elsif (/^no-ssl2$/)	{ $no_ssl2=1; }
+	elsif (/^no-ssl3-method$/) { $no_ssl3_method=1; }
 	elsif (/^no-ssl-trace$/) { $no_ssl_trace=1; }
 	elsif (/^no-capieng$/)	{ $no_capieng=1; }
 	elsif (/^no-jpake$/)	{ $no_jpake=1; }
@@ -1210,6 +1213,7 @@
 			if ($keyword eq "EC2M" && $no_ec2m) { return 0; }
 			if ($keyword eq "NEXTPROTONEG" && $no_nextprotoneg) { return 0; }
 			if ($keyword eq "SSL2" && $no_ssl2) { return 0; }
+			if ($keyword eq "SSL3_METHOD" && $no_ssl3_method) { return 0; }
 			if ($keyword eq "SSL_TRACE" && $no_ssl_trace) { return 0; }
 			if ($keyword eq "CAPIENG" && $no_capieng) { return 0; }
 			if ($keyword eq "JPAKE" && $no_jpake) { return 0; }
diff --git a/util/ssleay.num b/util/ssleay.num
index affe14a..a289559 100755
--- a/util/ssleay.num
+++ b/util/ssleay.num
@@ -101,9 +101,9 @@
 SSLv2_client_method                     113	EXIST::FUNCTION:RSA,SSL2
 SSLv2_method                            114	EXIST::FUNCTION:RSA,SSL2
 SSLv2_server_method                     115	EXIST::FUNCTION:RSA,SSL2
-SSLv3_client_method                     116	EXIST::FUNCTION:
-SSLv3_method                            117	EXIST::FUNCTION:
-SSLv3_server_method                     118	EXIST::FUNCTION:
+SSLv3_client_method                     116	EXIST::FUNCTION:SSL3_METHOD
+SSLv3_method                            117	EXIST::FUNCTION:SSL3_METHOD
+SSLv3_server_method                     118	EXIST::FUNCTION:SSL3_METHOD
 d2i_SSL_SESSION                         119	EXIST::FUNCTION:
 i2d_SSL_SESSION                         120	EXIST::FUNCTION:
 BIO_f_ssl                               121	EXIST::FUNCTION:BIO