OpenSSL CVS Repository
http://cvs.openssl.org/
____________________________________________________________
________________
Server: cvs.openssl.org Name: Dr.
Stephen Henson
Root: /v/openssl/cvs Email: steve openssl.org
Module: openssl Date:
12-Aug-2007 20:59:05
Branch: OpenSSL_0_9_8-stable Handle:
2007081219585706
Modified files: (Branch: OpenSSL_0_9_8-stable)
openssl CHANGES Configure
openssl/apps s_apps.h s_cb.c s_client.c
s_server.c
openssl/ssl s23_clnt.c s2_srvr.c s3_clnt.c
s3_lib.c s3_srvr.c
ssl.h ssl3.h ssl_asn1.c
ssl_err.c ssl_lib.c
ssl_locl.h ssl_sess.c ssl_txt.c
t1_lib.c tls1.h
Log:
Backport of TLS extension code to OpenSSL 0.9.8.
Include server name and RFC4507bis support.
This is not compiled in by default and must be
explicitly enabled with
the Configure option enable-tlsext
Summary:
Revision Changes Path
1.1238.2.74 +52 -0 openssl/CHANGES
1.488.2.41 +5 -0 openssl/Configure
1.16.2.1 +3 -0 openssl/apps/s_apps.h
1.17.2.2 +59 -0 openssl/apps/s_cb.c
1.76.2.10 +121 -1 openssl/apps/s_client.c
1.97.2.5 +283 -11 openssl/apps/s_server.c
1.28.2.4 +7 -0 openssl/ssl/s23_clnt.c
1.46.2.3 +1 -1 openssl/ssl/s2_srvr.c
1.88.2.8 +154 -2 openssl/ssl/s3_clnt.c
1.74.2.17 +50 -0 openssl/ssl/s3_lib.c
1.126.2.13 +128 -4 openssl/ssl/s3_srvr.c
1.161.2.12 +66 -0 openssl/ssl/ssl.h
1.30.2.3 +5 -0 openssl/ssl/ssl3.h
1.20.2.2 +100 -1 openssl/ssl/ssl_asn1.c
1.53.2.5 +13 -0 openssl/ssl/ssl_err.c
1.133.2.9 +63 -2 openssl/ssl/ssl_lib.c
1.63.2.6 +17 -1 openssl/ssl/ssl_locl.h
1.51.2.7 +51 -7 openssl/ssl/ssl_sess.c
1.14.2.3 +15 -0 openssl/ssl/ssl_txt.c
1.13.2.3 +511 -0 openssl/ssl/t1_lib.c
1.17.2.5 +49 -0 openssl/ssl/tls1.h
____________________________________________________________
________________
patch -p0 <<' .'
Index: openssl/CHANGES
============================================================
================
$ cvs diff -u -r1.1238.2.73 -r1.1238.2.74 CHANGES
--- openssl/CHANGES 19 Jul 2007 17:39:05
-0000 1.1238.2.73
+++ openssl/CHANGES 12 Aug 2007 18:58:57
-0000 1.1238.2.74
 -3,6 +3,58 
_______________
Changes between 0.9.8e and 0.9.8f [xx XXX xxxx]
+
+ *) Add RFC4507 support to OpenSSL. This includes the
corrections in
+ RFC4507bis. The encrypted ticket format is an
encrypted encoded
+ SSL_SESSION structure, that way new session features
are automatically
+ supported.
+
+ If a client application caches session in an
SSL_SESSION support it
+ should automatically be supported because an
extension includes the
+ ticket in the structure. The SSL_CTX structure
automatically generates
+ keys for ticket protection in servers so again
support should be possible
+ with no application modification.
+
+ If a client or server wishes to disable RFC4507
support then the option
+ SSL_OP_NO_TICKET can be set.
+
+ Add a TLS extension debugging callback to allow the
contents of any client
+ or server extensions to be examined.
+ [Steve Henson]
+
+ *) Add initial support for TLS extensions, specifically
for the server_name
+ extension so far. The SSL_SESSION, SSL_CTX, and SSL
data structures now
+ have new members for a host name. The SSL data
structure has an
+ additional member SSL_CTX *initial_ctx so that new
sessions can be
+ stored in that context to allow for session
resumption, even after the
+ SSL has been switched to a new SSL_CTX in reaction
to a client's
+ server_name extension.
+
+ New functions (subject to change):
+
+ SSL_get_servername()
+ SSL_get_servername_type()
+ SSL_set_SSL_CTX()
+
+ New CTRL codes and macros (subject to change):
+
+ SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+ -
SSL_CTX_set_tlsext_servername_callback()
+ SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
+ -
SSL_CTX_set_tlsext_servername_arg()
+ SSL_CTRL_SET_TLSEXT_HOSTNAME -
SSL_set_tlsext_host_name()
+
+ openssl s_client has a new '-servername ...'
option.
+
+ openssl s_server has new options '-servername_host
...', '-cert2 ...',
+ '-key2 ...', '-servername_fatal' (subject to
change). This allows
+ testing the HostName extension for a specific single
host name ('-cert'
+ and '-key' remain fallbacks for handshakes without
HostName
+ negotiation). If the unrecogninzed_name alert has
to be sent, this by
+ default is a warning; it becomes fatal with the
'-servername_fatal'
+ option.
+
+ [Peter Sylvester, Remy Allais, Christophe Renou,
Steve Henson]
*) Add AES and SSE2 assembly language support to VC++
build.
[Steve Henson]
 .
patch -p0 <<' .'
Index: openssl/Configure
============================================================
================
$ cvs diff -u -r1.488.2.40 -r1.488.2.41 Configure
--- openssl/Configure 31 Jul 2007 20:03:23
-0000 1.488.2.40
+++ openssl/Configure 12 Aug 2007 18:58:58
-0000 1.488.2.41
 -607,6 +607,7 
"rfc3779" =>
"default",
"seed" =>
"default",
"shared" =>
"default",
+ "tlsext" =>
"default",
"zlib" =>
"default",
"zlib-dynamic" =>
"default"
);
 -838,6 +839,10 
$disabled{"tls1"} = "forced";
}
+if (defined($disabled{"tls1"}))
+ {
+ $disabled{"tlsext"} = "forced";
+ }
if ($target eq "TABLE") {
foreach $target (sort keys %table) {
 .
patch -p0 <<' .'
Index: openssl/apps/s_apps.h
============================================================
================
$ cvs diff -u -r1.16 -r1.16.2.1 s_apps.h
--- openssl/apps/s_apps.h 26 Apr 2005 17:43:52 -0000 1.16
+++ openssl/apps/s_apps.h 12 Aug 2007 18:58:59
-0000 1.16.2.1
 -167,4 +167,7 
#ifdef HEADER_SSL_H
void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int
where, int ret);
void MS_CALLBACK msg_cb(int write_p, int version, int
content_type, const void *buf, size_t len, SSL *ssl, void
*arg);
+void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int
type,
+ unsigned char *data, int len,
+ void *arg);
#endif
 .
patch -p0 <<' .'
Index: openssl/apps/s_cb.c
============================================================
================
$ cvs diff -u -r1.17.2.1 -r1.17.2.2 s_cb.c
--- openssl/apps/s_cb.c 4 Jul 2007 13:09:26
-0000 1.17.2.1
+++ openssl/apps/s_cb.c 12 Aug 2007 18:58:59
-0000 1.17.2.2
 -575,3 +575,62 
}
(void)BIO_flush(bio);
}
+
+void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int
type,
+ unsigned char *data, int len,
+ void *arg)
+ {
+ BIO *bio = arg;
+ char *extname;
+
+ switch(type)
+ {
+ case TLSEXT_TYPE_server_name:
+ extname = "server name";
+ break;
+
+ case TLSEXT_TYPE_max_fragment_length:
+ extname = "max fragment length";
+ break;
+
+ case TLSEXT_TYPE_client_certificate_url:
+ extname = "client certificate URL";
+ break;
+
+ case TLSEXT_TYPE_trusted_ca_keys:
+ extname = "trusted CA keys";
+ break;
+
+ case TLSEXT_TYPE_truncated_hmac:
+ extname = "truncated HMAC";
+ break;
+
+ case TLSEXT_TYPE_status_request:
+ extname = "status request";
+ break;
+
+ case TLSEXT_TYPE_elliptic_curves:
+ extname = "elliptic curves";
+ break;
+
+ case TLSEXT_TYPE_ec_point_formats:
+ extname = "EC point formats";
+ break;
+
+ case TLSEXT_TYPE_session_ticket:
+ extname = "server ticket";
+ break;
+
+
+ default:
+ extname = "unknown";
+ break;
+
+ }
+
+ BIO_printf(bio, "TLS %s extension "%s"
(id=%d), len=%dn",
+ client_server ? "server":
"client",
+ extname, type, len);
+ BIO_dump(bio, (char *)data, len);
+ (void)BIO_flush(bio);
+ }
 .
patch -p0 <<' .'
Index: openssl/apps/s_client.c
============================================================
================
$ cvs diff -u -r1.76.2.9 -r1.76.2.10 s_client.c
--- openssl/apps/s_client.c 4 Jul 2007 13:09:26
-0000 1.76.2.9
+++ openssl/apps/s_client.c 12 Aug 2007 18:58:59
-0000 1.76.2.10
 -171,6 +171,9 
#endif
static int c_Pause=0;
static int c_debug=0;
+#ifndef OPENSSL_NO_TLSEXT
+static int c_tlsextdebug=0;
+#endif
static int c_msg=0;
static int c_showcerts=0;
 -231,9 +234,32 
BIO_printf(bio_err," -engine id - Initialise and
use the specified enginen");
#endif
BIO_printf(bio_err," -rand file%cfile%c...n",
LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
-
+#ifndef OPENSSL_NO_TLSEXT
+ BIO_printf(bio_err," -servername host - Set TLS
extension servername in ClientHellon");
+#endif
}
+#ifndef OPENSSL_NO_TLSEXT
+
+/* This is a context that we pass to callbacks */
+typedef struct tlsextctx_st {
+ BIO * biodebug;
+ int ack;
+} tlsextctx;
+
+
+static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad,
void *arg)
+ {
+ tlsextctx * p = (tlsextctx *) arg;
+ const char * hn= SSL_get_servername(s,
TLSEXT_NAMETYPE_host_name);
+ if (SSL_get_servername_type(s) != -1)
+ p->ack = !SSL_session_reused(s) &&
hn != NULL;
+ else
+ BIO_printf(bio_err,"Can't use
SSL_get_servernamen");
+
+ return SSL_TLSEXT_ERR_OK;
+ }
+#endif
enum
{
PROTO_OFF = 0,
 -287,6 +313,13 
struct timeval tv;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ char *servername = NULL;
+ tlsextctx tlsextcbp =
+ {NULL,0};
+#endif
+ char *sess_in = NULL;
+ char *sess_out = NULL;
struct sockaddr peer;
int peerlen = sizeof(peer);
int enable_timeouts = 0 ;
 -361,6 +394,16 
if (--argc < 1) goto bad;
cert_file= *(++argv);
}
+ else if (strcmp(*argv,"-sess_out") == 0)
+ {
+ if (--argc < 1) goto bad;
+ sess_out = *(++argv);
+ }
+ else if (strcmp(*argv,"-sess_in") == 0)
+ {
+ if (--argc < 1) goto bad;
+ sess_in = *(++argv);
+ }
else if (strcmp(*argv,"-certform") == 0)
{
if (--argc < 1) goto bad;
 -385,6 +428,10 
c_Pause=1;
else if (strcmp(*argv,"-debug") == 0)
c_debug=1;
+#ifndef OPENSSL_NO_TLSEXT
+ else if (strcmp(*argv,"-tlsextdebug") == 0)
+ c_tlsextdebug=1;
+#endif
#ifdef WATT32
else if (strcmp(*argv,"-wdebug") == 0)
dbug_init();
 -460,6 +507,10 
off|=SSL_OP_NO_SSLv3;
else if (strcmp(*argv,"-no_ssl2") == 0)
off|=SSL_OP_NO_SSLv2;
+#ifndef OPENSSL_NO_TLSEXT
+ else if (strcmp(*argv,"-no_ticket") == 0)
+ { off|=SSL_OP_NO_TICKET; }
+#endif
else if (strcmp(*argv,"-serverpref") == 0)
off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
else if (strcmp(*argv,"-cipher") == 0)
 -498,6 +549,14 
if (--argc < 1) goto bad;
inrand= *(++argv);
}
+#ifndef OPENSSL_NO_TLSEXT
+ else if (strcmp(*argv,"-servername") == 0)
+ {
+ if (--argc < 1) goto bad;
+ servername= *(++argv);
+ /* meth=TLSv1_client_method(); */
+ }
+#endif
else
{
BIO_printf(bio_err,"unknown option
%sn",*argv);
 -621,8 +680,51 
store = SSL_CTX_get_cert_store(ctx);
X509_STORE_set_flags(store, vflags);
+#ifndef OPENSSL_NO_TLSEXT
+ if (servername != NULL)
+ {
+ tlsextcbp.biodebug = bio_err;
+ SSL_CTX_set_tlsext_servername_callback(ctx,
ssl_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(ctx,
&tlsextcbp);
+ }
+#endif
con=SSL_new(ctx);
+ if (sess_in)
+ {
+ SSL_SESSION *sess;
+ BIO *stmp = BIO_new_file(sess_in, "r");
+ if (!stmp)
+ {
+ BIO_printf(bio_err, "Can't open session file
%sn",
+ sess_in);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
+ BIO_free(stmp);
+ if (!sess)
+ {
+ BIO_printf(bio_err, "Can't open session file
%sn",
+ sess_in);
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ SSL_set_session(con, sess);
+ SSL_SESSION_free(sess);
+ }
+#ifndef OPENSSL_NO_TLSEXT
+ if (servername != NULL)
+ {
+ if (!SSL_set_tlsext_host_name(con,servername))
+ {
+ BIO_printf(bio_err,"Unable to set TLS servername
extension.n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+#endif
+
#ifndef OPENSSL_NO_KRB5
if (con && (con->kssl_ctx = kssl_ctx_new())
!= NULL)
{
 -714,6 +816,13 
SSL_set_msg_callback(con, msg_cb);
SSL_set_msg_callback_arg(con, bio_c_out);
}
+#ifndef OPENSSL_NO_TLSEXT
+ if (c_tlsextdebug)
+ {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_c_out);
+ }
+#endif
SSL_set_bio(con,sbio,sbio);
SSL_set_connect_state(con);
 -837,6 +946,17 
if (in_init)
{
in_init=0;
+ if (sess_out)
+ {
+ BIO *stmp = BIO_new_file(sess_out, "w");
+ if (stmp)
+ {
+ PEM_write_bio_SSL_SESSION(stmp,
SSL_get_session(con));
+ BIO_free(stmp);
+ }
+ else
+ BIO_printf(bio_err, "Error writing session
file %sn", sess_out);
+ }
print_stuff(bio_c_out,con,full_log);
if (full_log > 0) full_log--;
 .
patch -p0 <<' .'
Index: openssl/apps/s_server.c
============================================================
================
$ cvs diff -u -r1.97.2.4 -r1.97.2.5 s_server.c
--- openssl/apps/s_server.c 29 Nov 2006 20:47:11
-0000 1.97.2.4
+++ openssl/apps/s_server.c 12 Aug 2007 18:58:59
-0000 1.97.2.5
 -238,6 +238,9 
static int accept_socket= -1;
#define TEST_CERT "server.pem"
+#ifndef OPENSSL_NO_TLSEXT
+#define TEST_CERT2 "server2.pem"
+#endif
#undef PROG
#define PROG s_server_main
 -247,6 +250,9 
static int s_server_verify=SSL_VERIFY_NONE;
static int s_server_session_id_context = 1; /* anything
will do */
static const char
*s_cert_file=TEST_CERT,*s_key_file=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+static const char
*s_cert_file2=TEST_CERT2,*s_key_file2=NULL;
+#endif
static char *s_dcert_file=NULL,*s_dkey_file=NULL;
#ifdef FIONBIO
static int s_nbio=0;
 -254,10 +260,16 
static int s_nbio_test=0;
int s_crlf=0;
static SSL_CTX *ctx=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+static SSL_CTX *ctx2=NULL;
+#endif
static int www=0;
static BIO *bio_s_out=NULL;
static int s_debug=0;
+#ifndef OPENSSL_NO_TLSEXT
+static int s_tlsextdebug=0;
+#endif
static int s_msg=0;
static int s_quiet=0;
 -285,6 +297,11 
s_dkey_file=NULL;
s_cert_file=TEST_CERT;
s_key_file=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+ s_cert_file2=TEST_CERT2;
+ s_key_file2=NULL;
+ ctx2=NULL;
+#endif
#ifdef FIONBIO
s_nbio=0;
#endif
 -371,6 +388,14 
#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);
+#ifndef OPENSSL_NO_TLSEXT
+ BIO_printf(bio_err," -servername host - servername
for HostName TLS extensionn");
+ BIO_printf(bio_err," -servername_fatal - on
mismatch send fatal alert (default warning alert)n");
+ BIO_printf(bio_err," -cert2 arg - certificate
file to use for servernamen");
+ BIO_printf(bio_err," (default is
%s)n",TEST_CERT2);
+ BIO_printf(bio_err," -key2 arg - Private Key
file to use for servername, in cert file ifn");
+ BIO_printf(bio_err," not specified
(default is %s)n",TEST_CERT2);
+#endif
}
static int local_argc=0;
 -526,6 +551,39 
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
+
+/* This is a context that we pass to callbacks */
+typedef struct tlsextctx_st {
+ char * servername;
+ BIO * biodebug;
+ int extension_error;
+} tlsextctx;
+
+
+static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad,
void *arg)
+ {
+ tlsextctx * p = (tlsextctx *) arg;
+ const char * servername = SSL_get_servername(s,
TLSEXT_NAMETYPE_host_name);
+ if (servername && p->biodebug)
+ BIO_printf(p->biodebug,"Hostname in TLS
extension: "%s"n",servername);
+
+ if (!p->servername)
+ return SSL_TLSEXT_ERR_NOACK;
+
+ if (servername)
+ {
+ if (strcmp(servername,p->servername))
+ return p->extension_error;
+ if (ctx2)
+ {
+ BIO_printf(p->biodebug,"Swiching server
context.n");
+ SSL_set_SSL_CTX(s,ctx2);
+ }
+ }
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif
int MAIN(int, char **);
int MAIN(int argc, char *argv[])
 -545,10 +603,7 
int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0;
int state=0;
SSL_METHOD *meth=NULL;
-#ifdef sock_type
-#undef sock_type
-#endif
- int sock_type=SOCK_STREAM;
+ int socket_type=SOCK_STREAM;
#ifndef OPENSSL_NO_ENGINE
ENGINE *e=NULL;
#endif
 -559,6 +614,14 
int s_dcert_format = FORMAT_PEM, s_dkey_format =
FORMAT_PEM;
X509 *s_cert = NULL, *s_dcert = NULL;
EVP_PKEY *s_key = NULL, *s_dkey = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+ EVP_PKEY *s_key2 = NULL;
+ X509 *s_cert2 = NULL;
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+ tlsextctx tlsextcbp = {NULL, NULL,
SSL_TLSEXT_ERR_ALERT_WARNING};
+#endif
#if !defined(OPENSSL_NO_SSL2) &&
!defined(OPENSSL_NO_SSL3)
meth=SSLv23_server_method();
 -724,6 +787,10 
}
else if (strcmp(*argv,"-debug") == 0)
{ s_debug=1; }
+#ifndef OPENSSL_NO_TLSEXT
+ else if (strcmp(*argv,"-tlsextdebug") == 0)
+ s_tlsextdebug=1;
+#endif
else if (strcmp(*argv,"-msg") == 0)
{ s_msg=1; }
else if (strcmp(*argv,"-hack") == 0)
 -754,6 +821,10 
{ off|=SSL_OP_NO_SSLv3; }
else if (strcmp(*argv,"-no_tls1") == 0)
{ off|=SSL_OP_NO_TLSv1; }
+#ifndef OPENSSL_NO_TLSEXT
+ else if (strcmp(*argv,"-no_ticket") == 0)
+ { off|=SSL_OP_NO_TICKET; }
+#endif
#ifndef OPENSSL_NO_SSL2
else if (strcmp(*argv,"-ssl2") == 0)
{ meth=SSLv2_server_method(); }
 -770,7 +841,7 
else if (strcmp(*argv,"-dtls1") == 0)
{
meth=DTLSv1_server_method();
- sock_type = SOCK_DGRAM;
+ socket_type = SOCK_DGRAM;
}
else if (strcmp(*argv,"-timeout") == 0)
enable_timeouts = 1;
 -799,6 +870,25 
if (--argc < 1) goto bad;
inrand= *(++argv);
}
+#ifndef OPENSSL_NO_TLSEXT
+ else if (strcmp(*argv,"-servername") == 0)
+ {
+ if (--argc < 1) goto bad;
+ tlsextcbp.servername= *(++argv);
+ }
+ else if (strcmp(*argv,"-servername_fatal") ==
0)
+ { tlsextcbp.extension_error =
SSL_TLSEXT_ERR_ALERT_FATAL; }
+ else if (strcmp(*argv,"-cert2") == 0)
+ {
+ if (--argc < 1) goto bad;
+ s_cert_file2= *(++argv);
+ }
+ else if (strcmp(*argv,"-key2") == 0)
+ {
+ if (--argc < 1) goto bad;
+ s_key_file2= *(++argv);
+ }
+#endif
else
{
BIO_printf(bio_err,"unknown option
%sn",*argv);
 -831,6 +921,10 
if (s_key_file == NULL)
s_key_file = s_cert_file;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s_key_file2 == NULL)
+ s_key_file2 = s_cert_file2;
+#endif
if (nocert == 0)
{
 -850,8 +944,29 
ERR_print_errors(bio_err);
goto end;
}
- }
+#ifndef OPENSSL_NO_TLSEXT
+ if (tlsextcbp.servername)
+ {
+ s_key2 = load_key(bio_err, s_key_file2, s_key_format,
0, pass, e,
+ "second server certificate private key
file");
+ if (!s_key2)
+ {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+
+ s_cert2 =
load_cert(bio_err,s_cert_file2,s_cert_format,
+ NULL, e, "second server certificate
file");
+
+ if (!s_cert2)
+ {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+#endif
+ }
if (s_dcert_file)
{
 -908,6 +1023,10 
s_key_file=NULL;
s_dcert_file=NULL;
s_dkey_file=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+ s_cert_file2=NULL;
+ s_key_file2=NULL;
+#endif
}
ctx=SSL_CTX_new(meth);
 -939,7 +1058,7 
/* DTLS: partial reads end up discarding unread UDP
bytes :-(
* Setting read ahead solves this problem.
*/
- if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx,
1);
+ if (socket_type == SOCK_DGRAM)
SSL_CTX_set_read_ahead(ctx, 1);
if (state)
SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
 -966,6 +1085,62 
}
store = SSL_CTX_get_cert_store(ctx);
X509_STORE_set_flags(store, vflags);
+#ifndef OPENSSL_NO_TLSEXT
+ if (s_cert2)
+ {
+ ctx2=SSL_CTX_new(meth);
+ if (ctx2 == NULL)
+ {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+
+ if (ctx2)
+ {
+ BIO_printf(bio_s_out,"Setting secondary ctx
parametersn");
+
+ if (session_id_prefix)
+ {
+ if(strlen(session_id_prefix) >= 32)
+ BIO_printf(bio_err,
+ "warning: id_prefix is too long, only one new
session will be possiblen");
+ else if(strlen(session_id_prefix) >= 16)
+ BIO_printf(bio_err,
+ "warning: id_prefix is too long if you use
SSLv2n");
+ if(!SSL_CTX_set_generate_session_id(ctx2,
generate_session_id))
+ {
+ BIO_printf(bio_err,"error setting
'id_prefix'n");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ BIO_printf(bio_err,"id_prefix '%s' set.n",
session_id_prefix);
+ }
+ SSL_CTX_set_quiet_shutdown(ctx2,1);
+ if (bugs) SSL_CTX_set_options(ctx2,SSL_OP_ALL);
+ if (hack)
SSL_CTX_set_options(ctx2,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_
BUG);
+ SSL_CTX_set_options(ctx2,off);
+
+ /* DTLS: partial reads end up discarding unread UDP
bytes :-(
+ * Setting read ahead solves this problem.
+ */
+ if (socket_type == SOCK_DGRAM)
SSL_CTX_set_read_ahead(ctx2, 1);
+
+
+ if (state)
SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback);
+
+ SSL_CTX_sess_set_cache_size(ctx2,128);
+
+ if
((!SSL_CTX_load_verify_locations(ctx2,CAfile,CApath)) ||
+ (!SSL_CTX_set_default_verify_paths(ctx2)))
+ {
+ ERR_print_errors(bio_err);
+ }
+ store = SSL_CTX_get_cert_store(ctx2);
+ X509_STORE_set_flags(store, vflags);
+ }
+#endif
+
#ifndef OPENSSL_NO_DH
if (!no_dhe)
 -989,6 +1164,24 
(void)BIO_flush(bio_s_out);
SSL_CTX_set_tmp_dh(ctx,dh);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2)
+ {
+ if (!dhfile)
+ {
+ DH *dh2=load_dh_param(s_cert_file2);
+ if (dh2 != NULL)
+ {
+ BIO_printf(bio_s_out,"Setting temp DH
parametersn");
+ (void)BIO_flush(bio_s_out);
+
+ DH_free(dh);
+ dh = dh2;
+ }
+ }
+ SSL_CTX_set_tmp_dh(ctx2,dh);
+ }
+#endif
DH_free(dh);
}
#endif
 -1034,12 +1227,20 
(void)BIO_flush(bio_s_out);
SSL_CTX_set_tmp_ecdh(ctx,ecdh);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2)
+ SSL_CTX_set_tmp_ecdh(ctx2,ecdh);
+#endif
EC_KEY_free(ecdh);
}
#endif
if (!set_cert_key_stuff(ctx,s_cert,s_key))
goto end;
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2 &&
!set_cert_key_stuff(ctx2,s_cert2,s_key2))
+ goto end;
+#endif
if (s_dcert != NULL)
{
if (!set_cert_key_stuff(ctx,s_dcert,s_dkey))
 -1049,7 +1250,13 
#ifndef OPENSSL_NO_RSA
#if 1
if (!no_tmp_rsa)
+ {
SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2)
+ SSL_CTX_set_tmp_rsa_callback(ctx2,tmp_rsa_cb);
+#endif
+ }
#else
if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx))
{
 -1065,6 +1272,16 
ERR_print_errors(bio_err);
goto end;
}
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2)
+ {
+ if (!SSL_CTX_set_tmp_rsa(ctx2,rsa))
+ {
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+ }
+#endif
RSA_free(rsa);
BIO_printf(bio_s_out,"n");
}
 -1076,19 +1293,46 
BIO_printf(bio_err,"error setting cipher
listn");
ERR_print_errors(bio_err);
goto end;
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2 &&
!SSL_CTX_set_cipher_list(ctx2,cipher))
+ {
+ BIO_printf(bio_err,"error setting cipher
listn");
+ ERR_print_errors(bio_err);
+ goto end;
+ }
+#endif
}
SSL_CTX_set_verify(ctx,s_server_verify,verify_callback);
SSL_CTX_set_session_id_context(ctx,(void*)&s_server_ses
sion_id_context,
sizeof s_server_session_id_context);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2)
+ {
+ SSL_CTX_set_verify(ctx2,s_server_verify,verify_callback);
+ SSL_CTX_set_session_id_context(ctx2,(void*)&s_server_
session_id_context,
+ sizeof s_server_session_id_context);
+
+ tlsextcbp.biodebug = bio_s_out;
+ SSL_CTX_set_tlsext_servername_callback(ctx2,
ssl_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(ctx2,
&tlsextcbp);
+ SSL_CTX_set_tlsext_servername_callback(ctx,
ssl_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(ctx,
&tlsextcbp);
+ }
+#endif
if (CAfile != NULL)
-
SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfil
e));
-
+ {
+ SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CA
file));
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2)
+ SSL_CTX_set_client_CA_list(ctx2,SSL_load_client_CA_file(
CAfile));
+#endif
+ }
BIO_printf(bio_s_out,"ACCEPTn");
if (www)
- do_server(port,sock_type,&accept_socket,www_body,
context);
+ do_server(port,socket_type,&accept_socket,www_body,
context);
else
- do_server(port,sock_type,&accept_socket,sv_body,
context);
+ do_server(port,socket_type,&accept_socket,sv_body,
context);
print_stats(bio_s_out,ctx);
ret=0;
end:
 -1105,6 +1349,13 
OPENSSL_free(pass);
if (dpass)
OPENSSL_free(dpass);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx2 != NULL) SSL_CTX_free(ctx2);
+ if (s_cert2)
+ X509_free(s_cert2);
+ if (s_key2)
+ EVP_PKEY_free(s_key2);
+#endif
if (bio_s_out != NULL)
{
BIO_free(bio_s_out);
 -1171,6 +1422,13 
if (con == NULL) {
con=SSL_new(ctx);
+#ifndef OPENSSL_NO_TLSEXT
+ if (s_tlsextdebug)
+ {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+#endif
#ifndef OPENSSL_NO_KRB5
if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
{
 -1241,6 +1499,13 
SSL_set_msg_callback(con, msg_cb);
SSL_set_msg_callback_arg(con, bio_s_out);
}
+#ifndef OPENSSL_NO_TLSEXT
+ if (s_tlsextdebug)
+ {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+#endif
width=s+1;
for (;;)
 -1606,6 +1871,13 
if (!BIO_set_write_buffer_size(io,bufsize)) goto err;
if ((con=SSL_new(ctx)) == NULL) goto err;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s_tlsextdebug)
+ {
+ SSL_set_tlsext_debug_callback(con, tlsext_cb);
+ SSL_set_tlsext_debug_arg(con, bio_s_out);
+ }
+#endif
#ifndef OPENSSL_NO_KRB5
if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
{
 .
patch -p0 <<' .'
Index: openssl/ssl/s23_clnt.c
============================================================
================
$ cvs diff -u -r1.28.2.3 -r1.28.2.4 s23_clnt.c
--- openssl/ssl/s23_clnt.c 29 Nov 2006 14:45:13
-0000 1.28.2.3
+++ openssl/ssl/s23_clnt.c 12 Aug 2007 18:59:01
-0000 1.28.2.4
 -360,6 +360,13 
*(p++)=comp->id;
}
*(p++)=0; /* Add the NULL method */
+#ifndef OPENSSL_NO_TLSEXT
+ if ((p = ssl_add_clienthello_tlsext(s, p,
buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+ {
+ SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+#endif
l = p-d;
*p = 42;
 .
patch -p0 <<' .'
Index: openssl/ssl/s2_srvr.c
============================================================
================
$ cvs diff -u -r1.46.2.2 -r1.46.2.3 s2_srvr.c
--- openssl/ssl/s2_srvr.c 5 Dec 2005 17:32:20
-0000 1.46.2.2
+++ openssl/ssl/s2_srvr.c 12 Aug 2007 18:59:01
-0000 1.46.2.3
 -607,7 +607,7 
else
{
i=ssl_get_prev_session(s,&(p[s->s2->tmp.cipher_s
pec_length]),
- s->s2->tmp.session_id_length);
+ s->s2->tmp.session_id_length, NULL);
if (i == 1)
{ /* previous session */
s->hit=1;
 .
patch -p0 <<' .'
Index: openssl/ssl/s3_clnt.c
============================================================
================
$ cvs diff -u -r1.88.2.7 -r1.88.2.8 s3_clnt.c
--- openssl/ssl/s3_clnt.c 9 Mar 2007 14:06:34
-0000 1.88.2.7
+++ openssl/ssl/s3_clnt.c 12 Aug 2007 18:59:01
-0000 1.88.2.8
 -137,6 +137,9 
static 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_TLSEXT
+static int ssl3_check_finished(SSL *s);
+#endif
#ifndef OPENSSL_NO_ECDH
static int curve_id2nid(int curve_id);
 -264,6 +267,17 
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+ ret=ssl3_check_finished(s);
+ if (ret <= 0) goto end;
+ if (ret == 2)
+ {
+ s->hit = 1;
+ s->state=SSL3_ST_CR_FINISHED_A;
+ s->init_num=0;
+ break;
+ }
+#endif
/* Check if it is anon DH/ECDH */
if (!(s->s3->tmp.new_cipher->algorithms &
SSL_aNULL))
{
 -416,11 +430,27 
}
else
{
+#ifndef OPENSSL_NO_TLSEXT
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected)
+ s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_
A;
+ else
+#endif
+
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
}
s->init_num=0;
break;
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_CR_SESSION_TICKET_A:
+ case SSL3_ST_CR_SESSION_TICKET_B:
+ ret=ssl3_get_new_session_ticket(s);
+ s->state=SSL3_ST_CR_FINISHED_A;
+ s->init_num=0;
+ break;
+#endif
+
case SSL3_ST_CR_FINISHED_A:
case SSL3_ST_CR_FINISHED_B:
 -600,7 +630,13 
}
#endif
*(p++)=0; /* Add the NULL method */
-
+#ifndef OPENSSL_NO_TLSEXT
+ 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;
+ }
+#endif
l=(p-d);
d=buf;
*(d++)=SSL3_MT_CLIENT_HELLO;
 -634,7 +670,7 
SSL3_ST_CR_SRVR_HELLO_A,
SSL3_ST_CR_SRVR_HELLO_B,
-1,
- 300, /* ?? */
+ 20000, /* ?? */
&ok);
if (!ok) return((int)n);
 -784,6 +820,24 
s->s3->tmp.new_compression=comp;
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extensions*/
+ 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 (ssl_check_serverhello_tlsext(s) <= 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLS
EXT);
+ goto err;
+ }
+ }
+#endif
+
if (p != (d+n))
{
 -1590,6 +1644,74 
{
return(X509_NAME_cmp(*a,*b));
}
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_get_new_session_ticket(SSL *s)
+ {
+ int ok,al,ret=0, ticklen;
+ long n;
+ const unsigned char *p;
+ unsigned char *d;
+
+ n=s->method->ssl_get_message(s,
+ SSL3_ST_CR_SESSION_TICKET_A,
+ SSL3_ST_CR_SESSION_TICKET_B,
+ -1,
+ 16384,
+ &ok);
+
+ if (!ok)
+ return((int)n);
+
+ if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+ {
+ s->s3->tmp.reuse_message=1;
+ return(1);
+ }
+ if (s->s3->tmp.message_type !=
SSL3_MT_NEWSESSION_TICKET)
+ {
+ al=SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAG
E_TYPE);
+ goto f_err;
+ }
+ if (n < 6)
+ {
+ /* need at least ticket_lifetime_hint + ticket length
*/
+ al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MIS
MATCH);
+ goto f_err;
+ }
+ p=d=(unsigned char *)s->init_msg;
+ n2l(p, s->session->tlsext_tick_lifetime_hint);
+ n2s(p, ticklen);
+ /* ticket_lifetime_hint + ticket_length + ticket */
+ if (ticklen + 6 != n)
+ {
+ al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATC
H);
+ goto f_err;
+ }
+ if (s->session->tlsext_tick)
+ {
+ OPENSSL_free(s->session->tlsext_tick);
+ s->session->tlsext_ticklen = 0;
+ }
+ s->session->tlsext_tick =
OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ {
+ SSLerr(SSL_F_SSL3_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE
);
+ goto err;
+ }
+ memcpy(s->session->tlsext_tick, p, ticklen);
+ s->session->tlsext_ticklen = ticklen;
+
+ ret=1;
+ return(ret);
+f_err:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+ return(-1);
+ }
+#endif
int ssl3_get_server_done(SSL *s)
{
 -2458,3 +2580,33 
return nid_list[curve_id];
}
#endif
+
+/* Check to see if handshake is full or resumed. Usually
this is just a
+ * case of checking to see if a cache hit has occurred.
In the case of
+ * session tickets we have to check the next message to
be sure.
+ */
+
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl3_check_finished(SSL *s)
+ {
+ int ok;
+ long n;
+ if (!s->session->tlsext_tick)
+ return 1;
+ /* this function is called when we really expect a
Certificate
+ * message, so permit appropriate message length */
+ n=s->method->ssl_get_message(s,
+ SSL3_ST_CR_CERT_A,
+ SSL3_ST_CR_CERT_B,
+ -1,
+ s->max_cert_list,
+ &ok);
+ if (!ok) return((int)n);
+ s->s3->tmp.reuse_message = 1;
+ if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
+ || (s->s3->tmp.message_type ==
SSL3_MT_NEWSESSION_TICKET))
+ return 2;
+
+ return 1;
+ }
+#endif
 .
patch -p0 <<' .'
Index: openssl/ssl/s3_lib.c
============================================================
================
$ cvs diff -u -r1.74.2.16 -r1.74.2.17 s3_lib.c
--- openssl/ssl/s3_lib.c 23 Apr 2007 23:50:20
-0000 1.74.2.16
+++ openssl/ssl/s3_lib.c 12 Aug 2007 18:59:01
-0000 1.74.2.17
 -1904,6 +1904,39 
}
break;
#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+ if (larg == TLSEXT_NAMETYPE_host_name)
+ {
+ if (s->tlsext_hostname != NULL)
+ OPENSSL_free(s->tlsext_hostname);
+ s->tlsext_hostname = NULL;
+
+ ret = 1;
+ if (parg == NULL)
+ break;
+ if (strlen((char *)parg) >
TLSEXT_MAXLEN_host_name)
+ {
+ SSLerr(SSL_F_SSL3_CTRL,
SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+ return 0;
+ }
+ if ((s->tlsext_hostname = BUF_strdup((char *)parg))
== NULL)
+ {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ else
+ {
+ SSLerr(SSL_F_SSL3_CTRL,
SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
+ return 0;
+ }
+ s->options |= SSL_OP_NO_SSLv2; /* can't use
extension w/ SSL 2.0 format */
+ break;
+ case SSL_CTRL_SET_TLSEXT_DEBUG_ARG:
+ s->tlsext_debug_arg=parg;
+ break;
+#endif /* !OPENSSL_NO_TLSEXT */
default:
break;
}
 -1955,6 +1988,12 
}
break;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
+ s->tlsext_debug_cb=(void (*)(SSL *,int ,int,
+ unsigned char *, int, void *))fp;
+ break;
+#endif
default:
break;
}
 -2088,6 +2127,11 
}
break;
#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
+ ctx->tlsext_servername_arg=parg;
+ break;
+#endif /* !OPENSSL_NO_TLSEXT */
/* A Thawte special */
case SSL_CTRL_EXTRA_CHAIN_CERT:
if (ctx->extra_certs == NULL)
 -2133,6 +2177,11 
}
break;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
+ ctx->tlsext_servername_callback=(int (*)(SSL *,int
*,void *))fp;
+ break;
+#endif
default:
return(0);
}
 -2178,6 +2227,7 
SSL_CIPHER *c,*ret=NULL;
STACK_OF(SSL_CIPHER) *prio, *allow;
int i,j,ok;
+
CERT *cert;
unsigned long alg,mask,emask;
 .
patch -p0 <<' .'
Index: openssl/ssl/s3_srvr.c
============================================================
================
$ cvs diff -u -r1.126.2.12 -r1.126.2.13 s3_srvr.c
--- openssl/ssl/s3_srvr.c 9 Mar 2007 14:06:34
-0000 1.126.2.12
+++ openssl/ssl/s3_srvr.c 12 Aug 2007 18:59:01
-0000 1.126.2.13
 -132,6 +132,7 
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
+#include <openssl/hmac.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_DH
#include <openssl/dh.h>
 -143,7 +144,6 
#include <openssl/md5.h>
static SSL_METHOD *ssl3_get_server_method(int ver);
-
#ifndef OPENSSL_NO_ECDH
static int nid2curve_id(int nid);
#endif
 -494,11 +494,26 
if (ret <= 0) goto end;
if (s->hit)
s->state=SSL_ST_OK;
+#ifndef OPENSSL_NO_TLSEXT
+ else if (s->tlsext_ticket_expected)
+ s->state=SSL3_ST_SW_SESSION_TICKET_A;
+#endif
else
s->state=SSL3_ST_SW_CHANGE_A;
s->init_num=0;
break;
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_SW_SESSION_TICKET_A:
+ case SSL3_ST_SW_SESSION_TICKET_B:
+ ret=ssl3_send_newsession_ticket(s);
+ if (ret <= 0) goto end;
+ s->state=SSL3_ST_SW_CHANGE_A;
+ s->init_num=0;
+ break;
+
+#endif
+
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
 -727,14 +742,14 
* might be written that become totally unsecure when
compiled with
* an earlier library version)
*/
- if (j == 0 || (s->new_session &&
(s->options &
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
+ if ((s->new_session && (s->options &
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
{
if (!ssl_get_new_session(s,1))
goto err;
}
else
{
- i=ssl_get_prev_session(s,p,j);
+ i=ssl_get_prev_session(s, p, j, d + n);
if (i == 1)
{ /* previous session */
s->hit=1;
 -897,6 +912,22 
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extensions*/
+ 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;
+ }
+ }
+ if (ssl_check_clienthello_tlsext(s) <= 0) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLS
EXT);
+ goto err;
+ }
+#endif
/* 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. */
 -1088,7 +1119,13 
else
*(p++)=s->s3->tmp.new_compression->id;
#endif
-
+#ifndef OPENSSL_NO_TLSEXT
+ 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;
+ }
+#endif
/* do the header */
l=(p-d);
d=buf;
 -2615,3 +2652,90 
}
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_send_newsession_ticket(SSL *s)
+ {
+ if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+ {
+ unsigned char *p, *senc, *macstart;
+ int len, slen;
+ unsigned int hlen;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+
+ /* get session encoding length */
+ slen = i2d_SSL_SESSION(s->session, NULL);
+ /* Some length values are 16 bits, so forget it if
session is
+ * too long
+ */
+ if (slen > 0xFF00)
+ return -1;
+ /* Grow buffer if need be: the length calculation is
as
+ * follows 1 (size of message name) + 3 (message
length
+ * bytes) + 4 (ticket lifetime hint) + 2 (ticket
length) +
+ * 16 (key name) + max_iv_len (iv length) +
+ * session_length + max_enc_block_size (max encrypted
session
+ * length) + max_md_size (HMAC).
+ */
+ if (!BUF_MEM_grow(s->init_buf,
+ 26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
+ EVP_MAX_MD_SIZE + slen))
+ return -1;
+ senc = OPENSSL_malloc(slen);
+ if (!senc)
+ return -1;
+ p = senc;
+ i2d_SSL_SESSION(s->session, &p);
+
+ p=(unsigned char *)s->init_buf->data;
+ /* do the header */
+ *(p++)=SSL3_MT_NEWSESSION_TICKET;
+ /* Skip message length for now */
+ p += 3;
+ l2n(s->session->tlsext_tick_lifetime_hint, p);
+ /* Skip ticket length for now */
+ p += 2;
+ /* Output key name */
+ macstart = p;
+ memcpy(p, s->ctx->tlsext_tick_key_name, 16);
+ p += 16;
+ /* Generate and output IV */
+ RAND_pseudo_bytes(p, 16);
+ EVP_CIPHER_CTX_init(&ctx);
+ /* Encrypt session data */
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ s->ctx->tlsext_tick_aes_key, p);
+ p += 16;
+ EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+ p += len;
+ EVP_EncryptFinal(&ctx, p, &len);
+ p += len;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ HMAC_CTX_init(&hctx);
+ HMAC_Init_ex(&hctx,
s->ctx->tlsext_tick_hmac_key, 16,
+ EVP_sha1(), NULL);
+ HMAC_Update(&hctx, macstart, p - macstart);
+ HMAC_Final(&hctx, p, &hlen);
+ HMAC_CTX_cleanup(&hctx);
+
+ p += hlen;
+ /* Now write out lengths: p points to end of data
written */
+ /* Total length */
+ len = p - (unsigned char *)s->init_buf->data;
+ p=(unsigned char *)s->init_buf->data + 1;
+ l2n3(len - 4, p); /* Message length */
+ p += 4;
+ s2n(len - 10, p); /* Ticket length */
+
+ /* number of bytes to write */
+ s->init_num= len;
+ s->state=SSL3_ST_SW_SESSION_TICKET_B;
+ s->init_off=0;
+ OPENSSL_free(senc);
+ }
+
+ /* SSL3_ST_SW_SESSION_TICKET_B */
+ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ }
+#endif
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl.h
============================================================
================
$ cvs diff -u -r1.161.2.11 -r1.161.2.12 ssl.h
--- openssl/ssl/ssl.h 25 Apr 2007 07:58:32
-0000 1.161.2.11
+++ openssl/ssl/ssl.h 12 Aug 2007 18:59:02
-0000 1.161.2.12
 -474,6 +474,13 
/* These are used to make removal of session-ids more
* efficient and to implement a maximum cache size. */
struct ssl_session_st *prev,*next;
+#ifndef OPENSSL_NO_TLSEXT
+ char *tlsext_hostname;
+ /* RFC4507 info */
+ unsigned char *tlsext_tick; /* Session ticket */
+ size_t tlsext_ticklen; /* Session ticket length */
+ long tlsext_tick_lifetime_hint; /* Session lifetime hint
in seconds */
+#endif
} SSL_SESSION;
 -502,6 +509,8 
#define SSL_OP_NO_QUERY_MTU 0x00001000L
/* Turn on Cookie Exchange (on relevant for servers) */
#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
+/* Don't use RFC4507 ticket extension */
+#define SSL_OP_NO_TICKET 0x00004000L
/* As server, disallow session resumption on
renegotiation */
#define
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
 -749,6 +758,17 
#endif
int quiet_shutdown;
+
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extensions servername callback */
+ int (*tlsext_servername_callback)(SSL*, int *, void *);
+ void *tlsext_servername_arg;
+ /* RFC 4507 session ticket keys */
+ unsigned char tlsext_tick_key_name[16];
+ unsigned char tlsext_tick_hmac_key[16];
+ unsigned char tlsext_tick_aes_key[16];
+#endif
+
};
#define SSL_SESS_CACHE_OFF 0x0000
 -970,6 +990,26 
int first_packet;
int client_version; /* what was passed, used for
* SSLv3/TLS rollback check */
+ unsigned int max_send_fragment;
+#ifndef OPENSSL_NO_TLSEXT
+ /* TLS extension debug callback */
+ void (*tlsext_debug_cb)(SSL *s, int client_server, int
type,
+ unsigned char *data, int len,
+ void *arg);
+ void *tlsext_debug_arg;
+ char *tlsext_hostname;
+ int servername_done; /* no further mod of servername
+ 0 : call the servername
extension callback.
+ 1 : prepare 2, allow last ack
just after in server callback.
+ 2 : don't call servername
callback, no ack in server hello
+ */
+ /* RFC4507 session ticket expected to be received or
sent */
+ int tlsext_ticket_expected;
+ SSL_CTX * initial_ctx; /* initial ctx, used to store
sessions */
+#define session_ctx initial_ctx
+#else
+#define session_ctx ctx
+#endif
};
#ifdef __cplusplus
 -1115,6 +1155,9 
#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /*
fatal */
#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
#define
SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
+#define
SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
+#define SSL_AD_CERTIFICATE_UNOBTAINABLE
TLS1_AD_CERTIFICATE_UNOBTAINABLE
+#define
SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
#define SSL_ERROR_NONE 0
#define SSL_ERROR_SSL 1
 -1173,6 +1216,15 
#define SSL_CTRL_GET_MAX_CERT_LIST 50
#define SSL_CTRL_SET_MAX_CERT_LIST 51
+/* see tls1.h for macros based on these */
+#ifndef OPENSSL_NO_TLSEXT
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
+#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+#define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56
+#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57
+#endif
+
#define SSL_session_reused(ssl)
SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
#define SSL_num_renegotiations(ssl)
 -1445,6 +1497,7 
SSL_SESSION *SSL_get_session(const SSL *ssl);
SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a
reference count */
SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
void SSL_set_info_callback(SSL *ssl,
void (*cb)(const SSL *ssl,int type,int val));
void (*SSL_get_info_callback(const SSL *ssl))(const SSL
*ssl,int type,int val);
 -1621,10 +1674,12 
#define SSL_F_SSL3_GET_FINISHED 140
#define SSL_F_SSL3_GET_KEY_EXCHANGE 141
#define SSL_F_SSL3_GET_MESSAGE 142
+#define SSL_F_SSL3_GET_NEW_SESSION_TICKET 283
#define SSL_F_SSL3_GET_RECORD 143
#define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144
#define SSL_F_SSL3_GET_SERVER_DONE 145
#define SSL_F_SSL3_GET_SERVER_HELLO 146
+#define SSL_F_SSL3_NEW_SESSION_TICKET 284
#define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147
#define SSL_F_SSL3_PEEK 235
#define SSL_F_SSL3_READ_BYTES 148
 -1640,8 +1695,10 
#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_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_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
 -1649,6 +1706,7 
#define SSL_F_SSL_CERT_INSTANTIATE 214
#define SSL_F_SSL_CERT_NEW 162
#define SSL_F_SSL_CHECK_PRIVATE_KEY 163
+#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 274
#define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230
#define SSL_F_SSL_CIPHER_STRENGTH_SORT 231
#define SSL_F_SSL_CLEAR 164
 -1681,6 +1739,8 
#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185
#define SSL_F_SSL_NEW 186
#define SSL_F_SSL_PEEK 270
+#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT 275
+#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT 276
#define SSL_F_SSL_READ 223
#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187
#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188
 -1763,6 +1823,7 
#define SSL_R_CIPHER_CODE_WRONG_LENGTH 137
#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138
#define SSL_R_CIPHER_TABLE_SRC_ERROR 139
+#define SSL_R_CLIENTHELLO_TLSEXT 157
#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140
#define SSL_R_COMPRESSION_FAILURE 141
#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE
307
 -1847,6 +1908,7 
#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297
#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
 -1870,11 +1932,14 
#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_SERVERHELLO_TLSEXT 224
#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277
#define SSL_R_SHORT_READ 219
#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220
#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221
#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 299
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 225
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 226
#define SSL_R_SSL3_SESSION_ID_TOO_LONG 300
#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222
#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
 -1909,6 +1974,7 
#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232
+#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227
#define
SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
234
#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl3.h
============================================================
================
$ cvs diff -u -r1.30.2.2 -r1.30.2.3 ssl3.h
--- openssl/ssl/ssl3.h 30 Sep 2005 23:38:20
-0000 1.30.2.2
+++ openssl/ssl/ssl3.h 12 Aug 2007 18:59:02
-0000 1.30.2.3
 -481,6 +481,8 
#define SSL3_ST_CR_CHANGE_B (0x1C1|SSL_ST_CONNECT)
#define SSL3_ST_CR_FINISHED_A (0x1D0|SSL_ST_CONNECT)
#define SSL3_ST_CR_FINISHED_B (0x1D1|SSL_ST_CONNECT)
+#define
SSL3_ST_CR_SESSION_TICKET_A (0x1E0|SSL_ST_CONNECT)
+#define
SSL3_ST_CR_SESSION_TICKET_B (0x1E1|SSL_ST_CONNECT)
/* server */
/* extra state */
 -522,10 +524,13 
#define SSL3_ST_SW_CHANGE_B (0x1D1|SSL_ST_ACCEPT)
#define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT)
#define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT)
+#define
SSL3_ST_SW_SESSION_TICKET_A (0x1F0|SSL_ST_CONNECT)
+#define
SSL3_ST_SW_SESSION_TICKET_B (0x1F1|SSL_ST_CONNECT)
#define SSL3_MT_HELLO_REQUEST 0
#define SSL3_MT_CLIENT_HELLO 1
#define SSL3_MT_SERVER_HELLO 2
+#define SSL3_MT_NEWSESSION_TICKET 4
#define SSL3_MT_CERTIFICATE 11
#define SSL3_MT_SERVER_KEY_EXCHANGE 12
#define SSL3_MT_CERTIFICATE_REQUEST 13
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl_asn1.c
============================================================
================
$ cvs diff -u -r1.20.2.1 -r1.20.2.2 ssl_asn1.c
--- openssl/ssl/ssl_asn1.c 5 Dec 2005 17:32:21
-0000 1.20.2.1
+++ openssl/ssl/ssl_asn1.c 12 Aug 2007 18:59:02
-0000 1.20.2.2
 -78,6 +78,11 
ASN1_INTEGER time;
ASN1_INTEGER timeout;
ASN1_INTEGER verify_result;
+#ifndef OPENSSL_NO_TLSEXT
+ ASN1_OCTET_STRING tlsext_hostname;
+ ASN1_INTEGER tlsext_tick_lifetime;
+ ASN1_OCTET_STRING tlsext_tick;
+#endif /* OPENSSL_NO_TLSEXT */
} SSL_SESSION_ASN1;
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
 -86,6 +91,10 
int v1=0,v2=0,v3=0,v4=0,v5=0;
unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
unsigned char
ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
+#ifndef OPENSSL_NO_TLSEXT
+ int v6=0,v9=0,v10=0;
+ unsigned char ibuf6[LSIZE2];
+#endif
long l;
SSL_SESSION_ASN1 a;
M_ASN1_I2D_vars(in);
 -178,7 +187,32 
ASN1_INTEGER_set(&a.verify_result,in->verify_result
);
}
-
+#ifndef OPENSSL_NO_TLSEXT
+ if (in->tlsext_hostname)
+ {
+
a.tlsext_hostname.length=strlen(in->tlsext_hostname);
+
a.tlsext_hostname.type=V_ASN1_OCTET_STRING;
+ a.tlsext_hostname.data=(unsigned char
*)in->tlsext_hostname;
+ }
+ if (in->tlsext_tick)
+ {
+ a.tlsext_tick.length=
in->tlsext_ticklen;
+ a.tlsext_tick.type=V_ASN1_OCTET_STRING;
+ a.tlsext_tick.data=(unsigned char
*)in->tlsext_tick;
+ /* If we have a ticket set session ID to empty because
+ * it will be bogus.
+ */
+ if (in->tlsext_ticklen)
+ a.session_id.length=0;
+ }
+ if (in->tlsext_tick_lifetime_hint != 0)
+ {
+ a.tlsext_tick_lifetime.length=LSIZE2;
+ a.tlsext_tick_lifetime.type=V_ASN1_INTEGER;
+ a.tlsext_tick_lifetime.data=ibuf6;
+ ASN1_INTEGER_set(&a.tlsext_tick_lifetime,in->tlsex
t_tick_lifetime_hint);
+ }
+#endif /* OPENSSL_NO_TLSEXT */
M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.cipher), i2d_ASN1_OCTET_STRING);
 -200,6 +234,14 
if (in->verify_result != X509_V_OK)
M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INT
EGER,5,v5);
+#ifndef OPENSSL_NO_TLSEXT
+ if (in->tlsext_tick_lifetime_hint)
+
M_ASN1_I2D_len_EXP_opt(&a.tlsext_tick_lifetime,
i2d_ASN1_INTEGER,9,v9);
+ if (in->tlsext_tick)
+ M_ASN1_I2D_len_EXP_opt(&(a.tlsext_tick),
i2d_ASN1_OCTET_STRING,10,v10);
+ if (in->tlsext_hostname)
+ M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname),
i2d_ASN1_OCTET_STRING,6,v6);
+#endif /* OPENSSL_NO_TLSEXT */
M_ASN1_I2D_seq_total();
M_ASN1_I2D_put(&(a.version), i2d_ASN1_INTEGER);
 -223,6 +265,14 
v4);
if (in->verify_result != X509_V_OK)
M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEG
ER,5,v5);
+#ifndef OPENSSL_NO_TLSEXT
+ if (in->tlsext_hostname)
+ M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname),
i2d_ASN1_OCTET_STRING,6,v6);
+ if (in->tlsext_tick_lifetime_hint)
+
M_ASN1_I2D_put_EXP_opt(&a.tlsext_tick_lifetime,
i2d_ASN1_INTEGER,9,v9);
+ if (in->tlsext_tick)
+ M_ASN1_I2D_put_EXP_opt(&(a.tlsext_tick),
i2d_ASN1_OCTET_STRING,10,v10);
+#endif /* OPENSSL_NO_TLSEXT */
M_ASN1_I2D_finish();
}
 -394,5 +444,54 
else
ret->verify_result=X509_V_OK;
+#ifndef OPENSSL_NO_TLSEXT
+ os.length=0;
+ os.data=NULL;
+ M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
+ if (os.data)
+ {
+ ret->tlsext_hostname = BUF_strndup((char *)os.data,
os.length);
+ OPENSSL_free(os.data);
+ os.data = NULL;
+ os.length = 0;
+ }
+ else
+ ret->tlsext_hostname=NULL;
+ ai.length=0;
+ M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,9);
+ if (ai.data != NULL)
+ {
+ ret->tlsext_tick_lifetime_hint=ASN1_INTEGER_get(aip);
+ OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
+ }
+ else
+ ret->tlsext_tick_lifetime_hint=0;
+ os.length=0;
+ os.data=NULL;
+ M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,10);
+ if (os.data)
+ {
+ ret->tlsext_tick = os.data;
+ ret->tlsext_ticklen = os.length;
+ os.data = NULL;
+ os.length = 0;
+#if 0
+ /* There are two ways to detect a resumed ticket
sesion.
+ * One is to set a random session ID and then the
server
+ * must return a match in ServerHello. This allows the
normal
+ * client session ID matching to work.
+ */
+ if (ret->session_id_length == 0)
+ {
+ ret->session_id_length=SSL3_MAX_SSL_SESSION_ID_LENGTH
;
+ RAND_pseudo_bytes(ret->session_id,
+ ret->session_id_length);
+ }
+#endif
+ }
+ else
+ ret->tlsext_tick=NULL;
+#endif /* OPENSSL_NO_TLSEXT */
+
M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION)
;
}
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl_err.c
============================================================
================
$ cvs diff -u -r1.53.2.4 -r1.53.2.5 ssl_err.c
--- openssl/ssl/ssl_err.c 21 Nov 2006 20:14:46
-0000 1.53.2.4
+++ openssl/ssl/ssl_err.c 12 Aug 2007 18:59:02
-0000 1.53.2.5
 -147,10 +147,12 
{ERR_FUNC(SSL_F_SSL3_GET_FINISHED), "SSL3_GET_FINISHED&
quot;},
{ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE), "SSL3_GET_KEY_E
XCHANGE"},
{ERR_FUNC(SSL_F_SSL3_GET_MESSAGE), "SSL3_GET_MESSAGE&qu
ot;},
+{ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET), "SSL3_GE
T_NEW_SESSION_TICKET"},
{ERR_FUNC(SSL_F_SSL3_GET_RECORD), "SSL3_GET_RECORD"
;},
{ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE), "SSL3_GET
_SERVER_CERTIFICATE"},
{ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE), "SSL3_GET_SERVER
_DONE"},
{ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO), "SSL3_GET_SERVE
R_HELLO"},
+{ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET), "SSL3_NEW_SE
SSION_TICKET"},
{ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN), "SSL3_OUTPUT_C
ERT_CHAIN"},
{ERR_FUNC(SSL_F_SSL3_PEEK), "SSL3_PEEK"},
{ERR_FUNC(SSL_F_SSL3_READ_BYTES), "SSL3_READ_BYTES"
;},
 -166,8 +168,10 
{ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "SSL3_SETUP_KEY_
BLOCK"},
{ERR_FUNC(SSL_F_SSL3_WRITE_BYTES), "SSL3_WRITE_BYTES&qu
ot;},
{ERR_FUNC(SSL_F_SSL3_WRITE_PENDING), "SSL3_WRITE_PENDIN
G"},
+{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT), "SSL_ADD_
CLIENTHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK), "S
SL_add_dir_cert_subjects_to_stack"},
{ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK), "
SSL_add_file_cert_subjects_to_stack"},
+{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT), "SSL_ADD_
SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_BAD_METHOD), "SSL_BAD_METHOD"}
,
{ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST), "SSL_BYTES_T
O_CIPHER_LIST"},
{ERR_FUNC(SSL_F_SSL_CERT_DUP), "SSL_CERT_DUP"},
 -175,6 +179,7 
{ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE), "SSL_CERT_INSTAN
TIATE"},
{ERR_FUNC(SSL_F_SSL_CERT_NEW), "SSL_CERT_NEW"},
{ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY), "SSL_check_priv
ate_key"},
+{ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT), "SSL_CH
ECK_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR), "SSL_CIPHE
R_PROCESS_RULESTR"},
{ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT), "SSL_CIPHER_
STRENGTH_SORT"},
{ERR_FUNC(SSL_F_SSL_CLEAR), "SSL_clear"},
 -207,6 +212,8 
{ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_cli
ent_CA_file"},
{ERR_FUNC(SSL_F_SSL_NEW), "SSL_new"},
{ERR_FUNC(SSL_F_SSL_PEEK), "SSL_peek"},
+{ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT), "SSL_
PREPARE_CLIENTHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT), "SSL_
PREPARE_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
{ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT), "SSL_RSA_PRIV
ATE_DECRYPT"},
{ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT), "SSL_RSA_PUBLI
C_ENCRYPT"},
 -292,6 +299,7 
{ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher
code wrong length"},
{ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher
or hash unavailable"},
{ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher
table src error"},
+{ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)
,"clienthello tlsext"},
{ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compress
ed length too long"},
{ERR_REASON(SSL_R_COMPRESSION_FAILURE)
,"compression failure"},
{ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),&
quot;compression id not within private range"},
 -376,6 +384,7 
{ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old
session cipher not returned"},
{ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only
tls allowed in fips mode"},
{ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet
length too long"},
+{ERR_REASON(SSL_R_PARSE_TLSEXT) ,"parse
tlsext"},
{ERR_REASON(SSL_R_PATH_TOO_LONG) ,"path too
long"},
{ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"p
eer did not return a certificate"},
{ERR_REASON(SSL_R_PEER_ERROR) ,"peer
error"},
 -399,11 +408,14 
{ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse
cert length not zero"},
{ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse
cert type not zero"},
{ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse
cipher list not zero"},
+{ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)
,"serverhello tlsext"},
{ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"se
ssion id context uninitialized"},
{ERR_REASON(SSL_R_SHORT_READ) ,"short
read"},
{ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),&qu
ot;signature for non signing certificate"},
{ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23
doing session id reuse"},
{ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2
connection id too long"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3
ext invalid servername"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"s
sl3 ext invalid servername type"},
{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3
session id too long"},
{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3
session id too short"},
{ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3
alert bad certificate"},
 -438,6 +450,7 
{ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1
alert unknown ca"},
{ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1
alert user cancelled"},
{ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),&quo
t;tls client cert req with anon cipher"},
+{ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls
invalid ecpointformat list"},
{ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_
LIST),"tls peer did not respond with certificate
list"},
{ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),&
quot;tls rsa encrypted value length is wrong"},
{ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tri
ed to use unsupported cipher"},
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl_lib.c
============================================================
================
$ cvs diff -u -r1.133.2.8 -r1.133.2.9 ssl_lib.c
--- openssl/ssl/ssl_lib.c 29 Nov 2006 20:47:15
-0000 1.133.2.8
+++ openssl/ssl/ssl_lib.c 12 Aug 2007 18:59:02
-0000 1.133.2.9
 -125,6 +125,7 
#include <openssl/objects.h>
#include <openssl/lhash.h>
#include <openssl/x509v3.h>
+#include <openssl/rand.h>
#ifndef OPENSSL_NO_DH
#include <openssl/dh.h>
#endif
 -306,7 +307,13 
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->ctx=ctx;
-
+#ifndef OPENSSL_NO_TLSEXT
+ s->tlsext_debug_cb = 0;
+ s->tlsext_debug_arg = NULL;
+ s->tlsext_ticket_expected = 0;
+ CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+ s->initial_ctx=ctx;
+#endif
s->verify_result=X509_V_OK;
s->method=ctx->method;
 -492,7 +499,9 
/* Free up if allocated */
if (s->ctx) SSL_CTX_free(s->ctx);
-
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+#endif
if (s->client_CA != NULL)
sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
 -1304,6 +1313,29 
return(NULL);
}
+#ifndef OPENSSL_NO_TLSEXT
+/** return a servername extension value if provided in
Client Hello, or NULL.
+ * So far, only host_name types are defined (RFC 3546).
+ */
+
+const char *SSL_get_servername(const SSL *s, const int
type)
+ {
+ if (type != TLSEXT_NAMETYPE_host_name)
+ return NULL;
+
+ return s->session && !s->tlsext_hostname
?
+ s->session->tlsext_hostname :
+ s->tlsext_hostname;
+ }
+
+int SSL_get_servername_type(const SSL *s)
+ {
+ if (s->session && (!s->tlsext_hostname ?
s->session->tlsext_hostname : s->tlsext_hostname))
+ return TLSEXT_NAMETYPE_host_name;
+ return -1;
+ }
+#endif
+
unsigned long SSL_SESSION_hash(const SSL_SESSION *a)
{
unsigned long l;
 -1453,6 +1485,17 
ret->extra_certs=NULL;
ret->comp_methods=SSL_COMP_get_compression_methods();
+#ifndef OPENSSL_NO_TLSEXT
+ ret->tlsext_servername_callback = 0;
+ ret->tlsext_servername_arg = NULL;
+ /* Setup RFC4507 ticket keys */
+ if ((RAND_pseudo_bytes(ret->tlsext_tick_key_name, 16)
<= 0)
+ || (RAND_bytes(ret->tlsext_tick_hmac_key, 16) <=
0)
+ || (RAND_bytes(ret->tlsext_tick_aes_key, 16) <=
0))
+ ret->options |= SSL_OP_NO_TICKET;
+
+#endif
+
return(ret);
err:
SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
 -2402,6 +2445,24 
return(ssl->ctx);
}
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
+ {
+ if (ssl->ctx == ctx)
+ return ssl->ctx;
+#ifndef OPENSSL_NO_TLSEXT
+ if (ctx == NULL)
+ ctx = ssl->initial_ctx;
+#endif
+ if (ssl->cert != NULL)
+ ssl_cert_free(ssl->cert);
+ ssl->cert = ssl_cert_dup(ctx->cert);
+ CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+ if (ssl->ctx != NULL)
+ SSL_CTX_free(ssl->ctx); /* decrement reference count
*/
+ ssl->ctx = ctx;
+ return(ssl->ctx);
+ }
+
#ifndef OPENSSL_NO_STDIO
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
{
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl_locl.h
============================================================
================
$ cvs diff -u -r1.63.2.5 -r1.63.2.6 ssl_locl.h
--- openssl/ssl/ssl_locl.h 23 Apr 2007 23:50:22
-0000 1.63.2.5
+++ openssl/ssl/ssl_locl.h 12 Aug 2007 18:59:02
-0000 1.63.2.6
 -716,7 +716,7 
void ssl_sess_cert_free(SESS_CERT *sc);
int ssl_set_peer_cert_type(SESS_CERT *c, int type);
int ssl_get_new_session(SSL *s, int session);
-int ssl_get_prev_session(SSL *s, unsigned char
*session,int len);
+int ssl_get_prev_session(SSL *s, unsigned char
*session,int len, const unsigned char *limit);
int ssl_cipher_id_cmp(const SSL_CIPHER *a,const
SSL_CIPHER *b);
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
const SSL_CIPHER * const *bp);
 -776,6 +776,7 
int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned
char *p);
void ssl3_init_finished_mac(SSL *s);
int ssl3_send_server_certificate(SSL *s);
+int ssl3_send_newsession_ticket(SSL *s);
int ssl3_get_finished(SSL *s,int state_a,int state_b);
int ssl3_setup_key_block(SSL *s);
int ssl3_send_change_cipher_spec(SSL *s,int state_a,int
state_b);
 -866,6 +867,7 
int ssl3_client_hello(SSL *s);
int ssl3_get_server_hello(SSL *s);
int ssl3_get_certificate_request(SSL *s);
+int ssl3_get_new_session_ticket(SSL *s);
int ssl3_get_server_done(SSL *s);
int ssl3_send_client_verify(SSL *s);
int ssl3_send_client_certificate(SSL *s);
 -947,5 +949,19 
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
+#ifndef OPENSSL_NO_TLSEXT
+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_prepare_clienthello_tlsext(SSL *s);
+int ssl_prepare_serverhello_tlsext(SSL *s);
+int ssl_check_clienthello_tlsext(SSL *s);
+int ssl_check_serverhello_tlsext(SSL *s);
+int tls1_process_ticket(SSL *s, unsigned char
*session_id, int len,
+ const unsigned char *limit, SSL_SESSION **ret);
+EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const
EVP_MD *md) ;
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
+#endif
#endif
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl_sess.c
============================================================
================
$ cvs diff -u -r1.51.2.6 -r1.51.2.7 ssl_sess.c
--- openssl/ssl/ssl_sess.c 21 Mar 2007 14:33:01
-0000 1.51.2.6
+++ openssl/ssl/ssl_sess.c 12 Aug 2007 18:59:03
-0000 1.51.2.7
 -122,6 +122,9 
ss->prev=NULL;
ss->next=NULL;
ss->compress_meth=0;
+#ifndef OPENSSL_NO_TLSEXT
+ ss->tlsext_hostname = NULL;
+#endif
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss,
&ss->ex_data);
return(ss);
}
 -216,6 +219,14 
SSL_SESSION_free(ss);
return(0);
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* If RFC4507 ticket use empty session ID */
+ if (s->tlsext_ticket_expected)
+ {
+ ss->session_id_length = 0;
+ goto sess_id_done;
+ }
+#endif
/* Choose which callback will set the session ID */
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
if(s->generate_session_id)
 -257,6 +268,17 
SSL_SESSION_free(ss);
return(0);
}
+#ifndef OPENSSL_NO_TLSEXT
+ sess_id_done:
+ if (s->tlsext_hostname) {
+ ss->tlsext_hostname =
BUF_strdup(s->tlsext_hostname);
+ if (ss->tlsext_hostname == NULL) {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION,
ERR_R_INTERNAL_ERROR);
+ SSL_SESSION_free(ss);
+ return 0;
+ }
+ }
+#endif
}
else
{
 -278,21 +300,39 
return(1);
}
-int ssl_get_prev_session(SSL *s, unsigned char
*session_id, int len)
+int ssl_get_prev_session(SSL *s, unsigned char
*session_id, int len,
+ const unsigned char *limit)
{
/* This is used only by servers. */
- SSL_SESSION *ret=NULL,data;
+ SSL_SESSION *ret=NULL;
int fatal = 0;
-
- data.ssl_version=s->version;
- data.session_id_length=len;
+#ifndef OPENSSL_NO_TLSEXT
+ int r;
+#endif
+
if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;
- memcpy(data.session_id,session_id,len);
-
+#ifndef OPENSSL_NO_TLSEXT
+ r = tls1_process_ticket(s, session_id, len, limit,
&ret);
+ if (r == -1)
+ {
+ fatal = 1;
+ goto err;
+ }
+ else if (r == 0)
+ goto err;
+ else if (!ret &&
!(s->session_ctx->session_cache_mode &
SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#else
if (!(s->ctx->session_cache_mode &
SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#endif
{
+ SSL_SESSION data;
+ data.ssl_version=s->version;
+ data.session_id_length=len;
+ if (len == 0)
+ return 0;
+ memcpy(data.session_id,session_id,len);
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
ret=(SSL_SESSION
*)lh_retrieve(s->ctx->sessions,&data);
if (ret != NULL)
 -548,6 +588,10 
if (ss->sess_cert != NULL)
ssl_sess_cert_free(ss->sess_cert);
if (ss->peer != NULL) X509_free(ss->peer);
if (ss->ciphers != NULL)
sk_SSL_CIPHER_free(ss->ciphers);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ss->tlsext_hostname != NULL)
OPENSSL_free(ss->tlsext_hostname);
+ if (ss->tlsext_tick != NULL)
OPENSSL_free(ss->tlsext_tick);
+#endif
OPENSSL_cleanse(ss,sizeof(*ss));
OPENSSL_free(ss);
}
 .
patch -p0 <<' .'
Index: openssl/ssl/ssl_txt.c
============================================================
================
$ cvs diff -u -r1.14.2.2 -r1.14.2.3 ssl_txt.c
--- openssl/ssl/ssl_txt.c 30 Sep 2005 23:38:20
-0000 1.14.2.2
+++ openssl/ssl/ssl_txt.c 12 Aug 2007 18:59:03
-0000 1.14.2.3
 -151,6 +151,21 
if
(BIO_printf(bp,"%02X",x->krb5_client_princ[i])
<= 0) goto err;
}
#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_TLSEXT
+ if (x->tlsext_tick_lifetime_hint)
+ {
+ if (BIO_printf(bp,
+ "n TLS session ticket lifetime hint: %ld
(seconds)",
+ x->tlsext_tick_lifetime_hint) <=0)
+ goto err;
+ }
+ if (x->tlsext_tick)
+ {
+ if (BIO_puts(bp, "n TLS session
ticket:n") <= 0) goto err;
+ if (BIO_dump_indent(bp, (char *)x->tlsext_tick,
x->tlsext_ticklen, 4) <= 0)
+ goto err;
+ }
+#endif
#ifndef OPENSSL_NO_COMP
if (x->compress_meth != 0)
{
 .
patch -p0 <<' .'
Index: openssl/ssl/t1_lib.c
============================================================
================
$ cvs diff -u -r1.13.2.2 -r1.13.2.3 t1_lib.c
--- openssl/ssl/t1_lib.c 21 Jan 2007 16:07:25
-0000 1.13.2.2
+++ openssl/ssl/t1_lib.c 12 Aug 2007 18:59:03
-0000 1.13.2.3
 -58,10 +58,18 
#include <stdio.h>
#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
#include "ssl_locl.h"
const char tls1_version_str[]="TLSv1"
OPENSSL_VERSION_PTEXT;
+#ifndef OPENSSL_NO_TLSEXT
+static int tls_decrypt_ticket(SSL *s, const unsigned char
*tick, int ticklen,
+ const unsigned char *sess_id, int sesslen,
+ SSL_SESSION **psess);
+#endif
+
SSL3_ENC_METHOD TLSv1_enc_data={
tls1_enc,
tls1_mac,
 -117,3 +125,506 
return(0);
}
#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+unsigned char *ssl_add_clienthello_tlsext(SSL *s,
unsigned char *p, unsigned char *limit)
+ {
+ int extdatalen=0;
+ unsigned char *ret = p;
+
+ ret+=2;
+
+ if (ret>=limit) return NULL; /* this really never
occurs, but ... */
+
+ if (s->tlsext_hostname != NULL)
+ {
+ /* Add TLS extension servername to the Client Hello
message */
+ unsigned long size_str;
+ long lenmax;
+
+ /* check for enough space.
+ 4 for the servername type and entension length
+ 2 for servernamelist length
+ 1 for the hostname type
+ 2 for hostname length
+ + hostname length
+ */
+
+ if ((lenmax = limit - p - 9) < 0
+ || (size_str = strlen(s->tlsext_hostname)) >
(unsigned long)lenmax)
+ return NULL;
+
+ /* extension type and length */
+ s2n(TLSEXT_TYPE_server_name,ret);
+ s2n(size_str+5,ret);
+
+ /* length of servername list */
+ s2n(size_str+3,ret);
+
+ /* hostname type, length and hostname */
+ *(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name;
+ s2n(size_str,ret);
+ memcpy(ret, s->tlsext_hostname, size_str);
+ ret+=size_str;
+
+ }
+
+ if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
+ {
+ int ticklen;
+ if (s->session &&
s->session->tlsext_tick)
+ ticklen = s->session->tlsext_ticklen;
+ else
+ ticklen = 0;
+ /* Check for enough room 2 for extension type, 2 for
len
+ * rest for ticket
+ */
+ if (limit - p - 4 - ticklen < 0)
+ return NULL;
+ s2n(TLSEXT_TYPE_session_ticket,ret);
+ s2n(ticklen,ret);
+ if (ticklen)
+ {
+ memcpy(ret, s->session->tlsext_tick, ticklen);
+ ret += ticklen;
+ }
+ }
+
+ 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;
+
+ ret+=2;
+ if (ret>=limit) return NULL; /* this really never
occurs, but ... */
+
+ if (!s->hit && s->servername_done == 1
&& s->session->tlsext_hostname != NULL)
+ {
+ if (limit - p - 4 < 0) return NULL;
+
+ s2n(TLSEXT_TYPE_server_name,ret);
+ s2n(0,ret);
+ }
+
+ if (s->tlsext_ticket_expected
+ && !(SSL_get_options(s) &
SSL_OP_NO_TICKET))
+ {
+ if (limit - p - 4 < 0) return NULL;
+ s2n(TLSEXT_TYPE_session_ticket,ret);
+ s2n(0,ret);
+ }
+
+ 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;
+ s->servername_done = 0;
+
+ if (data >= (d+n-2))
+ return 1;
+ n2s(data,len);
+
+ if (data > (d+n-len))
+ return 1;
+
+ while (data <= (d+n-4))
+ {
+ n2s(data,type);
+ n2s(data,size);
+
+ if (data+size > (d+n))
+ return 1;
+
+ if (s->tlsext_debug_cb)
+ s->tlsext_debug_cb(s, 0, type, data, size,
+ s->tlsext_debug_arg);
+/* The servername extension is treated as follows:
+
+ - Only the hostname type is supported with a maximum
length of 255.
+ - The servername is rejected if too long or if it
contains zeros,
+ in which case an fatal alert is generated.
+ - The servername field is maintained together with the
session cache.
+ - When a session is resumed, the servername call back
invoked in order
+ to allow the application to position itself to the
right context.
+ - The servername is acknowledged if it is new for a
session or when
+ it is identical to a previously used for the same
session.
+ Applications can control the behaviour. They can at
any time
+ set a 'desirable' servername for a new SSL object.
This can be the
+ case for example with HTTPS when a Host: header
field is received and
+ a renegotiation is requested. In this case, a
possible servername
+ presented in the new client hello is only
acknowledged if it matches
+ the value of the Host: field.
+ - Applications must use
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+ if they provide for changing an explicit servername
context for the session,
+ i.e. when the session has been established with a
servername extension.
+ - On session reconnect, the servername extension may
be absent.
+
+*/
+
+ if (type == TLSEXT_TYPE_server_name)
+ {
+ unsigned char *sdata;
+ int servname_type;
+ int dsize;
+
+ if (size < 2)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ n2s(data,dsize);
+ size -= 2;
+ if (dsize > size )
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ sdata = data;
+ while (dsize > 3)
+ {
+ servname_type = *(sdata++);
+ n2s(sdata,len);
+ dsize -= 3;
+
+ if (len > dsize)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ if (s->servername_done == 0)
+ switch (servname_type)
+ {
+ case TLSEXT_NAMETYPE_host_name:
+ if (s->session->tlsext_hostname == NULL)
+ {
+ if (len > TLSEXT_MAXLEN_host_name ||
+ ((s->session->tlsext_hostname =
OPENSSL_malloc(len+1)) == NULL))
+ {
+ *al = TLS1_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ memcpy(s->session->tlsext_hostname, sdata,
len);
+ s->session->tlsext_hostname[len]=' ';
+ if (strlen(s->session->tlsext_hostname) !=
len) {
+ OPENSSL_free(s->session->tlsext_hostname);
+ *al = TLS1_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ s->servername_done = 1;
+
+ }
+ else
+ s->servername_done =
strlen(s->session->tlsext_hostname) == len
+ &&
strncmp(s->session->tlsext_hostname, (char *)sdata,
len) == 0;
+
+ break;
+
+ default:
+ break;
+ }
+
+ dsize -= len;
+ }
+ if (dsize != 0)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ }
+ /* session ticket processed earlier */
+
+ data+=size;
+ }
+
+ *p = data;
+ 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 tlsext_servername = 0;
+
+ if (data >= (d+n-2))
+ return 1;
+
+ n2s(data,len);
+
+ while(data <= (d+n-4))
+ {
+ n2s(data,type);
+ n2s(data,size);
+
+ if (data+size > (d+n))
+ return 1;
+
+ if (s->tlsext_debug_cb)
+ s->tlsext_debug_cb(s, 1, type, data, size,
+ s->tlsext_debug_arg);
+
+ if (type == TLSEXT_TYPE_server_name)
+ {
+ if (s->tlsext_hostname == NULL || size > 0)
+ {
+ *al = TLS1_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ tlsext_servername = 1;
+ }
+ else if (type == TLSEXT_TYPE_session_ticket)
+ {
+ if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
+ || (size > 0))
+ {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ s->tlsext_ticket_expected = 1;
+ }
+
+ data+=size;
+ }
+
+ if (data != d+n)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!s->hit && tlsext_servername == 1)
+ {
+ if (s->tlsext_hostname)
+ {
+ if (s->session->tlsext_hostname == NULL)
+ {
+ s->session->tlsext_hostname =
BUF_strdup(s->tlsext_hostname);
+ if (!s->session->tlsext_hostname)
+ {
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+ }
+ else
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ }
+ }
+
+ *p = data;
+ return 1;
+ }
+
+int ssl_check_clienthello_tlsext(SSL *s)
+ {
+ int ret=SSL_TLSEXT_ERR_NOACK;
+ int al = SSL_AD_UNRECOGNIZED_NAME;
+
+ if (s->ctx != NULL &&
s->ctx->tlsext_servername_callback != 0)
+ ret = s->ctx->tlsext_servername_callback(s,
&al, s->ctx->tlsext_servername_arg);
+ else if (s->initial_ctx != NULL &&
s->initial_ctx->tlsext_servername_callback != 0)
+ ret =
s->initial_ctx->tlsext_servername_callback(s, &al,
s->initial_ctx->tlsext_servername_arg);
+
+ switch (ret)
+ {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return -1;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ ssl3_send_alert(s,SSL3_AL_WARNING,al);
+ return 1;
+
+ case SSL_TLSEXT_ERR_NOACK:
+ s->servername_done=0;
+ default:
+ return 1;
+ }
+ }
+
+int ssl_check_serverhello_tlsext(SSL *s)
+ {
+ int ret=SSL_TLSEXT_ERR_NOACK;
+ int al = SSL_AD_UNRECOGNIZED_NAME;
+
+ if (s->ctx != NULL &&
s->ctx->tlsext_servername_callback != 0)
+ ret = s->ctx->tlsext_servername_callback(s,
&al, s->ctx->tlsext_servername_arg);
+ else if (s->initial_ctx != NULL &&
s->initial_ctx->tlsext_servername_callback != 0)
+ ret =
s->initial_ctx->tlsext_servername_callback(s, &al,
s->initial_ctx->tlsext_servername_arg);
+
+ switch (ret)
+ {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return -1;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ ssl3_send_alert(s,SSL3_AL_WARNING,al);
+ return 1;
+
+ case SSL_TLSEXT_ERR_NOACK:
+ s->servername_done=0;
+ default:
+ return 1;
+ }
+ }
+
+/* Since the server cache lookup is done early on in the
processing of client
+ * hello and other operations depend on the result we
need to handle any TLS
+ * session ticket extension at the same time.
+ */
+
+int tls1_process_ticket(SSL *s, unsigned char
*session_id, int len,
+ const unsigned char *limit, SSL_SESSION **ret)
+ {
+ /* Point after session ID in client hello */
+ const unsigned char *p = session_id + len;
+ unsigned short i;
+ if ((s->version <= SSL3_VERSION) || !limit)
+ return 1;
+ if (p >= limit)
+ return -1;
+ /* Skip past cipher list */
+ n2s(p, i);
+ p+= i;
+ if (p >= limit)
+ return -1;
+ /* Skip past compression algorithm list */
+ i = *(p++);
+ p += i;
+ if (p > limit)
+ return -1;
+ /* Now at start of extensions */
+ if ((p + 2) >= limit)
+ return 1;
+ n2s(p, i);
+ while ((p + 4) <= limit)
+ {
+ unsigned short type, size;
+ n2s(p, type);
+ n2s(p, size);
+ if (p + size > limit)
+ return 1;
+ if (type == TLSEXT_TYPE_session_ticket)
+ {
+ /* If tickets disabled indicate cache miss which will
+ * trigger a full handshake
+ */
+ if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+ return 0;
+ /* If zero length not client will accept a ticket
+ * and indicate cache miss to trigger full handshake
+ */
+ if (size == 0)
+ {
+ s->tlsext_ticket_expected = 1;
+ return 0; /* Cache miss */
+ }
+ return tls_decrypt_ticket(s, p, size, session_id,
len,
+ ret);
+ }
+ p += size;
+ }
+ return 1;
+ }
+
+static int tls_decrypt_ticket(SSL *s, const unsigned char
*etick, int eticklen,
+ const unsigned char *sess_id, int sesslen,
+ SSL_SESSION **psess)
+ {
+ SSL_SESSION *sess;
+ unsigned char *sdec;
+ const unsigned char *p;
+ int slen, mlen;
+ unsigned char tick_hmac[EVP_MAX_MD_SIZE];
+ HMAC_CTX hctx;
+ EVP_CIPHER_CTX ctx;
+ /* Attempt to process session ticket, first conduct
sanity and
+ * integrity checks on ticket.
+ */
+ mlen = EVP_MD_size(EVP_sha1());
+ eticklen -= mlen;
+ /* Need at least keyname + iv + some encrypted data */
+ if (eticklen < 48)
+ goto tickerr;
+ /* Check key name matches */
+ if (memcmp(etick, s->ctx->tlsext_tick_key_name,
16))
+ goto tickerr;
+ /* Check HMAC of encrypted ticket */
+ HMAC_CTX_init(&hctx);
+ HMAC_Init_ex(&hctx,
s->ctx->tlsext_tick_hmac_key, 16,
+ EVP_sha1(), NULL);
+ HMAC_Update(&hctx, etick, eticklen);
+ HMAC_Final(&hctx, tick_hmac, NULL);
+ HMAC_CTX_cleanup(&hctx);
+ if (memcmp(tick_hmac, etick + eticklen, mlen))
+ goto tickerr;
+ /* Set p to start of IV */
+ p = etick + 16;
+ EVP_CIPHER_CTX_init(&ctx);
+ /* Attempt to decrypt session data */
+ EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ s->ctx->tlsext_tick_aes_key, p);
+ /* Move p after IV to start of encrypted ticket, update
length */
+ p += 16;
+ eticklen -= 32;
+ sdec = OPENSSL_malloc(eticklen);
+ if (!sdec)
+ {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return -1;
+ }
+ EVP_DecryptUpdate(&ctx, sdec, &slen, p,
eticklen);
+ if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen)
<= 0)
+ goto tickerr;
+ slen += mlen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ p = sdec;
+
+ sess = d2i_SSL_SESSION(NULL, &p, slen);
+ OPENSSL_free(sdec);
+ if (sess)
+ {
+ /* The session ID if non-empty is used by some clients
to
+ * detect that the ticket has been accepted. So we
copy it to
+ * the session structure. If it is empty set length to
zero
+ * as required by standard.
+ */
+ if (sesslen)
+ memcpy(sess->session_id, sess_id, sesslen);
+ sess->session_id_length = sesslen;
+ *psess = sess;
+ return 1;
+ }
+ /* If session decrypt failure indicate a cache miss and
set state to
+ * send a new ticket
+ */
+ tickerr:
+ s->tlsext_ticket_expected = 1;
+ return 0;
+ }
+
+#endif
 .
patch -p0 <<' .'
Index: openssl/ssl/tls1.h
============================================================
================
$ cvs diff -u -r1.17.2.4 -r1.17.2.5 tls1.h
--- openssl/ssl/tls1.h 23 Apr 2007 23:50:22
-0000 1.17.2.4
+++ openssl/ssl/tls1.h 12 Aug 2007 18:59:03
-0000 1.17.2.5
 -96,6 +96,55 
#define TLS1_AD_INTERNAL_ERROR 80 /* fatal */
#define TLS1_AD_USER_CANCELLED 90
#define TLS1_AD_NO_RENEGOTIATION 100
+/* codes 110-114 are from RFC3546 */
+#define TLS1_AD_UNSUPPORTED_EXTENSION 110
+#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
+#define TLS1_AD_UNRECOGNIZED_NAME 112
+#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
+#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+
+/* ExtensionType values from RFC 3546 */
+#define TLSEXT_TYPE_server_name 0
+#define TLSEXT_TYPE_max_fragment_length 1
+#define TLSEXT_TYPE_client_certificate_url 2
+#define TLSEXT_TYPE_trusted_ca_keys 3
+#define TLSEXT_TYPE_truncated_hmac 4
+#define TLSEXT_TYPE_status_request 5
+#define TLSEXT_TYPE_elliptic_curves 10
+#define TLSEXT_TYPE_ec_point_formats 11
+#define TLSEXT_TYPE_session_ticket 35
+
+/* NameType value from RFC 3546 */
+#define TLSEXT_NAMETYPE_host_name 0
+
+#ifndef OPENSSL_NO_TLSEXT
+
+#define TLSEXT_MAXLEN_host_name 255
+
+const char *SSL_get_servername(const SSL *s, const int
type) ;
+int SSL_get_servername_type(const SSL *s) ;
+
+#define SSL_set_tlsext_host_name(s,name)
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_hos
t_name,(char *)name)
+
+#define SSL_set_tlsext_debug_callback(ssl, cb)
+SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void
(*)(void))cb)
+
+#define SSL_set_tlsext_debug_arg(ssl, arg)
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void
*)arg)
+
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb)
+SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
,(void (*)(void))cb)
+
+#define SSL_TLSEXT_ERR_OK 0
+#define SSL_TLSEXT_ERR_ALERT_WARNING 1
+#define SSL_TLSEXT_ERR_ALERT_FATAL 2
+#define SSL_TLSEXT_ERR_NOACK 3
+
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0,
(void *)arg)
+#endif
/* Additional TLS ciphersuites from
draft-ietf-tls-56-bit-ciphersuites-00.txt
* (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is
defined, see
 .
____________________________________________________________
__________
OpenSSL Project http://www.openssl.org
CVS Repository Commit List
openssl-cvs openssl.org
Automated List Manager
majordomo openssl.org
|