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


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:47