栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

poha.mqtt.c tls连接时,openssl证书从文件加载改为内存加载

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

poha.mqtt.c tls连接时,openssl证书从文件加载改为内存加载

单向认证时,使用上一篇文章openssl 内存加载CA证书说到的方法可以正常连接上MQTT服务器,但是改成双向认证时,由于还有两个证书需要加载,所以还需要修改库源码才行。其实查看openssl库的源码可以发现,加载文件的接口,实际上就是先从文件中读取到证书内容,然后再配置给相应结构体。 我们要做的工作就是找到源码接口,然后把从文件读取替换成从内存读取。

SSL_CTX_use_PrivateKey_file和SSL_CTX_use_certificate_chain_file接口在ssl_rsa.c文件中

 SSL_CTX_load_verify_locations接口跟踪到最后的实现在by_file.c中

 

直接贴出修改后的源文件,主要还是修改SSLSocket_createContext接口,将加载证书文件的地方修改成加载内存。

 




#if defined(OPENSSL)

#include "SocketBuffer.h"
#include "MQTTClient.h"
#include "MQTTProtocolOut.h"
#include "SSLSocket.h"
#include "Log.h"
#include "StackTrace.h"
#include "Socket.h"

#include "Heap.h"

#include 
#include 
#include 
#include 
#include 

extern Sockets mod_s;

static int SSLSocket_error(char* aString, SSL* ssl, int sock, int rc, int (*cb)(const char *str, size_t len, void *u), void* u);
char* SSL_get_verify_result_string(int rc);
void SSL_CTX_info_callback(const SSL* ssl, int where, int ret);
char* SSLSocket_get_version_string(int version);
void SSL_CTX_msg_callback(
		int write_p,
		int version,
		int content_type,
		const void* buf, size_t len,
		SSL* ssl, void* arg);
int pem_passwd_cb(char* buf, int size, int rwflag, void* userdata);
int SSL_create_mutex(ssl_mutex_type* mutex);
int SSL_lock_mutex(ssl_mutex_type* mutex);
int SSL_unlock_mutex(ssl_mutex_type* mutex);
int SSL_destroy_mutex(ssl_mutex_type* mutex);
#if (OPENSSL_VERSION_NUMBER >= 0x010000000)
extern void SSLThread_id(CRYPTO_THREADID *id);
#else
extern unsigned long SSLThread_id(void);
#endif
extern void SSLLocks_callback(int mode, int n, const char *file, int line);
int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts);
void SSLSocket_destroyContext(networkHandles* net);
void SSLSocket_addPendingRead(int sock);


static int handle_openssl_init = 1;
static ssl_mutex_type* sslLocks = NULL;
static ssl_mutex_type sslCoreMutex;


static int tls_ex_index_ssl_opts;

#if defined(_WIN32) || defined(_WIN64)
#define iov_len len
#define iov_base buf
#define snprintf _snprintf
#endif


static int SSLSocket_error(char* aString, SSL* ssl, int sock, int rc, int (*cb)(const char *str, size_t len, void *u), void* u)
{
    int error;

    FUNC_ENTRY;
    if (ssl)
        error = SSL_get_error(ssl, rc);
    else
        error = ERR_get_error();
    if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
    {
		Log(TRACE_MIN, -1, "SSLSocket error WANT_READ/WANT_WRITE");
    }
    else
    {
        static char buf[120];

        if (strcmp(aString, "shutdown") != 0)
        	Log(TRACE_MIN, -1, "SSLSocket error %s(%d) in %s for socket %d rc %d errno %d %sn", buf, error, aString, sock, rc, errno, strerror(errno));
        if (cb)
            ERR_print_errors_cb(cb, u);
		if (error == SSL_ERROR_SSL || error == SSL_ERROR_SYSCALL)
			error = SSL_FATAL;
    }
    FUNC_EXIT_RC(error);
    return error;
}

static struct
{
	int code;
	char* string;
}
X509_message_table[] =
{
	{ X509_V_OK, "X509_V_OK" },
	{ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT" },
	{ X509_V_ERR_UNABLE_TO_GET_CRL, "X509_V_ERR_UNABLE_TO_GET_CRL" },
	{ X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE" },
	{ X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE" },
	{ X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY" },
	{ X509_V_ERR_CERT_SIGNATURE_FAILURE, "X509_V_ERR_CERT_SIGNATURE_FAILURE" },
	{ X509_V_ERR_CRL_SIGNATURE_FAILURE, "X509_V_ERR_CRL_SIGNATURE_FAILURE" },
	{ X509_V_ERR_CERT_NOT_YET_VALID, "X509_V_ERR_CERT_NOT_YET_VALID" },
	{ X509_V_ERR_CERT_HAS_EXPIRED, "X509_V_ERR_CERT_HAS_EXPIRED" },
	{ X509_V_ERR_CRL_NOT_YET_VALID, "X509_V_ERR_CRL_NOT_YET_VALID" },
	{ X509_V_ERR_CRL_HAS_EXPIRED, "X509_V_ERR_CRL_HAS_EXPIRED" },
	{ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD" },
	{ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD" },
	{ X509_V_ERR_ERROR_IN_CRL_LAST_UPDATe_FIELD, "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD" },
	{ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD" },
	{ X509_V_ERR_OUT_OF_MEM, "X509_V_ERR_OUT_OF_MEM" },
	{ X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT" },
	{ X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN" },
	{ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY" },
	{ X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE" },
	{ X509_V_ERR_CERT_CHAIN_TOO_LONG, "X509_V_ERR_CERT_CHAIN_TOO_LONG" },
	{ X509_V_ERR_CERT_REVOKED, "X509_V_ERR_CERT_REVOKED" },
	{ X509_V_ERR_INVALID_CA, "X509_V_ERR_INVALID_CA" },
	{ X509_V_ERR_PATH_LENGTH_EXCEEDED, "X509_V_ERR_PATH_LENGTH_EXCEEDED" },
	{ X509_V_ERR_INVALID_PURPOSE, "X509_V_ERR_INVALID_PURPOSE" },
	{ X509_V_ERR_CERT_UNTRUSTED, "X509_V_ERR_CERT_UNTRUSTED" },
	{ X509_V_ERR_CERT_REJECTED, "X509_V_ERR_CERT_REJECTED" },
	{ X509_V_ERR_SUBJECT_ISSUER_MISMATCH, "X509_V_ERR_SUBJECT_ISSUER_MISMATCH" },
	{ X509_V_ERR_AKID_SKID_MISMATCH, "X509_V_ERR_AKID_SKID_MISMATCH" },
	{ X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH" },
	{ X509_V_ERR_KEYUSAGE_NO_CERTSIGN, "X509_V_ERR_KEYUSAGE_NO_CERTSIGN" },
	{ X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER" },
	{ X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION" },
	{ X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN" },
	{ X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION" },
	{ X509_V_ERR_INVALID_NON_CA, "X509_V_ERR_INVALID_NON_CA" },
	{ X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED" },
	{ X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE" },
	{ X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED" },
	{ X509_V_ERR_INVALID_EXTENSION, "X509_V_ERR_INVALID_EXTENSION" },
	{ X509_V_ERR_INVALID_POLICY_EXTENSION, "X509_V_ERR_INVALID_POLICY_EXTENSION" },
	{ X509_V_ERR_NO_EXPLICIT_POLICY, "X509_V_ERR_NO_EXPLICIT_POLICY" },
	{ X509_V_ERR_UNNESTED_RESOURCE, "X509_V_ERR_UNNESTED_RESOURCE" },
#if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
	{ X509_V_ERR_DIFFERENT_CRL_SCOPE, "X509_V_ERR_DIFFERENT_CRL_SCOPE" },
	{ X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE, "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE" },
	{ X509_V_ERR_PERMITTED_VIOLATION, "X509_V_ERR_PERMITTED_VIOLATION" },
	{ X509_V_ERR_EXCLUDED_VIOLATION, "X509_V_ERR_EXCLUDED_VIOLATION" },
	{ X509_V_ERR_SUBTREE_MINMAX, "X509_V_ERR_SUBTREE_MINMAX" },
	{ X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE, "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE" },
	{ X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX, "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX" },
	{ X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX" },
#endif
};

#if !defined(ARRAY_SIZE)

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#endif

char* SSL_get_verify_result_string(int rc)
{
	int i;
	char* retstring = "undef";

	for (i = 0; i < ARRAY_SIZE(X509_message_table); ++i)
	{
		if (X509_message_table[i].code == rc)
		{
			retstring = X509_message_table[i].string;
			break;
		}
	}
	return retstring;
}


void SSL_CTX_info_callback(const SSL* ssl, int where, int ret)
{
	if (where & SSL_CB_LOOP)
	{
		Log(TRACE_PROTOCOL, 1, "SSL state %s:%s:%s",
                  (where & SSL_ST_CONNECT) ? "connect" : (where & SSL_ST_ACCEPT) ? "accept" : "undef",
                    SSL_state_string_long(ssl), SSL_get_cipher_name(ssl));
	}
	else if (where & SSL_CB_EXIT)
	{
		Log(TRACE_PROTOCOL, 1, "SSL %s:%s",
                  (where & SSL_ST_CONNECT) ? "connect" : (where & SSL_ST_ACCEPT) ? "accept" : "undef",
                    SSL_state_string_long(ssl));
	}
	else if (where & SSL_CB_alert)
	{
		Log(TRACE_PROTOCOL, 1, "SSL alert %s:%s:%s",
                  (where & SSL_CB_READ) ? "read" : "write",
                    SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
	}
	else if (where & SSL_CB_HANDSHAKE_START)
	{
		Log(TRACE_PROTOCOL, 1, "SSL handshake started %s:%s:%s",
                  (where & SSL_CB_READ) ? "read" : "write",
                    SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
	}
	else if (where & SSL_CB_HANDSHAKE_DONE)
	{
		Log(TRACE_PROTOCOL, 1, "SSL handshake done %s:%s:%s",
                  (where & SSL_CB_READ) ? "read" : "write",
                    SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
		Log(TRACE_PROTOCOL, 1, "SSL certificate verification: %s",
                    SSL_get_verify_result_string(SSL_get_verify_result(ssl)));
	}
	else
	{
		Log(TRACE_PROTOCOL, 1, "SSL state %s:%s:%s", SSL_state_string_long(ssl),
                   SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
	}
}


char* SSLSocket_get_version_string(int version)
{
	int i;
	static char buf[20];
	char* retstring = NULL;
	static struct
	{
		int code;
		char* string;
	}
	version_string_table[] =
	{
		{ SSL2_VERSION, "SSL 2.0" },
		{ SSL3_VERSION, "SSL 3.0" },
		{ TLS1_VERSION, "TLS 1.0" },
#if defined(TLS2_VERSION)
		{ TLS2_VERSION, "TLS 1.1" },
#endif
#if defined(TLS3_VERSION)
		{ TLS3_VERSION, "TLS 1.2" },
#endif
	};

	for (i = 0; i < ARRAY_SIZE(version_string_table); ++i)
	{
		if (version_string_table[i].code == version)
		{
			retstring = version_string_table[i].string;
			break;
		}
	}

	if (retstring == NULL)
	{
		if (snprintf(buf, sizeof(buf), "%i", version) >= sizeof(buf))
			buf[sizeof(buf)-1] = ''; 
		retstring = buf;
	}
	return retstring;
}


void SSL_CTX_msg_callback(int write_p, int version, int content_type, const void* buf, size_t len,
        SSL* ssl, void* arg)
{



	Log(TRACE_MINIMUM, -1, "%s %s %d buflen %d", (write_p ? "sent" : "received"),
		SSLSocket_get_version_string(version),
		content_type, (int)len);
}


int pem_passwd_cb(char* buf, int size, int rwflag, void* userdata)
{
	int rc = 0;

	FUNC_ENTRY;
	if (!rwflag)
	{
		strncpy(buf, (char*)(userdata), size);
		buf[size-1] = '';
		rc = (int)strlen(buf);
	}
	FUNC_EXIT_RC(rc);
	return rc;
}

int SSL_create_mutex(ssl_mutex_type* mutex)
{
	int rc = 0;

	FUNC_ENTRY;
#if defined(_WIN32) || defined(_WIN64)
	*mutex = CreateMutex(NULL, 0, NULL);
#else
	rc = pthread_mutex_init(mutex, NULL);
#endif
	FUNC_EXIT_RC(rc);
	return rc;
}

int SSL_lock_mutex(ssl_mutex_type* mutex)
{
	int rc = -1;

	
#if defined(_WIN32) || defined(_WIN64)
	if (WaitForSingleObject(*mutex, INFINITE) != WAIT_FAILED)
#else
	if ((rc = pthread_mutex_lock(mutex)) == 0)
#endif
	rc = 0;

	return rc;
}

int SSL_unlock_mutex(ssl_mutex_type* mutex)
{
	int rc = -1;

	
#if defined(_WIN32) || defined(_WIN64)
	if (ReleaseMutex(*mutex) != 0)
#else
	if ((rc = pthread_mutex_unlock(mutex)) == 0)
#endif
	rc = 0;

	return rc;
}

int SSL_destroy_mutex(ssl_mutex_type* mutex)
{
	int rc = 0;

	FUNC_ENTRY;
#if defined(_WIN32) || defined(_WIN64)
	rc = CloseHandle(*mutex);
#else
	rc = pthread_mutex_destroy(mutex);
#endif
	FUNC_EXIT_RC(rc);
	return rc;
}



#if (OPENSSL_VERSION_NUMBER >= 0x010000000)
extern void SSLThread_id(CRYPTO_THREADID *id)
{
#if defined(_WIN32) || defined(_WIN64)
	CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
#else
	CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self());
#endif
}
#else
extern unsigned long SSLThread_id(void)
{
#if defined(_WIN32) || defined(_WIN64)
	return (unsigned long)GetCurrentThreadId();
#else
	return (unsigned long)pthread_self();
#endif
}
#endif

extern void SSLLocks_callback(int mode, int n, const char *file, int line)
{
	if (sslLocks)
	{
		if (mode & CRYPTO_LOCK)
			SSL_lock_mutex(&sslLocks[n]);
		else
			SSL_unlock_mutex(&sslLocks[n]);
	}
}


void SSLSocket_handleOpensslInit(int bool_value)
{
	handle_openssl_init = bool_value;
}


int SSLSocket_initialize(void)
{
	int rc = 0;
	
	int i;
	int lockMemSize;

	FUNC_ENTRY;

	if (handle_openssl_init)
	{
		if ((rc = SSL_library_init()) != 1)
			rc = -1;

		ERR_load_crypto_strings();
		SSL_load_error_strings();

		

		OpenSSL_add_all_algorithms();

		lockMemSize = CRYPTO_num_locks() * sizeof(ssl_mutex_type);

		sslLocks = malloc(lockMemSize);
		if (!sslLocks)
		{
			rc = -1;
			goto exit;
		}
		else
			memset(sslLocks, 0, lockMemSize);

		for (i = 0; i < CRYPTO_num_locks(); i++)
		{
			SSL_create_mutex(&sslLocks[i]);
		}

#if (OPENSSL_VERSION_NUMBER >= 0x010000000)
		CRYPTO_THREADID_set_callback(SSLThread_id);
#else
		CRYPTO_set_id_callback(SSLThread_id);
#endif
		CRYPTO_set_locking_callback(SSLLocks_callback);

	}

	SSL_create_mutex(&sslCoreMutex);

	tls_ex_index_ssl_opts = SSL_get_ex_new_index(0, "paho ssl options", NULL, NULL, NULL);

exit:
	FUNC_EXIT_RC(rc);
	return rc;
}

void SSLSocket_terminate(void)
{
	FUNC_ENTRY;

	if (handle_openssl_init)
	{
		CRYPTO_set_locking_callback(NULL);
		ERR_free_strings();
		EVP_cleanup();
		if (sslLocks)
		{
			int i = 0;

			for (i = 0; i < CRYPTO_num_locks(); i++)
			{
				SSL_destroy_mutex(&sslLocks[i]);
			}
			free(sslLocks);
		}
	}

	SSL_destroy_mutex(&sslCoreMutex);

	FUNC_EXIT;
}

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)
{
	int rc = 0;

	FUNC_ENTRY;

	{
		SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
		MQTTClient_SSLOptions* opts = SSL_CTX_get_ex_data(ctx, tls_ex_index_ssl_opts);

		if (opts == NULL)
			goto exit;

		if (opts->ssl_psk_cb != NULL)
			rc = opts->ssl_psk_cb(hint, identity, max_identity_len, psk, max_psk_len, opts->ssl_psk_context);
	}
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}

char *prikey="-----BEGIN RSA PRIVATE KEY-----n
MIIEpAIBAAKCAQEA4hX5HGlQbIq1sekgcGN4denOY9BOcfThKbZhjlUP7pepNgtun
n6XMbyNrU3bwWsI7IVrffTWBckAXSfmh3U98vCFT56+jzaFVny2/cd2JBI5ZA1MZn
RIY5XqGTZMHUoPsDi75G24G6KNbT5uKujXOBhnlDLOVstgRXL8N8ZIZZceHPUiuPn
LZBA7AXyVmh98F6vsH1LLk4sFS6oU+Uab4WHjloe0j/eDK/mnX5Xk6SqA7MwaAGmn
Pt7SbPMg/5uyqftfPJgg1BNnAQvQ1pX0BnVhjqZbgPOE1ym+ffUpsGNF1oJST5Hln
hOceq9TtpfA+d73ZJ6+xqjI268ysCsaM5fEhwwIDAQABAoIBAFqu85eoymBvFsgAn
uUk7LMMm/+jbUcu1rGbdx62eguBxpqaN2VZh22ksrMzypR/SToNnfsMrJfvcpzq9n
zWYGjwKq34vL0IkXUE+juumCMYZJynzd5QGuUO6bIpLEiHP1mwt/S86Z70CYQrCWn
des4zFhS5VXpxDwR66K153wuw0vAdPsnn4TGJCIwif09Em8WkrqThHKa08J0t96Kn
ruE/wdsTWVIvn4Rjjac1lilX/hv7AuPN+BCttILcT53bYJi7DpvgMBFQb7f+2ugun
7wZtDyAo+kfHVPy7FL2EdFy552ttcMvuLJWBgM946l90pdYl0wptZgYP1k+Mw9kfn
gfqLjGkCgYEA/MuiM+AIEjf/HK2V15HE2QPa3p9Y7W/7J5LNbg9XxY1VQG4Va3Zvn
jCKjRqQIXanuG5MMsIuC53GCdLhR7r+Qj8xYbV2dTVNUlMcQyc+4jxwMRg/EGgLPn
ojhmDNZ45y4ZJP2ISjJ0NaDrPdvYdLqUD/n9BDIgCMX0yPXsDJKuWsUCgYEA5POpn
eliHvEBYK4v8VQ7/QjoCE66qFAa1rSZ3a3BjLF8GNXMa/sjS0ofVw8R++wECtXaIn
QhgUFW/tB+rlyKrHS4TyCSrxYbEUaj2u1aZLBUCI0pQzD9S2L1CP0yW39ghCkiGin
/sk6+mgpwkATWnyC+HoI9SuVwW50N8Aaso6D8ucCgYEAufq6V33Pkk++EQQoGKy6n
bIoogLYsv2ouFTwshHcnNMC44pDak1fr0uY8xyCwwu/crE6v/EZ3RPy+ZE6igIpQn
uWo1+CfyLUxMIrSdRkva1PZmlTjOJfDBfvANLA6xnirM9ujLVwLtefLsfnL6ZXKun
sV5SZb7W0H2KjDpYshtLyJ0CgYA2a9zLIiQRkVHj+ABgz5HJUjSQLSJsZDPnFo+on
UCyirWuyZMvz6BSEypj7UcfFLjZQn/4/h62ucs5q5WD9U+rPfqhxmW2LBSaPIl5en
loqakv5y35tLlgpAMOwfCoYxy0DXr3spCPgl8YCLleODzLjtC0T50gRk2DZz0gwGn
iW2/3QKBgQDgXbsRZWu4/Fy0Ev/RZxHov/wkeDsHZVxbuLOXaSuPM9Xz8umn2brfn
muWAAaKt+hdxhIonJpEMGvkAak1ZSR1T+CW9vOotcla6V8oZ/u/kMTdKT5XTWbtvn
5zqShbujNYAiJBvIPb6ZE1A/uvMGAlSFZT2IaUpTaFrwCggyTjZuXw==n
-----END RSA PRIVATE KEY-----n";

char *cacrt="-----BEGIN CERTIFICATE-----n
MIIDmzCCAoOgAwIBAgIJAPDSM1KhTBCVMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVn
BAYTAm1nMRAwDgYDVQQIDAdtb29yZ2VuMQ0wCwYDVQQHDAR0ZXN0MRAwDgYDVQQKn
DAdtb29yZ2VuMRAwDgYDVQQLDAdtb29yZ2VuMRAwDgYDVQQDDAdtb29yZ2VuMB4Xn
DTIxMDkyOTA1MjU0OFoXDTMxMDkyNzA1MjU0OFowZDELMAkGA1UEBhMCbWcxEDAOn
BgNVBAgMB21vb3JnZW4xDTALBgNVBAcMBHRlc3QxEDAOBgNVBAoMB21vb3JnZW4xn
EDAOBgNVBAsMB21vb3JnZW4xEDAOBgNVBAMMB21vb3JnZW4wggEiMA0GCSqGSIb3n
DQEBAQUAA4IBDwAwggEKAoIBAQDZPtIfZMYm4zecCugaW2UyzwR29Eydm4cUVQw2n
Mv3r3PR082eWKEVJuE8imq4pBX8iVFQPxz+0R2fSzc7sMlWYhWazgWX7r9uYFO8yn
HHjIjnE/U+uECw3Nk3O8OKYCEJ98ox8RkswjJ4cDP/Cboi1/kx7UykUXbvkxttqcn
Th0uBHf7BjQ7KH8ezlI4qJafBhJzNS7ae+YfdwSAFv3zh97eurL4DZjCj+uUGcQfn
ZOmRKvEeWazcxLH7mBeErF6r+lnGPjYRS8PbQ9zqiwszXAdTBzHpD6G3mSBsT3ZIn
CTARrlSjL17aj4FcH7NlHQmH6jE+lf0m3ktzXo2y+V0aeX+zAgMBAAGjUDBOMB0Gn
A1UdDgQWBBTmqUNbzJumi92sMLzQBXVie0+APTAfBgNVHSMEGDAWgBTmqUNbzJumn
i92sMLzQBXVie0+APTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQDCn
6UBadJxukIsSQMKCA5J2SOGzQp28IkVOmD+xoKp7ewp8GW6m4GVZg1Jnoi1FfC3Rn
MCjVFgXHsDY8rAAhlIt9aMSeElquN/9R/y7WzYzRQflf6Pz8RcPDIepz113DFCXkn
jmIXedBWHJBkN6WuK5UMcMhUYfTqy/jbD3ZsbfF//zNsJrLOhHOVOn+oXkDZVbWXn
P5E5LI7B+cYMNRHusqyWPX1J78dgM+xikKZere7iY0Y38muOiPlcLmEty4uYgB4Mn
xrqau3x80HvzhBzmdXfmAIpLLwQpCeUe805EAfewYPUDstwyOy00THTzZdAqFw8vn
/gQNfYEUcxYWky4bgFwQn
-----END CERTIFICATE-----n";

char *clentcrt="-----BEGIN CERTIFICATE-----n
MIIDOjCCAiICCQC1a0mwFdos4zANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJtn
ZzEQMA4GA1UECAwHbW9vcmdlbjENMAsGA1UEBwwEdGVzdDEQMA4GA1UECgwHbW9vn
cmdlbjEQMA4GA1UECwwHbW9vcmdlbjEQMA4GA1UEAwwHbW9vcmdlbjAeFw0yMTA5n
MjkwNjE1MDRaFw0zMTA5MjcwNjE1MDRaMFoxCzAJBgNVBAYTAm1nMQswCQYDVQQIn
DAJtZzELMAkGA1UEBwwCbWcxCzAJBgNwBAoMAm1nMQswCQYDVQQLDAJtZzEXMBUGn
A1UEAwwOMTkyLjE2OC4zMS4xOTUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKn
AoIBAQDiFfkcaVBsirWx6SBwY3h16c5f0E5x9OEptmGOVQ/ul6k2C26fpcxvI2tTn
dvBawjshWt99NYFyQBdJ+aHdT3y8IVPnr6PNoVWfLb9x3YkEjlkDUxlEhjleoZNkn
wdSg+wOLvkbbgboo1tPm4q6Nc4GGeUMd5Wy2BFcvw3xkhllx4c9SK48tkEDsBfJWn
aH3wXq+wfUsuTiwVLqhT5RpvhYeOWh7SP94Mr+adfleTpKoDszBoAaY+3tJs8yD/n
m7Kp+188mCDUE2cBC9DWlfQGdWGOpluq84TXKb599SmwY0XWglJPkeWE5x6r1O2ln
8D53vdknr7GqMjbrzKwKxozl8SHDAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHtKn
b89PQ96tpy0tl+QZwJkc/fG7yRp25aSFC4LBILrrEnZaqCazHK1qVo8jyBQNIdlAn
Ek1DlEEVIKsyCCDBBvn2Ygwv+gE1GhC1TmHQbTSEA75cWCrPocnSuPBO3nMMfMJin
zkijYKFsUiN2/y1SCoaLXsv5RnJBk4TmqMHJDFwpOQYD9V3XdOYReD2zNYvtE5hwn
riHXynZHV3fNX98d0i2ocfectPiVFZt1nax9g7N02ooUzhp5aP92ESZEG7rZmFLUn
cjijvjUhz9XpbowL3OKKCtlCK1yD3dwZNZSw3SUSJwfn8Ys/it7lA3cFaIIYM2CAn
xB4OFykkA2zK5ZMVock=n
-----END CERTIFICATE-----n";


int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file)
{
    BIO *in;
    int ret = 0;
    X509 *x = NULL;

    ERR_clear_error();          

    in = BIO_new_mem_buf(clentcrt, strlen(clentcrt));
    if (in == NULL) {
        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
        goto end;
    }


    x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
                              ctx->default_passwd_callback_userdata);
    if (x == NULL) {
        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
        goto end;
    }

    ret = SSL_CTX_use_certificate(ctx, x);

    if (ERR_peek_error() != 0)
        ret = 0;                
    if (ret) {
        
        X509 *ca;
        int r;
        unsigned long err;

        SSL_CTX_clear_chain_certs(ctx);

        while ((ca = PEM_read_bio_X509(in, NULL,
                                       ctx->default_passwd_callback,
                                       ctx->default_passwd_callback_userdata))
               != NULL) {
            r = SSL_CTX_add0_chain_cert(ctx, ca);
            if (!r) {
                X509_free(ca);
                ret = 0;
                goto end;
            }
            
        }
        
        err = ERR_peek_last_error();
        if (ERR_GET_LIB(err) == ERR_LIB_PEM
            && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
            ERR_clear_error();
        else
            ret = 0;            
    }

 end:
    if (x != NULL)
        X509_free(x);
    if (in != NULL)
        BIO_free(in);
    return (ret);
}

int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
{
	int rc = 1;

	FUNC_ENTRY;
	if (net->ctx == NULL)
	{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
		net->ctx = SSL_CTX_new(TLS_client_method());
#else
		int sslVersion = MQTT_SSL_VERSION_DEFAULT;
		if (opts->struct_version >= 1) sslVersion = opts->sslVersion;

		switch (sslVersion)
		{
		case MQTT_SSL_VERSION_DEFAULT:
			net->ctx = SSL_CTX_new(SSLv23_client_method()); 
			break;
#if defined(SSL_OP_NO_TLSv1) && !defined(OPENSSL_NO_TLS1)
		case MQTT_SSL_VERSION_TLS_1_0:
			net->ctx = SSL_CTX_new(TLSv1_client_method());
			break;
#endif
#if defined(SSL_OP_NO_TLSv1_1) && !defined(OPENSSL_NO_TLS1)
		case MQTT_SSL_VERSION_TLS_1_1:
			net->ctx = SSL_CTX_new(TLSv1_1_client_method());
			break;
#endif
#if defined(SSL_OP_NO_TLSv1_2) && !defined(OPENSSL_NO_TLS1)
		case MQTT_SSL_VERSION_TLS_1_2:
			net->ctx = SSL_CTX_new(TLSv1_2_client_method());
			break;
#endif
		default:
			break;
		}
#endif
		if (net->ctx == NULL)
		{
			if (opts->struct_version >= 3)
				SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
			else
				SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc, NULL, NULL);
			goto exit;
		}
	}

	if (opts->keyStore)
	{
		if ((rc = SSL_CTX_use_certificate_chain_file(net->ctx, opts->keyStore)) != 1)
//                if ((rc = SSL_CTX_use_certificate_chain(net->ctx, opts->keyStore)) != 1)
		{
			if (opts->struct_version >= 3)
				SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
			else
				SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc, NULL, NULL);
			goto free_ctx; 
		}

		if (opts->privateKey == NULL)
			opts->privateKey = opts->keyStore;   

		if (opts->privateKeyPassword != NULL)
		{
			SSL_CTX_set_default_passwd_cb(net->ctx, pem_passwd_cb);
			SSL_CTX_set_default_passwd_cb_userdata(net->ctx, (void*)opts->privateKeyPassword);
		}

		
                           
                BIO * cbio = BIO_new_mem_buf(prikey, strlen(prikey));
                EVP_PKEY *pkey = NULL;
                pkey = PEM_read_bio_PrivateKey(cbio, NULL,
                                       pem_passwd_cb,
                                       (void*)opts->privateKeyPassword);
                SSL_CTX_use_PrivateKey(net->ctx, pkey);
                EVP_PKEY_free(pkey);
                BIO_free(cbio);

                
//		rc = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM);
//		if (opts->privateKey == opts->keyStore)
//			opts->privateKey = NULL;
//		if (rc != 1)
//		{
//			if (opts->struct_version >= 3)
//				SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
//			else
//				SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, NULL, NULL);
//			goto free_ctx;
//		}
	}

	if (opts->trustStore || opts->CApath)
	{
            BIO * cbio = BIO_new_mem_buf(cacrt, strlen(cacrt));
            X509 * cert = PEM_read_bio_X509(cbio, NULL, 0, NULL); //PEM格式
            X509_STORE_add_cert(net->ctx->cert_store, cert);
            X509_free(cert);
            BIO_free(cbio);
//		if ((rc = SSL_CTX_load_verify_locations(net->ctx, opts->trustStore, opts->CApath)) != 1)
//		{
//			if (opts->struct_version >= 3)
//				SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
//			else
//				SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc, NULL, NULL);
//			goto free_ctx;
//		}
	}
	else if (!opts->disableDefaultTrustStore)
	{
		if ((rc = SSL_CTX_set_default_verify_paths(net->ctx)) != 1)
		{
			if (opts->struct_version >= 3)
				SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
			else
				SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc, NULL, NULL);
			goto free_ctx;
		}
	}

	if (opts->enabledCipherSuites)
	{
		if ((rc = SSL_CTX_set_cipher_list(net->ctx, opts->enabledCipherSuites)) != 1)
		{
			if (opts->struct_version >= 3)
				SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
			else
				SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc, NULL, NULL);
			goto free_ctx;
		}
	}

#ifndef OPENSSL_NO_PSK
	if (opts->ssl_psk_cb != NULL)
	{
		SSL_CTX_set_ex_data(net->ctx, tls_ex_index_ssl_opts, opts);
		SSL_CTX_set_psk_client_callback(net->ctx, call_ssl_psk_cb);
	}
#endif

#if (OPENSSL_VERSION_NUMBER >= 0x010002000) 
	if (opts->protos != NULL && opts->protos_len > 0)
	{
		
		if ((rc = SSL_CTX_set_alpn_protos(net->ctx, opts->protos, opts->protos_len)) != 0)
		{
			if (opts->struct_version >= 3)
				SSLSocket_error("SSL_CTX_set_alpn_protos", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
			else
				SSLSocket_error("SSL_CTX_set_alpn_protos", NULL, net->socket, rc, NULL, NULL);
			rc = 0; 
			goto free_ctx;
		}
		rc = 1; 
	}
#endif

	SSL_CTX_set_mode(net->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

	goto exit;
free_ctx:
	SSL_CTX_free(net->ctx);
	net->ctx = NULL;

exit:
	FUNC_EXIT_RC(rc);
	return rc;
}


int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts,
	const char* hostname, size_t hostname_len)
{
	int rc = 1;

	FUNC_ENTRY;

	if (net->ctx != NULL || (rc = SSLSocket_createContext(net, opts)) == 1)
	{
		char *hostname_plus_null;
		int i;

		SSL_CTX_set_info_callback(net->ctx, SSL_CTX_info_callback);
		SSL_CTX_set_msg_callback(net->ctx, SSL_CTX_msg_callback);
   		if (opts->enableServerCertAuth)
			SSL_CTX_set_verify(net->ctx, SSL_VERIFY_PEER, NULL);

		net->ssl = SSL_new(net->ctx);

		
		for (i = 0; ;i++)
		{
			const char* cipher = SSL_get_cipher_list(net->ssl, i);
			if (cipher == NULL)
				break;
			Log(TRACE_PROTOCOL, 1, "SSL cipher available: %d:%s", i, cipher);
		}
		if ((rc = SSL_set_fd(net->ssl, net->socket)) != 1) {
			if (opts->struct_version >= 3)
				SSLSocket_error("SSL_set_fd", net->ssl, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
			else
				SSLSocket_error("SSL_set_fd", net->ssl, net->socket, rc, NULL, NULL);
		}
		hostname_plus_null = malloc(hostname_len + 1u );
		if (hostname_plus_null)
		{
			MQTTStrncpy(hostname_plus_null, hostname, hostname_len + 1u);
			if ((rc = SSL_set_tlsext_host_name(net->ssl, hostname_plus_null)) != 1) {
				if (opts->struct_version >= 3)
					SSLSocket_error("SSL_set_tlsext_host_name", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
				else
					SSLSocket_error("SSL_set_tlsext_host_name", NULL, net->socket, rc, NULL, NULL);
			}
			free(hostname_plus_null);
		}
		else
			rc = PAHO_MEMORY_ERROR;
	}

	FUNC_EXIT_RC(rc);
	return rc;
}


int SSLSocket_connect(SSL* ssl, int sock, const char* hostname, int verify, int (*cb)(const char *str, size_t len, void *u), void* u)
{
	int rc = 0;

	FUNC_ENTRY;

	ERR_clear_error();
	rc = SSL_connect(ssl);
	if (rc != 1)
	{
		int error;
		error = SSLSocket_error("SSL_connect", ssl, sock, rc, cb, u);
		if (error == SSL_FATAL)
			rc = error;
		if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
			rc = TCPSOCKET_INTERRUPTED;
	}
#if (OPENSSL_VERSION_NUMBER >= 0x010002000) 
	else if (verify)
	{
		char* peername = NULL;
		int port;
		size_t hostname_len;

		X509* cert = SSL_get_peer_certificate(ssl);
		hostname_len = MQTTProtocol_addressPort(hostname, &port, NULL, MQTT_DEFAULT_PORT);

		rc = X509_check_host(cert, hostname, hostname_len, 0, &peername);
		if (rc == 1)
			Log(TRACE_PROTOCOL, -1, "peername from X509_check_host is %s", peername);
		else
			Log(TRACE_PROTOCOL, -1, "X509_check_host for hostname %.*s failed, rc %d",
					(int)hostname_len, hostname, rc);

		if (peername != NULL)
			OPENSSL_free(peername);

		
		if (rc == 0 || rc == -1 || rc == -2)
		{
			char* ip_addr = malloc(hostname_len + 1);
			
			if (ip_addr)
			{
				strncpy(ip_addr, hostname, hostname_len);
				ip_addr[hostname_len] = '';

				rc = X509_check_ip_asc(cert, ip_addr, 0);
				Log(TRACE_MIN, -1, "rc from X509_check_ip_asc is %d", rc);

				free(ip_addr);
			}

			if (rc == 0 || rc == -1 || rc == -2)
				rc = SSL_FATAL;
		}

		if (cert)
			X509_free(cert);
	}
#endif

	FUNC_EXIT_RC(rc);
	return rc;
}




int SSLSocket_getch(SSL* ssl, int socket, char* c)
{
	int rc = SOCKET_ERROR;

	FUNC_ENTRY;
	if ((rc = SocketBuffer_getQueuedChar(socket, c)) != SOCKETBUFFER_INTERRUPTED)
		goto exit;

	ERR_clear_error();
	if ((rc = SSL_read(ssl, c, (size_t)1)) < 0)
	{
		int err = SSLSocket_error("SSL_read - getch", ssl, socket, rc, NULL, NULL);
		if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
		{
			rc = TCPSOCKET_INTERRUPTED;
			SocketBuffer_interrupted(socket, 0);
		}
	}
	else if (rc == 0)
		rc = SOCKET_ERROR; 	
	else if (rc == 1)
	{
		SocketBuffer_queueChar(socket, *c);
		rc = TCPSOCKET_COMPLETE;
	}
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}




char *SSLSocket_getdata(SSL* ssl, int socket, size_t bytes, size_t* actual_len, int* rc)
{
	char* buf;

	FUNC_ENTRY;
	if (bytes == 0)
	{
		buf = SocketBuffer_complete(socket);
		goto exit;
	}

	buf = SocketBuffer_getQueuedData(socket, bytes, actual_len);

	ERR_clear_error();
	if ((*rc = SSL_read(ssl, buf + (*actual_len), (int)(bytes - (*actual_len)))) < 0)
	{
		*rc = SSLSocket_error("SSL_read - getdata", ssl, socket, *rc, NULL, NULL);
		if (*rc != SSL_ERROR_WANT_READ && *rc != SSL_ERROR_WANT_WRITE)
		{
			buf = NULL;
			goto exit;
		}
	}
	else if (*rc == 0) 
	{
		buf = NULL;
		goto exit;
	}
	else
		*actual_len += *rc;

	if (*actual_len == bytes)
	{
		SocketBuffer_complete(socket);
		
		if (SSL_pending(ssl) > 0) 
			SSLSocket_addPendingRead(socket);
	}
	else 
	{
		SocketBuffer_interrupted(socket, *actual_len);
		Log(TRACE_MAX, -1, "SSL_read: %lu bytes expected but %lu bytes now received", bytes, *actual_len);
	}
exit:
	FUNC_EXIT;
	return buf;
}

void SSLSocket_destroyContext(networkHandles* net)
{
	FUNC_ENTRY;
	if (net->ctx)
		SSL_CTX_free(net->ctx);
	net->ctx = NULL;
	FUNC_EXIT;
}

static List pending_reads = {NULL, NULL, NULL, 0, 0};

int SSLSocket_close(networkHandles* net)
{
	int rc = 1;

	FUNC_ENTRY;
	
	if (pending_reads.count > 0 && ListFindItem(&pending_reads, &net->socket, intcompare))
		ListRemoveItem(&pending_reads, &net->socket, intcompare);

	if (net->ssl)
	{
		ERR_clear_error();
		rc = SSL_shutdown(net->ssl);
		SSL_free(net->ssl);
		net->ssl = NULL;
	}
	SSLSocket_destroyContext(net);
	FUNC_EXIT_RC(rc);
	return rc;
}



int SSLSocket_putdatas(SSL* ssl, int socket, char* buf0, size_t buf0len, PacketBuffers bufs)
{
	int rc = 0;
	int i;
	char *ptr;
	iobuf iovec;
	int sslerror;

	FUNC_ENTRY;
	iovec.iov_len = (ULONG)buf0len;
	for (i = 0; i < bufs.count; i++)
		iovec.iov_len += (ULONG)bufs.buflens[i];

	ptr = iovec.iov_base = (char *)malloc(iovec.iov_len);
	if (!ptr)
	{
		rc = PAHO_MEMORY_ERROR;
		goto exit;
	}
	memcpy(ptr, buf0, buf0len);
	ptr += buf0len;
	for (i = 0; i < bufs.count; i++)
	{
		if (bufs.buffers[i] != NULL && bufs.buflens[i] > 0)
		{
			memcpy(ptr, bufs.buffers[i], bufs.buflens[i]);
			ptr += bufs.buflens[i];
		}
	}

	SSL_lock_mutex(&sslCoreMutex);
	ERR_clear_error();
	if ((rc = SSL_write(ssl, iovec.iov_base, iovec.iov_len)) == iovec.iov_len)
		rc = TCPSOCKET_COMPLETE;
	else
	{
		sslerror = SSLSocket_error("SSL_write", ssl, socket, rc, NULL, NULL);

		if (sslerror == SSL_ERROR_WANT_WRITE)
		{
			int* sockmem = (int*)malloc(sizeof(int));
			int free = 1;

			if (!sockmem)
			{
				rc = PAHO_MEMORY_ERROR;
				SSL_unlock_mutex(&sslCoreMutex);
				goto exit;
			}
			Log(TRACE_MIN, -1, "Partial write: incomplete write of %lu bytes on SSL socket %d",
				iovec.iov_len, socket);
			SocketBuffer_pendingWrite(socket, ssl, 1, &iovec, &free, iovec.iov_len, 0);
			*sockmem = socket;
			ListAppend(mod_s.write_pending, sockmem, sizeof(int));
			FD_SET(socket, &(mod_s.pending_wset));
			rc = TCPSOCKET_INTERRUPTED;
		}
		else
			rc = SOCKET_ERROR;
	}
	SSL_unlock_mutex(&sslCoreMutex);

	if (rc != TCPSOCKET_INTERRUPTED)
		free(iovec.iov_base);
	else
	{
		int i;
		free(buf0);
		for (i = 0; i < bufs.count; ++i)
		{
		    if (bufs.frees[i])
		    {
		    	free(bufs.buffers[i]);
		    	bufs.buffers[i] = NULL;
		    }
		}	
	}
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}


void SSLSocket_addPendingRead(int sock)
{
	FUNC_ENTRY;
	if (ListFindItem(&pending_reads, &sock, intcompare) == NULL) 
	{
		int* psock = (int*)malloc(sizeof(sock));
		if (psock)
		{
			*psock = sock;
			ListAppend(&pending_reads, psock, sizeof(sock));
		}
	}
	else
		Log(TRACE_MIN, -1, "SSLSocket_addPendingRead: socket %d already in the list", sock);

	FUNC_EXIT;
}


int SSLSocket_getPendingRead(void)
{
	int sock = -1;

	if (pending_reads.count > 0)
	{
		sock = *(int*)(pending_reads.first->content);
		ListRemoveHead(&pending_reads);
	}
	return sock;
}


int SSLSocket_continueWrite(pending_writes* pw)
{
	int rc = 0;

	FUNC_ENTRY;
	ERR_clear_error();
	if ((rc = SSL_write(pw->ssl, pw->iovecs[0].iov_base, pw->iovecs[0].iov_len)) == pw->iovecs[0].iov_len)
	{
		
		free(pw->iovecs[0].iov_base);
		Log(TRACE_MIN, -1, "SSL continueWrite: partial write now complete for socket %d", pw->socket);
		rc = 1;
	}
	else
	{
		int sslerror = SSLSocket_error("SSL_write", pw->ssl, pw->socket, rc, NULL, NULL);
		if (sslerror == SSL_ERROR_WANT_WRITE)
			rc = 0; 
	}
	FUNC_EXIT_RC(rc);
	return rc;
}
#endif

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/316839.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号