Skip Menu | | Logout
Logged in as guest
RT for openssl.org
 
 
#1751: [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
X  Ticket metadata  
X  The Basics  
Id: 1751
Status: open
Left: 0 min
Priority: 0/0
Queue: OpenSSL-Bugs

X  Custom Fields  
Milestone:
  • (no value)
Subsystem:
  • (no value)
Severity:
  • (no value)
Broken in:
  • (no value)

X  People  
Owner: Nobody
Requestors: dwmw2@infradead.org
Cc:
AdminCc:

X  Dates  
Created: Wed Oct 01 21:12:46 2008
Starts: Not set
Started: Not set
Last Contact: Wed Feb 25 16:38:54 2009
Due: Not set
Closed: Not set
Updated: Mon Apr 20 02:35:17 2009 by dwmw2@infradead.org

X  Links  
Depends on:
Depended on by:
Parents:
Children:
Refers to:
Referred to by:

X  Attachments  
openssl-stable-dtls.patch

X  More about David Woodhouse  
Comments about this user:
No comment entered about this user
This user's 10 highest priority tickets:
Groups this user belongs to:
  • Everyone
  • Unprivileged

X  History Display mode:[Brief headers] [Full headers]
#     Wed Oct 01 21:12:46 2008  dwmw2@infradead.org - Ticket created    
Subject: [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
Date: Wed, 01 Oct 2008 10:55:41 +0100
To: openssl-dev@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 7.7k
This patch against the stable branch makes my AnyConnect VPN client
( http://git.infradead.org/users/dwmw2/anyconnect.git ) work.

Cisco's VPN client uses OpenSSL, and a version of the DTLS protocol
which is newer than we had in 0.9.8e, but older than the final version
defined in the RFC and implemented in 0.9.8f. The patch against 0.9.8e,
for reference, is http://david.woodhou.se/openssl-0.9.8e-ciscodtls.patch

Their server does also respond to DTLS packets bearing the 'real' DTLS
protocol version number, but has other compatibility issues which I
haven't yet completely understood. (If I hack tls1_enc() to use 0x0100
(DTLS1_BAD_VER) as the protocol when calculating the MAC, the handshake
does succeed, but then the server ignores all my data packets).

But since their own clients use the old protocol version, that's
probably the best one for us to be using anyway. It's going to be the
only one that's tested properly with their server.

The code which uses this is at
http://git.infradead.org/users/dwmw2/anyconnect.git?a=blob;f=dtls.c;hb=HEAD

Advice on better ways to do this would be welcomed.

Index: ssl/d1_clnt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_clnt.c,v
retrieving revision 1.3.2.10
diff -u -p -r1.3.2.10 d1_clnt.c
--- ssl/d1_clnt.c 4 Jun 2008 18:35:25 -0000 1.3.2.10
+++ ssl/d1_clnt.c 29 Sep 2008 08:27:31 -0000
@@ -130,7 +130,7 @@ static int dtls1_get_hello_verify(SSL *s

static SSL_METHOD *dtls1_get_client_method(int ver)
{
- if (ver == DTLS1_VERSION)
+ if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
return(DTLSv1_client_method());
else
return(NULL);
@@ -181,7 +181,8 @@ int dtls1_connect(SSL *s)
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

- if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00))
+ if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
+ (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
{
SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
ret = -1;
Index: ssl/d1_lib.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_lib.c,v
retrieving revision 1.1.2.5
diff -u -p -r1.1.2.5 d1_lib.c
--- ssl/d1_lib.c 5 Oct 2007 21:05:27 -0000 1.1.2.5
+++ ssl/d1_lib.c 29 Sep 2008 08:38:49 -0000
@@ -186,7 +186,10 @@ void dtls1_free(SSL *s)
void dtls1_clear(SSL *s)
{
ssl3_clear(s);
- s->version=DTLS1_VERSION;
+ if (s->options & SSL_OP_CISCO_ANYCONNECT)
+ s->version=DTLS1_BAD_VER;
+ else
+ s->version=DTLS1_VERSION;
}

/*
Index: ssl/d1_pkt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_pkt.c,v
retrieving revision 1.4.2.12
diff -u -p -r1.4.2.12 d1_pkt.c
--- ssl/d1_pkt.c 14 Sep 2008 17:57:03 -0000 1.4.2.12
+++ ssl/d1_pkt.c 29 Sep 2008 08:27:31 -0000
@@ -986,15 +986,17 @@ start:
if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
{
struct ccs_header_st ccs_hdr;
+ int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;

dtls1_get_ccs_header(rr->data, &ccs_hdr);

/* 'Change Cipher Spec' is just a single byte, so we know
* exactly what the record payload has to look like */
/* XDTLS: check that epoch is consistent */
- if ( (s->client_version == DTLS1_BAD_VER && rr->length != 3) ||
- (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) ||
- (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
+ if (s->client_version == DTLS1_BAD_VER || s->version == DTLS1_BAD_VER)
+ ccs_hdr_len = 3;
+
+ if ((rr->length != ccs_hdr_len) || (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
{
i=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
@@ -1310,7 +1312,7 @@ int do_dtls1_write(SSL *s, int type, con
#if 0
/* 'create_empty_fragment' is true only when this function calls itself */
if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
- && SSL_version(s) != DTLS1_VERSION)
+ && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
{
/* countermeasure against known-IV weakness in CBC ciphersuites
* (see http://www.openssl.org/~bodo/tls-cbc.txt)
Index: ssl/s3_clnt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/s3_clnt.c,v
retrieving revision 1.88.2.17
diff -u -p -r1.88.2.17 s3_clnt.c
--- ssl/s3_clnt.c 16 Jun 2008 16:56:41 -0000 1.88.2.17
+++ ssl/s3_clnt.c 29 Sep 2008 08:27:31 -0000
@@ -708,7 +708,7 @@ int ssl3_get_server_hello(SSL *s)

if (!ok) return((int)n);

- if ( SSL_version(s) == DTLS1_VERSION)
+ if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
{
if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
{
Index: ssl/ssl.h
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl.h,v
retrieving revision 1.161.2.21
diff -u -p -r1.161.2.21 ssl.h
--- ssl/ssl.h 13 Aug 2008 19:44:44 -0000 1.161.2.21
+++ ssl/ssl.h 29 Sep 2008 08:39:24 -0000
@@ -510,6 +510,8 @@ typedef struct ssl_session_st
#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
/* Don't use RFC4507 ticket extension */
#define SSL_OP_NO_TICKET 0x00004000L
+/* Use Cisco's "speshul" version of DTLS1_BAD_VER (as client) */
+#define SSL_OP_CISCO_ANYCONNECT 0x00008000L

/* As server, disallow session resumption on renegotiation */
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
Index: ssl/ssl_lib.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl_lib.c,v
retrieving revision 1.133.2.15
diff -u -p -r1.133.2.15 ssl_lib.c
--- ssl/ssl_lib.c 16 Jun 2008 16:56:42 -0000 1.133.2.15
+++ ssl/ssl_lib.c 29 Sep 2008 08:37:16 -0000
@@ -993,7 +993,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,v
s->max_cert_list=larg;
return(l);
case SSL_CTRL_SET_MTU:
- if (SSL_version(s) == DTLS1_VERSION)
+ if (SSL_version(s) == DTLS1_VERSION ||
+ SSL_version(s) == DTLS1_BAD_VER)
{
s->d1->mtu = larg;
return larg;
Index: ssl/ssl_sess.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl_sess.c,v
retrieving revision 1.51.2.9
diff -u -p -r1.51.2.9 ssl_sess.c
--- ssl/ssl_sess.c 4 Jun 2008 18:35:27 -0000 1.51.2.9
+++ ssl/ssl_sess.c 29 Sep 2008 08:27:31 -0000
@@ -211,6 +211,11 @@ int ssl_get_new_session(SSL *s, int sess
ss->ssl_version=TLS1_VERSION;
ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
}
+ else if (s->version == DTLS1_BAD_VER)
+ {
+ ss->ssl_version=DTLS1_BAD_VER;
+ ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+ }
else if (s->version == DTLS1_VERSION)
{
ss->ssl_version=DTLS1_VERSION;
Index: ssl/t1_enc.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/t1_enc.c,v
retrieving revision 1.35.2.6
diff -u -p -r1.35.2.6 t1_enc.c
--- ssl/t1_enc.c 13 Sep 2008 18:25:36 -0000 1.35.2.6
+++ ssl/t1_enc.c 29 Sep 2008 08:35:54 -0000
@@ -757,10 +757,10 @@ int tls1_mac(SSL *ssl, unsigned char *md
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);

- if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER)
+ if (ssl->version == DTLS1_BAD_VER ||
+ (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER))
{
unsigned char dtlsseq[8],*p=dtlsseq;
-
s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
memcpy (p,&seq[2],6);

@@ -785,7 +785,7 @@ printf("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
#endif

- if ( SSL_version(ssl) != DTLS1_VERSION)
+ if ( SSL_version(ssl) != DTLS1_VERSION && SSL_version(ssl) != DTLS1_BAD_VER)
{
for (i=7; i>=0; i--)
{


--
dwmw2
#     Tue Oct 07 10:57:10 2008  openssl-dev@openssl.org - Ticket 1760: Ticket created    
Subject: [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
Date: Tue, 07 Oct 2008 10:12:18 +0100
To: openssl-dev@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 7.2k
This patch against the 0.9.8 branch adds an SSL option for compatibility
with the pre-RFC version of DTLS used by Cisco for their AnyConnect SSL
VPN. This is RT #1751.

With this patch, and with the two bug fixes I just posted, I now have a
fully functional client operating with Cisco's VPN servers.

Index: ssl/d1_clnt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_clnt.c,v
retrieving revision 1.3.2.10
diff -u -p -r1.3.2.10 d1_clnt.c
--- ssl/d1_clnt.c 4 Jun 2008 18:35:25 -0000 1.3.2.10
+++ ssl/d1_clnt.c 29 Sep 2008 08:27:31 -0000
@@ -130,7 +130,7 @@ static int dtls1_get_hello_verify(SSL *s

static SSL_METHOD *dtls1_get_client_method(int ver)
{
- if (ver == DTLS1_VERSION)
+ if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
return(DTLSv1_client_method());
else
return(NULL);
@@ -181,7 +181,8 @@ int dtls1_connect(SSL *s)
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

- if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00))
+ if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
+ (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
{
SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
ret = -1;
Index: ssl/d1_lib.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_lib.c,v
retrieving revision 1.1.2.5
diff -u -p -r1.1.2.5 d1_lib.c
--- ssl/d1_lib.c 5 Oct 2007 21:05:27 -0000 1.1.2.5
+++ ssl/d1_lib.c 29 Sep 2008 08:38:49 -0000
@@ -186,7 +186,10 @@ void dtls1_free(SSL *s)
void dtls1_clear(SSL *s)
{
ssl3_clear(s);
- s->version=DTLS1_VERSION;
+ if (s->options & SSL_OP_CISCO_ANYCONNECT)
+ s->version=DTLS1_BAD_VER;
+ else
+ s->version=DTLS1_VERSION;
}

/*
Index: ssl/d1_pkt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_pkt.c,v
retrieving revision 1.4.2.12
diff -u -p -r1.4.2.12 d1_pkt.c
--- ssl/d1_pkt.c 14 Sep 2008 17:57:03 -0000 1.4.2.12
+++ ssl/d1_pkt.c 29 Sep 2008 08:27:31 -0000
@@ -986,15 +986,17 @@ start:
if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
{
struct ccs_header_st ccs_hdr;
+ int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;

dtls1_get_ccs_header(rr->data, &ccs_hdr);

/* 'Change Cipher Spec' is just a single byte, so we know
* exactly what the record payload has to look like */
/* XDTLS: check that epoch is consistent */
- if ( (s->client_version == DTLS1_BAD_VER && rr->length != 3) ||
- (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) ||
- (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
+ if (s->client_version == DTLS1_BAD_VER || s->version == DTLS1_BAD_VER)
+ ccs_hdr_len = 3;
+
+ if ((rr->length != ccs_hdr_len) || (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
{
i=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
@@ -1310,7 +1312,7 @@ int do_dtls1_write(SSL *s, int type, con
#if 0
/* 'create_empty_fragment' is true only when this function calls itself */
if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
- && SSL_version(s) != DTLS1_VERSION)
+ && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
{
/* countermeasure against known-IV weakness in CBC ciphersuites
* (see http://www.openssl.org/~bodo/tls-cbc.txt)
Index: ssl/s3_clnt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/s3_clnt.c,v
retrieving revision 1.88.2.17
diff -u -p -r1.88.2.17 s3_clnt.c
--- ssl/s3_clnt.c 16 Jun 2008 16:56:41 -0000 1.88.2.17
+++ ssl/s3_clnt.c 29 Sep 2008 08:27:31 -0000
@@ -708,7 +708,7 @@ int ssl3_get_server_hello(SSL *s)

if (!ok) return((int)n);

- if ( SSL_version(s) == DTLS1_VERSION)
+ if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
{
if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
{
Index: ssl/ssl.h
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl.h,v
retrieving revision 1.161.2.21
diff -u -p -r1.161.2.21 ssl.h
--- ssl/ssl.h 13 Aug 2008 19:44:44 -0000 1.161.2.21
+++ ssl/ssl.h 29 Sep 2008 08:39:24 -0000
@@ -510,6 +510,8 @@ typedef struct ssl_session_st
#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
/* Don't use RFC4507 ticket extension */
#define SSL_OP_NO_TICKET 0x00004000L
+/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client) */
+#define SSL_OP_CISCO_ANYCONNECT 0x00008000L

/* As server, disallow session resumption on renegotiation */
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
Index: ssl/ssl_lib.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl_lib.c,v
retrieving revision 1.133.2.15
diff -u -p -r1.133.2.15 ssl_lib.c
--- ssl/ssl_lib.c 16 Jun 2008 16:56:42 -0000 1.133.2.15
+++ ssl/ssl_lib.c 29 Sep 2008 08:37:16 -0000
@@ -993,7 +993,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,v
s->max_cert_list=larg;
return(l);
case SSL_CTRL_SET_MTU:
- if (SSL_version(s) == DTLS1_VERSION)
+ if (SSL_version(s) == DTLS1_VERSION ||
+ SSL_version(s) == DTLS1_BAD_VER)
{
s->d1->mtu = larg;
return larg;
Index: ssl/ssl_sess.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl_sess.c,v
retrieving revision 1.51.2.9
diff -u -p -r1.51.2.9 ssl_sess.c
--- ssl/ssl_sess.c 4 Jun 2008 18:35:27 -0000 1.51.2.9
+++ ssl/ssl_sess.c 29 Sep 2008 08:27:31 -0000
@@ -211,6 +211,11 @@ int ssl_get_new_session(SSL *s, int sess
ss->ssl_version=TLS1_VERSION;
ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
}
+ else if (s->version == DTLS1_BAD_VER)
+ {
+ ss->ssl_version=DTLS1_BAD_VER;
+ ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+ }
else if (s->version == DTLS1_VERSION)
{
ss->ssl_version=DTLS1_VERSION;
Index: ssl/t1_enc.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/t1_enc.c,v
retrieving revision 1.35.2.6
diff -u -p -r1.35.2.6 t1_enc.c
--- ssl/t1_enc.c 13 Sep 2008 18:25:36 -0000 1.35.2.6
+++ ssl/t1_enc.c 29 Sep 2008 08:35:54 -0000
@@ -757,10 +757,10 @@ int tls1_mac(SSL *ssl, unsigned char *md
HMAC_CTX_init(&hmac);
HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);

- if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER)
+ if (ssl->version == DTLS1_BAD_VER ||
+ (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER))
{
unsigned char dtlsseq[8],*p=dtlsseq;
-
s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
memcpy (p,&seq[2],6);

@@ -785,7 +785,7 @@ printf("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
#endif

- if ( SSL_version(ssl) != DTLS1_VERSION)
+ if ( SSL_version(ssl) != DTLS1_VERSION && SSL_version(ssl) != DTLS1_BAD_VER)
{
for (i=7; i>=0; i--)
{


--
dwmw2

______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majordomo@openssl.org
#     Tue Oct 07 16:09:32 2008  jaenicke - Ticket 1760: Requestor dwmw2@infradead.org added    
#     Tue Oct 07 16:09:32 2008  jaenicke - Ticket 1760: Requestor openssl-dev@openssl.org deleted    
#     Tue Oct 07 16:12:09 2008  jaenicke - Ticket 1760: Merged into ticket #1751    
#     Tue Oct 07 16:12:09 2008  jaenicke - Merged into ticket #1751    
#     Sat Dec 20 14:00:34 2008  dwmw2@infradead.org - Correspondence added    
Subject: Re: [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN [openssl.org #1751]
Date: Sat, 20 Dec 2008 12:55:25 +0000
To: rt@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 661b
On Tue, 2008-10-07 at 10:12 +0100, David Woodhouse wrote:
> This patch against the 0.9.8 branch adds an SSL option for compatibility
> with the pre-RFC version of DTLS used by Cisco for their AnyConnect SSL
> VPN. This is RT #1751.
>
> With this patch, and with the two bug fixes I just posted, I now have a
> fully functional client operating with Cisco's VPN servers.

Leaving aside the question of adding this to HEAD, can we please at
least add it to the 0.9.8 branch?

We're shipping a completely functional client for this VPN now, and all
that remains is to get the pre-RFC version of DTLS working again, which
is implemented by this patch.

--
dwmw2
#     Wed Feb 25 16:38:53 2009  ben - Correspondence added    
Download (untitled)
text/plain 1k
> [dwmw2@infradead.org - Sat Dec 20 14:00:34 2008]:
>
> On Tue, 2008-10-07 at 10:12 +0100, David Woodhouse wrote:
> > This patch against the 0.9.8 branch adds an SSL option for compatibility
> > with the pre-RFC version of DTLS used by Cisco for their AnyConnect SSL
> > VPN. This is RT #1751.
> >
> > With this patch, and with the two bug fixes I just posted, I now have a
> > fully functional client operating with Cisco's VPN servers.
>
> Leaving aside the question of adding this to HEAD, can we please at
> least add it to the 0.9.8 branch?

Adding to HEAD seems less problematic.

Anyway, I'm mostly happy with this patch, except from d1_pkt.c, shouldn't:

if (s->client_version == DTLS1_BAD_VER || s->version == DTLS1_BAD_VER)
ccs_hdr_len = 3;

be

if (s->client_version == DTLS1_BAD_VER || (s->options &
SSL_OP_CISCO_ANYCONNECT))
ccs_hdr_len = 3;

also, the patch as an attachment would be nice.

>
> We're shipping a completely functional client for this VPN now, and all
> that remains is to get the pre-RFC version of DTLS working again, which
> is implemented by this patch.
>
>
>
#     Wed Feb 25 16:38:54 2009  RT_System - Status changed from 'new' to 'open'    
#     Thu Feb 26 05:05:21 2009  dwmw2@infradead.org - Correspondence added    
CC: openssl-dev@openssl.org
Subject: Re: [openssl.org #1751] [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
Date: Thu, 26 Feb 2009 13:00:43 +0900
To: rt@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 1.8k
On Wed, 2009-02-25 at 16:38 +0100, Ben Laurie via RT wrote:
> > [dwmw2@infradead.org - Sat Dec 20 14:00:34 2008]:
> >
> > On Tue, 2008-10-07 at 10:12 +0100, David Woodhouse wrote:
> > > This patch against the 0.9.8 branch adds an SSL option for compatibility
> > > with the pre-RFC version of DTLS used by Cisco for their AnyConnect SSL
> > > VPN. This is RT #1751.
> > >
> > > With this patch, and with the two bug fixes I just posted, I now have a
> > > fully functional client operating with Cisco's VPN servers.
> >
> > Leaving aside the question of adding this to HEAD, can we please at
> > least add it to the 0.9.8 branch?
>
> Adding to HEAD seems less problematic.

Well, the stable branch already has back-compat support for a new server
to talk to old clients. So it's kind of a no-brainer to make it work the
other way round too; new client code talking to old servers.

HEAD doesn't have that back-compat at all; a patch would be larger
there. I can certainly generate such a patch though. As soon as I'm not
in a hotel which blocks UDP traffic... :)

> Anyway, I'm mostly happy with this patch, except from d1_pkt.c, shouldn't:
>
> if (s->client_version == DTLS1_BAD_VER || s->version == DTLS1_BAD_VER)
> ccs_hdr_len = 3;
>
> be
>
> if (s->client_version == DTLS1_BAD_VER || (s->options &
> SSL_OP_CISCO_ANYCONNECT))
> ccs_hdr_len = 3;

Those are equivalent, I believe -- you should never hit this code path
with s->version == DTLS1_BAD_VER unless the ANYCONNECT option is set.

So it's purely a cosmetic thing -- I can change it if you prefer.

> also, the patch as an attachment would be nice.

I'm attaching the 0.9.8x patch I've been building with for the last few
months. Generating a patch against HEAD will take me a little longer
(and be less directly useful, in the foreseeable future, because
distributions are actually shipping 0.9.8x.)

--
dwmw2
#     Thu Feb 26 12:08:30 2009  dwmw2@infradead.org - Correspondence added    
CC: rt@openssl.org
Subject: Re: [openssl.org #1751] [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
Date: Thu, 26 Feb 2009 21:03:22 +0900
To: openssl-dev@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 569b
On Thu, 2009-02-26 at 13:00 +0900, David Woodhouse wrote:
> Generating a patch against HEAD will take me a little longer (and be
> less directly useful, in the foreseeable future, because distributions
> are actually shipping 0.9.8x.)

I'm working on this; I've rediscovered my standalone test case and will
spend much of the next 24 hours locked in airplanes where I can poke at
it.

My current patch against HEAD isn't working yet because I still need to
add some of the existing backward-compatibility support which is in the
stable branch but not HEAD.

--
dwmw2
#     Sun Apr 19 19:49:27 2009  dwmw2@infradead.org - Correspondence added    
CC: rt@openssl.org
Subject: Re: [openssl.org #1751] [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
Date: Sun, 19 Apr 2009 19:44:26 +0100
To: openssl-dev@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 11.8k
On Thu, 2009-02-26 at 21:03 +0900, David Woodhouse wrote:
> On Thu, 2009-02-26 at 13:00 +0900, David Woodhouse wrote:
> > Generating a patch against HEAD will take me a little longer (and be
> > less directly useful, in the foreseeable future, because distributions
> > are actually shipping 0.9.8x.)
>
> I'm working on this; I've rediscovered my standalone test case and will
> spend much of the next 24 hours locked in airplanes where I can poke at
> it.
>
> My current patch against HEAD isn't working yet because I still need to
> add some of the existing backward-compatibility support which is in the
> stable branch but not HEAD.

I finally threw away everything I'd done and started again from scratch,
and I have it working against openssl-1.0.0-beta1.

Again, this is required for interoperation with existing OpenSSL-based
deployments which are quite common "out there", and which can't be
updated to use the "real" protocol.

Index: ssl/d1_both.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_both.c,v
retrieving revision 1.14.2.4
diff -u -p -r1.14.2.4 d1_both.c
--- ssl/d1_both.c 15 Apr 2009 14:49:36 -0000 1.14.2.4
+++ ssl/d1_both.c 19 Apr 2009 18:35:41 -0000
@@ -300,7 +300,7 @@ int dtls1_do_write(SSL *s, int type)
const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
int xlen;

- if (frag_off == 0)
+ if (frag_off == 0 && s->version != DTLS1_BAD_VER)
{
/* reconstruct message header is if it
* is being sent in single fragment */
@@ -407,8 +407,10 @@ long dtls1_get_message(SSL *s, int st1,
s2n (msg_hdr->seq,p);
l2n3(0,p);
l2n3(msg_len,p);
- p -= DTLS1_HM_HEADER_LENGTH;
- msg_len += DTLS1_HM_HEADER_LENGTH;
+ if (s->version != DTLS1_BAD_VER) {
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+ }

ssl3_finish_mac(s, p, msg_len);
if (s->msg_callback)
@@ -775,6 +777,13 @@ int dtls1_send_change_cipher_spec(SSL *s
*p++=SSL3_MT_CCS;
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
s->init_num=DTLS1_CCS_HEADER_LENGTH;
+
+ if (s->version == DTLS1_BAD_VER) {
+ s->d1->next_handshake_write_seq++;
+ s2n(s->d1->handshake_write_seq,p);
+ s->init_num+=2;
+ }
+
s->init_off=0;

dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
@@ -989,7 +998,7 @@ dtls1_buffer_message(SSL *s, int is_ccs)
if ( is_ccs)
{
OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
- DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num);
+ ((s->version==DTLS1_VERSION)?DTLS1_CCS_HEADER_LENGTH:3) == (unsigned int)s->init_num);
}
else
{
Index: ssl/d1_clnt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_clnt.c,v
retrieving revision 1.16.2.3
diff -u -p -r1.16.2.3 d1_clnt.c
--- ssl/d1_clnt.c 14 Apr 2009 14:33:12 -0000 1.16.2.3
+++ ssl/d1_clnt.c 19 Apr 2009 17:42:51 -0000
@@ -130,7 +130,7 @@ static int dtls1_get_hello_verify(SSL *s

static const SSL_METHOD *dtls1_get_client_method(int ver)
{
- if (ver == DTLS1_VERSION)
+ if (ver == DTLS1_VERSION || ver == DTLS1_BAD_VER)
return(DTLSv1_client_method());
else
return(NULL);
@@ -181,7 +181,8 @@ int dtls1_connect(SSL *s)
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

- if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00))
+ if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
+ (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
{
SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
ret = -1;
Index: ssl/d1_lib.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_lib.c,v
retrieving revision 1.8.2.1
diff -u -p -r1.8.2.1 d1_lib.c
--- ssl/d1_lib.c 14 Apr 2009 14:20:56 -0000 1.8.2.1
+++ ssl/d1_lib.c 19 Apr 2009 17:42:51 -0000
@@ -176,7 +176,10 @@ void dtls1_free(SSL *s)
void dtls1_clear(SSL *s)
{
ssl3_clear(s);
- s->version=DTLS1_VERSION;
+ if (s->options & SSL_OP_CISCO_ANYCONNECT)
+ s->version=DTLS1_BAD_VER;
+ else
+ s->version=DTLS1_VERSION;
}

/*
Index: ssl/d1_pkt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_pkt.c,v
retrieving revision 1.27.2.4
diff -u -p -r1.27.2.4 d1_pkt.c
--- ssl/d1_pkt.c 15 Apr 2009 14:49:36 -0000 1.27.2.4
+++ ssl/d1_pkt.c 19 Apr 2009 18:37:44 -0000
@@ -591,7 +591,7 @@ again:
}
}

- if ((version & 0xff00) != (DTLS1_VERSION & 0xff00))
+ if ((version & 0xff00) != (s->version & 0xff00))
{
SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
goto err;
@@ -1067,13 +1067,17 @@ start:
if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
{
struct ccs_header_st ccs_hdr;
+ int ccs_hdr_len = DTLS1_CCS_HEADER_LENGTH;

dtls1_get_ccs_header(rr->data, &ccs_hdr);

+ if (s->version == DTLS1_BAD_VER)
+ ccs_hdr_len = 3;
+
/* 'Change Cipher Spec' is just a single byte, so we know
* exactly what the record payload has to look like */
/* XDTLS: check that epoch is consistent */
- if ( (rr->length != DTLS1_CCS_HEADER_LENGTH) ||
+ if ( (rr->length != ccs_hdr_len) ||
(rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
{
i=SSL_AD_ILLEGAL_PARAMETER;
@@ -1094,6 +1098,9 @@ start:
/* do this whenever CCS is processed */
dtls1_reset_seq_numbers(s, SSL3_CC_READ);

+ if (s->version == DTLS1_BAD_VER)
+ s->d1->handshake_read_seq++;
+
goto start;
}

@@ -1401,7 +1408,7 @@ int do_dtls1_write(SSL *s, int type, con
#if 0
/* 'create_empty_fragment' is true only when this function calls itself */
if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done
- && SSL_version(s) != DTLS1_VERSION)
+ && SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
{
/* countermeasure against known-IV weakness in CBC ciphersuites
* (see http://www.openssl.org/~bodo/tls-cbc.txt)
@@ -1428,7 +1435,6 @@ int do_dtls1_write(SSL *s, int type, con
s->s3->empty_fragment_done = 1;
}
#endif
-
p = wb->buf + prefix_len;

/* write the header */
Index: ssl/d1_srvr.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/d1_srvr.c,v
retrieving revision 1.20.2.2
diff -u -p -r1.20.2.2 d1_srvr.c
--- ssl/d1_srvr.c 14 Apr 2009 14:33:12 -0000 1.20.2.2
+++ ssl/d1_srvr.c 19 Apr 2009 18:17:04 -0000
@@ -292,7 +292,8 @@ int dtls1_accept(SSL *s)
s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;

/* HelloVerifyRequest resets Finished MAC */
- ssl3_init_finished_mac(s);
+ if (s->version != DTLS1_BAD_VER)
+ ssl3_init_finished_mac(s);
break;

case SSL3_ST_SW_SRVR_HELLO_A:
Index: ssl/dtls1.h
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/dtls1.h,v
retrieving revision 1.12.2.4
diff -u -p -r1.12.2.4 dtls1.h
--- ssl/dtls1.h 15 Apr 2009 14:49:36 -0000 1.12.2.4
+++ ssl/dtls1.h 19 Apr 2009 17:49:49 -0000
@@ -68,6 +68,7 @@ extern "C" {
#endif

#define DTLS1_VERSION 0xFEFF
+#define DTLS1_BAD_VER 0x0100

#if 0
/* this alert description is not specified anywhere... */
Index: ssl/s3_clnt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/s3_clnt.c,v
retrieving revision 1.129
diff -u -p -r1.129 s3_clnt.c
--- ssl/s3_clnt.c 14 Feb 2009 21:49:38 -0000 1.129
+++ ssl/s3_clnt.c 19 Apr 2009 17:42:51 -0000
@@ -737,7 +737,7 @@ int ssl3_get_server_hello(SSL *s)

if (!ok) return((int)n);

- if ( SSL_version(s) == DTLS1_VERSION)
+ if ( SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
{
if ( s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST)
{
Index: ssl/s3_pkt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/s3_pkt.c,v
retrieving revision 1.72.2.2
diff -u -p -r1.72.2.2 s3_pkt.c
--- ssl/s3_pkt.c 16 Apr 2009 17:22:50 -0000 1.72.2.2
+++ ssl/s3_pkt.c 19 Apr 2009 18:22:32 -0000
@@ -177,8 +177,8 @@ int ssl3_read_n(SSL *s, int n, int max,
}

/* extend reads should not span multiple packets for DTLS */
- if ( SSL_version(s) == DTLS1_VERSION &&
- extend)
+ if ( (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+ && extend)
{
if ( left > 0 && n > left)
n = left;
@@ -836,7 +836,8 @@ int ssl3_write_pending(SSL *s, int type,
return(s->s3->wpend_ret);
}
else if (i <= 0) {
- if (s->version == DTLS1_VERSION) {
+ if (s->version == DTLS1_VERSION ||
+ s->version == DTLS1_BAD_VER) {
/* For DTLS, just drop it. That's kind of the whole
point in using a datagram service */
wb->left = 0;
Index: ssl/s3_srvr.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/s3_srvr.c,v
retrieving revision 1.171
diff -u -p -r1.171 s3_srvr.c
--- ssl/s3_srvr.c 7 Jan 2009 23:44:27 -0000 1.171
+++ ssl/s3_srvr.c 19 Apr 2009 18:23:54 -0000
@@ -1920,7 +1920,7 @@ int ssl3_get_client_key_exchange(SSL *s)
}

/* TLS and [incidentally] DTLS{0xFEFF} */
- if (s->version > SSL3_VERSION)
+ if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER)
{
n2s(p,i);
if (n != i+2)
Index: ssl/ssl.h
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl.h,v
retrieving revision 1.221.2.3
diff -u -p -r1.221.2.3 ssl.h
--- ssl/ssl.h 7 Apr 2009 17:01:07 -0000 1.221.2.3
+++ ssl/ssl.h 19 Apr 2009 17:42:51 -0000
@@ -542,6 +542,8 @@ typedef struct ssl_session_st
#define SSL_OP_COOKIE_EXCHANGE 0x00002000L
/* Don't use RFC4507 ticket extension */
#define SSL_OP_NO_TICKET 0x00004000L
+/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client) */
+#define SSL_OP_CISCO_ANYCONNECT 0x00008000L

/* As server, disallow session resumption on renegotiation */
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L
Index: ssl/ssl_lib.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl_lib.c,v
retrieving revision 1.176.2.1
diff -u -p -r1.176.2.1 ssl_lib.c
--- ssl/ssl_lib.c 4 Apr 2009 17:57:33 -0000 1.176.2.1
+++ ssl/ssl_lib.c 19 Apr 2009 17:42:51 -0000
@@ -1038,7 +1038,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,v
s->max_cert_list=larg;
return(l);
case SSL_CTRL_SET_MTU:
- if (SSL_version(s) == DTLS1_VERSION)
+ if (SSL_version(s) == DTLS1_VERSION ||
+ SSL_version(s) == DTLS1_BAD_VER)
{
s->d1->mtu = larg;
return larg;
Index: ssl/ssl_sess.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/ssl_sess.c,v
retrieving revision 1.74
diff -u -p -r1.74 ssl_sess.c
--- ssl/ssl_sess.c 15 Nov 2008 17:18:11 -0000 1.74
+++ ssl/ssl_sess.c 19 Apr 2009 17:42:51 -0000
@@ -300,6 +300,11 @@ int ssl_get_new_session(SSL *s, int sess
ss->ssl_version=TLS1_VERSION;
ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
}
+ else if (s->version == DTLS1_BAD_VER)
+ {
+ ss->ssl_version=DTLS1_BAD_VER;
+ ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+ }
else if (s->version == DTLS1_VERSION)
{
ss->ssl_version=DTLS1_VERSION;
Index: ssl/t1_enc.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/t1_enc.c,v
retrieving revision 1.57
diff -u -p -r1.57 t1_enc.c
--- ssl/t1_enc.c 11 Jan 2009 20:34:23 -0000 1.57
+++ ssl/t1_enc.c 19 Apr 2009 18:40:43 -0000
@@ -882,7 +882,7 @@ int tls1_mac(SSL *ssl, unsigned char *md
mac_ctx = &hmac;
}

- if (ssl->version == DTLS1_VERSION)
+ if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
{
unsigned char dtlsseq[8],*p=dtlsseq;

@@ -911,7 +911,7 @@ printf("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
#endif

- if (ssl->version != DTLS1_VERSION)
+ if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
{
for (i=7; i>=0; i--)
{

--
dwmw2
#     Mon Apr 20 02:35:16 2009  dwmw2@infradead.org - Correspondence added    
CC: rt@openssl.org
Subject: Re: [openssl.org #1751] [PATCH] Support DTLS compatibility with Cisco AnyConnect VPN
Date: Mon, 20 Apr 2009 02:30:16 +0100
To: openssl-dev@openssl.org
From: David Woodhouse <dwmw2@infradead.org>
Download (untitled)
text/plain 945b
On Sun, 2009-04-19 at 19:44 +0100, David Woodhouse wrote:
> I finally threw away everything I'd done and started again from scratch,
> and I have it working against openssl-1.0.0-beta1.

Thanks for applying it to 0.9.8 and 1.0.0 branches. If we apply this
simple fix first, the 1.0.0 version of the patch also applies to HEAD...

Index: ssl/s3_pkt.c
===================================================================
RCS file: /home/dwmw2/openssl-cvs/openssl/ssl/s3_pkt.c,v
retrieving revision 1.73
diff -u -p -r1.73 s3_pkt.c
--- ssl/s3_pkt.c 7 Apr 2009 16:33:26 -0000 1.73
+++ ssl/s3_pkt.c 20 Apr 2009 01:28:10 -0000
@@ -837,8 +837,7 @@ int ssl3_write_pending(SSL *s, int type,
}
else if (i <= 0) {
if (s->version == DTLS1_VERSION) {
- /* For DTLS, just drop it. That's kind of the wh
-ole
+ /* For DTLS, just drop it. That's kind of the whole
point in using a datagram service */
wb->left = 0;
}

--
dwmw2
»|« RT 3.4.5 Copyright 1996-2005 Best Practical Solutions, LLC.
Time to display: 1.328266