1 /*
2  *  This file is part of nzbget. See <http://nzbget.net>.
3  *
4  *  Copyright (C) 2008-2017 Andrey Prygunkov <hugbug@users.sourceforge.net>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 #include "nzbget.h"
22 
23 #ifndef DISABLE_TLS
24 
25 #include "TlsSocket.h"
26 #include "Thread.h"
27 #include "Log.h"
28 #include "Util.h"
29 #include "FileSystem.h"
30 
31 CString TlsSocket::m_certStore;
32 
33 #ifdef HAVE_LIBGNUTLS
34 #ifdef NEED_GCRYPT_LOCKING
35 
36 /**
37  * Mutexes for gcryptlib
38  */
39 
40 std::vector<std::unique_ptr<Mutex>> g_GCryptLibMutexes;
41 
gcry_mutex_init(void ** priv)42 static int gcry_mutex_init(void **priv)
43 {
44 	g_GCryptLibMutexes.emplace_back(std::make_unique<Mutex>());
45 	*priv = g_GCryptLibMutexes.back().get();
46 	return 0;
47 }
48 
gcry_mutex_destroy(void ** lock)49 static int gcry_mutex_destroy(void **lock)
50 {
51 	Mutex* mutex = ((Mutex*)*lock);
52 	g_GCryptLibMutexes.erase(std::find_if(g_GCryptLibMutexes.begin(), g_GCryptLibMutexes.end(),
53 		[mutex](std::unique_ptr<Mutex>& itMutex)
54 		{
55 			return itMutex.get() == mutex;
56 		}));
57 	return 0;
58 }
59 
gcry_mutex_lock(void ** lock)60 static int gcry_mutex_lock(void **lock)
61 {
62 	((Mutex*)*lock)->Lock();
63 	return 0;
64 }
65 
gcry_mutex_unlock(void ** lock)66 static int gcry_mutex_unlock(void **lock)
67 {
68 	((Mutex*)*lock)->Unlock();
69 	return 0;
70 }
71 
72 static struct gcry_thread_cbs gcry_threads_Mutex =
73 {	GCRY_THREAD_OPTION_USER, nullptr,
74 	gcry_mutex_init, gcry_mutex_destroy,
75 	gcry_mutex_lock, gcry_mutex_unlock,
76 	nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
77 };
78 
79 #endif /* NEED_GCRYPT_LOCKING */
80 #endif /* HAVE_LIBGNUTLS */
81 
82 
83 #ifdef HAVE_OPENSSL
84 
85 #ifndef CRYPTO_set_locking_callback
86 #define NEED_CRYPTO_LOCKING
87 #endif
88 
89 #ifdef NEED_CRYPTO_LOCKING
90 
91 /**
92  * Mutexes for OpenSSL
93  */
94 
95 std::vector<std::unique_ptr<Mutex>> g_OpenSSLMutexes;
96 
openssl_locking(int mode,int n,const char * file,int line)97 static void openssl_locking(int mode, int n, const char* file, int line)
98 {
99 	Mutex* mutex = g_OpenSSLMutexes[n].get();
100 	if (mode & CRYPTO_LOCK)
101 	{
102 		mutex->Lock();
103 	}
104 	else
105 	{
106 		mutex->Unlock();
107 	}
108 }
109 
openssl_dynlock_create(const char * file,int line)110 static struct CRYPTO_dynlock_value* openssl_dynlock_create(const char *file, int line)
111 {
112 	return (CRYPTO_dynlock_value*)new Mutex();
113 }
114 
openssl_dynlock_destroy(struct CRYPTO_dynlock_value * l,const char * file,int line)115 static void openssl_dynlock_destroy(struct CRYPTO_dynlock_value *l, const char *file, int line)
116 {
117 	Mutex* mutex = (Mutex*)l;
118 	delete mutex;
119 }
120 
openssl_dynlock_lock(int mode,struct CRYPTO_dynlock_value * l,const char * file,int line)121 static void openssl_dynlock_lock(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
122 {
123 	Mutex* mutex = (Mutex*)l;
124 	if (mode & CRYPTO_LOCK)
125 	{
126 		mutex->Lock();
127 	}
128 	else
129 	{
130 		mutex->Unlock();
131 	}
132 }
133 
134 #endif /* NEED_CRYPTO_LOCKING */
135 #endif /* HAVE_OPENSSL */
136 
137 
Init()138 void TlsSocket::Init()
139 {
140 	debug("Initializing TLS library");
141 
142 #ifdef HAVE_LIBGNUTLS
143 	int error_code;
144 
145 #ifdef NEED_GCRYPT_LOCKING
146 	error_code = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_Mutex);
147 	if (error_code != 0)
148 	{
149 		error("Could not initialize libcrypt");
150 		return;
151 	}
152 #endif /* NEED_GCRYPT_LOCKING */
153 
154 	error_code = gnutls_global_init();
155 	if (error_code != 0)
156 	{
157 		error("Could not initialize libgnutls");
158 		return;
159 	}
160 
161 #endif /* HAVE_LIBGNUTLS */
162 
163 #ifdef HAVE_OPENSSL
164 
165 #ifdef NEED_CRYPTO_LOCKING
166 	for (int i = 0, num = CRYPTO_num_locks(); i < num; i++)
167 	{
168 		g_OpenSSLMutexes.emplace_back(std::make_unique<Mutex>());
169 	}
170 
171 	CRYPTO_set_locking_callback(openssl_locking);
172 	CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
173 	CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
174 	CRYPTO_set_dynlock_lock_callback(openssl_dynlock_lock);
175 #endif /* NEED_CRYPTO_LOCKING */
176 
177 	SSL_load_error_strings();
178 	SSL_library_init();
179 	OpenSSL_add_all_algorithms();
180 
181 #endif /* HAVE_OPENSSL */
182 }
183 
Final()184 void TlsSocket::Final()
185 {
186 #ifdef HAVE_LIBGNUTLS
187 	gnutls_global_deinit();
188 #endif /* HAVE_LIBGNUTLS */
189 
190 #ifdef HAVE_OPENSSL
191 #ifndef LIBRESSL_VERSION_NUMBER
192 	FIPS_mode_set(0);
193 #endif
194 #ifdef NEED_CRYPTO_LOCKING
195 	CRYPTO_set_locking_callback(nullptr);
196 	CRYPTO_set_id_callback(nullptr);
197 #endif
198 #if OPENSSL_VERSION_NUMBER < 0x10100000L
199 	ERR_remove_state(0);
200 #endif
201 #if	OPENSSL_VERSION_NUMBER >= 0x10002000L && ! defined (LIBRESSL_VERSION_NUMBER)
202 	SSL_COMP_free_compression_methods();
203 #endif
204 	//ENGINE_cleanup();
205 	CONF_modules_free();
206 	CONF_modules_unload(1);
207 #ifndef OPENSSL_NO_COMP
208 	COMP_zlib_cleanup();
209 #endif
210 	ERR_free_strings();
211 	EVP_cleanup();
212 	CRYPTO_cleanup_all_ex_data();
213 #endif /* HAVE_OPENSSL */
214 }
215 
~TlsSocket()216 TlsSocket::~TlsSocket()
217 {
218 	Close();
219 
220 #ifdef HAVE_OPENSSL
221 #if OPENSSL_VERSION_NUMBER < 0x10100000L
222 	ERR_remove_state(0);
223 #endif
224 #endif
225 }
226 
ReportError(const char * errMsg,bool suppressable)227 void TlsSocket::ReportError(const char* errMsg, bool suppressable)
228 {
229 #ifdef HAVE_LIBGNUTLS
230 	const char* errstr = gnutls_strerror(m_retCode);
231 	if (suppressable && m_suppressErrors)
232 	{
233 		debug("%s: %s", errMsg, errstr);
234 	}
235 	else
236 	{
237 		PrintError(BString<1024>("%s: %s", errMsg, errstr));
238 	}
239 #endif /* HAVE_LIBGNUTLS */
240 
241 #ifdef HAVE_OPENSSL
242 	int errcode = ERR_get_error();
243 	do
244 	{
245 		char errstr[1024];
246 		ERR_error_string_n(errcode, errstr, sizeof(errstr));
247 		errstr[1024-1] = '\0';
248 
249 		if (suppressable && m_suppressErrors)
250 		{
251 			debug("%s: %s", errMsg, errstr);
252 		}
253 		else if (errcode != 0)
254 		{
255 			PrintError(BString<1024>("%s: %s", errMsg, errstr));
256 		}
257 		else
258 		{
259 			PrintError(errMsg);
260 		}
261 
262 		errcode = ERR_get_error();
263 	} while (errcode);
264 #endif /* HAVE_OPENSSL */
265 }
266 
PrintError(const char * errMsg)267 void TlsSocket::PrintError(const char* errMsg)
268 {
269 	error("%s", errMsg);
270 }
271 
Start()272 bool TlsSocket::Start()
273 {
274 #ifdef HAVE_LIBGNUTLS
275 	gnutls_certificate_credentials_t cred;
276 	m_retCode = gnutls_certificate_allocate_credentials(&cred);
277 	if (m_retCode != 0)
278 	{
279 		ReportError("Could not create TLS context", false);
280 		return false;
281 	}
282 
283 	m_context = cred;
284 
285 	if (m_certFile && m_keyFile)
286 	{
287 		m_retCode = gnutls_certificate_set_x509_key_file((gnutls_certificate_credentials_t)m_context,
288 			m_certFile, m_keyFile, GNUTLS_X509_FMT_PEM);
289 		if (m_retCode != 0)
290 		{
291 			ReportError("Could not load certificate or key file", false);
292 			Close();
293 			return false;
294 		}
295 	}
296 
297 	gnutls_session_t sess;
298 	m_retCode = gnutls_init(&sess, m_isClient ? GNUTLS_CLIENT : GNUTLS_SERVER);
299 	if (m_retCode != 0)
300 	{
301 		ReportError("Could not create TLS session", false);
302 		Close();
303 		return false;
304 	}
305 
306 	m_session = sess;
307 
308 	m_initialized = true;
309 
310 	const char* priority = !m_cipher.Empty() ? m_cipher.Str() :
311 		(m_certFile && m_keyFile ? "NORMAL:!VERS-SSL3.0" : "NORMAL");
312 
313 	m_retCode = gnutls_priority_set_direct((gnutls_session_t)m_session, priority, nullptr);
314 	if (m_retCode != 0)
315 	{
316 		ReportError("Could not select cipher for TLS", false);
317 		Close();
318 		return false;
319 	}
320 
321 	if (m_host)
322 	{
323 		m_retCode = gnutls_server_name_set((gnutls_session_t)m_session, GNUTLS_NAME_DNS, m_host, m_host.Length());
324 		if (m_retCode != 0)
325 		{
326 			ReportError("Could not set hostname for TLS");
327 			Close();
328 			return false;
329 		}
330 	}
331 
332 	m_retCode = gnutls_credentials_set((gnutls_session_t)m_session, GNUTLS_CRD_CERTIFICATE,
333 		(gnutls_certificate_credentials_t*)m_context);
334 	if (m_retCode != 0)
335 	{
336 		ReportError("Could not initialize TLS session", false);
337 		Close();
338 		return false;
339 	}
340 
341 	gnutls_transport_set_ptr((gnutls_session_t)m_session, (gnutls_transport_ptr_t)(size_t)m_socket);
342 
343 	m_retCode = gnutls_handshake((gnutls_session_t)m_session);
344 	if (m_retCode != 0)
345 	{
346 		ReportError(BString<1024>("TLS handshake failed for %s", *m_host));
347 		Close();
348 		return false;
349 	}
350 
351 	if (m_isClient && !m_certStore.Empty() && !ValidateCert())
352 	{
353 		Close();
354 		return false;
355 	}
356 
357 	m_connected = true;
358 	return true;
359 #endif /* HAVE_LIBGNUTLS */
360 
361 #ifdef HAVE_OPENSSL
362 	m_context = SSL_CTX_new(SSLv23_method());
363 
364 	if (!m_context)
365 	{
366 		ReportError("Could not create TLS context", false);
367 		return false;
368 	}
369 
370 	if (m_certFile && m_keyFile)
371 	{
372 		if (SSL_CTX_use_certificate_chain_file((SSL_CTX*)m_context, m_certFile) != 1)
373 		{
374 			ReportError("Could not load certificate file", false);
375 			Close();
376 			return false;
377 		}
378 		if (SSL_CTX_use_PrivateKey_file((SSL_CTX*)m_context, m_keyFile, SSL_FILETYPE_PEM) != 1)
379 		{
380 			ReportError("Could not load key file", false);
381 			Close();
382 			return false;
383 		}
384 		if (!SSL_CTX_set_options((SSL_CTX*)m_context, SSL_OP_NO_SSLv3))
385 		{
386 			ReportError("Could not select minimum protocol version for TLS", false);
387 			Close();
388 			return false;
389 		}
390 
391 		// For ECC certificates
392 		EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
393 		if (!ecdh)
394 		{
395 			ReportError("Could not generate ecdh parameters for TLS", false);
396 			Close();
397 			return false;
398 		}
399 		if (!SSL_CTX_set_tmp_ecdh((SSL_CTX*)m_context, ecdh))
400 		{
401 			ReportError("Could not set ecdh parameters for TLS", false);
402 			EC_KEY_free(ecdh);
403 			Close();
404 			return false;
405 		}
406 		EC_KEY_free(ecdh);
407 	}
408 
409 	if (m_isClient && !m_certStore.Empty())
410 	{
411 		// Enable certificate validation
412 		if (SSL_CTX_load_verify_locations((SSL_CTX*)m_context, m_certStore, nullptr) != 1)
413 		{
414 			ReportError("Could not set certificate store location", false);
415 			Close();
416 			return false;
417 		}
418 
419 		SSL_CTX_set_verify((SSL_CTX*)m_context, SSL_VERIFY_PEER, nullptr);
420 	}
421 
422 	m_session = SSL_new((SSL_CTX*)m_context);
423 	if (!m_session)
424 	{
425 		ReportError("Could not create TLS session", false);
426 		Close();
427 		return false;
428 	}
429 
430 	if (!m_cipher.Empty() && !SSL_set_cipher_list((SSL*)m_session, m_cipher))
431 	{
432 		ReportError("Could not select cipher for TLS", false);
433 		Close();
434 		return false;
435 	}
436 
437 	if (m_isClient && m_host && !SSL_set_tlsext_host_name((SSL*)m_session, m_host))
438 	{
439 		ReportError("Could not set host name for TLS");
440 		Close();
441 		return false;
442 	}
443 
444 	if (!SSL_set_fd((SSL*)m_session, (int)m_socket))
445 	{
446 		ReportError("Could not set the file descriptor for TLS");
447 		Close();
448 		return false;
449 	}
450 
451 	int error_code = m_isClient ? SSL_connect((SSL*)m_session) : SSL_accept((SSL*)m_session);
452 	if (error_code < 1)
453 	{
454 		long verifyRes = SSL_get_verify_result((SSL*)m_session);
455 		if (verifyRes != X509_V_OK)
456 		{
457 			PrintError(BString<1024>("TLS certificate verification failed for %s: %s."
458 				" For more info visit http://nzbget.net/certificate-verification",
459 				*m_host, X509_verify_cert_error_string(verifyRes)));
460 		}
461 		else
462 		{
463 			ReportError(BString<1024>("TLS handshake failed for %s", *m_host));
464 		}
465 		Close();
466 		return false;
467 	}
468 
469 	if (m_isClient && !m_certStore.Empty() && !ValidateCert())
470 	{
471 		Close();
472 		return false;
473 	}
474 
475 	m_connected = true;
476 	return true;
477 #endif /* HAVE_OPENSSL */
478 }
479 
ValidateCert()480 bool TlsSocket::ValidateCert()
481 {
482 #ifdef HAVE_LIBGNUTLS
483 #if	GNUTLS_VERSION_NUMBER >= 0x030104
484 #if	GNUTLS_VERSION_NUMBER >= 0x030306
485 	if (FileSystem::DirectoryExists(m_certStore))
486 	{
487 		if (gnutls_certificate_set_x509_trust_dir((gnutls_certificate_credentials_t)m_context, m_certStore, GNUTLS_X509_FMT_PEM) < 0)
488 		{
489 			ReportError("Could not set certificate store location");
490 			return false;
491 		}
492 	}
493 	else
494 #endif
495 	{
496 		if (gnutls_certificate_set_x509_trust_file((gnutls_certificate_credentials_t)m_context, m_certStore, GNUTLS_X509_FMT_PEM) < 0)
497 		{
498 			ReportError("Could not set certificate store location");
499 			return false;
500 		}
501 	}
502 
503 	unsigned int status = 0;
504 	if (gnutls_certificate_verify_peers3((gnutls_session_t)m_session, m_host, &status) != 0 ||
505 		gnutls_certificate_type_get((gnutls_session_t)m_session) != GNUTLS_CRT_X509)
506 	{
507 		ReportError("Could not verify TLS certificate");
508 		return false;
509 	}
510 
511 	if (status != 0)
512 	{
513 		if (status & GNUTLS_CERT_UNEXPECTED_OWNER)
514 		{
515 			// Extracting hostname from the certificate
516 			unsigned int cert_list_size = 0;
517 			const gnutls_datum_t* cert_list = gnutls_certificate_get_peers((gnutls_session_t)m_session, &cert_list_size);
518 			if (cert_list_size > 0)
519 			{
520 				gnutls_x509_crt_t cert;
521 				gnutls_x509_crt_init(&cert);
522 				gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
523 				char dn[256];
524 				size_t size = sizeof(dn);
525 				if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, dn, &size) == 0)
526 				{
527 					PrintError(BString<1024>("TLS certificate verification failed for %s: certificate hostname mismatch (%s)."
528 						" For more info visit http://nzbget.net/certificate-verification", *m_host, dn));
529 					gnutls_x509_crt_deinit(cert);
530 					return false;
531 				}
532 				gnutls_x509_crt_deinit(cert);
533 			}
534 		}
535 
536 		gnutls_datum_t msgdata;
537 		if (gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &msgdata, 0) == 0)
538 		{
539 			PrintError(BString<1024>("TLS certificate verification failed for %s: %s."
540 				" For more info visit http://nzbget.net/certificate-verification", *m_host, msgdata.data));
541 			gnutls_free(&msgdata);
542 		}
543 		else
544 		{
545 			ReportError(BString<1024>("TLS certificate verification failed for %s."
546 				" For more info visit http://nzbget.net/certificate-verification", *m_host));
547 		}
548 		return false;
549 	}
550 #endif
551 	return true;
552 #endif /* HAVE_LIBGNUTLS */
553 
554 #ifdef HAVE_OPENSSL
555 	// verify a server certificate was presented during the negotiation
556 	X509* cert = SSL_get_peer_certificate((SSL*)m_session);
557 	if (!cert)
558 	{
559 		PrintError(BString<1024>("TLS certificate verification failed for %s: no certificate provided by server."
560 			" For more info visit http://nzbget.net/certificate-verification", *m_host));
561 		return false;
562 	}
563 
564 #ifdef HAVE_X509_CHECK_HOST
565 	// hostname verification
566 	if (!m_host.Empty() && X509_check_host(cert, m_host, m_host.Length(), 0, nullptr) != 1)
567 	{
568 		const unsigned char* certHost = nullptr;
569         // Find the position of the CN field in the Subject field of the certificate
570         int common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name(cert), NID_commonName, -1);
571         if (common_name_loc >= 0)
572 		{
573 			// Extract the CN field
574 			X509_NAME_ENTRY* common_name_entry = X509_NAME_get_entry(X509_get_subject_name(cert), common_name_loc);
575 			if (common_name_entry != nullptr)
576 			{
577 				// Convert the CN field to a C string
578 				ASN1_STRING* common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
579 				if (common_name_asn1 != nullptr)
580 				{
581 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
582 					certHost = ASN1_STRING_get0_data(common_name_asn1);
583 #else
584 					certHost = ASN1_STRING_data(common_name_asn1);
585 #endif
586 				}
587 			}
588         }
589 
590 		PrintError(BString<1024>("TLS certificate verification failed for %s: certificate hostname mismatch (%s)."
591 			" For more info visit http://nzbget.net/certificate-verification", *m_host, certHost));
592 		X509_free(cert);
593 		return false;
594 	}
595 #endif
596 
597 	X509_free(cert);
598 	return true;
599 #endif /* HAVE_OPENSSL */
600 }
601 
Close()602 void TlsSocket::Close()
603 {
604 	if (m_session)
605 	{
606 #ifdef HAVE_LIBGNUTLS
607 		if (m_connected)
608 		{
609 			gnutls_bye((gnutls_session_t)m_session, GNUTLS_SHUT_WR);
610 		}
611 		if (m_initialized)
612 		{
613 			gnutls_deinit((gnutls_session_t)m_session);
614 		}
615 #endif /* HAVE_LIBGNUTLS */
616 
617 #ifdef HAVE_OPENSSL
618 		if (m_connected)
619 		{
620 			SSL_shutdown((SSL*)m_session);
621 		}
622 		SSL_free((SSL*)m_session);
623 #endif /* HAVE_OPENSSL */
624 
625 		m_session = nullptr;
626 	}
627 
628 	if (m_context)
629 	{
630 #ifdef HAVE_LIBGNUTLS
631 		gnutls_certificate_free_credentials((gnutls_certificate_credentials_t)m_context);
632 #endif /* HAVE_LIBGNUTLS */
633 
634 #ifdef HAVE_OPENSSL
635 		SSL_CTX_free((SSL_CTX*)m_context);
636 #endif /* HAVE_OPENSSL */
637 
638 		m_context = nullptr;
639 	}
640 }
641 
Send(const char * buffer,int size)642 int TlsSocket::Send(const char* buffer, int size)
643 {
644 #ifdef HAVE_LIBGNUTLS
645 	m_retCode = gnutls_record_send((gnutls_session_t)m_session, buffer, size);
646 #endif /* HAVE_LIBGNUTLS */
647 
648 #ifdef HAVE_OPENSSL
649 	m_retCode = SSL_write((SSL*)m_session, buffer, size);
650 #endif /* HAVE_OPENSSL */
651 
652 	if (m_retCode < 0)
653 	{
654 #ifdef HAVE_OPENSSL
655 		if (ERR_peek_error() == 0)
656 		{
657 			ReportError("Could not write to TLS-Socket: Connection closed by remote host");
658 		}
659 		else
660 #endif /* HAVE_OPENSSL */
661 		ReportError("Could not write to TLS-Socket");
662 		return -1;
663 	}
664 
665 	return m_retCode;
666 }
667 
Recv(char * buffer,int size)668 int TlsSocket::Recv(char* buffer, int size)
669 {
670 #ifdef HAVE_LIBGNUTLS
671 	m_retCode = gnutls_record_recv((gnutls_session_t)m_session, buffer, size);
672 #endif /* HAVE_LIBGNUTLS */
673 
674 #ifdef HAVE_OPENSSL
675 	m_retCode = SSL_read((SSL*)m_session, buffer, size);
676 #endif /* HAVE_OPENSSL */
677 
678 	if (m_retCode < 0)
679 	{
680 #ifdef HAVE_OPENSSL
681 		if (ERR_peek_error() == 0)
682 		{
683 			ReportError("Could not read from TLS-Socket: Connection closed by remote host");
684 		}
685 		else
686 #endif /* HAVE_OPENSSL */
687 		{
688 			ReportError("Could not read from TLS-Socket");
689 		}
690 		return -1;
691 	}
692 
693 	return m_retCode;
694 }
695 
696 #endif
697