--- /dev/null
+diff -up openssl-0.9.7a/apps/s_client.c.reneg openssl-0.9.7a/apps/s_client.c
+--- openssl-0.9.7a/apps/s_client.c.reneg 2003-01-30 18:37:36.000000000 +0100
++++ openssl-0.9.7a/apps/s_client.c 2010-02-10 13:01:47.000000000 +0100
+@@ -226,14 +226,14 @@ static void sc_usage(void)
+ BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n");
+ #endif
+ BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
+-
++ BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
+ }
+
+ int MAIN(int, char **);
+
+ int MAIN(int argc, char **argv)
+ {
+- int off=0;
++ int off=0, clr = 0;
+ SSL *con=NULL,*con2=NULL;
+ X509_STORE *store = NULL;
+ int s,k,width,state=0;
+@@ -401,6 +401,12 @@ int MAIN(int argc, char **argv)
+ off|=SSL_OP_NO_SSLv2;
+ else if (strcmp(*argv,"-serverpref") == 0)
+ off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
++ else if (strcmp(*argv,"-legacy_renegotiation") == 0)
++ off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
++ else if (strcmp(*argv,"-legacy_server_connect") == 0)
++ { off|=SSL_OP_LEGACY_SERVER_CONNECT; }
++ else if (strcmp(*argv,"-no_legacy_server_connect") == 0)
++ { clr|=SSL_OP_LEGACY_SERVER_CONNECT; }
+ else if (strcmp(*argv,"-cipher") == 0)
+ {
+ if (--argc < 1) goto bad;
+@@ -488,6 +494,9 @@ bad:
+ else
+ SSL_CTX_set_options(ctx,off);
+
++ if (clr)
++ SSL_CTX_clear_options(ctx, clr);
++
+ if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
+ if (cipher != NULL)
+ if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
+@@ -1042,6 +1051,8 @@ static void print_stuff(BIO *bio, SSL *s
+ EVP_PKEY_bits(pktmp));
+ EVP_PKEY_free(pktmp);
+ }
++ BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
++ SSL_get_secure_renegotiation_support(s) ? "" : " NOT");
+ SSL_SESSION_print(bio,SSL_get_session(s));
+ BIO_printf(bio,"---\n");
+ if (peer != NULL)
+diff -up openssl-0.9.7a/apps/s_server.c.reneg openssl-0.9.7a/apps/s_server.c
+--- openssl-0.9.7a/apps/s_server.c.reneg 2003-01-30 18:37:36.000000000 +0100
++++ openssl-0.9.7a/apps/s_server.c 2010-02-10 13:01:47.000000000 +0100
+@@ -325,6 +325,7 @@ static void sv_usage(void)
+ #endif
+ BIO_printf(bio_err," -id_prefix arg - Generate SSL/TLS session IDs prefixed by 'arg'\n");
+ BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
++ BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
+ }
+
+ static int local_argc=0;
+@@ -605,6 +606,8 @@ int MAIN(int argc, char *argv[])
+ }
+ else if (strcmp(*argv,"-serverpref") == 0)
+ { off|=SSL_OP_CIPHER_SERVER_PREFERENCE; }
++ else if (strcmp(*argv,"-legacy_renegotiation") == 0)
++ off|=SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+ else if (strcmp(*argv,"-cipher") == 0)
+ {
+ if (--argc < 1) goto bad;
+@@ -1263,6 +1266,8 @@ static int init_ssl_connection(SSL *con)
+ if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) &
+ TLS1_FLAGS_TLS_PADDING_BUG)
+ BIO_printf(bio_s_out,"Peer has incorrect TLSv1 block padding\n");
++ BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
++ SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
+
+ return(1);
+ }
+diff -up openssl-0.9.7a/doc/ssl/SSL_CTX_set_options.pod.reneg openssl-0.9.7a/doc/ssl/SSL_CTX_set_options.pod
+--- openssl-0.9.7a/doc/ssl/SSL_CTX_set_options.pod.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/doc/ssl/SSL_CTX_set_options.pod 2010-02-18 16:48:45.000000000 +0100
+@@ -2,7 +2,7 @@
+
+ =head1 NAME
+
+-SSL_CTX_set_options, SSL_set_options, SSL_CTX_get_options, SSL_get_options - manipulate SSL engine options
++SSL_CTX_set_options, SSL_set_options, SSL_CTX_clear_options, SSL_clear_options, SSL_CTX_get_options, SSL_get_options, SSL_get_secure_renegotiation_support - manipulate SSL options
+
+ =head1 SYNOPSIS
+
+@@ -11,26 +11,41 @@ SSL_CTX_set_options, SSL_set_options, SS
+ long SSL_CTX_set_options(SSL_CTX *ctx, long options);
+ long SSL_set_options(SSL *ssl, long options);
+
++ long SSL_CTX_clear_options(SSL_CTX *ctx, long options);
++ long SSL_clear_options(SSL *ssl, long options);
++
+ long SSL_CTX_get_options(SSL_CTX *ctx);
+ long SSL_get_options(SSL *ssl);
+
++ long SSL_get_secure_renegotiation_support(SSL *ssl);
++
+ =head1 DESCRIPTION
+
++Note: all these functions are implemented using macros.
++
+ SSL_CTX_set_options() adds the options set via bitmask in B<options> to B<ctx>.
+ Options already set before are not cleared!
+
+ SSL_set_options() adds the options set via bitmask in B<options> to B<ssl>.
+ Options already set before are not cleared!
+
++SSL_CTX_clear_options() clears the options set via bitmask in B<options>
++to B<ctx>.
++
++SSL_clear_options() clears the options set via bitmask in B<options> to B<ssl>.
++
+ SSL_CTX_get_options() returns the options set for B<ctx>.
+
+ SSL_get_options() returns the options set for B<ssl>.
+
++SSL_get_secure_renegotiation_support() indicates whether the peer supports
++secure renegotiation.
++
+ =head1 NOTES
+
+ The behaviour of the SSL library can be changed by setting several options.
+ The options are coded as bitmasks and can be combined by a logical B<or>
+-operation (|). Options can only be added but can never be reset.
++operation (|).
+
+ SSL_CTX_set_options() and SSL_set_options() affect the (external)
+ protocol behaviour of the SSL library. The (internal) behaviour of
+@@ -199,17 +214,109 @@ Do not use the TLSv1 protocol.
+
+ When performing renegotiation as a server, always start a new session
+ (i.e., session resumption requests are only accepted in the initial
+-handshake). This option is not needed for clients.
++handshake). This option is not needed for clients.
++
++=item SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
++
++Allow legacy insecure renegotiation between OpenSSL and unpatched clients or
++servers. See the B<SECURE RENEGOTIATION> section for more details.
++
++=item SSL_OP_LEGACY_SERVER_CONNECT
++
++Allow legacy insecure renegotiation between OpenSSL and unpatched servers
++B<only>: this option is currently set by default. See the
++B<SECURE RENEGOTIATION> section for more details.
+
+ =back
+
++=head1 SECURE RENEGOTIATION
++
++OpenSSL 0.9.8m and later always attempts to use secure renegotiation as
++described in RFC5746. This counters the prefix attack described in
++CVE-2009-3555 and elsewhere.
++
++The deprecated and highly broken SSLv2 protocol does not support
++renegotiation at all: its use is B<strongly> discouraged.
++
++This attack has far reaching consequences which application writers should be
++aware of. In the description below an implementation supporting secure
++renegotiation is referred to as I<patched>. A server not supporting secure
++renegotiation is referred to as I<unpatched>.
++
++The following sections describe the operations permitted by OpenSSL's secure
++renegotiation implementation.
++
++=head2 Patched client and server
++
++Connections and renegotiation are always permitted by OpenSSL implementations.
++
++=head2 Unpatched client and patched OpenSSL server
++
++The initial connection suceeds but client renegotiation is denied by the
++server with a B<no_renegotiation> warning alert if TLS v1.0 is used or a fatal
++B<handshake_failure> alert in SSL v3.0.
++
++If the patched OpenSSL server attempts to renegotiate a fatal
++B<handshake_failure> alert is sent. This is because the server code may be
++unaware of the unpatched nature of the client.
++
++If the option B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> is set then
++renegotiation B<always> succeeds.
++
++B<NB:> a bug in OpenSSL clients earlier than 0.9.8m (all of which are
++unpatched) will result in the connection hanging if it receives a
++B<no_renegotiation> alert. OpenSSL versions 0.9.8m and later will regard
++a B<no_renegotiation> alert as fatal and respond with a fatal
++B<handshake_failure> alert. This is because the OpenSSL API currently has
++no provision to indicate to an application that a renegotiation attempt
++was refused.
++
++=head2 Patched OpenSSL client and unpatched server.
++
++If the option B<SSL_OP_LEGACY_SERVER_CONNECT> or
++B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> is set then initial connections
++and renegotiation between patched OpenSSL clients and unpatched servers
++succeeds. If neither option is set then initial connections to unpatched
++servers will fail.
++
++The option B<SSL_OP_LEGACY_SERVER_CONNECT> is currently set by default even
++though it has security implications: otherwise it would be impossible to
++connect to unpatched servers (i.e. all of them initially) and this is clearly
++not acceptable. Renegotiation is permitted because this does not add any
++additional security issues: during an attack clients do not see any
++renegotiations anyway.
++
++As more servers become patched the option B<SSL_OP_LEGACY_SERVER_CONNECT> will
++B<not> be set by default in a future version of OpenSSL.
++
++OpenSSL client applications wishing to ensure they can connect to unpatched
++servers should always B<set> B<SSL_OP_LEGACY_SERVER_CONNECT>
++
++OpenSSL client applications that want to ensure they can B<not> connect to
++unpatched servers (and thus avoid any security issues) should always B<clear>
++B<SSL_OP_LEGACY_SERVER_CONNECT> using SSL_CTX_clear_options() or
++SSL_clear_options().
++
++The difference between the B<SSL_OP_LEGACY_SERVER_CONNECT> and
++B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> options is that
++B<SSL_OP_LEGACY_SERVER_CONNECT> enables initial connections and secure
++renegotiation between OpenSSL clients and unpatched servers B<only>, while
++B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> allows initial connections
++and renegotiation between OpenSSL and unpatched clients or servers.
++
+ =head1 RETURN VALUES
+
+ SSL_CTX_set_options() and SSL_set_options() return the new options bitmask
+ after adding B<options>.
+
++SSL_CTX_clear_options() and SSL_clear_options() return the new options bitmask
++after clearing B<options>.
++
+ SSL_CTX_get_options() and SSL_get_options() return the current bitmask.
+
++SSL_get_secure_renegotiation_support() returns 1 is the peer supports
++secure renegotiation and 0 if it does not.
++
+ =head1 SEE ALSO
+
+ L<ssl(3)|ssl(3)>, L<SSL_new(3)|SSL_new(3)>, L<SSL_clear(3)|SSL_clear(3)>,
+@@ -232,4 +339,11 @@ Versions up to OpenSSL 0.9.6c do not inc
+ can be disabled with this option (in OpenSSL 0.9.6d, it was always
+ enabled).
+
++SSL_CTX_clear_options() and SSL_clear_options() were first added in OpenSSL
++0.9.8m.
++
++B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION>, B<SSL_OP_LEGACY_SERVER_CONNECT>
++and the function SSL_get_secure_renegotiation_support() were first added in
++OpenSSL 0.9.8m.
++
+ =cut
+diff -up openssl-0.9.7a/ssl/Makefile.ssl.reneg openssl-0.9.7a/ssl/Makefile.ssl
+--- openssl-0.9.7a/ssl/Makefile.ssl.reneg 2002-12-19 23:10:20.000000000 +0100
++++ openssl-0.9.7a/ssl/Makefile.ssl 2010-02-10 13:01:47.000000000 +0100
+@@ -34,7 +34,7 @@ LIBSRC= \
+ ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+ ssl_ciph.c ssl_stat.c ssl_rsa.c \
+ ssl_asn1.c ssl_txt.c ssl_algs.c \
+- bio_ssl.c ssl_err.c kssl.c
++ bio_ssl.c ssl_err.c kssl.c t1_reneg.c
+ LIBOBJ= \
+ s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \
+ s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \
+@@ -43,7 +43,7 @@ LIBOBJ= \
+ ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
+ ssl_ciph.o ssl_stat.o ssl_rsa.o \
+ ssl_asn1.o ssl_txt.o ssl_algs.o \
+- bio_ssl.o ssl_err.o kssl.o
++ bio_ssl.o ssl_err.o kssl.o t1_reneg.o
+
+ SRC= $(LIBSRC)
+
+diff -up openssl-0.9.7a/ssl/ssl_err.c.reneg openssl-0.9.7a/ssl/ssl_err.c
+--- openssl-0.9.7a/ssl/ssl_err.c.reneg 2002-11-12 14:23:36.000000000 +0100
++++ openssl-0.9.7a/ssl/ssl_err.c 2010-02-10 13:01:47.000000000 +0100
+@@ -138,8 +138,12 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_PACK(0,SSL_F_SSL3_SETUP_KEY_BLOCK,0), "SSL3_SETUP_KEY_BLOCK"},
+ {ERR_PACK(0,SSL_F_SSL3_WRITE_BYTES,0), "SSL3_WRITE_BYTES"},
+ {ERR_PACK(0,SSL_F_SSL3_WRITE_PENDING,0), "SSL3_WRITE_PENDING"},
++{ERR_PACK(0,SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,0), "SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT"},
++{ERR_PACK(0,SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,0), "SSL_ADD_CLIENTHELLO_TLSEXT"},
+ {ERR_PACK(0,SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,0), "SSL_add_dir_cert_subjects_to_stack"},
+ {ERR_PACK(0,SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,0), "SSL_add_file_cert_subjects_to_stack"},
++{ERR_PACK(0,SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT,0), "SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT"},
++{ERR_PACK(0,SSL_F_SSL_ADD_SERVERHELLO_TLSEXT,0), "SSL_ADD_SERVERHELLO_TLSEXT"},
+ {ERR_PACK(0,SSL_F_SSL_BAD_METHOD,0), "SSL_BAD_METHOD"},
+ {ERR_PACK(0,SSL_F_SSL_BYTES_TO_CIPHER_LIST,0), "SSL_BYTES_TO_CIPHER_LIST"},
+ {ERR_PACK(0,SSL_F_SSL_CERT_DUP,0), "SSL_CERT_DUP"},
+@@ -177,6 +181,10 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_PACK(0,SSL_F_SSL_INIT_WBIO_BUFFER,0), "SSL_INIT_WBIO_BUFFER"},
+ {ERR_PACK(0,SSL_F_SSL_LOAD_CLIENT_CA_FILE,0), "SSL_load_client_CA_file"},
+ {ERR_PACK(0,SSL_F_SSL_NEW,0), "SSL_new"},
++{ERR_PACK(0,SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,0), "SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT"},
++{ERR_PACK(0,SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,0), "SSL_PARSE_CLIENTHELLO_TLSEXT"},
++{ERR_PACK(0,SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,0), "SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT"},
++{ERR_PACK(0,SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,0), "SSL_PARSE_SERVERHELLO_TLSEXT"},
+ {ERR_PACK(0,SSL_F_SSL_READ,0), "SSL_read"},
+ {ERR_PACK(0,SSL_F_SSL_RSA_PRIVATE_DECRYPT,0), "SSL_RSA_PRIVATE_DECRYPT"},
+ {ERR_PACK(0,SSL_F_SSL_RSA_PUBLIC_ENCRYPT,0), "SSL_RSA_PUBLIC_ENCRYPT"},
+@@ -329,12 +337,14 @@ static ERR_STRING_DATA SSL_str_reasons[]
+ {SSL_R_NO_PRIVATE_KEY_ASSIGNED ,"no private key assigned"},
+ {SSL_R_NO_PROTOCOLS_AVAILABLE ,"no protocols available"},
+ {SSL_R_NO_PUBLICKEY ,"no publickey"},
++{SSL_R_NO_RENEGOTIATION ,"no renegotiation"},
+ {SSL_R_NO_SHARED_CIPHER ,"no shared cipher"},
+ {SSL_R_NO_VERIFY_CALLBACK ,"no verify callback"},
+ {SSL_R_NULL_SSL_CTX ,"null ssl ctx"},
+ {SSL_R_NULL_SSL_METHOD_PASSED ,"null ssl method passed"},
+ {SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED ,"old session cipher not returned"},
+ {SSL_R_PACKET_LENGTH_TOO_LONG ,"packet length too long"},
++{SSL_R_PARSE_TLSEXT ,"parse tlsext"},
+ {SSL_R_PATH_TOO_LONG ,"path too long"},
+ {SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE ,"peer did not return a certificate"},
+ {SSL_R_PEER_ERROR ,"peer error"},
+@@ -353,10 +363,14 @@ static ERR_STRING_DATA SSL_str_reasons[]
+ {SSL_R_RECORD_LENGTH_MISMATCH ,"record length mismatch"},
+ {SSL_R_RECORD_TOO_LARGE ,"record too large"},
+ {SSL_R_RECORD_TOO_SMALL ,"record too small"},
++{SSL_R_RENEGOTIATE_EXT_TOO_LONG ,"renegotiate ext too long"},
++{SSL_R_RENEGOTIATION_ENCODING_ERR ,"renegotiation encoding err"},
++{SSL_R_RENEGOTIATION_MISMATCH ,"renegotiation mismatch"},
+ {SSL_R_REQUIRED_CIPHER_MISSING ,"required cipher missing"},
+ {SSL_R_REUSE_CERT_LENGTH_NOT_ZERO ,"reuse cert length not zero"},
+ {SSL_R_REUSE_CERT_TYPE_NOT_ZERO ,"reuse cert type not zero"},
+ {SSL_R_REUSE_CIPHER_LIST_NOT_ZERO ,"reuse cipher list not zero"},
++{SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING ,"scsv received when renegotiating"},
+ {SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED ,"session id context uninitialized"},
+ {SSL_R_SHORT_READ ,"short read"},
+ {SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE,"signature for non signing certificate"},
+@@ -425,6 +439,7 @@ static ERR_STRING_DATA SSL_str_reasons[]
+ {SSL_R_UNKNOWN_REMOTE_ERROR_TYPE ,"unknown remote error type"},
+ {SSL_R_UNKNOWN_SSL_VERSION ,"unknown ssl version"},
+ {SSL_R_UNKNOWN_STATE ,"unknown state"},
++{SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED,"unsafe legacy renegotiation disabled"},
+ {SSL_R_UNSUPPORTED_CIPHER ,"unsupported cipher"},
+ {SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM ,"unsupported compression algorithm"},
+ {SSL_R_UNSUPPORTED_OPTION ,"unsupported option"},
+diff -up openssl-0.9.7a/ssl/ssl.h.reneg openssl-0.9.7a/ssl/ssl.h
+--- openssl-0.9.7a/ssl/ssl.h.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/ssl/ssl.h 2010-02-10 13:01:47.000000000 +0100
+@@ -463,6 +463,8 @@ typedef struct ssl_session_st
+
+ #define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
+ #define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
++/* Allow initial connection to servers that don't support RI */
++#define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L
+ #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L
+ #define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
+ #define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
+@@ -484,6 +486,8 @@ typedef struct ssl_session_st
+
+ /* As server, disallow session resumption on renegotiation */
+ #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
++/* Permit unsafe legacy renegotiation */
++#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
+ /* If set, always create a new key when using tmp_dh parameters */
+ #define SSL_OP_SINGLE_DH_USE 0x00100000L
+ /* Set to always use the tmp_rsa key when doing RSA operations,
+@@ -530,22 +534,32 @@ typedef struct ssl_session_st
+
+ #define SSL_CTX_set_options(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
++#define SSL_CTX_clear_options(ctx,op) \
++ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+ #define SSL_CTX_get_options(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL)
+ #define SSL_set_options(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
++#define SSL_clear_options(ssl,op) \
++ SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL)
+ #define SSL_get_options(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL)
+
+ #define SSL_CTX_set_mode(ctx,op) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
++#define SSL_CTX_clear_mode(ctx,op) \
++ SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
+ #define SSL_CTX_get_mode(ctx) \
+ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
++#define SSL_clear_mode(ssl,op) \
++ SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
+ #define SSL_set_mode(ssl,op) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
+ #define SSL_get_mode(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
+
++#define SSL_get_secure_renegotiation_support(ssl) \
++ SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
+
+ void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg));
+@@ -1131,6 +1145,10 @@ size_t SSL_get_peer_finished(SSL *s, voi
+ #define SSL_CTRL_GET_MAX_CERT_LIST 50
+ #define SSL_CTRL_SET_MAX_CERT_LIST 51
+
++#define SSL_CTRL_GET_RI_SUPPORT 76
++#define SSL_CTRL_CLEAR_OPTIONS 77
++#define SSL_CTRL_CLEAR_MODE 78
++
+ #define SSL_session_reused(ssl) \
+ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
+ #define SSL_num_renegotiations(ssl) \
+@@ -1548,8 +1566,12 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_SSL3_SETUP_KEY_BLOCK 157
+ #define SSL_F_SSL3_WRITE_BYTES 158
+ #define SSL_F_SSL3_WRITE_PENDING 159
++#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 285
++#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 272
+ #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215
+ #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216
++#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 286
++#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 273
+ #define SSL_F_SSL_BAD_METHOD 160
+ #define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161
+ #define SSL_F_SSL_CERT_DUP 221
+@@ -1587,6 +1609,10 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_SSL_INIT_WBIO_BUFFER 184
+ #define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185
+ #define SSL_F_SSL_NEW 186
++#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 287
++#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 290
++#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 289
++#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 291
+ #define SSL_F_SSL_READ 223
+ #define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187
+ #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188
+@@ -1736,12 +1762,14 @@ void ERR_load_SSL_strings(void);
+ #define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190
+ #define SSL_R_NO_PROTOCOLS_AVAILABLE 191
+ #define SSL_R_NO_PUBLICKEY 192
++#define SSL_R_NO_RENEGOTIATION 319
+ #define SSL_R_NO_SHARED_CIPHER 193
+ #define SSL_R_NO_VERIFY_CALLBACK 194
+ #define SSL_R_NULL_SSL_CTX 195
+ #define SSL_R_NULL_SSL_METHOD_PASSED 196
+ #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
+ #define SSL_R_PACKET_LENGTH_TOO_LONG 198
++#define SSL_R_PARSE_TLSEXT 223
+ #define SSL_R_PATH_TOO_LONG 270
+ #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199
+ #define SSL_R_PEER_ERROR 200
+@@ -1760,10 +1788,14 @@ void ERR_load_SSL_strings(void);
+ #define SSL_R_RECORD_LENGTH_MISMATCH 213
+ #define SSL_R_RECORD_TOO_LARGE 214
+ #define SSL_R_RECORD_TOO_SMALL 1093
++#define SSL_R_RENEGOTIATE_EXT_TOO_LONG 320
++#define SSL_R_RENEGOTIATION_ENCODING_ERR 321
++#define SSL_R_RENEGOTIATION_MISMATCH 322
+ #define SSL_R_REQUIRED_CIPHER_MISSING 215
+ #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216
+ #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217
+ #define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218
++#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 324
+ #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277
+ #define SSL_R_SHORT_READ 219
+ #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220
+@@ -1832,6 +1864,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253
+ #define SSL_R_UNKNOWN_SSL_VERSION 254
+ #define SSL_R_UNKNOWN_STATE 255
++#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 323
+ #define SSL_R_UNSUPPORTED_CIPHER 256
+ #define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257
+ #define SSL_R_UNSUPPORTED_OPTION 1091
+diff -up openssl-0.9.7a/ssl/ssl_lib.c.reneg openssl-0.9.7a/ssl/ssl_lib.c
+--- openssl-0.9.7a/ssl/ssl_lib.c.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/ssl/ssl_lib.c 2010-02-18 16:51:20.000000000 +0100
+@@ -933,14 +933,22 @@ long SSL_ctrl(SSL *s,int cmd,long larg,v
+
+ case SSL_CTRL_OPTIONS:
+ return(s->options|=larg);
++ case SSL_CTRL_CLEAR_OPTIONS:
++ return(s->options&=~larg);
+ case SSL_CTRL_MODE:
+ return(s->mode|=larg);
++ case SSL_CTRL_CLEAR_MODE:
++ return(s->mode &=~larg);
+ case SSL_CTRL_GET_MAX_CERT_LIST:
+ return(s->max_cert_list);
+ case SSL_CTRL_SET_MAX_CERT_LIST:
+ l=s->max_cert_list;
+ s->max_cert_list=larg;
+ return(l);
++ case SSL_CTRL_GET_RI_SUPPORT:
++ if (s->s3)
++ return s->s3->send_connection_binding;
++ else return 0;
+ default:
+ return(s->method->ssl_ctrl(s,cmd,larg,parg));
+ }
+@@ -1027,8 +1035,12 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,l
+ return(ctx->stats.sess_cache_full);
+ case SSL_CTRL_OPTIONS:
+ return(ctx->options|=larg);
++ case SSL_CTRL_CLEAR_OPTIONS:
++ return(ctx->options&=~larg);
+ case SSL_CTRL_MODE:
+ return(ctx->mode|=larg);
++ case SSL_CTRL_CLEAR_MODE:
++ return(ctx->mode&=~larg);
+ default:
+ return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
+ }
+@@ -1181,7 +1193,8 @@ char *SSL_get_shared_ciphers(SSL *s,char
+ return(buf);
+ }
+
+-int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p)
++int ssl_cipher_list_to_bytes_w_cb(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
++ int (*put_cb)(const SSL_CIPHER *, unsigned char *))
+ {
+ int i,j=0;
+ SSL_CIPHER *c;
+@@ -1200,18 +1213,42 @@ int ssl_cipher_list_to_bytes(SSL *s,STAC
+ if ((c->algorithms & SSL_KRB5) && nokrb5)
+ continue;
+ #endif /* OPENSSL_NO_KRB5 */
+- j=ssl_put_cipher_by_char(s,c,p);
++
++ j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
+ p+=j;
+ }
++ /* If p == q, no ciphers and caller indicates an error. Otherwise
++ * add SCSV if not renegotiating.
++ */
++ if (p != q && !s->new_session)
++ {
++ static SSL_CIPHER scsv =
++ {
++ 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0,
++ };
++ j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
++ p+=j;
++#ifdef OPENSSL_RI_DEBUG
++ fprintf(stderr, "SCSV sent by client\n");
++#endif
++ }
++
+ return(p-q);
+ }
+
++int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p)
++ {
++ return ssl_cipher_list_to_bytes_w_cb(s, sk, p, 0);
++ }
++
+ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
+ STACK_OF(SSL_CIPHER) **skp)
+ {
+ SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *sk;
+ int i,n;
++ if (s->s3)
++ s->s3->send_connection_binding = 0;
+
+ n=ssl_put_cipher_by_char(s,NULL,NULL);
+ if ((num%n) != 0)
+@@ -1229,6 +1266,26 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_ciphe
+
+ for (i=0; i<num; i+=n)
+ {
++ /* Check for SCSV */
++ if (s->s3 && (n != 3 || !p[0]) &&
++ (p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
++ (p[n-1] == (SSL3_CK_SCSV & 0xff)))
++ {
++ /* SCSV fatal if renegotiating */
++ if (s->new_session)
++ {
++ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
++ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
++ goto err;
++ }
++ s->s3->send_connection_binding = 1;
++ p += n;
++#ifdef OPENSSL_RI_DEBUG
++ fprintf(stderr, "SCSV received by server\n");
++#endif
++ continue;
++ }
++
+ c=ssl_get_cipher_by_char(s,p);
+ p+=n;
+ if (c != NULL)
+@@ -1391,6 +1448,11 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
+ ret->extra_certs=NULL;
+ ret->comp_methods=SSL_COMP_get_compression_methods();
+
++ /* Default is to connect to non-RI servers. When RI is more widely
++ * deployed might change this.
++ */
++ ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
++
+ return(ret);
+ err:
+ SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
+diff -up openssl-0.9.7a/ssl/ssl_locl.h.reneg openssl-0.9.7a/ssl/ssl_locl.h
+--- openssl-0.9.7a/ssl/ssl_locl.h.reneg 2010-02-10 13:01:45.000000000 +0100
++++ openssl-0.9.7a/ssl/ssl_locl.h 2010-02-10 14:48:01.000000000 +0100
+@@ -492,6 +492,8 @@ int ssl_cipher_ptr_id_cmp(const SSL_CIPH
+ const SSL_CIPHER * const *bp);
+ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
+ STACK_OF(SSL_CIPHER) **skp);
++int ssl_cipher_list_to_bytes_w_cb(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
++ int (*put_cb)(const SSL_CIPHER *, unsigned char *));
+ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p);
+ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
+ STACK_OF(SSL_CIPHER) **pref,
+@@ -616,5 +618,17 @@ int ssl_ok(SSL *s);
+ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
+ STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
+
++unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit);
++unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit);
++int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
++int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
++int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
++ int maxlen);
++int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
++ int *al);
++int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
++ int maxlen);
++int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
++ int *al);
+
+ #endif
+diff -up openssl-0.9.7a/ssl/ssl3.h.reneg openssl-0.9.7a/ssl/ssl3.h
+--- openssl-0.9.7a/ssl/ssl3.h.reneg 2010-02-10 13:01:45.000000000 +0100
++++ openssl-0.9.7a/ssl/ssl3.h 2010-02-10 13:01:47.000000000 +0100
+@@ -123,6 +123,9 @@
+ extern "C" {
+ #endif
+
++/* Signalling cipher suite value: from draft-ietf-tls-renegotiation-03.txt */
++#define SSL3_CK_SCSV 0x030000FF
++
+ #define SSL3_CK_RSA_NULL_MD5 0x03000001
+ #define SSL3_CK_RSA_NULL_SHA 0x03000002
+ #define SSL3_CK_RSA_RC4_40_MD5 0x03000003
+@@ -418,6 +421,12 @@ typedef struct ssl3_state_st
+ int cert_request;
+ } tmp;
+
++ /* Connection binding to prevent renegotiation attacks */
++ unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
++ unsigned char previous_client_finished_len;
++ unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
++ unsigned char previous_server_finished_len;
++ int send_connection_binding; /* TODOEKR */
+ } SSL3_STATE;
+
+ /* SSLv3 */
+diff -up openssl-0.9.7a/ssl/s3_both.c.reneg openssl-0.9.7a/ssl/s3_both.c
+--- openssl-0.9.7a/ssl/s3_both.c.reneg 2003-02-12 18:05:17.000000000 +0100
++++ openssl-0.9.7a/ssl/s3_both.c 2010-02-10 13:01:47.000000000 +0100
+@@ -163,6 +163,23 @@ int ssl3_send_finished(SSL *s, int a, in
+ p+=i;
+ l=i;
+
++ /* Copy the finished so we can use it for
++ renegotiation checks */
++ if(s->type == SSL_ST_CONNECT)
++ {
++ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
++ memcpy(s->s3->previous_client_finished,
++ s->s3->tmp.finish_md, i);
++ s->s3->previous_client_finished_len=i;
++ }
++ else
++ {
++ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
++ memcpy(s->s3->previous_server_finished,
++ s->s3->tmp.finish_md, i);
++ s->s3->previous_server_finished_len=i;
++ }
++
+ #ifdef OPENSSL_SYS_WIN16
+ /* MSVC 1.5 does not clear the top bytes of the word unless
+ * I do this.
+@@ -227,6 +244,23 @@ int ssl3_get_finished(SSL *s, int a, int
+ goto f_err;
+ }
+
++ /* Copy the finished so we can use it for
++ renegotiation checks */
++ if(s->type == SSL_ST_ACCEPT)
++ {
++ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
++ memcpy(s->s3->previous_client_finished,
++ s->s3->tmp.peer_finish_md, i);
++ s->s3->previous_client_finished_len=i;
++ }
++ else
++ {
++ OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
++ memcpy(s->s3->previous_server_finished,
++ s->s3->tmp.peer_finish_md, i);
++ s->s3->previous_server_finished_len=i;
++ }
++
+ return(1);
+ f_err:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+diff -up openssl-0.9.7a/ssl/s3_clnt.c.reneg openssl-0.9.7a/ssl/s3_clnt.c
+--- openssl-0.9.7a/ssl/s3_clnt.c.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/ssl/s3_clnt.c 2010-02-10 13:01:47.000000000 +0100
+@@ -587,7 +587,11 @@ static int ssl3_client_hello(SSL *s)
+ *(p++)=comp->id;
+ }
+ *(p++)=0; /* Add the NULL method */
+-
++ if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
++ {
++ SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
++ goto err;
++ }
+ l=(p-d);
+ d=buf;
+ *(d++)=SSL3_MT_CLIENT_HELLO;
+@@ -619,7 +623,7 @@ static int ssl3_get_server_hello(SSL *s)
+ SSL3_ST_CR_SRVR_HELLO_A,
+ SSL3_ST_CR_SRVR_HELLO_B,
+ SSL3_MT_SERVER_HELLO,
+- 300, /* ?? */
++ 1000, /* ?? */
+ &ok);
+
+ if (!ok) return((int)n);
+@@ -735,6 +739,17 @@ static int ssl3_get_server_hello(SSL *s)
+ s->s3->tmp.new_compression=comp;
+ }
+
++ /* TLS extensions - we parse renegotiate extension only */
++ if (s->version >= SSL3_VERSION)
++ {
++ if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
++ {
++ /* 'al' set by ssl_parse_serverhello_tlsext */
++ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
++ goto f_err;
++ }
++ }
++
+ if (p != (d+n))
+ {
+ /* wrong packet length */
+diff -up openssl-0.9.7a/ssl/s3_pkt.c.reneg openssl-0.9.7a/ssl/s3_pkt.c
+--- openssl-0.9.7a/ssl/s3_pkt.c.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/ssl/s3_pkt.c 2010-02-10 13:01:47.000000000 +0100
+@@ -1012,7 +1012,25 @@ start:
+ * now try again to obtain the (application) data we were asked for */
+ goto start;
+ }
+-
++ /* If we are a server and get a client hello when renegotiation isn't
++ * allowed send back a no renegotiation alert and carry on.
++ * WARNING: experimental code, needs reviewing (steve)
++ */
++ if (s->server &&
++ SSL_is_init_finished(s) &&
++ !s->s3->send_connection_binding &&
++ (s->version > SSL3_VERSION) &&
++ (s->s3->handshake_fragment_len >= 4) &&
++ (s->s3->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO) &&
++ (s->session != NULL) && (s->session->cipher != NULL) &&
++ !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
++
++ {
++ /*s->s3->handshake_fragment_len = 0;*/
++ rr->length = 0;
++ ssl3_send_alert(s,SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
++ goto start;
++ }
+ if (s->s3->alert_fragment_len >= 2)
+ {
+ int alert_level = s->s3->alert_fragment[0];
+@@ -1042,6 +1060,21 @@ start:
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return(0);
+ }
++ /* This is a warning but we receive it if we requested
++ * renegotiation and the peer denied it. Terminate with
++ * a fatal alert because if application tried to
++ * renegotiatie it presumably had a good reason and
++ * expects it to succeed.
++ *
++ * In future we might have a renegotiation where we
++ * don't care if the peer refused it where we carry on.
++ */
++ else if (alert_descr == SSL_AD_NO_RENEGOTIATION)
++ {
++ al = SSL_AD_HANDSHAKE_FAILURE;
++ SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_NO_RENEGOTIATION);
++ goto f_err;
++ }
+ }
+ else if (alert_level == 2) /* fatal */
+ {
+diff -up openssl-0.9.7a/ssl/s3_srvr.c.reneg openssl-0.9.7a/ssl/s3_srvr.c
+--- openssl-0.9.7a/ssl/s3_srvr.c.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/ssl/s3_srvr.c 2010-02-10 13:01:47.000000000 +0100
+@@ -255,6 +255,18 @@ int ssl3_accept(SSL *s)
+ s->state=SSL3_ST_SR_CLNT_HELLO_A;
+ s->ctx->stats.sess_accept++;
+ }
++ else if (!s->s3->send_connection_binding &&
++ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
++ {
++ /* Server attempting to renegotiate with
++ * client that doesn't support secure
++ * renegotiation.
++ */
++ SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
++ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
++ ret = -1;
++ goto end;
++ }
+ else
+ {
+ /* s->state == SSL_ST_RENEGOTIATE,
+@@ -815,6 +827,16 @@ static int ssl3_get_client_hello(SSL *s)
+ goto f_err;
+ }
+
++ /* TLS extensions - just parsing the renegotiation extension */
++ if (s->version >= SSL3_VERSION)
++ {
++ if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
++ {
++ /* 'al' set by ssl_parse_clienthello_tlsext */
++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
++ goto f_err;
++ }
++ }
+ /* Worst case, we will use the NULL compression, but if we have other
+ * options, we will now look for them. We have i-1 compression
+ * algorithms from the client, starting at q. */
+@@ -948,9 +970,10 @@ static int ssl3_send_server_hello(SSL *s
+ {
+ buf=(unsigned char *)s->init_buf->data;
+ p=s->s3->server_random;
+- Time=time(NULL); /* Time */
++ Time=(unsigned long)time(NULL); /* Time */
+ l2n(Time,p);
+- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
++ if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
++ return -1;
+ /* Do the message type and length last */
+ d=p= &(buf[4]);
+
+@@ -991,6 +1014,11 @@ static int ssl3_send_server_hello(SSL *s
+ *(p++)=0;
+ else
+ *(p++)=s->s3->tmp.new_compression->id;
++ if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
++ {
++ SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
++ return -1;
++ }
+
+ /* do the header */
+ l=(p-d);
+@@ -998,13 +1026,13 @@ static int ssl3_send_server_hello(SSL *s
+ *(d++)=SSL3_MT_SERVER_HELLO;
+ l2n3(l,d);
+
+- s->state=SSL3_ST_CW_CLNT_HELLO_B;
++ s->state=SSL3_ST_SW_SRVR_HELLO_B;
+ /* number of bytes to write */
+ s->init_num=p-buf;
+ s->init_off=0;
+ }
+
+- /* SSL3_ST_CW_CLNT_HELLO_B */
++ /* SSL3_ST_SW_SRVR_HELLO_B */
+ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ }
+
+@@ -1028,7 +1056,7 @@ static int ssl3_send_server_done(SSL *s)
+ s->init_off=0;
+ }
+
+- /* SSL3_ST_CW_CLNT_HELLO_B */
++ /* SSL3_ST_SW_SRVR_DONE_B */
+ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ }
+
+diff -up openssl-0.9.7a/ssl/tls1.h.reneg openssl-0.9.7a/ssl/tls1.h
+--- openssl-0.9.7a/ssl/tls1.h.reneg 2010-02-10 13:01:45.000000000 +0100
++++ openssl-0.9.7a/ssl/tls1.h 2010-02-10 13:01:47.000000000 +0100
+@@ -84,6 +84,9 @@ extern "C" {
+ #define TLS1_AD_USER_CANCELLED 90
+ #define TLS1_AD_NO_RENEGOTIATION 100
+
++/* Temporary extension type */
++#define TLSEXT_TYPE_renegotiate 0xff01
++
+ /* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt
+ * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
+ * s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably
+diff -up openssl-0.9.7a/ssl/t1_lib.c.reneg openssl-0.9.7a/ssl/t1_lib.c
+--- openssl-0.9.7a/ssl/t1_lib.c.reneg 2000-02-21 00:43:02.000000000 +0100
++++ openssl-0.9.7a/ssl/t1_lib.c 2010-02-18 16:52:37.000000000 +0100
+@@ -147,3 +147,202 @@ long tls1_callback_ctrl(SSL *s, int cmd,
+ return(0);
+ }
+ #endif
++
++unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
++ {
++ int extdatalen=0;
++ unsigned char *ret = p;
++
++ /* don't add extensions for SSLv3 unless doing secure renegotiation */
++ if (s->client_version == SSL3_VERSION
++ && !s->s3->send_connection_binding)
++ return p;
++
++ ret+=2;
++
++ if (ret>=limit) return NULL; /* this really never occurs, but ... */
++
++ /* Add RI if renegotiating */
++ if (s->new_session)
++ {
++ int el;
++
++ if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
++ {
++ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
++ return NULL;
++ }
++
++ if((limit - p - 4 - el) < 0) return NULL;
++
++ s2n(TLSEXT_TYPE_renegotiate,ret);
++ s2n(el,ret);
++
++ if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
++ {
++ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
++ return NULL;
++ }
++
++ ret += el;
++ }
++
++ if ((extdatalen = ret-p-2)== 0)
++ return p;
++
++ s2n(extdatalen,p);
++ return ret;
++ }
++
++unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
++ {
++ int extdatalen=0;
++ unsigned char *ret = p;
++
++ /* don't add extensions for SSLv3, unless doing secure renegotiation */
++ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
++ return p;
++
++ ret+=2;
++ if (ret>=limit) return NULL; /* this really never occurs, but ... */
++
++ if(s->s3->send_connection_binding)
++ {
++ int el;
++
++ if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0))
++ {
++ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
++ return NULL;
++ }
++
++ if((limit - p - 4 - el) < 0) return NULL;
++
++ s2n(TLSEXT_TYPE_renegotiate,ret);
++ s2n(el,ret);
++
++ if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el))
++ {
++ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
++ return NULL;
++ }
++
++ ret += el;
++ }
++
++ if ((extdatalen = ret-p-2)== 0)
++ return p;
++
++ s2n(extdatalen,p);
++ return ret;
++ }
++
++int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
++ {
++ unsigned short type;
++ unsigned short size;
++ unsigned short len;
++ unsigned char *data = *p;
++ int renegotiate_seen = 0;
++
++ if (data >= (d+n-2))
++ goto ri_check;
++
++ n2s(data,len);
++
++ if (data > (d+n-len))
++ goto ri_check;
++
++ while (data <= (d+n-4))
++ {
++ n2s(data,type);
++ n2s(data,size);
++
++ if (data+size > (d+n))
++ goto ri_check;
++
++ if (type == TLSEXT_TYPE_renegotiate)
++ {
++ if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
++ return 0;
++ renegotiate_seen = 1;
++ }
++
++ data+=size;
++ }
++ *p = data;
++
++ ri_check:
++
++ /* Need RI if renegotiating */
++
++ if (!renegotiate_seen && s->new_session &&
++ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
++ {
++ *al = SSL_AD_HANDSHAKE_FAILURE;
++ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,
++ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
++ return 0;
++ }
++
++ return 1;
++ }
++
++int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
++ {
++ unsigned short type;
++ unsigned short size;
++ unsigned short len;
++ unsigned char *data = *p;
++ int renegotiate_seen = 0;
++
++ if (data >= (d+n-2))
++ goto ri_check;
++
++ n2s(data,len);
++
++ while(data <= (d+n-4))
++ {
++ n2s(data,type);
++ n2s(data,size);
++
++ if (data+size > (d+n))
++ goto ri_check;
++ if (type == TLSEXT_TYPE_renegotiate)
++ {
++ if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
++ return 0;
++ renegotiate_seen = 1;
++ }
++ data+=size;
++ }
++
++ if (data != d+n)
++ {
++ *al = SSL_AD_DECODE_ERROR;
++ return 0;
++ }
++
++ *p = data;
++
++ ri_check:
++
++ /* Determine if we need to see RI. Strictly speaking if we want to
++ * avoid an attack we should *always* see RI even on initial server
++ * hello because the client doesn't see any renegotiation during an
++ * attack. However this would mean we could not connect to any server
++ * which doesn't support RI so for the immediate future tolerate RI
++ * absence on initial connect only.
++ */
++ if (!renegotiate_seen
++ && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
++ && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
++ {
++ *al = SSL_AD_HANDSHAKE_FAILURE;
++ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
++ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
++ return 0;
++ }
++
++ return 1;
++ }
+diff -up openssl-0.9.7a/ssl/t1_reneg.c.reneg openssl-0.9.7a/ssl/t1_reneg.c
+--- openssl-0.9.7a/ssl/t1_reneg.c.reneg 2010-02-10 13:01:47.000000000 +0100
++++ openssl-0.9.7a/ssl/t1_reneg.c 2010-02-10 13:01:47.000000000 +0100
+@@ -0,0 +1,292 @@
++/* ssl/t1_reneg.c */
++/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
++ * All rights reserved.
++ *
++ * This package is an SSL implementation written
++ * by Eric Young (eay@cryptsoft.com).
++ * The implementation was written so as to conform with Netscapes SSL.
++ *
++ * This library is free for commercial and non-commercial use as long as
++ * the following conditions are aheared to. The following conditions
++ * apply to all code found in this distribution, be it the RC4, RSA,
++ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
++ * included with this distribution is covered by the same copyright terms
++ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
++ *
++ * Copyright remains Eric Young's, and as such any Copyright notices in
++ * the code are not to be removed.
++ * If this package is used in a product, Eric Young should be given attribution
++ * as the author of the parts of the library used.
++ * This can be in the form of a textual message at program startup or
++ * in documentation (online or textual) provided with the package.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * "This product includes cryptographic software written by
++ * Eric Young (eay@cryptsoft.com)"
++ * The word 'cryptographic' can be left out if the rouines from the library
++ * being used are not cryptographic related :-).
++ * 4. If you include any Windows specific code (or a derivative thereof) from
++ * the apps directory (application code) you must include an acknowledgement:
++ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * The licence and distribution terms for any publically available version or
++ * derivative of this code cannot be changed. i.e. this code cannot simply be
++ * copied and put under another distribution licence
++ * [including the GNU Public Licence.]
++ */
++/* ====================================================================
++ * Copyright (c) 1998-2009 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * openssl-core@openssl.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++#include <stdio.h>
++#include <openssl/objects.h>
++#include "ssl_locl.h"
++
++/* Add the client's renegotiation binding */
++int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
++ int maxlen)
++ {
++ if(p)
++ {
++ if((s->s3->previous_client_finished_len+1) > maxlen)
++ {
++ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG);
++ return 0;
++ }
++
++ /* Length byte */
++ *p = s->s3->previous_client_finished_len;
++ p++;
++
++ memcpy(p, s->s3->previous_client_finished,
++ s->s3->previous_client_finished_len);
++#ifdef OPENSSL_RI_DEBUG
++ fprintf(stderr, "%s RI extension sent by client\n",
++ s->s3->previous_client_finished_len ? "Non-empty" : "Empty");
++#endif
++ }
++
++ *len=s->s3->previous_client_finished_len + 1;
++
++
++ return 1;
++ }
++
++/* Parse the client's renegotiation binding and abort if it's not
++ right */
++int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
++ int *al)
++ {
++ int ilen;
++
++ /* Parse the length byte */
++ if(len < 1)
++ {
++ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
++ *al=SSL_AD_ILLEGAL_PARAMETER;
++ return 0;
++ }
++ ilen = *d;
++ d++;
++
++ /* Consistency check */
++ if((ilen+1) != len)
++ {
++ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
++ *al=SSL_AD_ILLEGAL_PARAMETER;
++ return 0;
++ }
++
++ /* Check that the extension matches */
++ if(ilen != s->s3->previous_client_finished_len)
++ {
++ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
++ *al=SSL_AD_HANDSHAKE_FAILURE;
++ return 0;
++ }
++
++ if(memcmp(d, s->s3->previous_client_finished,
++ s->s3->previous_client_finished_len))
++ {
++ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
++ *al=SSL_AD_HANDSHAKE_FAILURE;
++ return 0;
++ }
++#ifdef OPENSSL_RI_DEBUG
++ fprintf(stderr, "%s RI extension received by server\n",
++ ilen ? "Non-empty" : "Empty");
++#endif
++
++ s->s3->send_connection_binding=1;
++
++ return 1;
++ }
++
++/* Add the server's renegotiation binding */
++int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
++ int maxlen)
++ {
++ if(p)
++ {
++ if((s->s3->previous_client_finished_len +
++ s->s3->previous_server_finished_len + 1) > maxlen)
++ {
++ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATE_EXT_TOO_LONG);
++ return 0;
++ }
++
++ /* Length byte */
++ *p = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len;
++ p++;
++
++ memcpy(p, s->s3->previous_client_finished,
++ s->s3->previous_client_finished_len);
++ p += s->s3->previous_client_finished_len;
++
++ memcpy(p, s->s3->previous_server_finished,
++ s->s3->previous_server_finished_len);
++#ifdef OPENSSL_RI_DEBUG
++ fprintf(stderr, "%s RI extension sent by server\n",
++ s->s3->previous_client_finished_len ? "Non-empty" : "Empty");
++#endif
++ }
++
++ *len=s->s3->previous_client_finished_len
++ + s->s3->previous_server_finished_len + 1;
++
++ return 1;
++ }
++
++/* Parse the server's renegotiation binding and abort if it's not
++ right */
++int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
++ int *al)
++ {
++ int expected_len=s->s3->previous_client_finished_len
++ + s->s3->previous_server_finished_len;
++ int ilen;
++
++ /* Check for logic errors */
++ OPENSSL_assert(!expected_len || s->s3->previous_client_finished_len);
++ OPENSSL_assert(!expected_len || s->s3->previous_server_finished_len);
++
++ /* Parse the length byte */
++ if(len < 1)
++ {
++ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
++ *al=SSL_AD_ILLEGAL_PARAMETER;
++ return 0;
++ }
++ ilen = *d;
++ d++;
++
++ /* Consistency check */
++ if(ilen+1 != len)
++ {
++ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
++ *al=SSL_AD_ILLEGAL_PARAMETER;
++ return 0;
++ }
++
++ /* Check that the extension matches */
++ if(ilen != expected_len)
++ {
++ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
++ *al=SSL_AD_HANDSHAKE_FAILURE;
++ return 0;
++ }
++
++ if(memcmp(d, s->s3->previous_client_finished,
++ s->s3->previous_client_finished_len))
++ {
++ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
++ *al=SSL_AD_HANDSHAKE_FAILURE;
++ return 0;
++ }
++ d += s->s3->previous_client_finished_len;
++
++ if(memcmp(d, s->s3->previous_server_finished,
++ s->s3->previous_server_finished_len))
++ {
++ SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
++ *al=SSL_AD_ILLEGAL_PARAMETER;
++ return 0;
++ }
++#ifdef OPENSSL_RI_DEBUG
++ fprintf(stderr, "%s RI extension received by client\n",
++ ilen ? "Non-empty" : "Empty");
++#endif
++ s->s3->send_connection_binding=1;
++
++ return 1;
++ }