1 /*-
2 * SSLsplit - transparent SSL/TLS interception
3 * https://www.roe.ch/SSLsplit
4 *
5 * Copyright (c) 2009-2019, Daniel Roethlisberger <daniel@roe.ch>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "ssl.h"
30 #include "cachemgr.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <netinet/in.h>
37 #include <time.h>
38
39 #include <check.h>
40
41 #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20501000L
42 #define TMP_SESS_FILE "extra/pki/session-libressl-2.5.0.pem"
43 #else
44 #define TMP_SESS_FILE "extra/pki/session.pem"
45 #endif
46
47 static SSL_SESSION *
ssl_session_from_file(const char * filename)48 ssl_session_from_file(const char *filename)
49 {
50 SSL_SESSION *sess;
51 FILE *f;
52
53 f = fopen(filename, "r");
54 if (!f)
55 return NULL;
56 sess = PEM_read_SSL_SESSION(f, NULL, NULL, NULL);
57 fclose(f);
58 /* to avoid having to regenerate the session, just bump its time */
59 SSL_SESSION_set_time(sess, time(NULL) - 1);
60 return sess;
61 }
62
63 static struct sockaddr_storage addr;
64 static socklen_t addrlen;
65 static char sni[] = "daniel.roe.ch";
66
67 static void
cachemgr_setup(void)68 cachemgr_setup(void)
69 {
70 if ((ssl_init() == -1) || (cachemgr_preinit() == -1))
71 exit(EXIT_FAILURE);
72 addrlen = sizeof(struct sockaddr_in);
73 memset(&addr, 0, addrlen);
74 addr.ss_family = AF_INET;
75 }
76
77 static void
cachemgr_teardown(void)78 cachemgr_teardown(void)
79 {
80 cachemgr_fini();
81 ssl_fini();
82 }
83
START_TEST(cache_dsess_01)84 START_TEST(cache_dsess_01)
85 {
86 SSL_SESSION *s1, *s2;
87
88 s1 = ssl_session_from_file(TMP_SESS_FILE);
89 fail_unless(!!s1, "creating session failed");
90 fail_unless(ssl_session_is_valid(s1), "session invalid");
91
92 cachemgr_dsess_set((struct sockaddr*)&addr, addrlen, sni, s1);
93 s2 = cachemgr_dsess_get((struct sockaddr*)&addr, addrlen, sni);
94 fail_unless(!!s2, "cache returned no session");
95 fail_unless(s2 != s1, "cache returned same pointer");
96 SSL_SESSION_free(s1);
97 SSL_SESSION_free(s2);
98 }
99 END_TEST
100
START_TEST(cache_dsess_02)101 START_TEST(cache_dsess_02)
102 {
103 SSL_SESSION *s1, *s2;
104
105 s1 = ssl_session_from_file(TMP_SESS_FILE);
106 fail_unless(!!s1, "creating session failed");
107 fail_unless(ssl_session_is_valid(s1), "session invalid");
108
109 s2 = cachemgr_dsess_get((struct sockaddr*)&addr, addrlen, sni);
110 fail_unless(s2 == NULL, "session was already in empty cache");
111 SSL_SESSION_free(s1);
112 }
113 END_TEST
114
START_TEST(cache_dsess_03)115 START_TEST(cache_dsess_03)
116 {
117 SSL_SESSION *s1, *s2;
118
119 s1 = ssl_session_from_file(TMP_SESS_FILE);
120 fail_unless(!!s1, "creating session failed");
121 fail_unless(ssl_session_is_valid(s1), "session invalid");
122
123 cachemgr_dsess_set((struct sockaddr*)&addr, addrlen, sni, s1);
124 cachemgr_dsess_del((struct sockaddr*)&addr, addrlen, sni);
125 s2 = cachemgr_dsess_get((struct sockaddr*)&addr, addrlen, sni);
126 fail_unless(s2 == NULL, "cache returned deleted session");
127 SSL_SESSION_free(s1);
128 }
129 END_TEST
130
131 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
START_TEST(cache_dsess_04)132 START_TEST(cache_dsess_04)
133 {
134 SSL_SESSION *s1, *s2;
135
136 s1 = ssl_session_from_file(TMP_SESS_FILE);
137 fail_unless(!!s1, "creating session failed");
138 fail_unless(ssl_session_is_valid(s1), "session invalid");
139
140 fail_unless(s1->references == 1, "refcount != 1");
141 cachemgr_dsess_set((struct sockaddr*)&addr, addrlen, sni, s1);
142 fail_unless(s1->references == 1, "refcount != 1");
143 s2 = cachemgr_dsess_get((struct sockaddr*)&addr, addrlen, sni);
144 fail_unless(s1->references == 1, "refcount != 1");
145 fail_unless(!!s2, "cache returned no session");
146 fail_unless(s2->references == 1, "refcount != 1");
147 cachemgr_dsess_set((struct sockaddr*)&addr, addrlen, sni, s1);
148 fail_unless(s1->references == 1, "refcount != 1");
149 cachemgr_dsess_del((struct sockaddr*)&addr, addrlen, sni);
150 fail_unless(s1->references == 1, "refcount != 1");
151 cachemgr_dsess_set((struct sockaddr*)&addr, addrlen, sni, s1);
152 fail_unless(s1->references == 1, "refcount != 1");
153 SSL_SESSION_free(s1);
154 SSL_SESSION_free(s2);
155 }
156 END_TEST
157 #endif
158
159 Suite *
cachedsess_suite(void)160 cachedsess_suite(void)
161 {
162 Suite *s;
163 TCase *tc;
164
165 s = suite_create("cachedsess");
166
167 tc = tcase_create("cache_dsess");
168 tcase_add_checked_fixture(tc, cachemgr_setup, cachemgr_teardown);
169 tcase_add_test(tc, cache_dsess_01);
170 tcase_add_test(tc, cache_dsess_02);
171 tcase_add_test(tc, cache_dsess_03);
172 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
173 tcase_add_test(tc, cache_dsess_04);
174 #endif
175 suite_add_tcase(s, tc);
176
177 return s;
178 }
179
180 /* vim: set noet ft=c: */
181