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 ] ) diff --git a/cyassl/internal.h b/cyassl/internal.h index 89f34b5a6..39947748a 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1151,19 +1151,25 @@ 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 */ + byte matched; /* Matching result */ +#endif } SNI; 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 + #endif /* HAVE_SNI */ #endif /* HAVE_TLS_EXTENSIONS */ diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 338564950..3ed5bc457 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -931,10 +931,30 @@ 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_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, + 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..c0eac3e51 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -409,7 +409,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef HAVE_SNI if (sniHostName) - if (CyaSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName))) + if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, + XSTRLEN(sniHostName))) err_sys("UseSNI failed"); #endif 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); } diff --git a/src/ssl.c b/src/ssl.c index aaf384066..60caf99d6 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; @@ -529,6 +527,25 @@ 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 +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) + TLSX_SNI_SetOptions(ssl->extensions, type, options); +} + +void CyaSSL_CTX_SNI_SetOptions(CYASSL_CTX* ctx, byte type, byte 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..6e5965595 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,12 @@ static int TLSX_SNI_Append(SNI** list, SNI_Type type, const void* data, sni->type = type; sni->next = *list; + +#ifndef NO_CYASSL_SERVER + sni->options = 0; + sni->matched = 0; +#endif + *list = sni; return 0; @@ -599,7 +604,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 +625,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 +643,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; @@ -648,6 +653,30 @@ static SNI* TLSX_SNI_Find(SNI *list, SNI_Type 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) { @@ -691,7 +720,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,18 +736,24 @@ 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)) { - SendAlert(ssl, alert_fatal, unrecognized_name); + case CYASSL_SNI_HOST_NAME: { + byte matched = (XSTRLEN(sni->data.host_name) == size) + && (XSTRNCMP(sni->data.host_name, + (const char *) input + offset, size) == 0); - 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); @@ -776,6 +811,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 @@ -1027,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;