1 #include <config.h>
2 
3 #ifdef WITH_TLS
4 # ifndef IN_TLS_C
5 #  define IN_TLS_C 1
6 # endif
7 
8 # include "ftpd.h"
9 # include "tls.h"
10 # include "ftpwho-update.h"
11 # include "globals.h"
12 # include "messages.h"
13 # include "alt_arc4random.h"
14 # include "tls_extcert.h"
15 
tls_error(const int line,int err)16 static void tls_error(const int line, int err)
17 {
18     if (err == 0) {
19         err = ERR_get_error();
20     }
21     if (err != 0) {
22         logfile(LOG_ERR, "TLS [%s](%d): %s",
23                 cert_file, line, ERR_error_string(err, NULL));
24     }
25     _EXIT(EXIT_FAILURE);
26 }
27 
validate_sni_name(const char * const sni_name)28 static int validate_sni_name(const char * const sni_name)
29 {
30     static const char *valid_chars =
31         "abcdefghijklmnopqrstuvwxyz.-0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
32     const char        *pnt = sni_name;
33 
34     if (strlen(sni_name) > 255) {
35         return -1;
36     }
37     while (*pnt != 0) {
38         if (strchr(valid_chars, *pnt) == NULL) {
39             return -1;
40         }
41         pnt++;
42     }
43     return 0;
44 }
45 
46 static int tls_create_new_context(const char *cert_file,
47                                   const char *key_file);
48 
ssl_servername_cb(SSL * cnx,int * al,void * arg)49 static int ssl_servername_cb(SSL *cnx, int *al, void *arg)
50 {
51     CertResult  result;
52     const char *sni_name;
53 
54     (void) al;
55     (void) arg;
56     if ((sni_name = SSL_get_servername(cnx, TLSEXT_NAMETYPE_host_name))
57         == NULL || *sni_name == 0 || validate_sni_name(sni_name) != 0) {
58         return SSL_TLSEXT_ERR_NOACK;
59     }
60     logfile(LOG_INFO, "SNI: [%s]", sni_name);
61     if (chrooted != 0 || loggedin != 0) {
62         return SSL_TLSEXT_ERR_NOACK;
63     }
64     if (use_extcert == 0) {
65         return SSL_TLSEXT_ERR_OK;
66     }
67     memset(&result, 0, sizeof result);
68     tls_extcert_get(&result, sni_name);
69     if (result.cert_ok != 1) {
70         die(400, LOG_ERR, "Cert handler not ready");
71     }
72     if (result.action == CERT_ACTION_DENY) {
73         die(400, LOG_INFO, MSG_LOGOUT);
74     }
75     if (result.action == CERT_ACTION_DEFAULT) {
76         return SSL_TLSEXT_ERR_OK;
77     }
78     if (result.cert_file == NULL) {
79         if (result.action == CERT_ACTION_STRICT) {
80             die(400, LOG_ERR, "Missing certificate");
81         } else {
82             return SSL_TLSEXT_ERR_OK;
83         }
84     }
85     if (result.key_file == NULL) {
86         result.key_file = result.cert_file;
87     }
88     SSL_CTX_free(tls_ctx);
89     tls_ctx = NULL;
90     if (tls_create_new_context(result.cert_file, result.key_file) != 0) {
91         if (result.action != CERT_ACTION_FALLBACK) {
92             die(400, LOG_ERR, "Invalid certificate");
93         }
94         if (tls_create_new_context(cert_file, key_file) != 0) {
95             die(400, LOG_ERR, "SSL error");
96         }
97     }
98     if ((client_sni_name = strdup(sni_name)) == NULL) {
99         die_mem();
100     }
101     if (tls_cnx != NULL) {
102         const long ctx_options = SSL_CTX_get_options(tls_ctx);
103         SSL_set_SSL_CTX(tls_cnx, tls_ctx);
104 # ifdef SSL_CTRL_CLEAR_OPTIONS
105         SSL_clear_options(tls_cnx,
106                           SSL_get_options(tls_cnx) & ~ctx_options);
107 # endif
108         SSL_set_options(tls_cnx, ctx_options);
109     }
110     if (tls_data_cnx != NULL) {
111         const long ctx_options = SSL_CTX_get_options(tls_ctx);
112         SSL_set_SSL_CTX(tls_data_cnx, tls_ctx);
113 # ifdef SSL_CTRL_CLEAR_OPTIONS
114         SSL_clear_options(tls_data_cnx,
115                           SSL_get_options(tls_cnx) & ~ctx_options);
116 # endif
117         SSL_set_options(tls_data_cnx, ctx_options);
118     }
119     return SSL_TLSEXT_ERR_OK;
120 }
121 
ssl_info_cb(const SSL * cnx,int where,int ret)122 static void ssl_info_cb(const SSL *cnx, int where, int ret)
123 {
124     (void) ret;
125 
126     if ((where & SSL_CB_HANDSHAKE_DONE) != 0) {
127         if (cnx == tls_cnx) {
128             tls_cnx_handshook = 1;
129         } else if (cnx == tls_data_cnx) {
130             tls_data_cnx_handshook = 1;
131         }
132     }
133 }
134 
tls_init_ecdh_curve(void)135 static int tls_init_ecdh_curve(void)
136 {
137 #ifdef SSL_CTRL_SET_ECDH_AUTO
138     SSL_CTX_ctrl(tls_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
139     return 0;
140 #else
141 # ifndef SSL_OP_SINGLE_ECDH_USE
142     errno = ENOTSUP;
143     return -1;
144 # else
145     const char *curve_name;
146     EC_KEY     *curve;
147     int         nid;
148 
149     curve_name = TLS_DEFAULT_ECDH_CURVE;
150     if ((nid = OBJ_sn2nid(curve_name)) == NID_undef) {
151         logfile(LOG_INFO, "Curve [%s] not supported", curve_name);
152         errno = ENOTSUP;
153         return -1;
154     }
155     if ((curve = EC_KEY_new_by_curve_name(nid)) == NULL) {
156         logfile(LOG_INFO, "Curve [%s] is not usable", curve_name);
157         errno = ENOTSUP;
158         return -1;
159     }
160     SSL_CTX_set_options(tls_ctx, SSL_OP_SINGLE_ECDH_USE);
161     SSL_CTX_set_tmp_ecdh(tls_ctx, curve);
162     EC_KEY_free(curve);
163 
164     return 0;
165 # endif
166 #endif
167 }
168 
169 #ifndef SSL_CTRL_SET_DH_AUTO
tls_load_dhparams_default(void)170 static int tls_load_dhparams_default(void)
171 {
172 # ifdef HAVE_DH_GET_2048_256
173     DH *dh;
174 
175     if ((dh = DH_get_2048_256()) == NULL) {
176         die_mem();
177     }
178 # else
179 #  if BN_BITS2 == 64
180 static const BN_ULONG dh2048_256_p[] = {
181     0xDB094AE91E1A1597ULL, 0x693877FAD7EF09CAULL, 0x6116D2276E11715FULL,
182     0xA4B54330C198AF12ULL, 0x75F26375D7014103ULL, 0xC3A3960A54E710C3ULL,
183     0xDED4010ABD0BE621ULL, 0xC0B857F689962856ULL, 0xB3CA3F7971506026ULL,
184     0x1CCACB83E6B486F6ULL, 0x67E144E514056425ULL, 0xF6A167B5A41825D9ULL,
185     0x3AD8347796524D8EULL, 0xF13C6D9A51BFA4ABULL, 0x2D52526735488A0EULL,
186     0xB63ACAE1CAA6B790ULL, 0x4FDB70C581B23F76ULL, 0xBC39A0BF12307F5CULL,
187     0xB941F54EB1E59BB8ULL, 0x6C5BFC11D45F9088ULL, 0x22E0B1EF4275BF7BULL,
188     0x91F9E6725B4758C0ULL, 0x5A8A9D306BCF67EDULL, 0x209E0C6497517ABDULL,
189     0x3BF4296D830E9A7CULL, 0x16C3D91134096FAAULL, 0xFAF7DF4561B2AA30ULL,
190     0xE00DF8F1D61957D4ULL, 0x5D2CEED4435E3B00ULL, 0x8CEEF608660DD0F2ULL,
191     0xFFBBD19C65195999ULL, 0x87A8E61DB4B6663CULL
192 };
193 static const BN_ULONG dh2048_256_g[] = {
194     0x664B4C0F6CC41659ULL, 0x5E2327CFEF98C582ULL, 0xD647D148D4795451ULL,
195     0x2F63078490F00EF8ULL, 0x184B523D1DB246C3ULL, 0xC7891428CDC67EB6ULL,
196     0x7FD028370DF92B52ULL, 0xB3353BBB64E0EC37ULL, 0xECD06E1557CD0915ULL,
197     0xB7D2BBD2DF016199ULL, 0xC8484B1E052588B9ULL, 0xDB2A3B7313D3FE14ULL,
198     0xD052B985D182EA0AULL, 0xA4BD1BFFE83B9C80ULL, 0xDFC967C1FB3F2E55ULL,
199     0xB5045AF2767164E1ULL, 0x1D14348F6F2F9193ULL, 0x64E67982428EBC83ULL,
200     0x8AC376D282D6ED38ULL, 0x777DE62AAAB8A862ULL, 0xDDF463E5E9EC144BULL,
201     0x0196F931C77A57F2ULL, 0xA55AE31341000A65ULL, 0x901228F8C28CBB18ULL,
202     0xBC3773BF7E8C6F62ULL, 0xBE3A6C1B0C6B47B1ULL, 0xFF4FED4AAC0BB555ULL,
203     0x10DBC15077BE463FULL, 0x07F4793A1A0BA125ULL, 0x4CA7B18F21EF2054ULL,
204     0x2E77506660EDBD48ULL, 0x3FB32C9B73134D0BULL
205 };
206 static const BN_ULONG dh2048_256_q[] = {
207     0xA308B0FE64F5FBD3ULL, 0x99B1A47D1EB3750BULL, 0xB447997640129DA2ULL,
208     0x8CF83642A709A097ULL
209 };
210 #  elif BN_BITS2 == 32
211 static const BN_ULONG dh2048_256_p[] = {
212     0x1E1A1597, 0xDB094AE9, 0xD7EF09CA, 0x693877FA, 0x6E11715F, 0x6116D227,
213     0xC198AF12, 0xA4B54330, 0xD7014103, 0x75F26375, 0x54E710C3, 0xC3A3960A,
214     0xBD0BE621, 0xDED4010A, 0x89962856, 0xC0B857F6, 0x71506026, 0xB3CA3F79,
215     0xE6B486F6, 0x1CCACB83, 0x14056425, 0x67E144E5, 0xA41825D9, 0xF6A167B5,
216     0x96524D8E, 0x3AD83477, 0x51BFA4AB, 0xF13C6D9A, 0x35488A0E, 0x2D525267,
217     0xCAA6B790, 0xB63ACAE1, 0x81B23F76, 0x4FDB70C5, 0x12307F5C, 0xBC39A0BF,
218     0xB1E59BB8, 0xB941F54E, 0xD45F9088, 0x6C5BFC11, 0x4275BF7B, 0x22E0B1EF,
219     0x5B4758C0, 0x91F9E672, 0x6BCF67ED, 0x5A8A9D30, 0x97517ABD, 0x209E0C64,
220     0x830E9A7C, 0x3BF4296D, 0x34096FAA, 0x16C3D911, 0x61B2AA30, 0xFAF7DF45,
221     0xD61957D4, 0xE00DF8F1, 0x435E3B00, 0x5D2CEED4, 0x660DD0F2, 0x8CEEF608,
222     0x65195999, 0xFFBBD19C, 0xB4B6663C, 0x87A8E61D
223 };
224 static const BN_ULONG dh2048_256_g[] = {
225     0x6CC41659, 0x664B4C0F, 0xEF98C582, 0x5E2327CF, 0xD4795451, 0xD647D148,
226     0x90F00EF8, 0x2F630784, 0x1DB246C3, 0x184B523D, 0xCDC67EB6, 0xC7891428,
227     0x0DF92B52, 0x7FD02837, 0x64E0EC37, 0xB3353BBB, 0x57CD0915, 0xECD06E15,
228     0xDF016199, 0xB7D2BBD2, 0x052588B9, 0xC8484B1E, 0x13D3FE14, 0xDB2A3B73,
229     0xD182EA0A, 0xD052B985, 0xE83B9C80, 0xA4BD1BFF, 0xFB3F2E55, 0xDFC967C1,
230     0x767164E1, 0xB5045AF2, 0x6F2F9193, 0x1D14348F, 0x428EBC83, 0x64E67982,
231     0x82D6ED38, 0x8AC376D2, 0xAAB8A862, 0x777DE62A, 0xE9EC144B, 0xDDF463E5,
232     0xC77A57F2, 0x0196F931, 0x41000A65, 0xA55AE313, 0xC28CBB18, 0x901228F8,
233     0x7E8C6F62, 0xBC3773BF, 0x0C6B47B1, 0xBE3A6C1B, 0xAC0BB555, 0xFF4FED4A,
234     0x77BE463F, 0x10DBC150, 0x1A0BA125, 0x07F4793A, 0x21EF2054, 0x4CA7B18F,
235     0x60EDBD48, 0x2E775066, 0x73134D0B, 0x3FB32C9B
236 };
237 static const BN_ULONG dh2048_256_q[] = {
238     0x64F5FBD3, 0xA308B0FE, 0x1EB3750B, 0x99B1A47D, 0x40129DA2, 0xB4479976,
239     0xA709A097, 0x8CF83642
240 };
241 #  else
242 #   error "unsupported BN_BITS2"
243 #  endif
244     static const BIGNUM p = {
245         (BN_ULONG *) dh2048_256_p,
246         sizeof(dh2048_256_p) / sizeof(BN_ULONG),
247         sizeof(dh2048_256_p) / sizeof(BN_ULONG),
248         0, BN_FLG_STATIC_DATA
249     };
250     static const BIGNUM g = {
251         (BN_ULONG *) dh2048_256_g,
252         sizeof(dh2048_256_g) / sizeof(BN_ULONG),
253         sizeof(dh2048_256_g) / sizeof(BN_ULONG),
254         0, BN_FLG_STATIC_DATA
255     };
256     static const BIGNUM q = {
257         (BN_ULONG *) dh2048_256_q,
258         sizeof(dh2048_256_q) / sizeof(BN_ULONG),
259         sizeof(dh2048_256_q) / sizeof(BN_ULONG),
260         0, BN_FLG_STATIC_DATA
261     };
262     DH *dh;
263 
264     if ((dh = DH_new()) == NULL) {
265         die_mem();
266     }
267     dh->p = BN_dup(&p);
268     dh->g = BN_dup(&g);
269     dh->q = BN_dup(&q);
270     if (dh->p == NULL || dh->g == NULL || dh->q == NULL) {
271         DH_free(dh);
272         die_mem();
273     }
274 # endif
275     SSL_CTX_set_tmp_dh(tls_ctx, dh);
276     DH_free(dh);
277 # ifdef SSL_OP_SINGLE_DH_USE
278     SSL_CTX_set_options(tls_ctx, SSL_OP_SINGLE_DH_USE);
279 # endif
280 
281     return 0;
282 }
283 #endif
284 
tls_init_dhparams(void)285 static void tls_init_dhparams(void)
286 {
287 # ifdef SSL_CTRL_SET_DH_AUTO
288     SSL_CTX_ctrl(tls_ctx, SSL_CTRL_SET_DH_AUTO, 1, NULL);
289 # else
290     tls_load_dhparams_default();
291 # endif
292 }
293 
tls_init_cache(void)294 static void tls_init_cache(void)
295 {
296     static const char *tls_ctx_id = "pure-ftpd";
297 
298     SSL_CTX_set_session_cache_mode(tls_ctx, SSL_SESS_CACHE_SERVER);
299     SSL_CTX_set_session_id_context(tls_ctx, (unsigned char *) tls_ctx_id,
300                                    (unsigned int) strlen(tls_ctx_id));
301     SSL_CTX_sess_set_cache_size(tls_ctx, 10);
302     SSL_CTX_set_timeout(tls_ctx, 60 * 60L);
303 }
304 
tls_init_options(void)305 static void tls_init_options(void)
306 {
307     static int passes;
308 
309 # ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
310     SSL_CTX_set_options(tls_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
311 # endif
312 # ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
313     SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
314 # endif
315     SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv2);
316     SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv3);
317 # ifdef SSL_OP_NO_TLSv1
318     SSL_CTX_set_options(tls_ctx, SSL_OP_NO_TLSv1);
319 # endif
320 # ifdef SSL_OP_NO_TLSv1_1
321     SSL_CTX_set_options(tls_ctx, SSL_OP_NO_TLSv1_1);
322 # endif
323 # ifdef SSL_OP_NO_TLSv1_2
324     SSL_CTX_clear_options(tls_ctx, SSL_OP_NO_TLSv1_2);
325 # endif
326 # ifdef SSL_OP_NO_TLSv1_3
327     SSL_CTX_clear_options(tls_ctx, SSL_OP_NO_TLSv1_3);
328 # endif
329     SSL_CTX_set_num_tickets(tls_ctx, 0);
330     if (tlsciphersuite != NULL) {
331         if (SSL_CTX_set_cipher_list(tls_ctx, tlsciphersuite) != 1) {
332             logfile(LOG_ERR, MSG_TLS_CIPHER_FAILED, tlsciphersuite);
333             _EXIT(EXIT_FAILURE);
334         }
335     }
336     SSL_CTX_set_info_callback(tls_ctx, ssl_info_cb);
337     if (passes == 0) {
338         SSL_CTX_set_tlsext_servername_callback(tls_ctx, ssl_servername_cb);
339         passes++;
340     }
341     SSL_CTX_set_verify_depth(tls_ctx, MAX_CERTIFICATE_DEPTH);
342 }
343 
tls_load_cert_file(const char * const cert_file,const char * const key_file)344 static void tls_load_cert_file(const char * const cert_file,
345                                const char * const key_file)
346 {
347     if (SSL_CTX_use_certificate_chain_file(tls_ctx, cert_file) != 1) {
348         die(421, LOG_ERR,
349             MSG_FILE_DOESNT_EXIST ": [%s]", cert_file);
350     }
351     if (SSL_CTX_use_PrivateKey_file(tls_ctx, key_file,
352                                     SSL_FILETYPE_PEM) != 1) {
353         die(421, LOG_ERR,
354             MSG_FILE_DOESNT_EXIST ": [%s]", key_file);
355     }
356     if (SSL_CTX_check_private_key(tls_ctx) != 1) {
357         tls_error(__LINE__, 0);
358     }
359 }
360 
tls_init_client_cert_verification(const char * cert_file)361 static void tls_init_client_cert_verification(const char *cert_file)
362 {
363     if (cert_file == NULL) {
364         tls_error(__LINE__, 0);
365     }
366     SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
367                        SSL_VERIFY_PEER, NULL);
368     if (SSL_CTX_load_verify_locations(tls_ctx, cert_file, NULL) != 1) {
369         tls_error(__LINE__, 0);
370     }
371 }
372 
tls_create_new_context(const char * cert_file,const char * key_file)373 static int tls_create_new_context(const char *cert_file,
374                                   const char *key_file)
375 {
376 # ifdef HAVE_TLS_SERVER_METHOD
377     if ((tls_ctx = SSL_CTX_new(TLS_server_method())) == NULL) {
378         tls_error(__LINE__, 0);
379     }
380 # else
381     if ((tls_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
382         tls_error(__LINE__, 0);
383     }
384 # endif
385     tls_init_options();
386     tls_init_cache();
387     tls_load_cert_file(cert_file, key_file);
388     if (ssl_verify_client_cert) {
389         tls_init_client_cert_verification(cert_file);
390     }
391     tls_init_ecdh_curve();
392     tls_init_dhparams();
393 
394     return 0;
395 }
396 
tls_init_rnd(void)397 static void tls_init_rnd(void)
398 {
399     unsigned int rnd;
400 
401     while (RAND_status() == 0) {
402         rnd = zrand();
403         RAND_seed(&rnd, (int) sizeof rnd);
404     }
405 }
406 
tls_init_library(void)407 int tls_init_library(void)
408 {
409     tls_cnx = NULL;
410     tls_data_cnx = NULL;
411     tls_ctx = NULL;
412 
413 # if (OPENSSL_VERSION_NUMBER < 0x10100000L) || !defined(OPENSSL_INIT_LOAD_SSL_STRINGS)
414     SSL_library_init();
415     SSL_load_error_strings();
416     OpenSSL_add_all_algorithms();
417 # else
418     OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
419                      OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
420     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
421                         OPENSSL_INIT_ADD_ALL_DIGESTS |
422                         OPENSSL_INIT_LOAD_CONFIG, NULL);
423 # endif
424     tls_init_rnd();
425     tls_create_new_context(cert_file, key_file);
426     tls_cnx_handshook = 0;
427     tls_data_cnx_handshook = 0;
428 
429     return 0;
430 }
431 
tls_free_library(void)432 void tls_free_library(void)
433 {
434     if (tls_data_cnx != NULL) {
435         tls_close_session(&tls_data_cnx);
436     }
437     if (tls_cnx != NULL) {
438         SSL_free(tls_cnx);
439         tls_cnx = NULL;
440     }
441     if (tls_ctx != NULL) {
442         SSL_CTX_free(tls_ctx);
443         tls_ctx = NULL;
444     }
445 # if OPENSSL_API_COMPAT < 0x10100000L
446     EVP_cleanup();
447 # endif
448 }
449 
tls_init_new_session(void)450 int tls_init_new_session(void)
451 {
452     const SSL_CIPHER *cipher;
453     int ret;
454     int ret_;
455 
456     if (tls_ctx == NULL || (tls_cnx = SSL_new(tls_ctx)) == NULL) {
457         tls_error(__LINE__, 0);
458     }
459     if (SSL_set_fd(tls_cnx, clientfd) != 1) {
460         tls_error(__LINE__, 0);
461     }
462     SSL_set_accept_state(tls_cnx);
463     for (;;) {
464         ret = SSL_accept(tls_cnx);
465         if (ret != 1) {
466             ret_ = SSL_get_error(tls_cnx, ret);
467             if (ret == -1 &&
468                 (ret_ == SSL_ERROR_WANT_READ ||
469                  ret_ == SSL_ERROR_WANT_WRITE)) {
470                 continue;
471             }
472             die(400, LOG_WARNING, MSG_TLS_NEEDED);
473         }
474         break;
475     }
476     if ((cipher = SSL_get_current_cipher(tls_cnx)) != NULL) {
477         int strength_bits = SSL_CIPHER_get_bits(cipher, NULL);
478 
479         logfile(LOG_INFO, MSG_TLS_INFO, SSL_CIPHER_get_version(cipher),
480                 SSL_CIPHER_get_name(cipher), strength_bits);
481         if (strength_bits < MINIMAL_CIPHER_STRENGTH_BITS) {
482             die(534, LOG_ERR, MSG_TLS_WEAK);
483         }
484     }
485     return 0;
486 }
487 
tls_init_data_session(const int fd,const int passive)488 int tls_init_data_session(const int fd, const int passive)
489 {
490     const SSL_CIPHER *cipher;
491     int ret;
492     int ret_;
493 
494     (void) passive;
495     if (tls_ctx == NULL) {
496         logfile(LOG_ERR, MSG_TLS_NO_CTX);
497         tls_error(__LINE__, 0);
498     }
499     if (tls_data_cnx != NULL) {
500         tls_close_session(&tls_data_cnx);
501     } else if ((tls_data_cnx = SSL_new(tls_ctx)) == NULL) {
502         tls_error(__LINE__, 0);
503     }
504     if (SSL_set_fd(tls_data_cnx, fd) != 1) {
505         tls_error(__LINE__, 0);
506     }
507     SSL_set_accept_state(tls_data_cnx);
508     for (;;) {
509         ret = SSL_accept(tls_data_cnx);
510         if (ret <= 0) {
511             ret_ = SSL_get_error(tls_data_cnx, ret);
512             if (ret == -1 && (ret_ == SSL_ERROR_WANT_READ ||
513                               ret_ == SSL_ERROR_WANT_WRITE)) {
514                 continue;
515             }
516             logfile(LOG_INFO, MSG_LOGOUT);
517             _EXIT(EXIT_FAILURE);
518         }
519         break;
520     }
521     if ((cipher = SSL_get_current_cipher(tls_data_cnx)) != NULL) {
522         int strength_bits = SSL_CIPHER_get_bits(cipher, NULL);
523 
524         logfile(LOG_INFO, MSG_TLS_INFO, SSL_CIPHER_get_version(cipher),
525                 SSL_CIPHER_get_name(cipher), strength_bits);
526         if (strength_bits < MINIMAL_CIPHER_STRENGTH_BITS) {
527             die(534, LOG_ERR, MSG_TLS_WEAK);
528         }
529     }
530     return 0;
531 }
532 
tls_close_session(SSL ** const cnx)533 void tls_close_session(SSL ** const cnx)
534 {
535     unsigned int retries = 10U;
536     unsigned int max_shutdowns = 2;
537 
538     if (*cnx == NULL) {
539         return;
540     }
541 retry:
542     switch (SSL_shutdown(*cnx)) {
543     case 0:
544         if (--max_shutdowns > 0) {
545             goto retry;
546         }
547     case 1:
548         break;
549     default: {
550         switch (SSL_get_error(*cnx, -1)) {
551         case SSL_ERROR_WANT_READ:
552         case SSL_ERROR_WANT_WRITE: {
553             struct pollfd pfd;
554             pfd.fd = SSL_get_fd(*cnx);
555             pfd.events = POLLIN | POLLOUT | POLLERR | POLLHUP;
556             pfd.revents = 0;
557             if (poll(&pfd, 1U, idletime * 1000UL) > 0 && retries-- > 0U) {
558                 goto retry;
559             }
560           }
561         }
562         if (SSL_clear(*cnx) == 1) {
563             break;
564         }
565         tls_error(__LINE__, 0);
566       }
567     }
568     if (*cnx == tls_cnx) {
569         tls_cnx_handshook = 0;
570     } else if (*cnx == tls_data_cnx) {
571         tls_data_cnx_handshook = 0;
572     }
573     SSL_free(*cnx);
574     *cnx = NULL;
575 }
576 
577 #endif
578