Skip to content

Commit 4cc70c2

Browse files
committed
fixup! Add client-side session caching
1 parent 5623de7 commit 4cc70c2

File tree

6 files changed

+146
-30
lines changed

6 files changed

+146
-30
lines changed

doc/man3/SSL_set1_cache_id.pod

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
=head1 NAME
44

55
SSL_set1_cache_id,
6-
SSL_get0_cache_id,
6+
SSL_get1_cache_id,
77
SSL_SESSION_set1_cache_id,
8-
SSL_SESSION_get0_cache_id,
8+
SSL_SESSION_get1_cache_id,
99
SSL_get1_previous_client_session - use application-defined cache identifier for session caching
1010

1111
=head1 SYNOPSIS
1212

1313
#include <openssl/ssl.h>
1414

1515
int SSL_set1_cache_id(SSL *s, const unsigned char *data, size_t len);
16-
int SSL_get0_cache_id(const SSL *s, const unsigned char **data, size_t *len);
16+
int SSL_get1_cache_id(const SSL *s, const unsigned char **data, size_t *len);
1717

1818
int SSL_SESSION_set1_cache_id(SSL_SESSION *ss, const unsigned char *data, size_t len);
19-
int SSL_SESSION_get0_cache_id(const SSL_SESSION *ss, const unsigned char **data, size_t *len);
19+
int SSL_SESSION_get1_cache_id(const SSL_SESSION *ss, const unsigned char **data, size_t *len);
2020

2121
int SSL_get1_previous_client_session(SSL *s, int flags);
2222

@@ -26,13 +26,13 @@ SSL_set1_cache_id() sets the cache identifier specified by B<data> and B<len>
2626
into B<s>. This cache identifier is application-defined, and can be a domain
2727
name, IP address, port or other identifier.
2828

29-
SSL_get0_cache_id() returns the cache identifier of B<s> into the B<data> and
29+
SSL_get1_cache_id() returns the cache identifier of B<s> into the B<data> and
3030
B<len> variables. The cache identifier is application-defined.
3131

3232
SSL_SESSION_set1_cache_id() sets the cache identifier specified by B<data> and B<len>
3333
into B<ss>. This cache identifier is application-defined.
3434

35-
SSL_SESSION_get0_cache_id() returns the cache identifier of B<ss> into the B<data> and
35+
SSL_SESSION_get1_cache_id() returns the cache identifier of B<ss> into the B<data> and
3636
B<len> variables. The cache identifier is application-defined.
3737

3838
SSL_get1_previous_client_session() is used to search for and return a
@@ -68,12 +68,14 @@ function can only be used on non-cached SSL_SESSIONs.
6868
SSL_set1_cache_id() and SSL_SESSION_set1_cache_id() should not be used by servers,
6969
the functions will fail.
7070

71+
The memory returned by SSL_get1_cache_id() and SSL_SESSION_get1_cache_id() must be freed.
72+
7173
=head1 RETURN VALUES
7274

73-
The SSL_set1_cache_id(), SSL_get0_cache_id(), SSL_SESSION_set1_cache_id() and
74-
SSL_SESSION_get0_cache_id() functions return 1 on success, 0 on failure.
75+
The SSL_set1_cache_id(), SSL_get1_cache_id(), SSL_SESSION_set1_cache_id() and
76+
SSL_SESSION_get1_cache_id() functions return 1 on success, 0 on failure.
7577

76-
The SSL_get0_cache_id() function fills in the B<data> and B<len> parameters
78+
The SSL_get1_cache_id() function fills in the B<data> and B<len> parameters
7779
with the data from the B<s>.
7880

7981
The SSL_get_previous_client_session() returns an SSL_SESSION on success, or NULL on
@@ -98,9 +100,9 @@ L<SSL_set_SSL_CTX(3)>,
98100
=head1 HISTORY
99101

100102
The SSL_set1_cache_id(),
101-
SSL_get0_cache_id(),
103+
SSL_get1_cache_id(),
102104
SSL_SESSION_set1_cache_id(),
103-
SSL_SESSION_get0_cache_id(), and
105+
SSL_SESSION_get1_cache_id(), and
104106
SSL_get1_previous_client_session() functions were added in OpenSSL 3.5.
105107

106108
=head1 COPYRIGHT

include/openssl/ssl.h.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,9 +2883,9 @@ int SSL_set_quic_tls_early_data_enabled(SSL *s, int enabled);
28832883
/* Client cache implementation */
28842884
__owur SSL_SESSION *SSL_get1_previous_client_session(SSL *s);
28852885
__owur int SSL_set1_cache_id(SSL *s, const unsigned char *data, size_t len);
2886-
__owur int SSL_get0_cache_id(const SSL *s, const unsigned char **data, size_t *len);
2886+
__owur int SSL_get1_cache_id(const SSL *s, unsigned char **data, size_t *len);
28872887
__owur int SSL_SESSION_set1_cache_id(SSL_SESSION *ss, const unsigned char *data, size_t len);
2888-
__owur int SSL_SESSION_get0_cache_id(const SSL_SESSION *ss, const unsigned char **data,
2888+
__owur int SSL_SESSION_get1_cache_id(const SSL_SESSION *ss, unsigned char **data,
28892889
size_t *len);
28902890

28912891
# ifdef __cplusplus

ssl/ssl_sess.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,18 +1595,14 @@ int SSL_set1_cache_id(SSL *s, const unsigned char *data, size_t len)
15951595
return 1;
15961596
}
15971597

1598-
int SSL_get0_cache_id(const SSL *s, const unsigned char **data, size_t *len)
1598+
int SSL_get1_cache_id(const SSL *s, unsigned char **data, size_t *len)
15991599
{
16001600
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
16011601

1602-
if (sc == NULL)
1603-
return 0;
1604-
if (sc->server)
1602+
if (sc == NULL || sc->server || sc->cache_id == NULL)
16051603
return 0;
1606-
1607-
if (sc->cache_id == NULL)
1604+
if ((*data = OPENSSL_memdup(sc->cache_id, sc->cache_id_len)) == NULL)
16081605
return 0;
1609-
*data = sc->cache_id;
16101606
*len = sc->cache_id_len;
16111607
return 1;
16121608
}
@@ -1633,11 +1629,12 @@ int SSL_SESSION_set1_cache_id(SSL_SESSION *ss, const unsigned char *data, size_t
16331629
return 1;
16341630
}
16351631

1636-
int SSL_SESSION_get0_cache_id(const SSL_SESSION *ss, const unsigned char **data, size_t *len)
1632+
int SSL_SESSION_get1_cache_id(const SSL_SESSION *ss, unsigned char **data, size_t *len)
16371633
{
1638-
if (ss->cache_id == NULL)
1634+
if (ss == NULL || ss->cache_id == NULL)
1635+
return 0;
1636+
if ((*data = OPENSSL_memdup(ss->cache_id, ss->cache_id_len)) == NULL)
16391637
return 0;
1640-
*data = ss->cache_id;
16411638
*len = ss->cache_id_len;
16421639
return 1;
16431640
}

test/client_cache_test.c

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,108 @@ static const unsigned char sid_ctx[] = "sid";
2121
static const unsigned char cache_id[] = "this is a test";
2222
static const unsigned char cache_id2[] = "different";
2323

24+
static SSL_SESSION *external_cache = NULL;
25+
static SSL_SESSION *session_get_cb(SSL *ssl, const unsigned char *data, int len, int *copy)
26+
{
27+
unsigned char *cid;
28+
size_t cid_len;
29+
30+
if (!SSL_SESSION_get1_cache_id(external_cache, &cid, &cid_len))
31+
return NULL;
32+
33+
if (len != (int)cid_len || memcmp(cid, data, len) != 0) {
34+
OPENSSL_free(cid);
35+
return NULL;
36+
}
37+
38+
OPENSSL_free(cid);
39+
*copy = 1;
40+
return external_cache;
41+
}
42+
43+
static int test_client_cache_external(void)
44+
{
45+
int ret = 0;
46+
SSL_CTX *cctx = NULL, *sctx = NULL;
47+
SSL *cssl = NULL, *sssl = NULL;
48+
uint32_t mode;
49+
SSL_SESSION *sess1 = NULL;
50+
51+
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
52+
TLS_client_method(), TLS1_VERSION, TLS1_2_VERSION,
53+
&sctx, &cctx, cert, privkey)))
54+
return 0;
55+
56+
mode = SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
57+
if (!TEST_true(SSL_CTX_set_session_cache_mode(cctx, mode))
58+
|| !TEST_true(SSL_CTX_set_session_id_context(sctx, sid_ctx, sizeof(sid_ctx)))
59+
|| !TEST_true(SSL_CTX_set_session_id_context(cctx, sid_ctx, sizeof(sid_ctx))))
60+
goto end;
61+
62+
SSL_CTX_sess_set_get_cb(cctx, session_get_cb);
63+
64+
/* Initial connection - establishes external_cache */
65+
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
66+
|| !TEST_true(SSL_set1_cache_id(cssl, cache_id, sizeof(cache_id)))
67+
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
68+
|| !TEST_ptr(external_cache = SSL_get1_session(cssl)))
69+
goto end;
70+
71+
shutdown_ssl_connection(sssl, cssl);
72+
sssl = cssl = NULL;
73+
74+
/* Test automatic assignment of session when client has cache_id set */
75+
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
76+
|| !TEST_true(SSL_set1_cache_id(cssl, cache_id, sizeof(cache_id)))
77+
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
78+
|| !TEST_true(SSL_session_reused(cssl))
79+
|| !TEST_ptr(sess1 = SSL_get1_session(cssl)))
80+
goto end;
81+
82+
shutdown_ssl_connection(sssl, cssl);
83+
sssl = cssl = NULL;
84+
85+
/* Ensure client is resumed when no cache_id is set, but session is assigned */
86+
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
87+
|| !TEST_true(SSL_set_session(cssl, sess1))
88+
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
89+
|| !TEST_true(SSL_session_reused(cssl)))
90+
goto end;
91+
92+
shutdown_ssl_connection(sssl, cssl);
93+
sssl = cssl = NULL;
94+
95+
/* Ensure client is not resumed when no cache_id is set */
96+
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
97+
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
98+
|| !TEST_false(SSL_session_reused(cssl)))
99+
goto end;
100+
101+
shutdown_ssl_connection(sssl, cssl);
102+
sssl = cssl = NULL;
103+
104+
/* Ensure client is not resumed when a different cache_id is set */
105+
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
106+
|| !TEST_true(SSL_set1_cache_id(cssl, cache_id2, sizeof(cache_id2)))
107+
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
108+
|| !TEST_false(SSL_session_reused(cssl)))
109+
goto end;
110+
111+
shutdown_ssl_connection(sssl, cssl);
112+
sssl = cssl = NULL;
113+
114+
ret = 1;
115+
end:
116+
SSL_free(sssl);
117+
SSL_free(cssl);
118+
SSL_SESSION_free(external_cache);
119+
external_cache = NULL;
120+
SSL_SESSION_free(sess1);
121+
SSL_CTX_free(sctx);
122+
SSL_CTX_free(cctx);
123+
return ret;
124+
}
125+
24126
static int test_client_cache(void)
25127
{
26128
int ret = 0;
@@ -33,8 +135,8 @@ static int test_client_cache(void)
33135
&sctx, &cctx, cert, privkey)))
34136
return 0;
35137

36-
SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT);
37-
if (!TEST_true(SSL_CTX_set_session_id_context(sctx, sid_ctx, sizeof(sid_ctx)))
138+
if (!TEST_true(SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT))
139+
|| !TEST_true(SSL_CTX_set_session_id_context(sctx, sid_ctx, sizeof(sid_ctx)))
38140
|| !TEST_true(SSL_CTX_set_session_id_context(cctx, sid_ctx, sizeof(sid_ctx))))
39141
goto end;
40142

@@ -62,6 +164,16 @@ static int test_client_cache(void)
62164
shutdown_ssl_connection(sssl, cssl);
63165
sssl = cssl = NULL;
64166

167+
/* Ensure client is resumed when no cache_id is set, but session is assigned */
168+
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
169+
|| !TEST_true(SSL_set_session(cssl, sess3))
170+
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
171+
|| !TEST_true(SSL_session_reused(cssl)))
172+
goto end;
173+
174+
shutdown_ssl_connection(sssl, cssl);
175+
sssl = cssl = NULL;
176+
65177
/* Ensure client is not resumed when no cache_id is set */
66178
if (!TEST_true(create_ssl_objects(sctx, cctx, &sssl, &cssl, NULL, NULL))
67179
|| !TEST_true(create_ssl_connection(sssl, cssl, SSL_ERROR_NONE))
@@ -117,6 +229,7 @@ int setup_tests(void)
117229
goto err;
118230

119231
ADD_TEST(test_client_cache);
232+
ADD_TEST(test_client_cache_external);
120233
return 1;
121234

122235
err:

test/sslapitest.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,7 +2073,7 @@ static int execute_test_session(int maxprot, int use_int_cache,
20732073
int testresult = 0, numnewsesstick = 1;
20742074
const unsigned char cache_id[] = "this is a test";
20752075
size_t cache_id_len = sizeof("this is a test");
2076-
const unsigned char *new_cache_id;
2076+
unsigned char *new_cache_id = NULL;
20772077
size_t new_cache_id_len;
20782078

20792079
new_called = remove_called = 0;
@@ -2115,15 +2115,18 @@ static int execute_test_session(int maxprot, int use_int_cache,
21152115
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1,
21162116
NULL, NULL))
21172117
|| !TEST_true(SSL_set1_cache_id(clientssl1, cache_id, cache_id_len))
2118-
|| !TEST_true(SSL_get0_cache_id(clientssl1, &new_cache_id, &new_cache_id_len))
2118+
|| !TEST_true(SSL_get1_cache_id(clientssl1, &new_cache_id, &new_cache_id_len))
21192119
|| !TEST_mem_eq(cache_id, cache_id_len, new_cache_id, new_cache_id_len)
21202120
|| !TEST_true(create_ssl_connection(serverssl1, clientssl1, SSL_ERROR_NONE))
21212121
|| !TEST_false(SSL_set1_cache_id(clientssl1, cache_id, cache_id_len))
21222122
|| !TEST_ptr(sess1 = SSL_get1_session(clientssl1)))
21232123
goto end;
21242124

2125+
OPENSSL_free(new_cache_id);
2126+
new_cache_id = NULL;
2127+
21252128
if (use_int_cache
2126-
&& (!TEST_true(SSL_SESSION_get0_cache_id(sess1, &new_cache_id, &new_cache_id_len))
2129+
&& (!TEST_true(SSL_SESSION_get1_cache_id(sess1, &new_cache_id, &new_cache_id_len))
21272130
|| !TEST_mem_eq(cache_id, cache_id_len, new_cache_id, new_cache_id_len)
21282131
|| !TEST_ptr(sess3 = SSL_get1_previous_client_session(clientssl1))
21292132
|| !TEST_ptr_eq(sess1, sess3)
@@ -2392,6 +2395,7 @@ static int execute_test_session(int maxprot, int use_int_cache,
23922395
SSL_SESSION_free(sess3);
23932396
SSL_CTX_free(sctx);
23942397
SSL_CTX_free(cctx);
2398+
OPENSSL_free(new_cache_id);
23952399

23962400
return testresult;
23972401
}

util/libssl.num

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,6 @@ SSL_get_domain_flags ? 3_5_0 EXIST::FUNCTION:
608608
SSL_CTX_set_new_pending_conn_cb ? 3_5_0 EXIST::FUNCTION:
609609
SSL_get1_previous_client_session ? 3_5_0 EXIST::FUNCTION:
610610
SSL_set1_cache_id ? 3_5_0 EXIST::FUNCTION:
611-
SSL_get0_cache_id ? 3_5_0 EXIST::FUNCTION:
611+
SSL_get1_cache_id ? 3_5_0 EXIST::FUNCTION:
612612
SSL_SESSION_set1_cache_id ? 3_5_0 EXIST::FUNCTION:
613-
SSL_SESSION_get0_cache_id ? 3_5_0 EXIST::FUNCTION:
613+
SSL_SESSION_get1_cache_id ? 3_5_0 EXIST::FUNCTION:

0 commit comments

Comments
 (0)