mirror of https://github.com/wolfSSL/wolfssl.git
added new function to retrieve SNI from a buffer.
parent
6bdbc83924
commit
ba18f8b03e
|
@ -1153,6 +1153,8 @@ CYASSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type,
|
|||
CYASSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type);
|
||||
CYASSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type,
|
||||
void** data);
|
||||
CYASSL_LOCAL int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
|
||||
byte type, byte* sni, word32* inOutSz);
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
|
|
@ -1187,6 +1187,10 @@ CYASSL_API unsigned char CyaSSL_SNI_Status(CYASSL* ssl, unsigned char type);
|
|||
CYASSL_API unsigned short CyaSSL_SNI_GetRequest(CYASSL *ssl, unsigned char type,
|
||||
void** data);
|
||||
|
||||
CYASSL_API int CyaSSL_SNI_GetFromBuffer(
|
||||
const unsigned char* buffer, unsigned int bufferSz,
|
||||
unsigned char type, unsigned char* sni, unsigned int* inOutSz);
|
||||
|
||||
#endif /* NO_CYASSL_SERVER */
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
|
|
10
src/ssl.c
10
src/ssl.c
|
@ -568,6 +568,16 @@ word16 CyaSSL_SNI_GetRequest(CYASSL* ssl, byte type, void** data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CyaSSL_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz, byte type,
|
||||
byte* sni, word32* inOutSz)
|
||||
{
|
||||
if (buffer && bufferSz > 0 && sni && inOutSz && inOutSz > 0)
|
||||
return TLSX_SNI_GetFromBuffer(buffer, bufferSz, type, sni, inOutSz);
|
||||
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#endif /* NO_CYASSL_SERVER */
|
||||
|
||||
#endif /* HAVE_SNI */
|
||||
|
|
124
src/tls.c
124
src/tls.c
|
@ -376,6 +376,14 @@ static INLINE void ato16(const byte* c, word16* u16)
|
|||
{
|
||||
*u16 = (c[0] << 8) | (c[1]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
/* convert a 24 bit integer into a 32 bit one */
|
||||
static INLINE void c24to32(const word24 u24, word32* u32)
|
||||
{
|
||||
*u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* convert 32 bit integer to opaque */
|
||||
|
@ -854,6 +862,122 @@ void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
|
|||
if (sni)
|
||||
sni->options = options;
|
||||
}
|
||||
|
||||
int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz,
|
||||
byte type, byte* sni, word32* inOutSz)
|
||||
{
|
||||
word32 offset = 0;
|
||||
word32 len32 = 0;
|
||||
word16 len16 = 0;
|
||||
|
||||
if (bufferSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
/* TLS record header */
|
||||
if ((enum ContentType) buffer[offset++] != handshake)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (buffer[offset++] != SSLv3_MAJOR)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (buffer[offset++] < TLSv1_MINOR)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
ato16(buffer + offset, &len16);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (offset + len16 > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
/* Handshake header */
|
||||
if ((enum HandShakeType) buffer[offset] != client_hello)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
c24to32(buffer + offset + 1, &len32);
|
||||
offset += HANDSHAKE_HEADER_SZ;
|
||||
|
||||
if (offset + len32 > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
/* client hello */
|
||||
offset += VERSION_SZ + RAN_LEN; /* version, random */
|
||||
|
||||
if (offset + buffer[offset] > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
offset += ENUM_LEN + buffer[offset]; /* session id */
|
||||
|
||||
ato16(buffer + offset, &len16);
|
||||
offset += OPAQUE16_LEN; /* cypher suites len */
|
||||
|
||||
if (offset + len16 > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
offset += len16; /* cypher suites */
|
||||
|
||||
if (offset + buffer[offset] > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
offset += ENUM_LEN + buffer[offset]; /* compression methods */
|
||||
|
||||
ato16(buffer + offset, &len16);
|
||||
offset += OPAQUE16_LEN; /* EXTENSIONS LEN */
|
||||
|
||||
if (offset + len16 > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
while (len16 > OPAQUE16_LEN + OPAQUE16_LEN) {
|
||||
word16 extType;
|
||||
word16 extLen;
|
||||
|
||||
ato16(buffer + offset, &extType);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
ato16(buffer + offset, &extLen);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (offset + extLen > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
if (extType != SERVER_NAME_INDICATION) {
|
||||
offset += extLen;
|
||||
continue;
|
||||
} else {
|
||||
word16 listLen;
|
||||
|
||||
ato16(buffer + offset, &listLen);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (offset + listLen > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
while (listLen > ENUM_LEN + OPAQUE16_LEN) {
|
||||
byte sniType = buffer[offset++];
|
||||
word16 sniLen;
|
||||
|
||||
ato16(buffer + offset, &sniLen);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
if (offset + sniLen > bufferSz)
|
||||
return INCOMPLETE_DATA;
|
||||
|
||||
if (sniType != type) {
|
||||
offset += sniLen;
|
||||
continue;
|
||||
}
|
||||
|
||||
*inOutSz = min(sniLen, *inOutSz);
|
||||
XMEMCPY(sni, buffer + offset, *inOutSz);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SNI_FREE_ALL TLSX_SNI_FreeAll
|
||||
|
|
53
tests/api.c
53
tests/api.c
|
@ -332,6 +332,57 @@ static void verify_SNI_fake_matching(CYASSL* ssl)
|
|||
AssertStrEQ(name, request);
|
||||
}
|
||||
|
||||
static void test_CyaSSL_SNI_GetFromBuffer(void)
|
||||
{
|
||||
byte buffer[] = { /* api.textmate.org */
|
||||
0x16, 0x03, 0x01, 0x00, 0xc6, 0x01, 0x00, 0x00, 0xc2, 0x03, 0x03, 0x52,
|
||||
0x8b, 0x7b, 0xca, 0x69, 0xec, 0x97, 0xd5, 0x08, 0x03, 0x50, 0xfe, 0x3b,
|
||||
0x99, 0xc3, 0x20, 0xce, 0xa5, 0xf6, 0x99, 0xa5, 0x71, 0xf9, 0x57, 0x7f,
|
||||
0x04, 0x38, 0xf6, 0x11, 0x0b, 0xb8, 0xd3, 0x00, 0x00, 0x5e, 0x00, 0xff,
|
||||
0xc0, 0x24, 0xc0, 0x23, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x07, 0xc0, 0x08,
|
||||
0xc0, 0x28, 0xc0, 0x27, 0xc0, 0x14, 0xc0, 0x13, 0xc0, 0x11, 0xc0, 0x12,
|
||||
0xc0, 0x26, 0xc0, 0x25, 0xc0, 0x2a, 0xc0, 0x29, 0xc0, 0x05, 0xc0, 0x04,
|
||||
0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x0f, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x0d,
|
||||
0x00, 0x3d, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x05, 0x00, 0x04, 0x00, 0x35,
|
||||
0x00, 0x0a, 0x00, 0x67, 0x00, 0x6b, 0x00, 0x33, 0x00, 0x39, 0x00, 0x16,
|
||||
0x00, 0xaf, 0x00, 0xae, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0x8a, 0x00, 0x8b,
|
||||
0x00, 0xb1, 0x00, 0xb0, 0x00, 0x2c, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x3b,
|
||||
0x00, 0x00, 0x00, 0x15, 0x00, 0x13, 0x00, 0x00, 0x10, 0x61, 0x70, 0x69,
|
||||
0x2e, 0x74, 0x65, 0x78, 0x74, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x6f, 0x72,
|
||||
0x67, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
|
||||
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x0c, 0x00,
|
||||
0x0a, 0x05, 0x01, 0x04, 0x01, 0x02, 0x01, 0x04, 0x03, 0x02, 0x03
|
||||
};
|
||||
|
||||
byte buffer2[] = { /* www.paypal.com */
|
||||
0x16, 0x03, 0x03, 0x00, 0x64, 0x01, 0x00, 0x00, 0x60, 0x03, 0x03, 0x5c,
|
||||
0xc4, 0xb3, 0x8c, 0x87, 0xef, 0xa4, 0x09, 0xe0, 0x02, 0xab, 0x86, 0xca,
|
||||
0x76, 0xf0, 0x9e, 0x01, 0x65, 0xf6, 0xa6, 0x06, 0x13, 0x1d, 0x0f, 0xa5,
|
||||
0x79, 0xb0, 0xd4, 0x77, 0x22, 0xeb, 0x1a, 0x00, 0x00, 0x16, 0x00, 0x6b,
|
||||
0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0x00, 0x3d, 0x00, 0x3c, 0x00, 0x35,
|
||||
0x00, 0x2f, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x21,
|
||||
0x00, 0x00, 0x00, 0x13, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x77, 0x77, 0x77,
|
||||
0x2e, 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x02, 0x01
|
||||
};
|
||||
|
||||
byte result[32] = {0};
|
||||
word32 length = 32;
|
||||
|
||||
// AssertIntEQ(-228, CyaSSL_SNI_GetFromBuffer((const byte*) "\x16\x03\x00\x00\x01", 5, 0,
|
||||
// result, &length));
|
||||
|
||||
AssertIntEQ(0, CyaSSL_SNI_GetFromBuffer(buffer, sizeof(buffer), 0, result,
|
||||
&length));
|
||||
result[length] = 0;
|
||||
AssertStrEQ("api.textmate.org", (const char*) result);
|
||||
|
||||
AssertIntEQ(0, CyaSSL_SNI_GetFromBuffer(buffer2, sizeof(buffer2), 0, result,
|
||||
&length));
|
||||
result[length] = 0;
|
||||
AssertStrEQ("www.paypal.com", (const char*) result);
|
||||
}
|
||||
|
||||
void test_CyaSSL_UseSNI(void)
|
||||
{
|
||||
callback_functions client_callbacks = {CyaSSLv23_client_method, 0, 0, 0};
|
||||
|
@ -390,6 +441,8 @@ void test_CyaSSL_UseSNI(void)
|
|||
server_callbacks.on_result = verify_SNI_fake_matching;
|
||||
|
||||
test_CyaSSL_client_server(&client_callbacks, &server_callbacks);
|
||||
|
||||
test_CyaSSL_SNI_GetFromBuffer();
|
||||
}
|
||||
#endif /* HAVE_SNI */
|
||||
|
||||
|
|
Loading…
Reference in New Issue