From 5c665fe614c9d20f54e4b88958b8ad9cb27770d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Thu, 30 May 2013 15:22:38 -0300 Subject: [PATCH 1/6] Added options to SNI (now it is possible to choose whether or not to abort on a SNI Host Name mismatch) Exposed SNI Type at ssl.h --- cyassl/internal.h | 18 +++++++++++------- cyassl/ssl.h | 17 +++++++++++++++++ examples/server/server.c | 9 +++++++-- src/ssl.c | 15 +++++++++++++++ src/tls.c | 35 ++++++++++++++++++++++++----------- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 89f34b5a6..f53733d83 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1151,19 +1151,23 @@ CYASSL_LOCAL int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, /* Server Name Indication */ #ifdef HAVE_SNI -typedef enum { - HOST_NAME = 0 -} SNI_Type; - typedef struct SNI { - SNI_Type type; /* SNI Type */ - union { char* host_name; } data; /* SNI Data */ - struct SNI* next; /* List Behavior */ + byte type; /* SNI Type */ + union { char* host_name; } data; /* SNI Data */ + struct SNI* next; /* List Behavior */ +#ifndef NO_CYASSL_SERVER + byte options; /* Behaviour options */ +#endif } SNI; CYASSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size); +#ifndef NO_CYASSL_SERVER +CYASSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type, + byte options); +#endif + #endif /* HAVE_SNI */ #endif /* HAVE_TLS_EXTENSIONS */ diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 338564950..85807ace3 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -931,10 +931,27 @@ CYASSL_API int CyaSSL_CTX_UseCavium(CYASSL_CTX*, int devId); /* tls extensions */ #ifdef HAVE_SNI +/* SNI types */ +enum { + CYASSL_SNI_HOST_NAME = 0 +}; + CYASSL_API int CyaSSL_UseSNI(CYASSL* ssl, unsigned char type, const void* data, unsigned short size); CYASSL_API int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, const void* data, unsigned short size); + +#ifndef NO_CYASSL_SERVER +/* SNI options */ +enum { + CYASSL_SNI_ABORT_ON_MISMATCH = 0x01 +}; + +CYASSL_API void CyaSSL_SNI_SetOptions(CYASSL* ssl, unsigned char type, + unsigned char options); +CYASSL_API void CyaSSL_CTX_SNI_SetOptions(CYASSL_CTX* ctx, unsigned char type, + unsigned char options); +#endif #endif #define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */ diff --git a/examples/server/server.c b/examples/server/server.c index da6fccf45..ffa29bc08 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -408,9 +408,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #ifdef HAVE_SNI - if (sniHostName) - if (CyaSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName))) + if (sniHostName) { + if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, + XSTRLEN(sniHostName))) err_sys("UseSNI failed"); + else + CyaSSL_CTX_SNI_SetOptions(ctx, CYASSL_SNI_HOST_NAME, + CYASSL_SNI_ABORT_ON_MISMATCH); + } #endif ssl = SSL_new(ctx); diff --git a/src/ssl.c b/src/ssl.c index aaf384066..7b9cb1f64 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -529,6 +529,21 @@ int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, const void* data, return TLSX_UseSNI(&ctx->extensions, type, data, size); } +#ifndef NO_CYASSL_SERVER +void CyaSSL_SNI_SetOptions(CYASSL* ssl, unsigned char type, + unsigned char options) +{ + if (ssl && ssl->extensions) + TLSX_SNI_SetOptions(ssl->extensions, type, options); +} +void CyaSSL_CTX_SNI_SetOptions(CYASSL_CTX* ctx, unsigned char type, + unsigned char options) +{ + if (ctx && ctx->extensions) + TLSX_SNI_SetOptions(ctx->extensions, type, options); +} +#endif + #endif /* HAVE_SNI */ #ifndef CYASSL_LEANPSK diff --git a/src/tls.c b/src/tls.c index 2776b5e86..8cc4d3098 100644 --- a/src/tls.c +++ b/src/tls.c @@ -531,7 +531,7 @@ static void TLSX_SNI_Free(SNI* sni) { if (sni) { switch (sni->type) { - case HOST_NAME: + case CYASSL_SNI_HOST_NAME: XFREE(sni->data.host_name, 0, DYNAMIC_TYPE_TLSX); break; } @@ -550,8 +550,7 @@ static void TLSX_SNI_FreeAll(SNI* list) } } -static int TLSX_SNI_Append(SNI** list, SNI_Type type, const void* data, - word16 size) +static int TLSX_SNI_Append(SNI** list, byte type, const void* data, word16 size) { SNI* sni; @@ -562,7 +561,7 @@ static int TLSX_SNI_Append(SNI** list, SNI_Type type, const void* data, return MEMORY_E; switch (type) { - case HOST_NAME: { + case CYASSL_SNI_HOST_NAME: { sni->data.host_name = XMALLOC(size + 1, 0, DYNAMIC_TYPE_TLSX); if (sni->data.host_name) { @@ -583,6 +582,7 @@ static int TLSX_SNI_Append(SNI** list, SNI_Type type, const void* data, sni->type = type; sni->next = *list; + sni->options = 0; *list = sni; return 0; @@ -599,7 +599,7 @@ static word16 TLSX_SNI_GetSize(SNI* list) length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */ switch (sni->type) { - case HOST_NAME: + case CYASSL_SNI_HOST_NAME: length += XSTRLEN((char*) sni->data.host_name); break; } @@ -620,7 +620,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) output[offset++] = sni->type; /* sni type */ switch (sni->type) { - case HOST_NAME: + case CYASSL_SNI_HOST_NAME: length = XSTRLEN((char*) sni->data.host_name); c16toa(length, output + offset); /* sni length */ @@ -638,7 +638,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) return offset; } -static SNI* TLSX_SNI_Find(SNI *list, SNI_Type type) +static SNI* TLSX_SNI_Find(SNI *list, byte type) { SNI *sni = list; @@ -691,7 +691,7 @@ static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length, for (size = 0; offset < length; offset += size) { SNI *sni; - SNI_Type type = input[offset++]; + byte type = input[offset++]; if (offset + OPAQUE16_LEN > length) return INCOMPLETE_DATA; @@ -707,9 +707,11 @@ static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length, } switch(type) { - case HOST_NAME: - if (XSTRNCMP(sni->data.host_name, - (const char *) input + offset, size)) { + case CYASSL_SNI_HOST_NAME: + if ((sni->options & CYASSL_SNI_ABORT_ON_MISMATCH) + && ((XSTRLEN(sni->data.host_name) != size) + || XSTRNCMP(sni->data.host_name, + (const char *) input + offset, size))) { SendAlert(ssl, alert_fatal, unrecognized_name); return UNKNOWN_SNI_HOST_NAME_E; @@ -776,6 +778,17 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) return 0; } +#ifndef NO_CYASSL_SERVER +void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) +{ + TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni) + sni->options = options; +} +#endif + #define SNI_FREE_ALL TLSX_SNI_FreeAll #define SNI_GET_SIZE TLSX_SNI_GetSize #define SNI_WRITE TLSX_SNI_Write From 79fad81c32d133a4822c6a06e4082e56b9ca1306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Thu, 30 May 2013 15:40:10 -0300 Subject: [PATCH 2/6] shrinking function names --- src/ssl.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 7b9cb1f64..cd86c938a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -511,8 +511,7 @@ int CyaSSL_CTX_UseCavium(CYASSL_CTX* ctx, int devId) #ifdef HAVE_SNI -int CyaSSL_UseSNI(CYASSL* ssl, unsigned char type, const void* data, - unsigned short size) +int CyaSSL_UseSNI(CYASSL* ssl, byte type, const void* data, word16 size) { if (ssl == NULL) return BAD_FUNC_ARG; @@ -520,8 +519,7 @@ int CyaSSL_UseSNI(CYASSL* ssl, unsigned char type, const void* data, return TLSX_UseSNI(&ssl->extensions, type, data, size); } -int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, const void* data, - unsigned short size) +int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, byte type, const void* data, word16 size) { if (ctx == NULL) return BAD_FUNC_ARG; @@ -530,14 +528,13 @@ int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, const void* data, } #ifndef NO_CYASSL_SERVER -void CyaSSL_SNI_SetOptions(CYASSL* ssl, unsigned char type, - unsigned char options) +void CyaSSL_SNI_SetOptions(CYASSL* ssl, byte type, byte options) { if (ssl && ssl->extensions) TLSX_SNI_SetOptions(ssl->extensions, type, options); } -void CyaSSL_CTX_SNI_SetOptions(CYASSL_CTX* ctx, unsigned char type, - unsigned char options) + +void CyaSSL_CTX_SNI_SetOptions(CYASSL_CTX* ctx, byte type, byte options) { if (ctx && ctx->extensions) TLSX_SNI_SetOptions(ctx->extensions, type, options); From ebd03368c71f2dd311eadeb9e265c2e6e037bf6a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 31 May 2013 13:48:49 -0700 Subject: [PATCH 3/6] for DTLS handshakes, put change cipher spec and finished messages in same datagram --- src/internal.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/internal.c b/src/internal.c index fcfe8f9cc..f545407ae 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4802,6 +4802,13 @@ int SendChangeCipher(CYASSL* ssl) if (ssl->options.groupMessages) return 0; + #ifdef CYASSL_DTLS + else if (ssl->options.dtls) { + /* If using DTLS, force the ChangeCipherSpec message to be in the + * same datagram as the finished message. */ + return 0; + } + #endif else return SendBuffered(ssl); } From 4ad91673ca8c03357e280cb5e32a265527da72c8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 31 May 2013 17:57:08 -0700 Subject: [PATCH 4/6] fixed description for filesystem configure option to match default --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8bf41a590..74fea8f44 100644 --- a/configure.ac +++ b/configure.ac @@ -942,7 +942,7 @@ fi # Filesystem Build AC_ARG_ENABLE([filesystem], - [ --enable-filesystem Enable Filesystem support (default: disabled)], + [ --enable-filesystem Enable Filesystem support (default: enabled)], [ ENABLED_FILESYSTEM=$enableval ], [ ENABLED_FILESYSTEM=yes ] ) From cb2082edee592e3d8bf6eb06b099308b5a519f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20Guimar=C3=A3es?= Date: Mon, 3 Jun 2013 10:04:49 -0300 Subject: [PATCH 5/6] changed CYASSL_SNI_ABORT_ON_MISMATCH to CYASSL_SNI_CONTINUE_ON_MISMATCH --- cyassl/ssl.h | 2 +- examples/server/server.c | 6 +----- src/tls.c | 15 +++++++++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 85807ace3..0af93fdfe 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -944,7 +944,7 @@ CYASSL_API int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, #ifndef NO_CYASSL_SERVER /* SNI options */ enum { - CYASSL_SNI_ABORT_ON_MISMATCH = 0x01 + CYASSL_SNI_CONTINUE_ON_MISMATCH = 0x01 }; CYASSL_API void CyaSSL_SNI_SetOptions(CYASSL* ssl, unsigned char type, diff --git a/examples/server/server.c b/examples/server/server.c index ffa29bc08..c0eac3e51 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -408,14 +408,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #ifdef HAVE_SNI - if (sniHostName) { + if (sniHostName) if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, XSTRLEN(sniHostName))) err_sys("UseSNI failed"); - else - CyaSSL_CTX_SNI_SetOptions(ctx, CYASSL_SNI_HOST_NAME, - CYASSL_SNI_ABORT_ON_MISMATCH); - } #endif ssl = SSL_new(ctx); diff --git a/src/tls.c b/src/tls.c index 8cc4d3098..b902738ef 100644 --- a/src/tls.c +++ b/src/tls.c @@ -708,10 +708,17 @@ static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length, switch(type) { case CYASSL_SNI_HOST_NAME: - if ((sni->options & CYASSL_SNI_ABORT_ON_MISMATCH) - && ((XSTRLEN(sni->data.host_name) != size) - || XSTRNCMP(sni->data.host_name, - (const char *) input + offset, size))) { + if (XSTRLEN(sni->data.host_name) != size + || XSTRNCMP(sni->data.host_name, + (const char *) input + offset, size)) { + if (sni->options & CYASSL_SNI_CONTINUE_ON_MISMATCH) + break; + /** + * Better client thinks the server is not using SNI, + * instead of thinking that the host_name matched. + * No empty SNI response in this case. + */ + SendAlert(ssl, alert_fatal, unrecognized_name); return UNKNOWN_SNI_HOST_NAME_E; From f1d1898ddf995ccf9339fe38383cc38a00f489f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20Guimar=C3=A3es?= Date: Mon, 3 Jun 2013 17:55:06 -0300 Subject: [PATCH 6/6] Added new option to SNI: CYASSL_SNI_ANSWER_ON_MISMATCH Added new function to SNI API: CyaSSL_SNI_Matched() --- cyassl/internal.h | 2 ++ cyassl/ssl.h | 5 +++- src/ssl.c | 5 ++++ src/tls.c | 66 +++++++++++++++++++++++++++++++++-------------- 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index f53733d83..39947748a 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1157,6 +1157,7 @@ typedef struct SNI { struct SNI* next; /* List Behavior */ #ifndef NO_CYASSL_SERVER byte options; /* Behaviour options */ + byte matched; /* Matching result */ #endif } SNI; @@ -1164,6 +1165,7 @@ CYASSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size); #ifndef NO_CYASSL_SERVER +CYASSL_LOCAL byte TLSX_SNI_Matched(TLSX* extensions, byte type); CYASSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options); #endif diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 0af93fdfe..3ed5bc457 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -944,9 +944,12 @@ CYASSL_API int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, unsigned char type, #ifndef NO_CYASSL_SERVER /* SNI options */ enum { - CYASSL_SNI_CONTINUE_ON_MISMATCH = 0x01 + CYASSL_SNI_CONTINUE_ON_MISMATCH = 0x01, /* do not abort on mismatch flag */ + CYASSL_SNI_ANSWER_ON_MISMATCH = 0x02 /* fake match on mismatch flag */ }; +CYASSL_API unsigned char CyaSSL_SNI_Matched(CYASSL* ssl, unsigned char type); + CYASSL_API void CyaSSL_SNI_SetOptions(CYASSL* ssl, unsigned char type, unsigned char options); CYASSL_API void CyaSSL_CTX_SNI_SetOptions(CYASSL_CTX* ctx, unsigned char type, diff --git a/src/ssl.c b/src/ssl.c index cd86c938a..60caf99d6 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -528,6 +528,11 @@ int CyaSSL_CTX_UseSNI(CYASSL_CTX* ctx, byte type, const void* data, word16 size) } #ifndef NO_CYASSL_SERVER +byte CyaSSL_SNI_Matched(CYASSL* ssl, byte type) +{ + return TLSX_SNI_Matched(ssl ? ssl->extensions : NULL, type); +} + void CyaSSL_SNI_SetOptions(CYASSL* ssl, byte type, byte options) { if (ssl && ssl->extensions) diff --git a/src/tls.c b/src/tls.c index b902738ef..6e5965595 100644 --- a/src/tls.c +++ b/src/tls.c @@ -582,7 +582,12 @@ static int TLSX_SNI_Append(SNI** list, byte type, const void* data, word16 size) sni->type = type; sni->next = *list; + +#ifndef NO_CYASSL_SERVER sni->options = 0; + sni->matched = 0; +#endif + *list = sni; return 0; @@ -648,6 +653,30 @@ static SNI* TLSX_SNI_Find(SNI *list, byte type) return sni; } +#ifndef NO_CYASSL_SERVER +static void TLSX_SNI_SetMatched(TLSX* extensions, byte type) +{ + TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni) { + sni->matched = 1; + CYASSL_MSG("SNI did match!"); + } +} + +byte TLSX_SNI_Matched(TLSX* extensions, byte type) +{ + TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + + if (sni) + return sni->matched; + + return 0; +} +#endif + static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest) { @@ -707,27 +736,24 @@ static int TLSX_SNI_Parse(CYASSL* ssl, byte* input, word16 length, } switch(type) { - case CYASSL_SNI_HOST_NAME: - if (XSTRLEN(sni->data.host_name) != size - || XSTRNCMP(sni->data.host_name, - (const char *) input + offset, size)) { - if (sni->options & CYASSL_SNI_CONTINUE_ON_MISMATCH) - break; - /** - * Better client thinks the server is not using SNI, - * instead of thinking that the host_name matched. - * No empty SNI response in this case. - */ + case CYASSL_SNI_HOST_NAME: { + byte matched = (XSTRLEN(sni->data.host_name) == size) + && (XSTRNCMP(sni->data.host_name, + (const char *) input + offset, size) == 0); - SendAlert(ssl, alert_fatal, unrecognized_name); - - return UNKNOWN_SNI_HOST_NAME_E; - } else { + if (matched || sni->options & CYASSL_SNI_ANSWER_ON_MISMATCH) { int r = TLSX_UseSNI(&ssl->extensions, type, (byte *) "", 0); if (r) return r; /* throw error */ + + if (matched) TLSX_SNI_SetMatched(ssl->extensions, type); + } else if (!(sni->options & CYASSL_SNI_CONTINUE_ON_MISMATCH)) { + SendAlert(ssl, alert_fatal, unrecognized_name); + + return UNKNOWN_SNI_HOST_NAME_E; } break; + } } TLSX_SetResponse(ssl, SERVER_NAME_INDICATION); @@ -788,11 +814,11 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) #ifndef NO_CYASSL_SERVER void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); - SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); + TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); - if (sni) - sni->options = options; + if (sni) + sni->options = options; } #endif @@ -1047,6 +1073,8 @@ int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest, switch (type) { case SERVER_NAME_INDICATION: + CYASSL_MSG("SNI extension received"); + ret = SNI_PARSE(ssl, input + offset, size, isRequest); break;