diff options
Diffstat (limited to 'test/ssl.t.c')
| -rw-r--r-- | test/ssl.t.c | 806 |
1 files changed, 806 insertions, 0 deletions
diff --git a/test/ssl.t.c b/test/ssl.t.c new file mode 100644 index 0000000..52bef29 --- /dev/null +++ b/test/ssl.t.c @@ -0,0 +1,806 @@ +/*- + * SSLsplit - transparent SSL/TLS interception + * https://www.roe.ch/SSLsplit + * + * Copyright (c) 2009-2018, Daniel Roethlisberger <[email protected]>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "base64.h" +#include "ssl.h" + +#include <stdlib.h> + +#include <check.h> + +#define TESTKEY "extra/pki/server.key" +#define TESTCERT "extra/pki/server.crt" +#define TESTCERT2 "extra/pki/rsa.crt" + +static void +ssl_setup(void) +{ + if (ssl_init() == -1) + exit(EXIT_FAILURE); +} + +static void +ssl_teardown(void) +{ + ssl_fini(); +} + +static char wildcard1[] = "*.example.org"; +static char wildcard2[] = "www.*.example.org"; +static char wildcard3[] = "*.*.org"; +static char wildcard4[] = "www*.example.org"; +static char wildcard5[] = "*"; +static char wildcard6[] = "*.xn--r-1ga.ch"; +static char wildcard7[] = "xn--r-1ga*.xn--r-1ga.ch"; +static char wildcard8[] = "xn--r-1ga.*.xn--r-1ga.ch"; +static char name1[] = "www.example.org"; +static char name2[] = "www.example.com"; +static char name3[] = "example.org"; +static char name4[] = "www.example.org.co.uk"; +static char name5[] = "test.www.example.org"; +static char name6[] = "www.test.example.org"; +static char name7[] = "wwwtest.example.org"; +static char name8[] = "ch"; +static char name9[] = "www.xn--r-1ga.ch"; +static char name10[] = "xn--r-1ga.xn--r-1ga.ch"; +static char name11[] = ""; + +START_TEST(ssl_wildcardify_01) +{ + char *wc = ssl_wildcardify(name1); + fail_unless(!strcmp(wc, wildcard1), "mismatch for 'www.example.org'"); + free(wc); +} +END_TEST + +START_TEST(ssl_wildcardify_02) +{ + char *wc = ssl_wildcardify(name8); + fail_unless(!strcmp(wc, wildcard5), "mismatch for 'ch'"); + free(wc); +} +END_TEST + +START_TEST(ssl_wildcardify_03) +{ + char *wc = ssl_wildcardify(name11); + fail_unless(!strcmp(wc, wildcard5), "mismatch for ''"); + free(wc); +} +END_TEST + +START_TEST(ssl_dnsname_match_01) +{ + fail_unless( + ssl_dnsname_match(name1, sizeof(name1) - 1, + name1, sizeof(name1) - 1), + "Hostname does not match itself"); +} +END_TEST + +START_TEST(ssl_dnsname_match_02) +{ + fail_unless( + !ssl_dnsname_match(name1, sizeof(name1) - 1, + name2, sizeof(name2) - 1), + "Hostname matches hostname with different TLD"); +} +END_TEST + +START_TEST(ssl_dnsname_match_03) +{ + fail_unless( + ssl_dnsname_match(wildcard1, sizeof(wildcard1) - 1, + name1, sizeof(name1) - 1), + "Regular wildcard does not match"); +} +END_TEST + +START_TEST(ssl_dnsname_match_04) +{ + fail_unless( + !ssl_dnsname_match(wildcard1, sizeof(wildcard1) - 1, + name2, sizeof(name2) - 1), + "Regular wildcard matches other TLD"); +} +END_TEST + +START_TEST(ssl_dnsname_match_05) +{ + fail_unless( + !ssl_dnsname_match(wildcard1, sizeof(wildcard1) - 1, + name3, sizeof(name3) - 1), + "Regular wildcard matches upper level domain"); +} +END_TEST + +START_TEST(ssl_dnsname_match_06) +{ + fail_unless( + !ssl_dnsname_match(wildcard1, sizeof(wildcard1) - 1, + name4, sizeof(name4) - 1), + "Regular wildcard matches despite added suffix"); +} +END_TEST + +START_TEST(ssl_dnsname_match_07) +{ + fail_unless( + !ssl_dnsname_match(wildcard1, sizeof(wildcard1) - 1, + name5, sizeof(name5) - 1), + "Regular wildcard matches two elements"); +} +END_TEST + +START_TEST(ssl_dnsname_match_08) +{ + fail_unless( + !ssl_dnsname_match(wildcard2, sizeof(wildcard2) - 1, + name6, sizeof(name6) - 1), + "Wildcard matches in non-leftmost element"); +} +END_TEST + +START_TEST(ssl_dnsname_match_09) +{ + fail_unless( + !ssl_dnsname_match(wildcard3, sizeof(wildcard3) - 1, + name5, sizeof(name5) - 1), + "Multiple wildcard matches"); +} +END_TEST + +START_TEST(ssl_dnsname_match_10) +{ + fail_unless( + !ssl_dnsname_match(wildcard4, sizeof(wildcard4) - 1, + name7, sizeof(name7) - 1), + "Partial label wildcard matches"); +} +END_TEST + +START_TEST(ssl_dnsname_match_11) +{ + fail_unless( + !ssl_dnsname_match(wildcard5, sizeof(wildcard5) - 1, + name1, sizeof(name1) - 1), + "Global wildcard * matches fqdn"); +} +END_TEST + +START_TEST(ssl_dnsname_match_12) +{ + fail_unless( + ssl_dnsname_match(wildcard5, sizeof(wildcard5) - 1, + name8, sizeof(name8) - 1), + "Global wildcard * does not match TLD"); +} +END_TEST + +START_TEST(ssl_dnsname_match_13) +{ + fail_unless( + ssl_dnsname_match(wildcard6, sizeof(wildcard6) - 1, + name9, sizeof(name9) - 1), + "IDN wildcard does not match"); +} +END_TEST + +START_TEST(ssl_dnsname_match_14) +{ + fail_unless( + ssl_dnsname_match(wildcard6, sizeof(wildcard6) - 1, + name10, sizeof(name10) - 1), + "IDN wildcard does not match IDN element"); +} +END_TEST + +START_TEST(ssl_dnsname_match_15) +{ + fail_unless( + !ssl_dnsname_match(wildcard7, sizeof(wildcard7) - 1, + name10, sizeof(name10) - 1), + "Illegal IDN wildcard matches"); +} +END_TEST + +START_TEST(ssl_dnsname_match_16) +{ + fail_unless( + !ssl_dnsname_match(wildcard8, sizeof(wildcard8) - 1, + name10, sizeof(name10) - 1), + "Illegal IDN wildcard matches IDN element"); +} +END_TEST + +static unsigned char clienthello00[] = + "\x80\x2b\x01\x00\x02\x00\x12\x00\x00\x00\x10\x07\x00\xc0\x03\x00" + "\x80\x01\x00\x80\x06\x00\x40\x04\x00\x80\x02\x00\x80\xe0\xc3\x4a" + "\xc6\xa4\x89\x23\x21\xb1\xbb\x51\xc7\x9c\x06\xa5\xff"; + /* SSL 2.0 */ + +static unsigned char clienthello01[] = + "\x80\x67\x01\x03\x00\x00\x4e\x00\x00\x00\x10\x01\x00\x80\x03\x00" + "\x80\x07\x00\xc0\x06\x00\x40\x02\x00\x80\x04\x00\x80\x00\x00\x39" + "\x00\x00\x38\x00\x00\x35\x00\x00\x33\x00\x00\x32\x00\x00\x04\x00" + "\x00\x05\x00\x00\x2f\x00\x00\x16\x00\x00\x13\x00\xfe\xff\x00\x00" + "\x0a\x00\x00\x15\x00\x00\x12\x00\xfe\xfe\x00\x00\x09\x00\x00\x64" + "\x00\x00\x62\x00\x00\x03\x00\x00\x06\xa8\xb8\x93\xbb\x90\xe9\x2a" + "\xa2\x4d\x6d\xcc\x1c\xe7\x2a\x80\x21"; + /* SSL 3.0 in SSL 2.0 record */ + +static unsigned char clienthello02[] = + "\x16\x03\x00\x00\x73\x01\x00\x00\x6f\x03\x00\x00\x34\x01\x1e\x67" + "\x3a\xfa\xce\xd9\x51\xba\xe4\xfc\x64\x95\x03\x82\x63\x0f\xe3\x39" + "\x6b\xc7\xbd\x2b\xe5\x51\x37\x23\x48\x5b\xfb\x20\xa3\xca\xad\x46" + "\x95\x5d\x64\xbb\x33\xec\xb5\x12\x91\x21\xa3\x50\xd2\xc0\xc5\xf6" + "\x67\xc3\xcc\x9e\xc0\x4a\x71\x1b\x92\xdc\x58\x55\x00\x28\x00\x39" + "\x00\x38\x00\x35\x00\x33\x00\x32\x00\x04\x00\x05\x00\x2f\x00\x16" + "\x00\x13\xfe\xff\x00\x0a\x00\x15\x00\x12\xfe\xfe\x00\x09\x00\x64" + "\x00\x62\x00\x03\x00\x06\x01\x00"; + /* SSL 3.0, no TLS extensions */ + +static unsigned char clienthello03[] = + "\x16\x03\x01\x00\x9b\x01\x00\x00\x97\x03\x01\x4b\x99\x46\xac\x38" + "\x08\xbb\xa7\x1c\x9b\xea\x79\xc5\xd6\x70\x3d\xed\x20\x80\x60\xb4" + "\x7e\xb5\x07\x13\xcf\x9a\x1c\xec\x6f\x64\xe5\x00\x00\x46\xc0\x0a" + "\xc0\x09\xc0\x07\xc0\x08\xc0\x13\xc0\x14\xc0\x11\xc0\x12\xc0\x04" + "\xc0\x05\xc0\x02\xc0\x03\xc0\x0e\xc0\x0f\xc0\x0c\xc0\x0d\x00\x2f" + "\x00\x05\x00\x04\x00\x35\x00\x0a\x00\x09\x00\x03\x00\x08\x00\x06" + "\x00\x32\x00\x33\x00\x38\x00\x39\x00\x16\x00\x15\x00\x14\x00\x13" + "\x00\x12\x00\x11\x01\x00\x00\x28\x00\x00\x00\x12\x00\x10\x00\x00" + "\x0d\x31\x39\x32\x2e\x31\x36\x38\x2e\x31\x30\x30\x2e\x34\x00\x0a" + "\x00\x08\x00\x06\x00\x17\x00\x18\x00\x19\x00\x0b\x00\x02\x01\x00"; + /* TLS 1.0, SNI extension with hostname "192.168.100.4"; + * Note: IP addresses are not legal values */ + +static unsigned char clienthello04[] = + "\x16\x03\x01\x00\x6c\x01\x00\x00\x68\x03\x01\x4a\x9d\x49\x75\xb2" + "\x7e\xf9\xbc\xc3\x76\xac\x19\x78\xfb\x6a\xee\x50\x55\x5e\x35\x4c" + "\xca\xf2\x21\x15\xf3\x8a\x2a\xfc\xb5\x35\xed\x00\x00\x28\x00\x39" + "\x00\x38\x00\x35\x00\x16\x00\x13\x00\x0a\x00\x33\x00\x32\x00\x2f" + "\x00\x07\x00\x05\x00\x04\x00\x15\x00\x12\x00\x09\x00\x14\x00\x11" + "\x00\x08\x00\x06\x00\x03\x01\x00\x00\x17\x00\x00\x00\x0f\x00\x0d" + "\x00\x00\x0a\x6b\x61\x6d\x65\x73\x68\x2e\x63\x6f\x6d\x00\x23\x00" + "\x00"; + /* TLS 1.0, SNI extension with hostname "kamesh.com" */ + +static unsigned char clienthello05[] = + "\x16\x03\x03\x01\x7d\x01\x00\x01\x79\x03\x03\x4f\x7f\x27\xd0\x76" + "\x5f\xc1\x3b\xba\x73\xd5\x07\x8b\xd9\x79\xf9\x51\xd4\xce\x7d\x9a" + "\xdb\xdf\xf8\x4e\x95\x86\x38\x61\xdd\x84\x2a\x00\x00\xca\xc0\x30" + "\xc0\x2c\xc0\x28\xc0\x24\xc0\x14\xc0\x0a\xc0\x22\xc0\x21\x00\xa3" + "\x00\x9f\x00\x6b\x00\x6a\x00\x39\x00\x38\x00\x88\x00\x87\xc0\x19" + "\xc0\x20\x00\xa7\x00\x6d\x00\x3a\x00\x89\xc0\x32\xc0\x2e\xc0\x2a" + "\xc0\x26\xc0\x0f\xc0\x05\x00\x9d\x00\x3d\x00\x35\x00\x84\xc0\x12" + "\xc0\x08\xc0\x1c\xc0\x1b\x00\x16\x00\x13\xc0\x17\xc0\x1a\x00\x1b" + "\xc0\x0d\xc0\x03\x00\x0a\xc0\x2f\xc0\x2b\xc0\x27\xc0\x23\xc0\x13" + "\xc0\x09\xc0\x1f\xc0\x1e\x00\xa2\x00\x9e\x00\x67\x00\x40\x00\x33" + "\x00\x32\x00\x9a\x00\x99\x00\x45\x00\x44\xc0\x18\xc0\x1d\x00\xa6" + "\x00\x6c\x00\x34\x00\x9b\x00\x46\xc0\x31\xc0\x2d\xc0\x29\xc0\x25" + "\xc0\x0e\xc0\x04\x00\x9c\x00\x3c\x00\x2f\x00\x96\x00\x41\x00\x07" + "\xc0\x11\xc0\x07\xc0\x16\x00\x18\xc0\x0c\xc0\x02\x00\x05\x00\x04" + "\x00\x15\x00\x12\x00\x1a\x00\x09\x00\x14\x00\x11\x00\x19\x00\x08" + "\x00\x06\x00\x17\x00\x03\x00\xff\x02\x01\x00\x00\x85\x00\x00\x00" + "\x12\x00\x10\x00\x00\x0d\x64\x61\x6e\x69\x65\x6c\x2e\x72\x6f\x65" + "\x2e\x63\x68\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x34\x00" + "\x32\x00\x0e\x00\x0d\x00\x19\x00\x0b\x00\x0c\x00\x18\x00\x09\x00" + "\x0a\x00\x16\x00\x17\x00\x08\x00\x06\x00\x07\x00\x14\x00\x15\x00" + "\x04\x00\x05\x00\x12\x00\x13\x00\x01\x00\x02\x00\x03\x00\x0f\x00" + "\x10\x00\x11\x00\x23\x00\x00\x00\x0d\x00\x22\x00\x20\x06\x01\x06" + "\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03" + "\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x01\x01\x00\x0f\x00" + "\x01\x01"; + /* TLS 1.2, SNI extension with hostname "daniel.roe.ch" */ + +static unsigned char clienthello06[] = + "I will start TLS now: " + "\x16\x03\x03\x01\x7d\x01\x00\x01\x79\x03\x03\x4f\x7f\x27\xd0\x76" + "\x5f\xc1\x3b\xba\x73\xd5\x07\x8b\xd9\x79\xf9\x51\xd4\xce\x7d\x9a" + "\xdb\xdf\xf8\x4e\x95\x86\x38\x61\xdd\x84\x2a\x00\x00\xca\xc0\x30" + "\xc0\x2c\xc0\x28\xc0\x24\xc0\x14\xc0\x0a\xc0\x22\xc0\x21\x00\xa3" + "\x00\x9f\x00\x6b\x00\x6a\x00\x39\x00\x38\x00\x88\x00\x87\xc0\x19" + "\xc0\x20\x00\xa7\x00\x6d\x00\x3a\x00\x89\xc0\x32\xc0\x2e\xc0\x2a" + "\xc0\x26\xc0\x0f\xc0\x05\x00\x9d\x00\x3d\x00\x35\x00\x84\xc0\x12" + "\xc0\x08\xc0\x1c\xc0\x1b\x00\x16\x00\x13\xc0\x17\xc0\x1a\x00\x1b" + "\xc0\x0d\xc0\x03\x00\x0a\xc0\x2f\xc0\x2b\xc0\x27\xc0\x23\xc0\x13" + "\xc0\x09\xc0\x1f\xc0\x1e\x00\xa2\x00\x9e\x00\x67\x00\x40\x00\x33" + "\x00\x32\x00\x9a\x00\x99\x00\x45\x00\x44\xc0\x18\xc0\x1d\x00\xa6" + "\x00\x6c\x00\x34\x00\x9b\x00\x46\xc0\x31\xc0\x2d\xc0\x29\xc0\x25" + "\xc0\x0e\xc0\x04\x00\x9c\x00\x3c\x00\x2f\x00\x96\x00\x41\x00\x07" + "\xc0\x11\xc0\x07\xc0\x16\x00\x18\xc0\x0c\xc0\x02\x00\x05\x00\x04" + "\x00\x15\x00\x12\x00\x1a\x00\x09\x00\x14\x00\x11\x00\x19\x00\x08" + "\x00\x06\x00\x17\x00\x03\x00\xff\x02\x01\x00\x00\x85\x00\x00\x00" + "\x12\x00\x10\x00\x00\x0d\x64\x61\x6e\x69\x65\x6c\x2e\x72\x6f\x65" + "\x2e\x63\x68\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x34\x00" + "\x32\x00\x0e\x00\x0d\x00\x19\x00\x0b\x00\x0c\x00\x18\x00\x09\x00" + "\x0a\x00\x16\x00\x17\x00\x08\x00\x06\x00\x07\x00\x14\x00\x15\x00" + "\x04\x00\x05\x00\x12\x00\x13\x00\x01\x00\x02\x00\x03\x00\x0f\x00" + "\x10\x00\x11\x00\x23\x00\x00\x00\x0d\x00\x22\x00\x20\x06\x01\x06" + "\x02\x06\x03\x05\x01\x05\x02\x05\x03\x04\x01\x04\x02\x04\x03\x03" + "\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02\x03\x01\x01\x00\x0f\x00" + "\x01\x01"; + /* TLS 1.2, SNI extension with hostname "daniel.roe.ch" */ + +START_TEST(ssl_tls_clienthello_parse_00) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = (void *)0xDEADBEEF; + + rv = ssl_tls_clienthello_parse(clienthello00, + sizeof(clienthello00) - 1, + 0, &ch, &sni); +#ifdef HAVE_SSLV2 + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni == NULL, "sni not NULL"); +#else /* !HAVE_SSLV2 */ + fail_unless(rv == 1, "rv not 1"); + fail_unless(ch == NULL, "ch not NULL"); + fail_unless(sni == (void*)0xDEADBEEF, "sni modified"); +#endif /* !HAVE_SSLV2 */ +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_01) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = (void *)0xDEADBEEF; + + rv = ssl_tls_clienthello_parse(clienthello01, + sizeof(clienthello01) - 1, + 0, &ch, &sni); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni == NULL, "sni not NULL"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_02) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = (void *)0xDEADBEEF; + + rv = ssl_tls_clienthello_parse(clienthello02, + sizeof(clienthello02) - 1, + 0, &ch, &sni); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni == NULL, "sni not NULL"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_03) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = NULL; + + rv = ssl_tls_clienthello_parse(clienthello03, + sizeof(clienthello03) - 1, + 0, &ch, &sni); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni && !strcmp(sni, "192.168.100.4"), + "sni not '192.168.100.4' but should be"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_04) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = NULL; + + rv = ssl_tls_clienthello_parse(clienthello04, + sizeof(clienthello04) - 1, + 0, &ch, &sni); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni && !strcmp(sni, "kamesh.com"), + "sni not 'kamesh.com' but should be"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_05) +{ + for (size_t i = 0; i < sizeof(clienthello04) - 1; i++) { + int rv; + const unsigned char *ch = NULL; + char *sni = (void*)0xDEADBEEF; + ssize_t sz; + + sz = (ssize_t)i; + rv = ssl_tls_clienthello_parse(clienthello04, sz, 0, &ch, &sni); + fail_unless(rv == 1, "rv not 1"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni == (void*)0xDEADBEEF, "sni modified"); + } +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_06) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = NULL; + + rv = ssl_tls_clienthello_parse(clienthello05, + sizeof(clienthello05) - 1, + 0, &ch, &sni); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni && !strcmp(sni, "daniel.roe.ch"), + "sni not 'daniel.roe.ch' but should be"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_07) +{ + for (size_t i = 0; i < sizeof(clienthello05) - 1; i++) { + int rv; + const unsigned char *ch = NULL; + char *sni = (void*)0xDEADBEEF; + ssize_t sz; + + sz = (ssize_t)i; + rv = ssl_tls_clienthello_parse(clienthello05, sz, 0, &ch, &sni); + fail_unless(rv == 1, "rv not 1"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless(sni == (void*)0xDEADBEEF, "sni modified"); + } +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_08) +{ + int rv; + const unsigned char *ch = (void *)0xDEADBEEF; + char *sni = (void *)0xDEADBEEF; + + rv = ssl_tls_clienthello_parse(clienthello06, + sizeof(clienthello06) - 1, + 0, &ch, &sni); + fail_unless(rv == 1, "rv not 1"); + fail_unless(ch == NULL, "ch not NULL"); + fail_unless(sni == (void*)0xDEADBEEF, "sni modified"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_09) +{ + int rv; + const unsigned char *ch = NULL; + char *sni = NULL; + + rv = ssl_tls_clienthello_parse(clienthello06, + sizeof(clienthello06) - 1, + 1, &ch, &sni); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless((ch - clienthello06) != 21, "ch does not point to start"); + fail_unless(sni && !strcmp(sni, "daniel.roe.ch"), + "sni not 'daniel.roe.ch' but should be"); +} +END_TEST + +START_TEST(ssl_tls_clienthello_parse_10) +{ + int rv; + const unsigned char *ch = NULL; + + rv = ssl_tls_clienthello_parse(clienthello06, + sizeof(clienthello06) - 1, + 1, &ch, NULL); + fail_unless(rv == 0, "rv not 0"); + fail_unless(ch != NULL, "ch is NULL"); + fail_unless((ch - clienthello06) != 21, "ch does not point to start"); +} +END_TEST + +START_TEST(ssl_key_identifier_sha1_01) +{ + X509 *c; + EVP_PKEY *k; + unsigned char keyid[SSL_KEY_IDSZ]; + + c = ssl_x509_load(TESTCERT); + fail_unless(!!c, "loading certificate failed"); + k = ssl_key_load(TESTKEY); + fail_unless(!!k, "loading key failed"); + + fail_unless(ssl_key_identifier_sha1(k, keyid) == 0, + "ssl_key_identifier_sha1() failed"); + + int loc = X509_get_ext_by_NID(c, NID_subject_key_identifier, -1); + X509_EXTENSION *ext = X509_get_ext(c, loc); + fail_unless(!!ext, "loading ext failed"); + ASN1_STRING *value = X509_EXTENSION_get_data(ext); + fail_unless(ASN1_STRING_length(value) - 2 == SSL_KEY_IDSZ, + "extension length mismatch"); + fail_unless(!memcmp(ASN1_STRING_get0_data(value) + 2, keyid, SSL_KEY_IDSZ), + "key id mismatch"); +} +END_TEST + +START_TEST(ssl_x509_names_01) +{ + X509 *c; + char **names, **p; + + c = ssl_x509_load(TESTCERT); + fail_unless(!!c, "loading certificate failed"); + names = ssl_x509_names(c); + fail_unless(!!names, "parsing names failed"); + fail_unless(!!names[0], "first name"); + fail_unless(!strcmp(names[0], "daniel.roe.ch"), "first name"); + fail_unless(!!names[1], "second name"); + fail_unless(!strcmp(names[1], "daniel.roe.ch"), "second name"); + fail_unless(!!names[2], "third name"); + fail_unless(!strcmp(names[2], "www.roe.ch"), "third name"); + fail_unless(!!names[3], "fourth name"); + fail_unless(!strcmp(names[3], "*.roe.ch"), "fourth name"); + fail_unless(!names[4], "too many names"); + p = names; + while (*p) + free(*p++); + free(names); + X509_free(c); +} +END_TEST + +START_TEST(ssl_x509_names_to_str_01) +{ + X509 *c; + char *names; + + c = ssl_x509_load(TESTCERT); + fail_unless(!!c, "loading certificate failed"); + names = ssl_x509_names_to_str(c); + fail_unless(!!names, "no string"); + fail_unless(!strcmp(names, + "daniel.roe.ch/daniel.roe.ch/www.roe.ch/*.roe.ch"), + "wrong name string"); + X509_free(c); +} +END_TEST + +START_TEST(ssl_x509_names_to_str_02) +{ + X509 *c; + char *names; + + c = ssl_x509_load(TESTCERT2); + fail_unless(!!c, "loading certificate failed"); + names = ssl_x509_names_to_str(c); + fail_unless(!!names, "no string"); + fail_unless(!strcmp(names, "SSLsplit Root CA"), "wrong name string"); + X509_free(c); +} +END_TEST + +START_TEST(ssl_x509_subject_01) +{ + X509 *c; + char *subject; + + c = ssl_x509_load(TESTCERT); + fail_unless(!!c, "loading certificate failed"); + subject = ssl_x509_subject(c); + fail_unless(!!subject, "no string"); + fail_unless(!strcmp(subject, "/C=CH/O=SSLsplit Test Certificate/" + "CN=daniel.roe.ch"), + "wrong subject string"); + X509_free(c); +} +END_TEST + +START_TEST(ssl_x509_subject_cn_01) +{ + X509 *c; + char *cn; + size_t sz; + size_t expsz = strlen("daniel.roe.ch") + 1; + + c = ssl_x509_load(TESTCERT); + fail_unless(!!c, "loading certificate failed"); + cn = ssl_x509_subject_cn(c, &sz); + fail_unless(!!cn, "no string"); + fail_unless(sz >= expsz, "subject CN size too small"); + fail_unless(!strcmp(cn, "daniel.roe.ch"), "wrong subject CN string"); +#if 0 + for (unsigned int i = expsz; i < sz; i++) { + fail_unless(cn[i] == '\0', "extra byte != 0"); + } +#endif + X509_free(c); +} +END_TEST + +START_TEST(ssl_x509_ocsps_01) +{ + X509 *c; + char **ocsps, **p; + + c = ssl_x509_load(TESTCERT); + fail_unless(!!c, "loading certificate failed"); + ocsps = ssl_x509_ocsps(c); + fail_unless(!!ocsps, "parsing OCSP extensions failed"); + fail_unless(!!ocsps[0], "first OCSP"); + fail_unless(!strcmp(ocsps[0], "http://daniel.roe.ch/test/ocsp"), + "first OCSP"); + fail_unless(!ocsps[1], "too many OCSPs"); + p = ocsps; + while (*p) + free(*p++); + free(ocsps); + X509_free(c); +} +END_TEST + +START_TEST(ssl_x509_ocsps_02) +{ + X509 *c; + char **ocsps; + + c = ssl_x509_load(TESTCERT2); + fail_unless(!!c, "loading certificate failed"); + ocsps = ssl_x509_ocsps(c); + fail_unless(!ocsps, "unexpected OCSP extensions"); + X509_free(c); +} +END_TEST + +static char ocspreq01[] = + "MEIwQDA+MDwwOjAJBgUrDgMCGgUABBT4cyABkyiCIhU4JpmIB" + "ewdDnn8ZgQUbyBZ44kgy35o7xW5BMzM8FTvyTwCAQE="; + +START_TEST(ssl_is_ocspreq_01) +{ + unsigned char *buf; + size_t sz; + + buf = base64_dec(ocspreq01, sizeof(ocspreq01) - 1, &sz); + fail_unless(!!buf, "failed to base64 decode"); + fail_unless(ssl_is_ocspreq(buf, sz), "is not ocsp req"); +} +END_TEST + +START_TEST(ssl_features_01) +{ + long vdiff = ((OPENSSL_VERSION_NUMBER ^ SSLeay()) & 0xfffff000L); + + fail_unless(!vdiff, "OpenSSL version mismatch at runtime"); +} +END_TEST + +START_TEST(ssl_features_02) +{ + int have_threads = 0; +#ifdef OPENSSL_THREADS + have_threads = 1; +#endif /* OPENSSL_THREADS */ + fail_unless(have_threads, "!OPENSSL_THREADS: no threading support"); +} +END_TEST + +Suite * +ssl_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("ssl"); + + tc = tcase_create("ssl_wildcardify"); + tcase_add_test(tc, ssl_wildcardify_01); + tcase_add_test(tc, ssl_wildcardify_02); + tcase_add_test(tc, ssl_wildcardify_03); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_dnsname_match"); + tcase_add_test(tc, ssl_dnsname_match_01); + tcase_add_test(tc, ssl_dnsname_match_02); + tcase_add_test(tc, ssl_dnsname_match_03); + tcase_add_test(tc, ssl_dnsname_match_04); + tcase_add_test(tc, ssl_dnsname_match_05); + tcase_add_test(tc, ssl_dnsname_match_06); + tcase_add_test(tc, ssl_dnsname_match_07); + tcase_add_test(tc, ssl_dnsname_match_08); + tcase_add_test(tc, ssl_dnsname_match_09); + tcase_add_test(tc, ssl_dnsname_match_10); + tcase_add_test(tc, ssl_dnsname_match_11); + tcase_add_test(tc, ssl_dnsname_match_12); + tcase_add_test(tc, ssl_dnsname_match_13); + tcase_add_test(tc, ssl_dnsname_match_14); + tcase_add_test(tc, ssl_dnsname_match_15); + tcase_add_test(tc, ssl_dnsname_match_16); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_tls_clienthello_parse"); + tcase_add_test(tc, ssl_tls_clienthello_parse_00); + tcase_add_test(tc, ssl_tls_clienthello_parse_01); + tcase_add_test(tc, ssl_tls_clienthello_parse_02); + tcase_add_test(tc, ssl_tls_clienthello_parse_03); + tcase_add_test(tc, ssl_tls_clienthello_parse_04); + tcase_add_test(tc, ssl_tls_clienthello_parse_05); + tcase_add_test(tc, ssl_tls_clienthello_parse_06); + tcase_add_test(tc, ssl_tls_clienthello_parse_07); + tcase_add_test(tc, ssl_tls_clienthello_parse_08); + tcase_add_test(tc, ssl_tls_clienthello_parse_09); + tcase_add_test(tc, ssl_tls_clienthello_parse_10); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_key_identifier_sha1"); + tcase_add_checked_fixture(tc, ssl_setup, ssl_teardown); + tcase_add_test(tc, ssl_key_identifier_sha1_01); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_x509_names"); + tcase_add_checked_fixture(tc, ssl_setup, ssl_teardown); + tcase_add_test(tc, ssl_x509_names_01); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_x509_names_to_str"); + tcase_add_checked_fixture(tc, ssl_setup, ssl_teardown); + tcase_add_test(tc, ssl_x509_names_to_str_01); + tcase_add_test(tc, ssl_x509_names_to_str_02); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_x509_subject"); + tcase_add_checked_fixture(tc, ssl_setup, ssl_teardown); + tcase_add_test(tc, ssl_x509_subject_01); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_x509_subject_cn"); + tcase_add_checked_fixture(tc, ssl_setup, ssl_teardown); + tcase_add_test(tc, ssl_x509_subject_cn_01); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_x509_ocsps"); + tcase_add_checked_fixture(tc, ssl_setup, ssl_teardown); + tcase_add_test(tc, ssl_x509_ocsps_01); + tcase_add_test(tc, ssl_x509_ocsps_02); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_is_ocspreq"); + tcase_add_test(tc, ssl_is_ocspreq_01); + suite_add_tcase(s, tc); + + tc = tcase_create("ssl_features"); + tcase_add_test(tc, ssl_features_01); + tcase_add_test(tc, ssl_features_02); + suite_add_tcase(s, tc); + + return s; +} + +/* vim: set noet ft=c: */ |
