• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2022 IBM Corp., Ian Craggs
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  *    https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  *   http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  *    Ian Craggs, Allan Stockdill-Mander - initial implementation
15  *    Ian Craggs - fix for bug #409702
16  *    Ian Craggs - allow compilation for OpenSSL < 1.0
17  *    Ian Craggs - fix for bug #453883
18  *    Ian Craggs - fix for bug #480363, issue 13
19  *    Ian Craggs - SNI support
20  *    Ian Craggs - fix for issues #155, #160
21  *******************************************************************************/
22 
23 /**
24  * @file
25  * \brief SSL  related functions
26  *
27  */
28 
29 #if defined(OPENSSL)
30 
31 #include "SocketBuffer.h"
32 #include "MQTTClient.h"
33 #include "MQTTProtocolOut.h"
34 #include "SSLSocket.h"
35 #include "Log.h"
36 #include "StackTrace.h"
37 #include "Socket.h"
38 
39 #include "Heap.h"
40 
41 #include <string.h>
42 #include <openssl/ssl.h>
43 #include <openssl/err.h>
44 #include <openssl/crypto.h>
45 #include <openssl/x509v3.h>
46 
47 extern Sockets mod_s;
48 
49 static int SSLSocket_error(char* aString, SSL* ssl, SOCKET sock, int rc, int (*cb)(const char *str, size_t len, void *u), void* u);
50 char* SSL_get_verify_result_string(int rc);
51 void SSL_CTX_info_callback(const SSL* ssl, int where, int ret);
52 char* SSLSocket_get_version_string(int version);
53 void SSL_CTX_msg_callback(
54 		int write_p,
55 		int version,
56 		int content_type,
57 		const void* buf, size_t len,
58 		SSL* ssl, void* arg);
59 int pem_passwd_cb(char* buf, int size, int rwflag, void* userdata);
60 int SSL_create_mutex(ssl_mutex_type* mutex);
61 int SSL_lock_mutex(ssl_mutex_type* mutex);
62 int SSL_unlock_mutex(ssl_mutex_type* mutex);
63 int SSL_destroy_mutex(ssl_mutex_type* mutex);
64 #if (OPENSSL_VERSION_NUMBER >= 0x010000000)
65 extern void SSLThread_id(CRYPTO_THREADID *id);
66 #else
67 extern unsigned long SSLThread_id(void);
68 #endif
69 extern void SSLLocks_callback(int mode, int n, const char *file, int line);
70 int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts);
71 void SSLSocket_destroyContext(networkHandles* net);
72 void SSLSocket_addPendingRead(SOCKET sock);
73 
74 /* 1 ~ we are responsible for initializing openssl; 0 ~ openssl init is done externally */
75 static int handle_openssl_init = 1;
76 static ssl_mutex_type* sslLocks = NULL;
77 static ssl_mutex_type sslCoreMutex;
78 
79 /* Used to store MQTTClient_SSLOptions for TLS-PSK callback */
80 static int tls_ex_index_ssl_opts;
81 
82 #if defined(_WIN32) || defined(_WIN64)
83 #define iov_len len
84 #define iov_base buf
85 #define snprintf _snprintf
86 #endif
87 
88 /**
89  * Gets the specific error corresponding to SOCKET_ERROR
90  * @param aString the function that was being used when the error occurred
91  * @param sock the socket on which the error occurred
92  * @param rc the return code
93  * @param cb the callback function to be passed as first argument to ERR_print_errors_cb
94  * @param u context to be passed as second argument to ERR_print_errors_cb
95  * @return the specific TCP error code
96  */
SSLSocket_error(char * aString,SSL * ssl,SOCKET sock,int rc,int (* cb)(const char * str,size_t len,void * u),void * u)97 static int SSLSocket_error(char* aString, SSL* ssl, SOCKET sock, int rc, int (*cb)(const char *str, size_t len, void *u), void* u)
98 {
99     int error;
100 
101     FUNC_ENTRY;
102     if (ssl)
103         error = SSL_get_error(ssl, rc);
104     else
105         error = ERR_get_error();
106     if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
107     {
108 		Log(TRACE_MIN, -1, "SSLSocket error WANT_READ/WANT_WRITE");
109     }
110     else
111     {
112         static char buf[120];
113 
114         if (strcmp(aString, "shutdown") != 0)
115         	Log(TRACE_MIN, -1, "SSLSocket error %s(%d) in %s for socket %d rc %d errno %d %s\n", buf, error, aString, sock, rc, errno, strerror(errno));
116         if (cb)
117             ERR_print_errors_cb(cb, u);
118 		if (error == SSL_ERROR_SSL || error == SSL_ERROR_SYSCALL)
119 			error = SSL_FATAL;
120     }
121     FUNC_EXIT_RC(error);
122     return error;
123 }
124 
125 static struct
126 {
127 	int code;
128 	char* string;
129 }
130 X509_message_table[] =
131 {
132 	{ X509_V_OK, "X509_V_OK" },
133 	{ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT" },
134 	{ X509_V_ERR_UNABLE_TO_GET_CRL, "X509_V_ERR_UNABLE_TO_GET_CRL" },
135 	{ X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE" },
136 	{ X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE" },
137 	{ X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY" },
138 	{ X509_V_ERR_CERT_SIGNATURE_FAILURE, "X509_V_ERR_CERT_SIGNATURE_FAILURE" },
139 	{ X509_V_ERR_CRL_SIGNATURE_FAILURE, "X509_V_ERR_CRL_SIGNATURE_FAILURE" },
140 	{ X509_V_ERR_CERT_NOT_YET_VALID, "X509_V_ERR_CERT_NOT_YET_VALID" },
141 	{ X509_V_ERR_CERT_HAS_EXPIRED, "X509_V_ERR_CERT_HAS_EXPIRED" },
142 	{ X509_V_ERR_CRL_NOT_YET_VALID, "X509_V_ERR_CRL_NOT_YET_VALID" },
143 	{ X509_V_ERR_CRL_HAS_EXPIRED, "X509_V_ERR_CRL_HAS_EXPIRED" },
144 	{ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD" },
145 	{ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD" },
146 	{ X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD" },
147 	{ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD" },
148 	{ X509_V_ERR_OUT_OF_MEM, "X509_V_ERR_OUT_OF_MEM" },
149 	{ X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT" },
150 	{ X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN" },
151 	{ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY" },
152 	{ X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE" },
153 	{ X509_V_ERR_CERT_CHAIN_TOO_LONG, "X509_V_ERR_CERT_CHAIN_TOO_LONG" },
154 	{ X509_V_ERR_CERT_REVOKED, "X509_V_ERR_CERT_REVOKED" },
155 	{ X509_V_ERR_INVALID_CA, "X509_V_ERR_INVALID_CA" },
156 	{ X509_V_ERR_PATH_LENGTH_EXCEEDED, "X509_V_ERR_PATH_LENGTH_EXCEEDED" },
157 	{ X509_V_ERR_INVALID_PURPOSE, "X509_V_ERR_INVALID_PURPOSE" },
158 	{ X509_V_ERR_CERT_UNTRUSTED, "X509_V_ERR_CERT_UNTRUSTED" },
159 	{ X509_V_ERR_CERT_REJECTED, "X509_V_ERR_CERT_REJECTED" },
160 	{ X509_V_ERR_SUBJECT_ISSUER_MISMATCH, "X509_V_ERR_SUBJECT_ISSUER_MISMATCH" },
161 	{ X509_V_ERR_AKID_SKID_MISMATCH, "X509_V_ERR_AKID_SKID_MISMATCH" },
162 	{ X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH" },
163 	{ X509_V_ERR_KEYUSAGE_NO_CERTSIGN, "X509_V_ERR_KEYUSAGE_NO_CERTSIGN" },
164 	{ X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER" },
165 	{ X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION" },
166 	{ X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN" },
167 	{ X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION" },
168 	{ X509_V_ERR_INVALID_NON_CA, "X509_V_ERR_INVALID_NON_CA" },
169 	{ X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED" },
170 	{ X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE" },
171 	{ X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED" },
172 	{ X509_V_ERR_INVALID_EXTENSION, "X509_V_ERR_INVALID_EXTENSION" },
173 	{ X509_V_ERR_INVALID_POLICY_EXTENSION, "X509_V_ERR_INVALID_POLICY_EXTENSION" },
174 	{ X509_V_ERR_NO_EXPLICIT_POLICY, "X509_V_ERR_NO_EXPLICIT_POLICY" },
175 	{ X509_V_ERR_UNNESTED_RESOURCE, "X509_V_ERR_UNNESTED_RESOURCE" },
176 #if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
177 	{ X509_V_ERR_DIFFERENT_CRL_SCOPE, "X509_V_ERR_DIFFERENT_CRL_SCOPE" },
178 	{ X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE, "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE" },
179 	{ X509_V_ERR_PERMITTED_VIOLATION, "X509_V_ERR_PERMITTED_VIOLATION" },
180 	{ X509_V_ERR_EXCLUDED_VIOLATION, "X509_V_ERR_EXCLUDED_VIOLATION" },
181 	{ X509_V_ERR_SUBTREE_MINMAX, "X509_V_ERR_SUBTREE_MINMAX" },
182 	{ X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE, "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE" },
183 	{ X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX, "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX" },
184 	{ X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX" },
185 #endif
186 };
187 
188 #if !defined(ARRAY_SIZE)
189 /**
190  * Macro to calculate the number of entries in an array
191  */
192 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
193 #endif
194 
SSL_get_verify_result_string(int rc)195 char* SSL_get_verify_result_string(int rc)
196 {
197 	int i;
198 	char* retstring = "undef";
199 
200 	for (i = 0; i < ARRAY_SIZE(X509_message_table); ++i)
201 	{
202 		if (X509_message_table[i].code == rc)
203 		{
204 			retstring = X509_message_table[i].string;
205 			break;
206 		}
207 	}
208 	return retstring;
209 }
210 
211 
SSL_CTX_info_callback(const SSL * ssl,int where,int ret)212 void SSL_CTX_info_callback(const SSL* ssl, int where, int ret)
213 {
214 	if (where & SSL_CB_LOOP)
215 	{
216 		Log(TRACE_PROTOCOL, 1, "SSL state %s:%s:%s",
217                   (where & SSL_ST_CONNECT) ? "connect" : (where & SSL_ST_ACCEPT) ? "accept" : "undef",
218                     SSL_state_string_long(ssl), SSL_get_cipher_name(ssl));
219 	}
220 	else if (where & SSL_CB_EXIT)
221 	{
222 		Log(TRACE_PROTOCOL, 1, "SSL %s:%s",
223                   (where & SSL_ST_CONNECT) ? "connect" : (where & SSL_ST_ACCEPT) ? "accept" : "undef",
224                     SSL_state_string_long(ssl));
225 	}
226 	else if (where & SSL_CB_ALERT)
227 	{
228 		Log(TRACE_PROTOCOL, 1, "SSL alert %s:%s:%s",
229                   (where & SSL_CB_READ) ? "read" : "write",
230                     SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
231 	}
232 	else if (where & SSL_CB_HANDSHAKE_START)
233 	{
234 		Log(TRACE_PROTOCOL, 1, "SSL handshake started %s:%s:%s",
235                   (where & SSL_CB_READ) ? "read" : "write",
236                     SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
237 	}
238 	else if (where & SSL_CB_HANDSHAKE_DONE)
239 	{
240 		Log(TRACE_PROTOCOL, 1, "SSL handshake done %s:%s:%s",
241                   (where & SSL_CB_READ) ? "read" : "write",
242                     SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
243 		Log(TRACE_PROTOCOL, 1, "SSL certificate verification: %s",
244                     SSL_get_verify_result_string(SSL_get_verify_result(ssl)));
245 	}
246 	else
247 	{
248 		Log(TRACE_PROTOCOL, 1, "SSL state %s:%s:%s", SSL_state_string_long(ssl),
249                    SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
250 	}
251 }
252 
253 
SSLSocket_get_version_string(int version)254 char* SSLSocket_get_version_string(int version)
255 {
256 	int i;
257 	static char buf[20];
258 	char* retstring = NULL;
259 	static struct
260 	{
261 		int code;
262 		char* string;
263 	}
264 	version_string_table[] =
265 	{
266 		{ SSL2_VERSION, "SSL 2.0" },
267 		{ SSL3_VERSION, "SSL 3.0" },
268 		{ TLS1_VERSION, "TLS 1.0" },
269 #if defined(TLS2_VERSION)
270 		{ TLS2_VERSION, "TLS 1.1" },
271 #endif
272 #if defined(TLS3_VERSION)
273 		{ TLS3_VERSION, "TLS 1.2" },
274 #endif
275 	};
276 
277 	for (i = 0; i < ARRAY_SIZE(version_string_table); ++i)
278 	{
279 		if (version_string_table[i].code == version)
280 		{
281 			retstring = version_string_table[i].string;
282 			break;
283 		}
284 	}
285 
286 	if (retstring == NULL)
287 	{
288 		if (snprintf(buf, sizeof(buf), "%i", version) >= sizeof(buf))
289 			buf[sizeof(buf)-1] = '\0'; /* just in case of snprintf buffer overflow */
290 		retstring = buf;
291 	}
292 	return retstring;
293 }
294 
295 
SSL_CTX_msg_callback(int write_p,int version,int content_type,const void * buf,size_t len,SSL * ssl,void * arg)296 void SSL_CTX_msg_callback(int write_p, int version, int content_type, const void* buf, size_t len,
297         SSL* ssl, void* arg)
298 {
299 
300 /*
301 called by the SSL/TLS library for a protocol message, the function arguments have the following meaning:
302 
303 write_p
304 This flag is 0 when a protocol message has been received and 1 when a protocol message has been sent.
305 
306 version
307 The protocol version according to which the protocol message is interpreted by the library. Currently, this is one of SSL2_VERSION, SSL3_VERSION and TLS1_VERSION (for SSL 2.0, SSL 3.0 and TLS 1.0, respectively).
308 
309 content_type
310 In the case of SSL 2.0, this is always 0. In the case of SSL 3.0 or TLS 1.0, this is one of the ContentType values defined in the protocol specification (change_cipher_spec(20), alert(21), handshake(22); but never application_data(23) because the callback will only be called for protocol messages).
311 
312 buf, len
313 buf points to a buffer containing the protocol message, which consists of len bytes. The buffer is no longer valid after the callback function has returned.
314 
315 ssl
316 The SSL object that received or sent the message.
317 
318 arg
319 The user-defined argument optionally defined by SSL_CTX_set_msg_callback_arg() or SSL_set_msg_callback_arg().
320 
321 */
322 
323 	Log(TRACE_MINIMUM, -1, "%s %s %d buflen %d", (write_p ? "sent" : "received"),
324 		SSLSocket_get_version_string(version),
325 		content_type, (int)len);
326 }
327 
328 
pem_passwd_cb(char * buf,int size,int rwflag,void * userdata)329 int pem_passwd_cb(char* buf, int size, int rwflag, void* userdata)
330 {
331 	int rc = 0;
332 
333 	FUNC_ENTRY;
334 	if (!rwflag)
335 	{
336 		strncpy(buf, (char*)(userdata), size);
337 		buf[size-1] = '\0';
338 		rc = (int)strlen(buf);
339 	}
340 	FUNC_EXIT_RC(rc);
341 	return rc;
342 }
343 
SSL_create_mutex(ssl_mutex_type * mutex)344 int SSL_create_mutex(ssl_mutex_type* mutex)
345 {
346 	int rc = 0;
347 
348 	FUNC_ENTRY;
349 #if defined(_WIN32) || defined(_WIN64)
350 	*mutex = CreateMutex(NULL, 0, NULL);
351 #elif defined(COMPAT_CMSIS)
352 	*mutex = osMutexNew(NULL);
353 	rc = (*mutex == NULL) ? -1 : 0;
354 #else
355 	rc = pthread_mutex_init(mutex, NULL);
356 #endif
357 	FUNC_EXIT_RC(rc);
358 	return rc;
359 }
360 
SSL_lock_mutex(ssl_mutex_type * mutex)361 int SSL_lock_mutex(ssl_mutex_type* mutex)
362 {
363 	int rc = -1;
364 
365 	/* don't add entry/exit trace points, as trace gets lock too, and it might happen quite frequently  */
366 #if defined(_WIN32) || defined(_WIN64)
367 	if (WaitForSingleObject(*mutex, INFINITE) != WAIT_FAILED)
368 #elif defined(COMPAT_CMSIS)
369 	if ((rc = osMutexAcquire(*mutex, osWaitForever)) == osOK)
370 #else
371 	if ((rc = pthread_mutex_lock(mutex)) == 0)
372 #endif
373 	rc = 0;
374 
375 	return rc;
376 }
377 
SSL_unlock_mutex(ssl_mutex_type * mutex)378 int SSL_unlock_mutex(ssl_mutex_type* mutex)
379 {
380 	int rc = -1;
381 
382 	/* don't add entry/exit trace points, as trace gets lock too, and it might happen quite frequently  */
383 #if defined(_WIN32) || defined(_WIN64)
384 	if (ReleaseMutex(*mutex) != 0)
385 #elif defined (COMPAT_CMSIS)
386 	if ((rc = osMutexRelease(*mutex)) == osOK)
387 #else
388 	if ((rc = pthread_mutex_unlock(mutex)) == 0)
389 #endif
390 	rc = 0;
391 
392 	return rc;
393 }
394 
SSL_destroy_mutex(ssl_mutex_type * mutex)395 int SSL_destroy_mutex(ssl_mutex_type* mutex)
396 {
397 	int rc = 0;
398 
399 	FUNC_ENTRY;
400 #if defined(_WIN32) || defined(_WIN64)
401 	if (*mutex != NULL)
402 		rc = CloseHandle(*mutex);
403 #elif defined(COMPAT_CMSIS)
404 	if (*mutex != NULL)
405 		rc = osMutexDelete(*mutex);
406 #else
407 	rc = pthread_mutex_destroy(mutex);
408 #endif
409 	FUNC_EXIT_RC(rc);
410 	return rc;
411 }
412 
413 
414 
415 #if (OPENSSL_VERSION_NUMBER >= 0x010000000)
SSLThread_id(CRYPTO_THREADID * id)416 extern void SSLThread_id(CRYPTO_THREADID *id)
417 {
418 #if defined(_WIN32) || defined(_WIN64)
419 	CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
420 #else
421 	CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self());
422 #endif
423 }
424 #else
SSLThread_id(void)425 extern unsigned long SSLThread_id(void)
426 {
427 #if defined(_WIN32) || defined(_WIN64)
428 	return (unsigned long)GetCurrentThreadId();
429 #else
430 	return (unsigned long)pthread_self();
431 #endif
432 }
433 #endif
434 
SSLLocks_callback(int mode,int n,const char * file,int line)435 extern void SSLLocks_callback(int mode, int n, const char *file, int line)
436 {
437 	if (sslLocks)
438 	{
439 		if (mode & CRYPTO_LOCK)
440 			SSL_lock_mutex(&sslLocks[n]);
441 		else
442 			SSL_unlock_mutex(&sslLocks[n]);
443 	}
444 }
445 
446 
SSLSocket_handleOpensslInit(int bool_value)447 void SSLSocket_handleOpensslInit(int bool_value)
448 {
449 	handle_openssl_init = bool_value;
450 }
451 
452 
SSLSocket_initialize(void)453 int SSLSocket_initialize(void)
454 {
455 	int rc = 0;
456 	/*int prc;*/
457 	int i;
458 	int lockMemSize;
459 
460 	FUNC_ENTRY;
461 
462 	if (handle_openssl_init)
463 	{
464 		if ((rc = SSL_library_init()) != 1)
465 			rc = -1;
466 
467 		ERR_load_crypto_strings();
468 		SSL_load_error_strings();
469 
470 		/* OpenSSL 0.9.8o and 1.0.0a and later added SHA2 algorithms to SSL_library_init().
471 		Applications which need to use SHA2 in earlier versions of OpenSSL should call
472 		OpenSSL_add_all_algorithms() as well. */
473 
474 		OpenSSL_add_all_algorithms();
475 
476 		lockMemSize = CRYPTO_num_locks() * sizeof(ssl_mutex_type);
477 
478 		sslLocks = malloc(lockMemSize);
479 		if (!sslLocks)
480 		{
481 			rc = -1;
482 			goto exit;
483 		}
484 		else
485 			memset(sslLocks, 0, lockMemSize);
486 
487 		for (i = 0; i < CRYPTO_num_locks(); i++)
488 		{
489 			/* prc = */SSL_create_mutex(&sslLocks[i]);
490 		}
491 
492 #if (OPENSSL_VERSION_NUMBER >= 0x010000000)
493 		CRYPTO_THREADID_set_callback(SSLThread_id);
494 #else
495 		CRYPTO_set_id_callback(SSLThread_id);
496 #endif
497 		CRYPTO_set_locking_callback(SSLLocks_callback);
498 
499 	}
500 
501 	SSL_create_mutex(&sslCoreMutex);
502 
503 	tls_ex_index_ssl_opts = SSL_get_ex_new_index(0, "paho ssl options", NULL, NULL, NULL);
504 
505 exit:
506 	FUNC_EXIT_RC(rc);
507 	return rc;
508 }
509 
SSLSocket_terminate(void)510 void SSLSocket_terminate(void)
511 {
512 	FUNC_ENTRY;
513 
514 	if (handle_openssl_init)
515 	{
516 		CRYPTO_set_locking_callback(NULL);
517 		ERR_free_strings();
518 		EVP_cleanup();
519 		if (sslLocks)
520 		{
521 			int i = 0;
522 
523 			for (i = 0; i < CRYPTO_num_locks(); i++)
524 			{
525 				SSL_destroy_mutex(&sslLocks[i]);
526 			}
527 			free(sslLocks);
528 		}
529 	}
530 
531 	SSL_destroy_mutex(&sslCoreMutex);
532 
533 	FUNC_EXIT;
534 }
535 
call_ssl_psk_cb(SSL * ssl,const char * hint,char * identity,unsigned int max_identity_len,unsigned char * psk,unsigned int max_psk_len)536 static unsigned int call_ssl_psk_cb(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len)
537 {
538 	int rc = 0;
539 
540 	FUNC_ENTRY;
541 
542 	{
543 		SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
544 		MQTTClient_SSLOptions* opts = SSL_CTX_get_ex_data(ctx, tls_ex_index_ssl_opts);
545 
546 		if (opts == NULL)
547 			goto exit;
548 
549 		if (opts->ssl_psk_cb != NULL)
550 			rc = opts->ssl_psk_cb(hint, identity, max_identity_len, psk, max_psk_len, opts->ssl_psk_context);
551 	}
552 exit:
553 	FUNC_EXIT_RC(rc);
554 	return rc;
555 }
556 
SSLSocket_createContext(networkHandles * net,MQTTClient_SSLOptions * opts)557 int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
558 {
559 	int rc = 1;
560 
561 	FUNC_ENTRY;
562 	if (net->ctx == NULL)
563 	{
564 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
565 		net->ctx = SSL_CTX_new(TLS_client_method());
566 #else
567 		int sslVersion = MQTT_SSL_VERSION_DEFAULT;
568 		if (opts->struct_version >= 1) sslVersion = opts->sslVersion;
569 /* SSL_OP_NO_TLSv1_1 is defined in ssl.h if the library version supports TLSv1.1.
570  * OPENSSL_NO_TLS1 is defined in opensslconf.h or on the compiler command line
571  * if TLS1.x was removed at OpenSSL library build time via Configure options.
572  */
573 		switch (sslVersion)
574 		{
575 		case MQTT_SSL_VERSION_DEFAULT:
576 			net->ctx = SSL_CTX_new(SSLv23_client_method()); /* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */
577 			break;
578 #if defined(SSL_OP_NO_TLSv1) && !defined(OPENSSL_NO_TLS1)
579 		case MQTT_SSL_VERSION_TLS_1_0:
580 			net->ctx = SSL_CTX_new(TLSv1_client_method());
581 			break;
582 #endif
583 #if defined(SSL_OP_NO_TLSv1_1) && !defined(OPENSSL_NO_TLS1)
584 		case MQTT_SSL_VERSION_TLS_1_1:
585 			net->ctx = SSL_CTX_new(TLSv1_1_client_method());
586 			break;
587 #endif
588 #if defined(SSL_OP_NO_TLSv1_2) && !defined(OPENSSL_NO_TLS1)
589 		case MQTT_SSL_VERSION_TLS_1_2:
590 			net->ctx = SSL_CTX_new(TLSv1_2_client_method());
591 			break;
592 #endif
593 		default:
594 			break;
595 		}
596 #endif
597 		if (net->ctx == NULL)
598 		{
599 			if (opts->struct_version >= 3)
600 				SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
601 			else
602 				SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc, NULL, NULL);
603 			goto exit;
604 		}
605 	}
606 
607 
608 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
609 	SSL_CTX_set_security_level(net->ctx, 1);
610 #endif
611 
612 
613 	if (opts->keyStore)
614 	{
615 		if ((rc = SSL_CTX_use_certificate_chain_file(net->ctx, opts->keyStore)) != 1)
616 		{
617 			if (opts->struct_version >= 3)
618 				SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
619 			else
620 				SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc, NULL, NULL);
621 			goto free_ctx; /*If we can't load the certificate (chain) file then loading the privatekey won't work either as it needs a matching cert already loaded */
622 		}
623 
624 		if (opts->privateKey == NULL)
625 			opts->privateKey = opts->keyStore;   /* the privateKey can be included in the keyStore */
626 
627 		if (opts->privateKeyPassword != NULL)
628 		{
629 			SSL_CTX_set_default_passwd_cb(net->ctx, pem_passwd_cb);
630 			SSL_CTX_set_default_passwd_cb_userdata(net->ctx, (void*)opts->privateKeyPassword);
631 		}
632 
633 		/* support for ASN.1 == DER format? DER can contain only one certificate? */
634 		rc = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM);
635 		if (opts->privateKey == opts->keyStore)
636 			opts->privateKey = NULL;
637 		if (rc != 1)
638 		{
639 			if (opts->struct_version >= 3)
640 				SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
641 			else
642 				SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, NULL, NULL);
643 			goto free_ctx;
644 		}
645 	}
646 
647 	if (opts->trustStore || opts->CApath)
648 	{
649 		if ((rc = SSL_CTX_load_verify_locations(net->ctx, opts->trustStore, opts->CApath)) != 1)
650 		{
651 			if (opts->struct_version >= 3)
652 				SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
653 			else
654 				SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc, NULL, NULL);
655 			goto free_ctx;
656 		}
657 	}
658 	else if (!opts->disableDefaultTrustStore)
659 	{
660 		if ((rc = SSL_CTX_set_default_verify_paths(net->ctx)) != 1)
661 		{
662 			if (opts->struct_version >= 3)
663 				SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
664 			else
665 				SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc, NULL, NULL);
666 			goto free_ctx;
667 		}
668 	}
669 
670 	if (opts->enabledCipherSuites)
671 	{
672 		if ((rc = SSL_CTX_set_cipher_list(net->ctx, opts->enabledCipherSuites)) != 1)
673 		{
674 			if (opts->struct_version >= 3)
675 				SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
676 			else
677 				SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc, NULL, NULL);
678 			goto free_ctx;
679 		}
680 	}
681 
682 #ifndef OPENSSL_NO_PSK
683 	if (opts->ssl_psk_cb != NULL)
684 	{
685 		SSL_CTX_set_ex_data(net->ctx, tls_ex_index_ssl_opts, opts);
686 		SSL_CTX_set_psk_client_callback(net->ctx, call_ssl_psk_cb);
687 	}
688 #endif
689 
690 #if (OPENSSL_VERSION_NUMBER >= 0x010002000) /* 1.0.2 and later */
691 	if (opts->protos != NULL && opts->protos_len > 0)
692 	{
693 		/* SSL_CTX_set_alpn_protos() returns 0 on success as opposed to the other SSL functions,
694 		   so we need to flip the meaning of rc or the return code will be wrong. */
695 		if ((rc = SSL_CTX_set_alpn_protos(net->ctx, opts->protos, opts->protos_len)) != 0)
696 		{
697 			if (opts->struct_version >= 3)
698 				SSLSocket_error("SSL_CTX_set_alpn_protos", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
699 			else
700 				SSLSocket_error("SSL_CTX_set_alpn_protos", NULL, net->socket, rc, NULL, NULL);
701 			rc = 0; /* report an error according to the convention in other OpenSSL functions */
702 			goto free_ctx;
703 		}
704 		rc = 1; /* report success according to the convention in other OpenSSL functions */
705 	}
706 #endif
707 
708 	SSL_CTX_set_mode(net->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
709 
710 	goto exit;
711 free_ctx:
712 	SSL_CTX_free(net->ctx);
713 	net->ctx = NULL;
714 
715 exit:
716 	FUNC_EXIT_RC(rc);
717 	return rc;
718 }
719 
720 
SSLSocket_setSocketForSSL(networkHandles * net,MQTTClient_SSLOptions * opts,const char * hostname,size_t hostname_len)721 int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts,
722 	const char* hostname, size_t hostname_len)
723 {
724 	int rc = 1;
725 
726 	FUNC_ENTRY;
727 
728 	if (net->ctx != NULL || (rc = SSLSocket_createContext(net, opts)) == 1)
729 	{
730 		char *hostname_plus_null;
731 		int i;
732 
733 		SSL_CTX_set_info_callback(net->ctx, SSL_CTX_info_callback);
734 		SSL_CTX_set_msg_callback(net->ctx, SSL_CTX_msg_callback);
735    		if (opts->enableServerCertAuth)
736 			SSL_CTX_set_verify(net->ctx, SSL_VERIFY_PEER, NULL);
737 
738 		net->ssl = SSL_new(net->ctx);
739 
740 		/* Log all ciphers available to the SSL sessions (loaded in ctx) */
741 		for (i = 0; ;i++)
742 		{
743 			const char* cipher = SSL_get_cipher_list(net->ssl, i);
744 			if (cipher == NULL)
745 				break;
746 			Log(TRACE_PROTOCOL, 1, "SSL cipher available: %d:%s", i, cipher);
747 		}
748 		if ((rc = (int)SSL_set_fd(net->ssl, (int)net->socket)) != 1) {
749 			if (opts->struct_version >= 3)
750 				SSLSocket_error("SSL_set_fd", net->ssl, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
751 			else
752 				SSLSocket_error("SSL_set_fd", net->ssl, net->socket, rc, NULL, NULL);
753 		}
754 		hostname_plus_null = malloc(hostname_len + 1u );
755 		if (hostname_plus_null)
756 		{
757 			MQTTStrncpy(hostname_plus_null, hostname, hostname_len + 1u);
758 			if ((rc = SSL_set_tlsext_host_name(net->ssl, hostname_plus_null)) != 1) {
759 				if (opts->struct_version >= 3)
760 					SSLSocket_error("SSL_set_tlsext_host_name", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
761 				else
762 					SSLSocket_error("SSL_set_tlsext_host_name", NULL, net->socket, rc, NULL, NULL);
763 			}
764 			free(hostname_plus_null);
765 		}
766 		else
767 			rc = PAHO_MEMORY_ERROR;
768 	}
769 
770 	FUNC_EXIT_RC(rc);
771 	return rc;
772 }
773 
774 /*
775  * Return value: 1 - success, TCPSOCKET_INTERRUPTED - try again, anything else is failure
776  */
SSLSocket_connect(SSL * ssl,SOCKET sock,const char * hostname,int verify,int (* cb)(const char * str,size_t len,void * u),void * u)777 int SSLSocket_connect(SSL* ssl, SOCKET sock, const char* hostname, int verify, int (*cb)(const char *str, size_t len, void *u), void* u)
778 {
779 	int rc = 0;
780 
781 	FUNC_ENTRY;
782 
783 	ERR_clear_error();
784 	rc = SSL_connect(ssl);
785 	if (rc != 1)
786 	{
787 		int error;
788 		error = SSLSocket_error("SSL_connect", ssl, sock, rc, cb, u);
789 		if (error == SSL_FATAL)
790 			rc = error;
791 		if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
792 			rc = TCPSOCKET_INTERRUPTED;
793 	}
794 #if (OPENSSL_VERSION_NUMBER >= 0x010002000) /* 1.0.2 and later */
795 	else if (verify)
796 	{
797 		char* peername = NULL;
798 		int port;
799 		size_t hostname_len;
800 
801 		X509* cert = SSL_get_peer_certificate(ssl);
802 		hostname_len = MQTTProtocol_addressPort(hostname, &port, NULL, MQTT_DEFAULT_PORT);
803 
804 		rc = X509_check_host(cert, hostname, hostname_len, 0, &peername);
805 		if (rc == 1)
806 			Log(TRACE_PROTOCOL, -1, "peername from X509_check_host is %s", peername);
807 		else
808 			Log(TRACE_PROTOCOL, -1, "X509_check_host for hostname %.*s failed, rc %d",
809 					(int)hostname_len, hostname, rc);
810 
811 		if (peername != NULL)
812 			OPENSSL_free(peername);
813 
814 		/* 0 == fail, -1 == SSL internal error, -2 == malformed input */
815 		if (rc == 0 || rc == -1 || rc == -2)
816 		{
817 			char* ip_addr = malloc(hostname_len + 1);
818 			/* cannot use = strndup(hostname, hostname_len); here because of custom Heap */
819 			if (ip_addr)
820 			{
821 				strncpy(ip_addr, hostname, hostname_len);
822 				ip_addr[hostname_len] = '\0';
823 
824 				rc = X509_check_ip_asc(cert, ip_addr, 0);
825 				Log(TRACE_MIN, -1, "rc from X509_check_ip_asc is %d", rc);
826 
827 				free(ip_addr);
828 			}
829 
830 			if (rc == 0 || rc == -1 || rc == -2)
831 				rc = SSL_FATAL;
832 		}
833 
834 		if (cert)
835 			X509_free(cert);
836 	}
837 #endif
838 
839 	FUNC_EXIT_RC(rc);
840 	return rc;
841 }
842 
843 
844 
845 /**
846  *  Reads one byte from a socket
847  *  @param socket the socket to read from
848  *  @param c the character read, returned
849  *  @return completion code
850  */
SSLSocket_getch(SSL * ssl,SOCKET socket,char * c)851 int SSLSocket_getch(SSL* ssl, SOCKET socket, char* c)
852 {
853 	int rc = SOCKET_ERROR;
854 
855 	FUNC_ENTRY;
856 	if ((rc = SocketBuffer_getQueuedChar(socket, c)) != SOCKETBUFFER_INTERRUPTED)
857 		goto exit;
858 
859 	ERR_clear_error();
860 	if ((rc = SSL_read(ssl, c, (size_t)1)) < 0)
861 	{
862 		int err = SSLSocket_error("SSL_read - getch", ssl, socket, rc, NULL, NULL);
863 		if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
864 		{
865 			rc = TCPSOCKET_INTERRUPTED;
866 			SocketBuffer_interrupted(socket, 0);
867 		}
868 	}
869 	else if (rc == 0)
870 		rc = SOCKET_ERROR; 	/* The return value from recv is 0 when the peer has performed an orderly shutdown. */
871 	else if (rc == 1)
872 	{
873 		SocketBuffer_queueChar(socket, *c);
874 		rc = TCPSOCKET_COMPLETE;
875 	}
876 exit:
877 	FUNC_EXIT_RC(rc);
878 	return rc;
879 }
880 
881 
882 
883 /**
884  *  Attempts to read a number of bytes from a socket, non-blocking. If a previous read did not
885  *  finish, then retrieve that data.
886  *  @param socket the socket to read from
887  *  @param bytes the number of bytes to read
888  *  @param actual_len the actual number of bytes read
889  *  @return completion code
890  */
SSLSocket_getdata(SSL * ssl,SOCKET socket,size_t bytes,size_t * actual_len,int * rc)891 char *SSLSocket_getdata(SSL* ssl, SOCKET socket, size_t bytes, size_t* actual_len, int* rc)
892 {
893 	char* buf;
894 
895 	FUNC_ENTRY;
896 	if (bytes == 0)
897 	{
898 		buf = SocketBuffer_complete(socket);
899 		goto exit;
900 	}
901 
902 	buf = SocketBuffer_getQueuedData(socket, bytes, actual_len);
903 
904 	if (*actual_len != bytes)
905 	{
906 		ERR_clear_error();
907 		if ((*rc = SSL_read(ssl, buf + (*actual_len), (int)(bytes - (*actual_len)))) < 0)
908 		{
909 			*rc = SSLSocket_error("SSL_read - getdata", ssl, socket, *rc, NULL, NULL);
910 			if (*rc != SSL_ERROR_WANT_READ && *rc != SSL_ERROR_WANT_WRITE)
911 			{
912 				buf = NULL;
913 				goto exit;
914 			}
915 		}
916 		else if (*rc == 0) /* rc 0 means the other end closed the socket */
917 		{
918 			buf = NULL;
919 			goto exit;
920 		}
921 		else
922 			*actual_len += *rc;
923 	}
924 
925 	if (*actual_len == bytes)
926 	{
927 		SocketBuffer_complete(socket);
928 		/* if we read the whole packet, there might still be data waiting in the SSL buffer, which
929 		isn't picked up by select.  So here we should check for any data remaining in the SSL buffer, and
930 		if so, add this socket to a new "pending SSL reads" list.
931 		*/
932 		if (SSL_pending(ssl) > 0) /* return no of bytes pending */
933 			SSLSocket_addPendingRead(socket);
934 	}
935 	else /* we didn't read the whole packet */
936 	{
937 		SocketBuffer_interrupted(socket, *actual_len);
938 		Log(TRACE_MAX, -1, "SSL_read: %lu bytes expected but %lu bytes now received", bytes, *actual_len);
939 	}
940 exit:
941 	FUNC_EXIT;
942 	return buf;
943 }
944 
SSLSocket_destroyContext(networkHandles * net)945 void SSLSocket_destroyContext(networkHandles* net)
946 {
947 	FUNC_ENTRY;
948 	if (net->ctx)
949 		SSL_CTX_free(net->ctx);
950 	net->ctx = NULL;
951 	FUNC_EXIT;
952 }
953 
954 static List pending_reads = {NULL, NULL, NULL, 0, 0};
955 
SSLSocket_close(networkHandles * net)956 int SSLSocket_close(networkHandles* net)
957 {
958 	int rc = 1;
959 
960 	FUNC_ENTRY;
961 	/* clean up any pending reads for this socket */
962 	if (pending_reads.count > 0 && ListFindItem(&pending_reads, &net->socket, intcompare))
963 		ListRemoveItem(&pending_reads, &net->socket, intcompare);
964 
965 	if (net->ssl)
966 	{
967 		ERR_clear_error();
968 		rc = SSL_shutdown(net->ssl);
969 		SSL_free(net->ssl);
970 		net->ssl = NULL;
971 	}
972 	SSLSocket_destroyContext(net);
973 	FUNC_EXIT_RC(rc);
974 	return rc;
975 }
976 
977 
978 /* No SSL_writev() provided by OpenSSL. Boo. */
SSLSocket_putdatas(SSL * ssl,SOCKET socket,char * buf0,size_t buf0len,PacketBuffers bufs)979 int SSLSocket_putdatas(SSL* ssl, SOCKET socket, char* buf0, size_t buf0len, PacketBuffers bufs)
980 {
981 	int rc = 0;
982 	int i;
983 	char *ptr;
984 	iobuf iovec;
985 	int sslerror;
986 
987 	FUNC_ENTRY;
988 	iovec.iov_len = (ULONG)buf0len;
989 	for (i = 0; i < bufs.count; i++)
990 		iovec.iov_len += (ULONG)bufs.buflens[i];
991 
992 	ptr = iovec.iov_base = (char *)malloc(iovec.iov_len);
993 	if (!ptr)
994 	{
995 		rc = PAHO_MEMORY_ERROR;
996 		goto exit;
997 	}
998 	memcpy(ptr, buf0, buf0len);
999 	ptr += buf0len;
1000 	for (i = 0; i < bufs.count; i++)
1001 	{
1002 		if (bufs.buffers[i] != NULL && bufs.buflens[i] > 0)
1003 		{
1004 			memcpy(ptr, bufs.buffers[i], bufs.buflens[i]);
1005 			ptr += bufs.buflens[i];
1006 		}
1007 	}
1008 
1009 	SSL_lock_mutex(&sslCoreMutex);
1010 	ERR_clear_error();
1011 	if ((rc = SSL_write(ssl, iovec.iov_base, iovec.iov_len)) == iovec.iov_len)
1012 		rc = TCPSOCKET_COMPLETE;
1013 	else
1014 	{
1015 		sslerror = SSLSocket_error("SSL_write", ssl, socket, rc, NULL, NULL);
1016 
1017 		if (sslerror == SSL_ERROR_WANT_WRITE)
1018 		{
1019 			SOCKET* sockmem = (SOCKET*)malloc(sizeof(SOCKET));
1020 			int free = 1;
1021 
1022 			if (!sockmem)
1023 			{
1024 				rc = PAHO_MEMORY_ERROR;
1025 				SSL_unlock_mutex(&sslCoreMutex);
1026 				goto exit;
1027 			}
1028 			Log(TRACE_MIN, -1, "Partial write: incomplete write of %lu bytes on SSL socket %d",
1029 				iovec.iov_len, socket);
1030 			SocketBuffer_pendingWrite(socket, ssl, 1, &iovec, &free, iovec.iov_len, 0);
1031 			*sockmem = socket;
1032 			ListAppend(mod_s.write_pending, sockmem, sizeof(int));
1033 #if defined(USE_SELECT)
1034 			FD_SET(socket, &(mod_s.pending_wset));
1035 #endif
1036 			rc = TCPSOCKET_INTERRUPTED;
1037 		}
1038 		else
1039 			rc = SOCKET_ERROR;
1040 	}
1041 	SSL_unlock_mutex(&sslCoreMutex);
1042 
1043 	if (rc != TCPSOCKET_INTERRUPTED)
1044 		free(iovec.iov_base);
1045 	else
1046 	{
1047 		int i;
1048 		free(buf0);
1049 		for (i = 0; i < bufs.count; ++i)
1050 		{
1051 		    if (bufs.frees[i])
1052 		    {
1053 		    	free(bufs.buffers[i]);
1054 		    	bufs.buffers[i] = NULL;
1055 		    }
1056 		}
1057 	}
1058 exit:
1059 	FUNC_EXIT_RC(rc);
1060 	return rc;
1061 }
1062 
1063 
SSLSocket_addPendingRead(SOCKET sock)1064 void SSLSocket_addPendingRead(SOCKET sock)
1065 {
1066 	FUNC_ENTRY;
1067 	if (ListFindItem(&pending_reads, &sock, intcompare) == NULL) /* make sure we don't add the same socket twice */
1068 	{
1069 		SOCKET* psock = (SOCKET*)malloc(sizeof(SOCKET));
1070 		if (psock)
1071 		{
1072 			*psock = sock;
1073 			ListAppend(&pending_reads, psock, sizeof(sock));
1074 		}
1075 	}
1076 	else
1077 		Log(TRACE_MIN, -1, "SSLSocket_addPendingRead: socket %d already in the list", sock);
1078 
1079 	FUNC_EXIT;
1080 }
1081 
1082 
SSLSocket_getPendingRead(void)1083 SOCKET SSLSocket_getPendingRead(void)
1084 {
1085 	SOCKET sock = -1;
1086 
1087 	if (pending_reads.count > 0)
1088 	{
1089 		sock = *(int*)(pending_reads.first->content);
1090 		ListRemoveHead(&pending_reads);
1091 	}
1092 	return sock;
1093 }
1094 
1095 
SSLSocket_continueWrite(pending_writes * pw)1096 int SSLSocket_continueWrite(pending_writes* pw)
1097 {
1098 	int rc = 0;
1099 
1100 	FUNC_ENTRY;
1101 	ERR_clear_error();
1102 	if ((rc = SSL_write(pw->ssl, pw->iovecs[0].iov_base, pw->iovecs[0].iov_len)) == pw->iovecs[0].iov_len)
1103 	{
1104 		/* topic and payload buffers are freed elsewhere, when all references to them have been removed */
1105 		free(pw->iovecs[0].iov_base);
1106 		Log(TRACE_MIN, -1, "SSL continueWrite: partial write now complete for socket %d", pw->socket);
1107 		rc = 1;
1108 	}
1109 	else
1110 	{
1111 		int sslerror = SSLSocket_error("SSL_write", pw->ssl, pw->socket, rc, NULL, NULL);
1112 		if (sslerror == SSL_ERROR_WANT_WRITE)
1113 			rc = 0; /* indicate we haven't finished writing the payload yet */
1114 	}
1115 	FUNC_EXIT_RC(rc);
1116 	return rc;
1117 }
1118 
1119 
SSLSocket_abortWrite(pending_writes * pw)1120 int SSLSocket_abortWrite(pending_writes* pw)
1121 {
1122 	int rc = 0;
1123 
1124 	FUNC_ENTRY;
1125 	free(pw->iovecs[0].iov_base);
1126 	FUNC_EXIT_RC(rc);
1127 	return rc;
1128 }
1129 #endif
1130