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