Optimize session cache flushing
Sort SSL_SESSION structures by timeout in the linked list.
Iterate over the linked list for timeout, stopping when no more
session can be flushed.
Do SSL_SESSION_free() outside of SSL_CTX lock
Update timeout upon use
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8687)
Todd Short authored 5 years ago
Pauli committed 2 years ago
104 | 104 | Enable both SSL_SESS_CACHE_NO_INTERNAL_LOOKUP and |
105 | 105 | SSL_SESS_CACHE_NO_INTERNAL_STORE at the same time. |
106 | 106 | |
107 | =item SSL_SESS_CACHE_UPDATE_TIME | |
108 | ||
109 | Updates the timestamp of the session when it is used, increasing the lifespan | |
110 | of the session. The session timeout applies to last use, rather then creation | |
111 | time. | |
107 | 112 | |
108 | 113 | =back |
109 | 114 |
669 | 669 | # define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 |
670 | 670 | # define SSL_SESS_CACHE_NO_INTERNAL \ |
671 | 671 | (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE) |
672 | # define SSL_SESS_CACHE_UPDATE_TIME 0x0400 | |
672 | 673 | |
673 | 674 | LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx); |
674 | 675 | # define SSL_CTX_sess_number(ctx) \ |
162 | 162 | ssl_session_oinit(&as.session_id_context, &sid_ctx, |
163 | 163 | in->sid_ctx, in->sid_ctx_length); |
164 | 164 | |
165 | as.time = in->time; | |
166 | as.timeout = in->timeout; | |
165 | as.time = (int64_t)in->time; | |
166 | as.timeout = (int64_t)in->timeout; | |
167 | 167 | as.verify_result = in->verify_result; |
168 | 168 | |
169 | 169 | as.peer = in->peer; |
301 | 301 | ret->master_key_length = tmpl; |
302 | 302 | |
303 | 303 | if (as->time != 0) |
304 | ret->time = (long)as->time; | |
305 | else | |
306 | ret->time = (long)time(NULL); | |
304 | ret->time = (time_t)as->time; | |
305 | else | |
306 | ret->time = time(NULL); | |
307 | 307 | |
308 | 308 | if (as->timeout != 0) |
309 | ret->timeout = (long)as->timeout; | |
309 | ret->timeout = (time_t)as->timeout; | |
310 | 310 | else |
311 | 311 | ret->timeout = 3; |
312 | ssl_session_calculate_timeout(ret); | |
312 | 313 | |
313 | 314 | X509_free(ret->peer); |
314 | 315 | ret->peer = as->peer; |
592 | 592 | */ |
593 | 593 | long verify_result; /* only for servers */ |
594 | 594 | CRYPTO_REF_COUNT references; |
595 | long timeout; | |
596 | long time; | |
595 | time_t timeout; | |
596 | time_t time; | |
597 | time_t calc_timeout; | |
598 | int timeout_ovf; | |
597 | 599 | unsigned int compress_meth; /* Need to lookup the method */ |
598 | 600 | const SSL_CIPHER *cipher; |
599 | 601 | unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used to |
633 | 635 | unsigned char *ticket_appdata; |
634 | 636 | size_t ticket_appdata_len; |
635 | 637 | uint32_t flags; |
638 | SSL_CTX *owner; | |
636 | 639 | CRYPTO_RWLOCK *lock; |
637 | 640 | }; |
638 | 641 | |
2842 | 2845 | int ssl_srp_calc_a_param_intern(SSL *s); |
2843 | 2846 | int ssl_srp_server_param_with_username_intern(SSL *s, int *ad); |
2844 | 2847 | |
2848 | void ssl_session_calculate_timeout(SSL_SESSION* ss); | |
2849 | ||
2845 | 2850 | # else /* OPENSSL_UNIT_TEST */ |
2846 | 2851 | |
2847 | 2852 | # define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer |
22 | 22 | static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); |
23 | 23 | static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); |
24 | 24 | static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); |
25 | ||
26 | DEFINE_STACK_OF(SSL_SESSION) | |
27 | ||
28 | __owur static int sess_timedout(time_t t, SSL_SESSION *ss) | |
29 | { | |
30 | /* if timeout overflowed, it can never timeout! */ | |
31 | if (ss->timeout_ovf) | |
32 | return 0; | |
33 | return t > ss->calc_timeout; | |
34 | } | |
35 | ||
36 | /* | |
37 | * Returns -1/0/+1 as other XXXcmp-type functions | |
38 | * Takes overflow of calculated timeout into consideration | |
39 | */ | |
40 | __owur static int timeoutcmp(SSL_SESSION *a, SSL_SESSION *b) | |
41 | { | |
42 | /* if only one overflowed, then it is greater */ | |
43 | if (a->timeout_ovf && !b->timeout_ovf) | |
44 | return 1; | |
45 | if (!a->timeout_ovf && b->timeout_ovf) | |
46 | return -1; | |
47 | /* No overflow, or both overflowed, so straight compare is safe */ | |
48 | if (a->calc_timeout < b->calc_timeout) | |
49 | return -1; | |
50 | if (a->calc_timeout > b->calc_timeout) | |
51 | return 1; | |
52 | return 0; | |
53 | } | |
54 | ||
55 | /* | |
56 | * Calculates effective timeout, saving overflow state | |
57 | * Locking must be done by the caller of this function | |
58 | */ | |
59 | void ssl_session_calculate_timeout(SSL_SESSION *ss) | |
60 | { | |
61 | /* Force positive timeout */ | |
62 | if (ss->timeout < 0) | |
63 | ss->timeout = 0; | |
64 | ss->calc_timeout = ss->time + ss->timeout; | |
65 | /* | |
66 | * |timeout| is always zero or positive, so the check for | |
67 | * overflow only needs to consider if |time| is positive | |
68 | */ | |
69 | ss->timeout_ovf = ss->time > 0 && ss->calc_timeout < ss->time; | |
70 | /* | |
71 | * N.B. Realistic overflow can only occur in our lifetimes on a | |
72 | * 32-bit machine in January 2038. | |
73 | * However, There are no controls to limit the |timeout| | |
74 | * value, except to keep it positive. | |
75 | */ | |
76 | } | |
25 | 77 | |
26 | 78 | /* |
27 | 79 | * SSL_get_session() and SSL_get1_session() are problematic in TLS1.3 because, |
82 | 134 | ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ |
83 | 135 | ss->references = 1; |
84 | 136 | ss->timeout = 60 * 5 + 4; /* 5 minute timeout by default */ |
85 | ss->time = (unsigned long)time(NULL); | |
137 | ss->time = time(NULL); | |
138 | ssl_session_calculate_timeout(ss); | |
86 | 139 | ss->lock = CRYPTO_THREAD_lock_new(); |
87 | 140 | if (ss->lock == NULL) { |
88 | 141 | ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); |
586 | 639 | goto err; |
587 | 640 | } |
588 | 641 | |
589 | if (ret->timeout < (long)(time(NULL) - ret->time)) { /* timeout */ | |
642 | if (sess_timedout(time(NULL), ret)) { | |
590 | 643 | tsan_counter(&s->session_ctx->stats.sess_timeout); |
591 | 644 | if (try_session_cache) { |
592 | 645 | /* session was from the cache, so remove it */ |
687 | 740 | s = c; |
688 | 741 | } |
689 | 742 | |
690 | /* Put at the head of the queue unless it is already in the cache */ | |
691 | if (s == NULL) | |
692 | SSL_SESSION_list_add(ctx, c); | |
743 | /* Adjust last used time, and add back into the cache at the appropriate spot */ | |
744 | if (ctx->session_cache_mode & SSL_SESS_CACHE_UPDATE_TIME) { | |
745 | c->time = time(NULL); | |
746 | ssl_session_calculate_timeout(c); | |
747 | } | |
748 | SSL_SESSION_list_add(ctx, c); | |
693 | 749 | |
694 | 750 | if (s != NULL) { |
695 | 751 | /* |
831 | 887 | |
832 | 888 | long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) |
833 | 889 | { |
890 | time_t new_timeout = (time_t)t; | |
891 | ||
892 | if (s == NULL || t < 0) | |
893 | return 0; | |
894 | if (s->owner != NULL) { | |
895 | if (!CRYPTO_THREAD_write_lock(s->owner->lock)) | |
896 | return 0; | |
897 | s->timeout = new_timeout; | |
898 | ssl_session_calculate_timeout(s); | |
899 | SSL_SESSION_list_add(s->owner, s); | |
900 | CRYPTO_THREAD_unlock(s->owner->lock); | |
901 | } else { | |
902 | s->timeout = new_timeout; | |
903 | ssl_session_calculate_timeout(s); | |
904 | } | |
905 | return 1; | |
906 | } | |
907 | ||
908 | long SSL_SESSION_get_timeout(const SSL_SESSION *s) | |
909 | { | |
834 | 910 | if (s == NULL) |
835 | 911 | return 0; |
836 | s->timeout = t; | |
837 | return 1; | |
838 | } | |
839 | ||
840 | long SSL_SESSION_get_timeout(const SSL_SESSION *s) | |
912 | return (long)s->timeout; | |
913 | } | |
914 | ||
915 | long SSL_SESSION_get_time(const SSL_SESSION *s) | |
841 | 916 | { |
842 | 917 | if (s == NULL) |
843 | 918 | return 0; |
844 | return s->timeout; | |
845 | } | |
846 | ||
847 | long SSL_SESSION_get_time(const SSL_SESSION *s) | |
848 | { | |
919 | return (long)s->time; | |
920 | } | |
921 | ||
922 | long SSL_SESSION_set_time(SSL_SESSION *s, long t) | |
923 | { | |
924 | time_t new_time = (time_t)t; | |
925 | ||
849 | 926 | if (s == NULL) |
850 | 927 | return 0; |
851 | return s->time; | |
852 | } | |
853 | ||
854 | long SSL_SESSION_set_time(SSL_SESSION *s, long t) | |
855 | { | |
856 | if (s == NULL) | |
857 | return 0; | |
858 | s->time = t; | |
928 | if (s->owner != NULL) { | |
929 | if (!CRYPTO_THREAD_write_lock(s->owner->lock)) | |
930 | return 0; | |
931 | s->time = new_time; | |
932 | ssl_session_calculate_timeout(s); | |
933 | SSL_SESSION_list_add(s->owner, s); | |
934 | CRYPTO_THREAD_unlock(s->owner->lock); | |
935 | } else { | |
936 | s->time = new_time; | |
937 | ssl_session_calculate_timeout(s); | |
938 | } | |
859 | 939 | return t; |
860 | 940 | } |
861 | 941 | |
1049 | 1129 | return 0; |
1050 | 1130 | } |
1051 | 1131 | |
1052 | typedef struct timeout_param_st { | |
1053 | SSL_CTX *ctx; | |
1054 | long time; | |
1055 | LHASH_OF(SSL_SESSION) *cache; | |
1056 | } TIMEOUT_PARAM; | |
1057 | ||
1058 | static void timeout_cb(SSL_SESSION *s, TIMEOUT_PARAM *p) | |
1059 | { | |
1060 | if ((p->time == 0) || (p->time > (s->time + s->timeout))) { /* timeout */ | |
1061 | /* | |
1062 | * The reason we don't call SSL_CTX_remove_session() is to save on | |
1063 | * locking overhead | |
1064 | */ | |
1065 | (void)lh_SSL_SESSION_delete(p->cache, s); | |
1066 | SSL_SESSION_list_remove(p->ctx, s); | |
1067 | s->not_resumable = 1; | |
1068 | if (p->ctx->remove_session_cb != NULL) | |
1069 | p->ctx->remove_session_cb(p->ctx, s); | |
1070 | SSL_SESSION_free(s); | |
1071 | } | |
1072 | } | |
1073 | ||
1074 | IMPLEMENT_LHASH_DOALL_ARG(SSL_SESSION, TIMEOUT_PARAM); | |
1075 | ||
1076 | 1132 | void SSL_CTX_flush_sessions(SSL_CTX *s, long t) |
1077 | 1133 | { |
1134 | STACK_OF(SSL_SESSION) *sk; | |
1135 | SSL_SESSION *current; | |
1078 | 1136 | unsigned long i; |
1079 | TIMEOUT_PARAM tp; | |
1080 | ||
1081 | tp.ctx = s; | |
1082 | tp.cache = s->sessions; | |
1083 | if (tp.cache == NULL) | |
1084 | return; | |
1085 | tp.time = t; | |
1137 | ||
1086 | 1138 | if (!CRYPTO_THREAD_write_lock(s->lock)) |
1087 | 1139 | return; |
1140 | ||
1141 | sk = sk_SSL_SESSION_new_null(); | |
1088 | 1142 | i = lh_SSL_SESSION_get_down_load(s->sessions); |
1089 | 1143 | lh_SSL_SESSION_set_down_load(s->sessions, 0); |
1090 | lh_SSL_SESSION_doall_TIMEOUT_PARAM(tp.cache, timeout_cb, &tp); | |
1144 | ||
1145 | /* | |
1146 | * Iterate over the list from the back (oldest), and stop | |
1147 | * when a session can no longer be removed. | |
1148 | * Add the session to a temporary list to be freed outside | |
1149 | * the SSL_CTX lock. | |
1150 | * But still do the remove_session_cb() within the lock. | |
1151 | */ | |
1152 | while (s->session_cache_tail != NULL) { | |
1153 | current = s->session_cache_tail; | |
1154 | if (t == 0 || sess_timedout((time_t)t, current)) { | |
1155 | lh_SSL_SESSION_delete(s->sessions, current); | |
1156 | SSL_SESSION_list_remove(s, current); | |
1157 | current->not_resumable = 1; | |
1158 | if (s->remove_session_cb != NULL) | |
1159 | s->remove_session_cb(s, current); | |
1160 | /* | |
1161 | * Throw the session on a stack, it's entirely plausible | |
1162 | * that while freeing outside the critical section, the | |
1163 | * session could be re-added, so avoid using the next/prev | |
1164 | * pointers. If the stack failed to create, or the session | |
1165 | * couldn't be put on the stack, just free it here | |
1166 | */ | |
1167 | if (sk == NULL || !sk_SSL_SESSION_push(sk, current)) | |
1168 | SSL_SESSION_free(current); | |
1169 | } else { | |
1170 | break; | |
1171 | } | |
1172 | } | |
1173 | ||
1091 | 1174 | lh_SSL_SESSION_set_down_load(s->sessions, i); |
1092 | 1175 | CRYPTO_THREAD_unlock(s->lock); |
1176 | ||
1177 | sk_SSL_SESSION_pop_free(sk, SSL_SESSION_free); | |
1093 | 1178 | } |
1094 | 1179 | |
1095 | 1180 | int ssl_clear_bad_session(SSL *s) |
1131 | 1216 | } |
1132 | 1217 | } |
1133 | 1218 | s->prev = s->next = NULL; |
1219 | s->owner = NULL; | |
1134 | 1220 | } |
1135 | 1221 | |
1136 | 1222 | static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) |
1137 | 1223 | { |
1224 | SSL_SESSION *next; | |
1225 | ||
1138 | 1226 | if ((s->next != NULL) && (s->prev != NULL)) |
1139 | 1227 | SSL_SESSION_list_remove(ctx, s); |
1140 | 1228 | |
1144 | 1232 | s->prev = (SSL_SESSION *)&(ctx->session_cache_head); |
1145 | 1233 | s->next = (SSL_SESSION *)&(ctx->session_cache_tail); |
1146 | 1234 | } else { |
1147 | s->next = ctx->session_cache_head; | |
1148 | s->next->prev = s; | |
1149 | s->prev = (SSL_SESSION *)&(ctx->session_cache_head); | |
1150 | ctx->session_cache_head = s; | |
1151 | } | |
1235 | if (timeoutcmp(s, ctx->session_cache_head) >= 0) { | |
1236 | /* | |
1237 | * if we timeout after (or the same time as) the first | |
1238 | * session, put us first - usual case | |
1239 | */ | |
1240 | s->next = ctx->session_cache_head; | |
1241 | s->next->prev = s; | |
1242 | s->prev = (SSL_SESSION *)&(ctx->session_cache_head); | |
1243 | ctx->session_cache_head = s; | |
1244 | } else if (timeoutcmp(s, ctx->session_cache_tail) < 0) { | |
1245 | /* if we timeout before the last session, put us last */ | |
1246 | s->prev = ctx->session_cache_tail; | |
1247 | s->prev->next = s; | |
1248 | s->next = (SSL_SESSION *)&(ctx->session_cache_tail); | |
1249 | ctx->session_cache_tail = s; | |
1250 | } else { | |
1251 | /* | |
1252 | * we timeout somewhere in-between - if there is only | |
1253 | * one session in the cache it will be caught above | |
1254 | */ | |
1255 | next = ctx->session_cache_head->next; | |
1256 | while (next != (SSL_SESSION*)&(ctx->session_cache_tail)) { | |
1257 | if (timeoutcmp(s, next) >= 0) { | |
1258 | s->next = next; | |
1259 | s->prev = next->prev; | |
1260 | next->prev->next = s; | |
1261 | next->prev = s; | |
1262 | break; | |
1263 | } | |
1264 | next = next->next; | |
1265 | } | |
1266 | } | |
1267 | } | |
1268 | s->owner = ctx; | |
1152 | 1269 | } |
1153 | 1270 | |
1154 | 1271 | void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, |
2509 | 2509 | s->session = new_sess; |
2510 | 2510 | } |
2511 | 2511 | |
2512 | /* | |
2513 | * Technically the cast to long here is not guaranteed by the C standard - | |
2514 | * but we use it elsewhere, so this should be ok. | |
2515 | */ | |
2516 | s->session->time = (long)time(NULL); | |
2512 | s->session->time = time(NULL); | |
2513 | ssl_session_calculate_timeout(s->session); | |
2517 | 2514 | |
2518 | 2515 | OPENSSL_free(s->session->ext.tick); |
2519 | 2516 | s->session->ext.tick = NULL; |
3632 | 3632 | */ |
3633 | 3633 | if (!WPACKET_put_bytes_u32(pkt, |
3634 | 3634 | (s->hit && !SSL_IS_TLS13(s)) |
3635 | ? 0 : s->session->timeout)) { | |
3635 | ? 0 : (uint32_t)s->session->timeout)) { | |
3636 | 3636 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
3637 | 3637 | return 0; |
3638 | 3638 | } |
3929 | 3929 | } |
3930 | 3930 | s->session->master_key_length = hashlen; |
3931 | 3931 | |
3932 | s->session->time = (long)time(NULL); | |
3932 | s->session->time = time(NULL); | |
3933 | ssl_session_calculate_timeout(s->session); | |
3933 | 3934 | if (s->s3.alpn_selected != NULL) { |
3934 | 3935 | OPENSSL_free(s->session->ext.alpn_selected); |
3935 | 3936 | s->session->ext.alpn_selected = |
8121 | 8121 | } |
8122 | 8122 | #endif /* OPENSSL_NO_TLS1_2 */ |
8123 | 8123 | |
8124 | static int test_session_timeout(int test) | |
8125 | { | |
8126 | /* | |
8127 | * Test session ordering and timeout | |
8128 | * Can't explicitly test performance of the new code, | |
8129 | * but can test to see if the ordering of the sessions | |
8130 | * are correct, and they they are removed as expected | |
8131 | */ | |
8132 | SSL_SESSION *early = NULL; | |
8133 | SSL_SESSION *middle = NULL; | |
8134 | SSL_SESSION *late = NULL; | |
8135 | SSL_CTX *ctx; | |
8136 | int testresult = 0; | |
8137 | long now = (long)time(NULL); | |
8138 | #define TIMEOUT 10 | |
8139 | ||
8140 | if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_method())) | |
8141 | || !TEST_ptr(early = SSL_SESSION_new()) | |
8142 | || !TEST_ptr(middle = SSL_SESSION_new()) | |
8143 | || !TEST_ptr(late = SSL_SESSION_new())) | |
8144 | goto end; | |
8145 | ||
8146 | /* assign unique session ids */ | |
8147 | early->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; | |
8148 | memset(early->session_id, 1, SSL3_SSL_SESSION_ID_LENGTH); | |
8149 | middle->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; | |
8150 | memset(middle->session_id, 2, SSL3_SSL_SESSION_ID_LENGTH); | |
8151 | late->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; | |
8152 | memset(late->session_id, 3, SSL3_SSL_SESSION_ID_LENGTH); | |
8153 | ||
8154 | if (!TEST_int_eq(SSL_CTX_add_session(ctx, early), 1) | |
8155 | || !TEST_int_eq(SSL_CTX_add_session(ctx, middle), 1) | |
8156 | || !TEST_int_eq(SSL_CTX_add_session(ctx, late), 1)) | |
8157 | goto end; | |
8158 | ||
8159 | /* Make sure they are all added */ | |
8160 | if (!TEST_ptr(early->prev) | |
8161 | || !TEST_ptr(middle->prev) | |
8162 | || !TEST_ptr(late->prev)) | |
8163 | goto end; | |
8164 | ||
8165 | if (!TEST_int_ne(SSL_SESSION_set_time(early, now - 10), 0) | |
8166 | || !TEST_int_ne(SSL_SESSION_set_time(middle, now), 0) | |
8167 | || !TEST_int_ne(SSL_SESSION_set_time(late, now + 10), 0)) | |
8168 | goto end; | |
8169 | ||
8170 | if (!TEST_int_ne(SSL_SESSION_set_timeout(early, TIMEOUT), 0) | |
8171 | || !TEST_int_ne(SSL_SESSION_set_timeout(middle, TIMEOUT), 0) | |
8172 | || !TEST_int_ne(SSL_SESSION_set_timeout(late, TIMEOUT), 0)) | |
8173 | goto end; | |
8174 | ||
8175 | /* Make sure they are all still there */ | |
8176 | if (!TEST_ptr(early->prev) | |
8177 | || !TEST_ptr(middle->prev) | |
8178 | || !TEST_ptr(late->prev)) | |
8179 | goto end; | |
8180 | ||
8181 | /* Make sure they are in the expected order */ | |
8182 | if (!TEST_ptr_eq(late->next, middle) | |
8183 | || !TEST_ptr_eq(middle->next, early) | |
8184 | || !TEST_ptr_eq(early->prev, middle) | |
8185 | || !TEST_ptr_eq(middle->prev, late)) | |
8186 | goto end; | |
8187 | ||
8188 | /* This should remove "early" */ | |
8189 | SSL_CTX_flush_sessions(ctx, now + TIMEOUT - 1); | |
8190 | if (!TEST_ptr_null(early->prev) | |
8191 | || !TEST_ptr(middle->prev) | |
8192 | || !TEST_ptr(late->prev)) | |
8193 | goto end; | |
8194 | ||
8195 | /* This should remove "middle" */ | |
8196 | SSL_CTX_flush_sessions(ctx, now + TIMEOUT + 1); | |
8197 | if (!TEST_ptr_null(early->prev) | |
8198 | || !TEST_ptr_null(middle->prev) | |
8199 | || !TEST_ptr(late->prev)) | |
8200 | goto end; | |
8201 | ||
8202 | /* This should remove "late" */ | |
8203 | SSL_CTX_flush_sessions(ctx, now + TIMEOUT + 11); | |
8204 | if (!TEST_ptr_null(early->prev) | |
8205 | || !TEST_ptr_null(middle->prev) | |
8206 | || !TEST_ptr_null(late->prev)) | |
8207 | goto end; | |
8208 | ||
8209 | /* Add them back in again */ | |
8210 | if (!TEST_int_eq(SSL_CTX_add_session(ctx, early), 1) | |
8211 | || !TEST_int_eq(SSL_CTX_add_session(ctx, middle), 1) | |
8212 | || !TEST_int_eq(SSL_CTX_add_session(ctx, late), 1)) | |
8213 | goto end; | |
8214 | ||
8215 | /* Make sure they are all added */ | |
8216 | if (!TEST_ptr(early->prev) | |
8217 | || !TEST_ptr(middle->prev) | |
8218 | || !TEST_ptr(late->prev)) | |
8219 | goto end; | |
8220 | ||
8221 | /* This should remove all of them */ | |
8222 | SSL_CTX_flush_sessions(ctx, 0); | |
8223 | if (!TEST_ptr_null(early->prev) | |
8224 | || !TEST_ptr_null(middle->prev) | |
8225 | || !TEST_ptr_null(late->prev)) | |
8226 | goto end; | |
8227 | ||
8228 | (void)SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_UPDATE_TIME | |
8229 | | SSL_CTX_get_session_cache_mode(ctx)); | |
8230 | ||
8231 | /* make sure |now| is NOT equal to the current time */ | |
8232 | now -= 10; | |
8233 | if (!TEST_int_ne(SSL_SESSION_set_time(early, now), 0) | |
8234 | || !TEST_int_eq(SSL_CTX_add_session(ctx, early), 1) | |
8235 | || !TEST_long_ne(SSL_SESSION_get_time(early), now)) | |
8236 | goto end; | |
8237 | ||
8238 | testresult = 1; | |
8239 | end: | |
8240 | SSL_CTX_free(ctx); | |
8241 | SSL_SESSION_free(early); | |
8242 | SSL_SESSION_free(middle); | |
8243 | SSL_SESSION_free(late); | |
8244 | return testresult; | |
8245 | } | |
8246 | ||
8124 | 8247 | /* |
8125 | 8248 | * Test 0: Client sets servername and server acknowledges it (TLSv1.2) |
8126 | 8249 | * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2) |
9286 | 9409 | #endif |
9287 | 9410 | ADD_TEST(test_inherit_verify_param); |
9288 | 9411 | ADD_TEST(test_set_alpn); |
9412 | ADD_ALL_TESTS(test_session_timeout, 1); | |
9289 | 9413 | return 1; |
9290 | 9414 | |
9291 | 9415 | err: |