mirror of
https://github.com/sonertari/SSLproxy
synced 2024-11-04 12:00:15 +00:00
807 lines
25 KiB
C
807 lines
25 KiB
C
/*-
|
|
* SSLsplit - transparent SSL/TLS interception
|
|
* https://www.roe.ch/SSLsplit
|
|
*
|
|
* Copyright (c) 2009-2018, Daniel Roethlisberger <daniel@roe.ch>.
|
|
* 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: */
|