示例#1
0
/* {{{ proto string connect()
    Connection apple apple_push service  */
PHP_METHOD(apple_push, init)
{
    zend_class_entry * _this_ce;

    zval * _this_zval = NULL;
    const char * x = NULL;
    int x_len = 0;
    const char * y = NULL;
    int y_len = 0;
    BIO *bio;
    SSL_CTX  *ssl_ctx;
    SSL_library_init();
    char *certificate_dir,*passphraseStr,*gatewayurl;
    zval *certificate = zend_read_static_property(apple_push_ce_ptr, ZEND_STRL("certificate"), sizeof ("certificate"));
    spprintf(&certificate_dir, 0, "%s", Z_STRVAL_P(certificate));
    zval *passphrase = zend_read_static_property(apple_push_ce_ptr, ZEND_STRL("passphrase"), sizeof ("passphrase"));
    spprintf(&passphraseStr, 0, "%s", Z_STRVAL_P(passphrase));
    zval *gateway = zend_read_static_property(apple_push_ce_ptr, ZEND_STRL("gateway"), sizeof ("gateway"));
    spprintf(&gatewayurl, 0, "%s", Z_STRVAL_P(gateway));
    ssl_ctx = SSL_CTX_new(SSLv23_method());
    if (ssl_ctx == NULL)
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_INIT_FAIL",  2 TSRMLS_CC);
        return ;
    }
    if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certificate_dir) != 1)
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "CERTIFICATE_NOT_FOUNT",  2 TSRMLS_CC);
        return ;
    }
    SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx,passphraseStr);

    if (SSL_CTX_use_PrivateKey_file(ssl_ctx, certificate_dir, SSL_FILETYPE_PEM) != 1)
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "CERTIFICATE_PASSWORD_FAIL",  2 TSRMLS_CC);
        return ;
    }
    bio = BIO_new_connect(gatewayurl);
    if(!bio)
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL",  2 TSRMLS_CC);
        return ;
    }
    if (BIO_do_connect(bio) <= 0)
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL",  2 TSRMLS_CC);
        return ;
    }
    if (!(ssl = SSL_new(ssl_ctx)))
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL",  2 TSRMLS_CC);
        return ;
    }
    SSL_set_bio(ssl, bio, bio);
    if (SSL_connect(ssl) <= 0)
    {
        zend_throw_exception_ex(apple_push_ce_ptr, 0 TSRMLS_CC, "SSL_CONNECT_FAIL",  2 TSRMLS_CC);
        return ;
    }
    RETURN_TRUE;
}
示例#2
0
文件: check_ssl.c 项目: Sir168/dsnat
static int
build_ssl_ctx(void)
{
	SSL_DATA *ssl;

	/* Library initialization */
	SSL_library_init();

	SSL_load_error_strings();
	bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

	if (!check_data->ssl)
		ssl = (SSL_DATA *) MALLOC(sizeof (ssl_data));
	else
		ssl = check_data->ssl;

	/* Initialize SSL context for SSL v2/3 */
	ssl->meth = SSLv23_method();
	ssl->ctx = SSL_CTX_new(ssl->meth);

	/* return for autogen context */
	if (!check_data->ssl) {
		check_data->ssl = ssl;
		goto end;
	}

	/* Load our keys and certificates */
	if (check_data->ssl->keyfile)
		if (!
		    (SSL_CTX_use_certificate_chain_file
		     (ssl->ctx, check_data->ssl->keyfile))) {
			log_message(LOG_INFO,
			       "SSL error : Cant load certificate file...");
			return 0;
		}

	/* Handle password callback using userdata ssl */
	if (check_data->ssl->password) {
		SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx,
						       check_data->ssl);
		SSL_CTX_set_default_passwd_cb(ssl->ctx, password_cb);
	}

	if (check_data->ssl->keyfile)
		if (!
		    (SSL_CTX_use_PrivateKey_file
		     (ssl->ctx, check_data->ssl->keyfile, SSL_FILETYPE_PEM))) {
			log_message(LOG_INFO, "SSL error : Cant load key file...");
			return 0;
		}

	/* Load the CAs we trust */
	if (check_data->ssl->cafile)
		if (!
		    (SSL_CTX_load_verify_locations
		     (ssl->ctx, check_data->ssl->cafile, 0))) {
			log_message(LOG_INFO, "SSL error : Cant load CA file...");
			return 0;
		}

      end:
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
	SSL_CTX_set_verify_depth(ssl->ctx, 1);
#endif

	return 1;
}
示例#3
0
SSL *SSLSocket::createSSL(SSL_CTX *ctx) {
  ERR_clear_error();

  /* look at options in the stream and set appropriate verification flags */
  if (m_context["verify_peer"].toBoolean()) {
    /* turn on verification callback */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);

    /* CA stuff */
    String cafile = m_context["cafile"];
    String capath = m_context["capath"];

    if (!cafile.empty() || !capath.empty()) {
      if (!SSL_CTX_load_verify_locations(ctx, cafile.data(), capath.data())) {
        raise_warning("Unable to set verify locations `%s' `%s'",
                      cafile.data(), capath.data());
        return NULL;
      }
    }

    int64 depth = m_context["verify_depth"].toInt64();
    if (depth) {
      SSL_CTX_set_verify_depth(ctx, depth);
    }
  } else {
    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
  }

  /* callback for the passphrase (for localcert) */
  if (!m_context["passphrase"].toString().empty()) {
    SSL_CTX_set_default_passwd_cb_userdata(ctx, this);
    SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
  }

  String cipherlist = m_context["ciphers"].toString();
  if (cipherlist.empty()) {
    cipherlist = "DEFAULT";
  }
  SSL_CTX_set_cipher_list(ctx, cipherlist.data());

  String certfile = m_context["local_cert"].toString();
  if (!certfile.empty()) {
    String resolved_path_buff = File::TranslatePath(certfile);
    if (!resolved_path_buff.empty()) {
      /* a certificate to use for authentication */
      if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data())
          != 1) {
        raise_warning("Unable to set local cert chain file `%s'; Check "
                      "that your cafile/capath settings include details of "
                      "your certificate and its issuer", certfile.data());
        return NULL;
      }

      if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(),
                                      SSL_FILETYPE_PEM) != 1) {
        raise_warning("Unable to set private key file `%s'",
                      resolved_path_buff.data());
        return NULL;
      }

      SSL *tmpssl = SSL_new(ctx);
      X509 *cert = SSL_get_certificate(tmpssl);
      if (cert) {
        EVP_PKEY *key = X509_get_pubkey(cert);
        EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
        EVP_PKEY_free(key);
      }
      SSL_free(tmpssl);

      if (!SSL_CTX_check_private_key(ctx)) {
        raise_warning("Private key does not match certificate!");
      }
    }
  }

  SSL *ssl = SSL_new(ctx);
  if (ssl) {
    SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */
  }
  return ssl;
}
示例#4
0
int	CSSLClient::SSLConnect(SWL_socket_t sockfd, bool bVerifyPeer, const char *pHost, const char *pCertFile, \
						   const char *pPriteKeyFile, const char *pCAPath, const char *pCAFile, const char *pPassWd)
{
	s_Lock.Lock();
	if (!s_bHasInitial)
	{
		printf("ssl not initial\n");
		s_Lock.UnLock();
		return -1;
	}
	s_Lock.UnLock();
	
	if (pCertFile!=NULL && pPriteKeyFile!=NULL)
	{
		if (pCAPath)
		{
			if(SSL_CTX_load_verify_locations(s_SSLCTX, pCAFile, NULL) <= 0)
			{
				printf("Failed to set CA location...\n");
				return -1;
			}
		}
		if (SSL_CTX_use_certificate_file(s_SSLCTX, pCertFile, SSL_FILETYPE_PEM) <= 0) 
		{
			printf("%s %s %d failed\n", __FILE__, __FUNCTION__, __LINE__);
			int errNum = ERR_get_error();
			printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum));
			printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum));
			return -1;
		}
		if (pPassWd)
		{
			SSL_CTX_set_default_passwd_cb_userdata(s_SSLCTX, (void*)pPassWd);
		}
		if (SSL_CTX_use_PrivateKey_file(s_SSLCTX, pPriteKeyFile, SSL_FILETYPE_PEM) <= 0) 
		{
			printf("%s %s %d failed\n", __FILE__, __FUNCTION__, __LINE__);
			int errNum = ERR_get_error();
			printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum));
			printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum));
			return -1;
		}

		if (!SSL_CTX_check_private_key(s_SSLCTX)) 
		{
			printf("%s %s %d failed\n", __FILE__, __FUNCTION__, __LINE__);
			int errNum = ERR_get_error();
			printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum));
			printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum));
			return -1;
		}
	}

	if (NULL == m_pSSL)
	{
		if (bVerifyPeer)
		{
			SSL_CTX_set_verify(s_SSLCTX, SSL_VERIFY_PEER, VerifyCallBack);
		}
		m_pSSL = SSL_new(s_SSLCTX);
		if (NULL == m_pSSL)
		{
			printf("ssl new err\n");
			return -1;
		}
	}

	if (1 != SSL_set_fd(m_pSSL, sockfd))
	{
		int errNum = ERR_get_error();
		printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum));
		printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum));
		return -1;
	}
	SSL_set_connect_state(m_pSSL);

	unsigned long reTry = 0; 
	int ret = 0, err = 0;
	while(reTry++ < SSL_SOCKET_CONNECT_RETRIES)
	{
		if((ret = SSL_connect(m_pSSL)) == 1)
		{
			break;
		}
		err = SSL_get_error(m_pSSL, ret);
		if(SSL_ERROR_WANT_CONNECT == err || SSL_ERROR_WANT_READ == err || SSL_ERROR_WANT_WRITE == err)
		{
			PUB_Sleep(10); // wait a while
		}
		else
		{
			printf("SSL_connect Err : %d\n", err);
			int errNum = ERR_get_error();
			printf("%s:%s:%d, ssl connect error:%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_reason_error_string(errNum));
			printf("%s:%s:%d, error function=%s\n", __FUNCTION__, __FILE__, __LINE__, ERR_func_error_string(errNum));
			FreeRsource();
			return -1;
		}
	}
	if (reTry >= SSL_SOCKET_CONNECT_RETRIES)
	{
		printf("reTry >= SSL_SOCKET_CONNECT_RETRIES\n");
		FreeRsource();
		return -1;
	}

	if (pHost)
	{
		if (PostConnectCheck(m_pSSL, pHost) < 0)
		{
			return -1;
		}
	}
	
	return 0;
}
示例#5
0
BOOL CSSLContext::LoadCertAndKey(SSL_CTX* sslCtx, int iVerifyMode, LPCTSTR lpszPemCertFile, LPCTSTR lpszPemKeyFile, LPCTSTR lpszKeyPasswod, LPCTSTR lpszCAPemCertFileOrPath)
{
	USES_CONVERSION;

	if(lpszCAPemCertFileOrPath != nullptr)
	{
		LPCTSTR lpszCAPemCertFile = nullptr;
		LPCTSTR lpszCAPemCertPath = nullptr;

		if(!ATLPath::FileExists(lpszCAPemCertFileOrPath))
		{
			::SetLastError(ERROR_FILE_NOT_FOUND);
			return FALSE;
		}

		if(!ATLPath::IsDirectory(lpszCAPemCertFileOrPath))
			lpszCAPemCertFile = lpszCAPemCertFileOrPath;
		else
			lpszCAPemCertPath = lpszCAPemCertFileOrPath;

		if(!SSL_CTX_load_verify_locations(sslCtx, T2CA(lpszCAPemCertFile), T2CA(lpszCAPemCertPath)))
		{
			::SetLastError(ERROR_INVALID_DATA);
			return FALSE;
		}

		if(!SSL_CTX_set_default_verify_paths(sslCtx))
		{
			::SetLastError(ERROR_FUNCTION_FAILED);
			return FALSE;
		}

		if(m_enSessionMode == SSL_SM_SERVER && iVerifyMode & SSL_VM_PEER)
		{
			STACK_OF(X509_NAME)* caCertNames = SSL_load_client_CA_file(T2CA(lpszCAPemCertFileOrPath));

			if(caCertNames == nullptr)
			{
				::SetLastError(ERROR_EMPTY);
				return FALSE;
			}

			SSL_CTX_set_client_CA_list(sslCtx, caCertNames);
		}
	}

	if(lpszPemCertFile != nullptr)
	{
		if(	!ATLPath::FileExists(lpszPemCertFile)	||
			ATLPath::IsDirectory(lpszPemCertFile)	)
		{
			::SetLastError(ERROR_FILE_NOT_FOUND);
			return FALSE;
		}

		if(	lpszPemKeyFile == nullptr				||
			!ATLPath::FileExists(lpszPemKeyFile)	||
			ATLPath::IsDirectory(lpszPemKeyFile)	)
		{
			::SetLastError(ERROR_FILE_NOT_FOUND);
			return FALSE;
		}
		
		if(lpszKeyPasswod != nullptr)
			SSL_CTX_set_default_passwd_cb_userdata(sslCtx, (void*)T2CA(lpszKeyPasswod));

		if(!SSL_CTX_use_PrivateKey_file(sslCtx, T2CA(lpszPemKeyFile), SSL_FILETYPE_PEM))
		{
			::SetLastError(ERROR_INVALID_PASSWORD);
			return FALSE;
		}

		if(!SSL_CTX_use_certificate_chain_file(sslCtx, T2CA(lpszPemCertFile)))
		{
			::SetLastError(ERROR_INVALID_DATA);
			return FALSE;
		}

		if(!SSL_CTX_check_private_key(sslCtx))
		{
			::SetLastError(ERROR_INVALID_ACCESS);
			return FALSE;
		}
	}

	return TRUE;
}
示例#6
0
BOOL connect_ssl(int sockfd, 
    const char* ca_crt_root,
    const char* ca_crt_client,
    const char* ca_password,
    const char* ca_key_client,
    SSL** pp_ssl, SSL_CTX** pp_ssl_ctx)
{
    SSL_METHOD* meth = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x010100000L
    meth = (SSL_METHOD*)TLS_client_method();
#else
    meth = (SSL_METHOD*)SSLv23_client_method();
#endif /* OPENSSL_VERSION_NUMBER */
        
    *pp_ssl_ctx = SSL_CTX_new(meth);

    if(!*pp_ssl_ctx)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
        uTrace.Write(Trace_Error, "SSL_CTX_new: %s\n", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl3;
    }

    if(ca_crt_root && ca_crt_client && ca_password && ca_key_client)
    {
        SSL_CTX_load_verify_locations(*pp_ssl_ctx, ca_crt_root, NULL);
        if(SSL_CTX_use_certificate_file(*pp_ssl_ctx, ca_crt_client, SSL_FILETYPE_PEM) <= 0)
        {
            CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
            uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
            goto clean_ssl2;
        }

        SSL_CTX_set_default_passwd_cb_userdata(*pp_ssl_ctx, (char*)ca_password);
        if(SSL_CTX_use_PrivateKey_file(*pp_ssl_ctx, ca_key_client, SSL_FILETYPE_PEM) <= 0)
        {
            CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
            uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
            goto clean_ssl2;

        }
        
        if(!SSL_CTX_check_private_key(*pp_ssl_ctx))
        {
            CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
            uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
            goto clean_ssl2;
        }
    }
    
    *pp_ssl = SSL_new(*pp_ssl_ctx);
    if(!*pp_ssl)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
        uTrace.Write(Trace_Error, "SSL_new: %s\n", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl2;
    }
    
    if(SSL_set_fd(*pp_ssl, sockfd) <= 0)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
        uTrace.Write(Trace_Error, "SSL_set_fd: %s\n", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl1;
    }
    
    if(SSL_connect(*pp_ssl) <= 0)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
        uTrace.Write(Trace_Error, "SSL_connect: %s\n", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl1;
    }
        
    return TRUE;

clean_ssl1:
    if(*pp_ssl)
    {
		SSL_free(*pp_ssl);
        *pp_ssl = NULL;
    }
clean_ssl2:
    if(*pp_ssl_ctx)
    {
		SSL_CTX_free(*pp_ssl_ctx);
        *pp_ssl_ctx = NULL;
    }
clean_ssl3:
    return FALSE;
}
示例#7
0
文件: tls.c 项目: Zabrane/SPOCP
SSL_CTX        *
tls_init(srv_t * srv)
{
	char            path[_POSIX_PATH_MAX];
	SSL_CTX        *ctx;
	int             r;
	char            errorstr[1024];
	unsigned long   e;

	SSL_library_init();
	SSL_load_error_strings();	/* basic set up */
	OpenSSL_add_ssl_algorithms();

	/*
	 * Create a TLS context 
	 */

	if (!(ctx = SSL_CTX_new(SSLv23_method()))) {
		LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error allocation SSL_CTX");
		return 0;
	}

	LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Do we have enough randomness ??");

	if (!RAND_status()) {
		/*
		 * load entropy from files 
		 */
		add_entropy(srv->SslEntropyFile);
		add_entropy(RAND_file_name(path, sizeof(path)));

		/*
		 * load entropy from egd sockets 
		 */
#ifdef HAVE_RAND_EGD
		add_entropy(getenv("EGDSOCKET"));
		snprintf(path, sizeof(path), "%s/.entropy", NONULL(Homedir));
		add_entropy(path);
		add_entropy("/tmp/entropy");
#endif

		/*
		 * shuffle $RANDFILE (or ~/.rnd if unset) 
		 */
		RAND_write_file(RAND_file_name(path, sizeof(path)));
		if (!RAND_status()) {
			LOG(SPOCP_ERR)
				traceLog(LOG_ERR,
				    "Failed to find enough entropy on your system");
			return 0;
		}
	}

	/*
	 * Initialize with DH parameters if supplied 
	 */

	if (srv->dhFile) {
		if (init_dh(ctx, (unsigned char *) srv->dhFile) == FALSE) {
			LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error initializing DH");
			SSL_CTX_free(ctx);
			return 0;
		} else
			LOG(SPOCP_ERR) traceLog(LOG_ERR,"Initializing DH OK");
	}

	/*
	 * and a RSA key too 
	 */

	if (generate_eph_rsa_key(ctx, 512) == FALSE) {
		LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error initializing RSA key");
		SSL_CTX_free(ctx);
		return 0;
	} else
		LOG(SPOCP_ERR) traceLog(LOG_ERR,"Initializing RSA key OK");

	/*
	 * Set up certificates and keys 
	 */

	if (srv->certificateFile != NULL) {
		LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Certificate File");
		if (!SSL_CTX_use_certificate_chain_file
		    (ctx, srv->certificateFile)) {
			LOG(SPOCP_ERR)
			    traceLog(LOG_ERR,"Error in SSL_CTX_use_certificate_file");
			SSL_CTX_free(ctx);
			return 0;
		}
	}

	if (srv->privateKey != NULL) {

		if (srv->passwd) {
			SSL_CTX_set_default_passwd_cb_userdata(ctx,
							       (void *) srv->
							       passwd);
			SSL_CTX_set_default_passwd_cb(ctx, password_cb);
		}

		LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Private Key File");
		r = SSL_CTX_use_PrivateKey_file(ctx, srv->privateKey,
						SSL_FILETYPE_PEM);
		if (r == 0) {
			e = ERR_get_error();
			ERR_error_string_n(e, errorstr, 1024);

			LOG(SPOCP_ERR)
			    traceLog(LOG_ERR,"Error in SSL_CTX_use_PrivateKey_file");
			LOG(SPOCP_ERR) traceLog(LOG_ERR,"%s", errorstr);

			SSL_CTX_free(ctx);
			return 0;
		}
	}

	if (srv->caList != NULL) {
		LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Trusted CAs File");
		if (!SSL_CTX_load_verify_locations(ctx, srv->caList, 0)) {
			LOG(SPOCP_ERR)
			    traceLog(LOG_ERR,"Error in SSL_CTX_load_verify_locations");
			SSL_CTX_free(ctx);
			return 0;
		}
	}

	if (srv->clientcert == NONE)
		SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback_ok);
	else {
		int             i = SSL_VERIFY_PEER;
		if (srv->clientcert == HARD)
			i |= SSL_VERIFY_CLIENT_ONCE;

		SSL_CTX_set_verify(ctx, i, verify_callback);
	}

	SSL_CTX_set_verify_depth(ctx, srv->sslverifydepth);

	SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);

	if (SSL_CTX_set_cipher_list(ctx, CIPHER_LIST) != 1) {
		LOG(SPOCP_ERR) traceLog(LOG_ERR,"No valid ciphers in cipherlist");
		SSL_CTX_free(ctx);
		return 0;
	}

	LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Initialised TLS");

	return ctx;
}
示例#8
0
文件: IoSecureServer.c 项目: ADTSH/io
IoSecureServer *IoSecureServer_proto(void *state)
{
	initSSL();
	
	IoObject *self = IoObject_new(state);
	
	IoObject_tag_(self, IoSecureServer_newTag(state));
	
	IoObject_setDataPointer_(self, (SecureServerData *)calloc(1, sizeof(SecureServerData)));
	SSL_CTX *ctx = SSL_CTX_new(TLSv1_server_method());
	DATA(self)->ssl_ctx = ctx;
	SSL_CTX_set_default_passwd_cb(ctx, IoSecureSockets_Password_Callback);
	SSL_CTX_set_default_passwd_cb_userdata(ctx, self);
	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, IoSecureSockets_Verify_Callback);
	
	#ifdef DTLS_IMPLEMENTED
	IoObject_setSlot_to_(self, IOSYMBOL("supportsDTLS"), IOTRUE(self));
	#else
	IoObject_setSlot_to_(self, IOSYMBOL("supportsDTLS"), IOFALSE(self));
	#endif
	//doc SecureServer supportsDTLS Returns true if server supports DTLS, false otherwise.

	IoState_registerProtoWithFunc_((IoState *)state, self, IoSecureServer_proto);
	
	{
		IoMethodTable methodTable[] = {
		{"setKeyFile", IoSecureServer_setKeyFile},
		//doc SecureServer setKeyFile(path) Sets the key file. Returns self.
		
		{"setCertFile", IoSecureServer_setCertFile},
		//doc SecureServer setCertFile(path) Sets the certificate file. Returns self.
		
		{"setCAFile", IoSecureServer_setCAFile},
		//doc SecureServer setCAFile(path) Sets the CA file. Returns self.
		
		{"setCRLFile", IoSecureServer_setCRLFile},
		//doc SecureServer setCRLFile(path) Sets the CRL file. Returns self.
		
		{"useTLS", IoSecureServer_useTLS},
		//doc SecureServer useTLS Returns useTLS value.

		{"useDTLS", IoSecureServer_useDTLS},
		//doc SecureServer useDTLS Returns useDTLS value.

		{"setRequiresClientCertificate", IoSecureServer_setRequiresClientCertificate},
		//doc SecureServer setRequiresClientCertificate(aBool) Sets the requires client certificate attribute. Returns self.
		
		{"tlsWrap", IoSecureServer_tlsWrap},
		//doc SecureServer tlsWrap Returns tlsWrap value.
		
		#ifdef DTLS_IMPLEMENTED
		{"dtlsWrap", IoSecureServer_dtlsWrap},
		//doc SecureServer dtlsWrap Returns dtlsWrap value.
		
		{"udpRecvIP", IoSecureServer_udpRecvIP},
		//doc SecureServer udpRecvIP Returns udpRecvIP value.
		
		{"dispatchUdp", IoSecureServer_dispatchUDP},
		//doc SecureServer dispatchUdp Returns dispatchUdp value.
		
		#endif
		{NULL, NULL}
		};
		IoObject_addMethodTable_(self, methodTable);
	}
	
	return self;
}
示例#9
0
static
int tls_init_context(tls_t *tls, tls_issues_t const *ti)
{
  int verify;
  static int random_loaded;

  ONCE_INIT(tls_init_once);

  if (!random_loaded) {
    random_loaded = 1;

    if (ti->randFile &&
	!RAND_load_file(ti->randFile, 1024 * 1024)) {
      if (ti->configured > 1) {
	SU_DEBUG_3(("%s: cannot open randFile %s\n",
		   "tls_init_context", ti->randFile));
	tls_log_errors(3, "tls_init_context", 0);
      }
      /* errno = EIO; */
      /* return -1; */
    }
  }

#if HAVE_SIGPIPE
  /* Avoid possible SIGPIPE when sending close_notify */
  signal(SIGPIPE, SIG_IGN);
#endif

  if (tls->ctx == NULL) {
    const SSL_METHOD *meth;

    /* meth = SSLv3_method(); */
    /* meth = SSLv23_method(); */

    if (ti->version)
      meth = TLSv1_method();
    else
      meth = SSLv23_method();

    tls->ctx = SSL_CTX_new((SSL_METHOD*)meth);
  }

  if (tls->ctx == NULL) {
    tls_log_errors(1, "tls_init_context", 0);
    errno = EIO;
    return -1;
  }

  /* Set callback if we have a passphrase */
  if (ti->passphrase != NULL) {
    SSL_CTX_set_default_passwd_cb(tls->ctx, passwd_cb);
    SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, (void *)ti);
  }

  if (!SSL_CTX_use_certificate_file(tls->ctx,
				    ti->cert,
				    SSL_FILETYPE_PEM)) {
    if (ti->configured > 0) {
      SU_DEBUG_1(("%s: invalid local certificate: %s\n",
		 "tls_init_context", ti->cert));
      tls_log_errors(3, "tls_init_context", 0);
#if require_client_certificate
      errno = EIO;
      return -1;
#endif
    }
  }

  if (!SSL_CTX_use_PrivateKey_file(tls->ctx,
                                   ti->key,
                                   SSL_FILETYPE_PEM)) {
    if (ti->configured > 0) {
      SU_DEBUG_1(("%s: invalid private key: %s\n",
		 "tls_init_context", ti->key));
      tls_log_errors(3, "tls_init_context(key)", 0);
#if require_client_certificate
      errno = EIO;
      return -1;
#endif
    }
  }

  if (!SSL_CTX_check_private_key(tls->ctx)) {
    if (ti->configured > 0) {
      SU_DEBUG_1(("%s: private key does not match the certificate public key\n",
		  "tls_init_context"));
    }
#if require_client_certificate
    errno = EIO;
    return -1;
#endif
  }

  if (!SSL_CTX_load_verify_locations(tls->ctx,
                                     ti->CAfile,
                                     ti->CApath)) {
    SU_DEBUG_1(("%s: error loading CA list: %s\n",
		 "tls_init_context", ti->CAfile));
    if (ti->configured > 0)
      tls_log_errors(3, "tls_init_context(CA)", 0);
    errno = EIO;
    return -1;
  }

  /* corresponds to (enum tport_tls_verify_policy) */
  tls->verify_incoming = (ti->policy & 0x1) ? 1 : 0;
  tls->verify_outgoing = (ti->policy & 0x2) ? 1 : 0;
  tls->verify_subj_in  = (ti->policy & 0x4) ? tls->verify_incoming : 0;
  tls->verify_subj_out = (ti->policy & 0x8) ? tls->verify_outgoing : 0;
  tls->verify_date     = (ti->verify_date)  ? 1 : 0;

  if (tls->verify_incoming)
    verify = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  else
    verify = SSL_VERIFY_NONE;

  SSL_CTX_set_verify_depth(tls->ctx, ti->verify_depth);
  SSL_CTX_set_verify(tls->ctx, verify, tls_verify_cb);

  if (!SSL_CTX_set_cipher_list(tls->ctx, ti->cipher)) {
    SU_DEBUG_1(("%s: error setting cipher list\n", "tls_init_context"));
    tls_log_errors(3, "tls_init_context", 0);
    errno = EIO;
    return -1;
  }

  return 0;
}
示例#10
0
/**
 * Once per rd_kafka_t handle initialization of OpenSSL
 *
 * Locality: application thread
 *
 * NOTE: rd_kafka_wrlock() MUST be held
 */
int rd_kafka_transport_ssl_ctx_init (rd_kafka_t *rk,
				     char *errstr, size_t errstr_size) {
	int r;
	SSL_CTX *ctx;

	call_once(&rd_kafka_ssl_init_once, rd_kafka_transport_ssl_init);

	
	ctx = SSL_CTX_new(SSLv23_client_method());
	if (!ctx)
		goto fail;


	/* Key file password callback */
	SSL_CTX_set_default_passwd_cb(ctx, rd_kafka_transport_ssl_passwd_cb);
	SSL_CTX_set_default_passwd_cb_userdata(ctx, rk);

	/* Ciphers */
	if (rk->rk_conf.ssl.cipher_suites) {
		rd_kafka_dbg(rk, SECURITY, "SSL",
			     "Setting cipher list: %s",
			     rk->rk_conf.ssl.cipher_suites);
		if (!SSL_CTX_set_cipher_list(ctx,
					     rk->rk_conf.ssl.cipher_suites)) {
			rd_snprintf(errstr, errstr_size,
				    "No recognized ciphers");
			goto fail;
		}
	}


	if (rk->rk_conf.ssl.ca_location) {
		/* CA certificate location, either file or directory. */
		int is_dir = rd_kafka_path_is_dir(rk->rk_conf.ssl.ca_location);

		rd_kafka_dbg(rk, SECURITY, "SSL",
			     "Loading CA certificate(s) from %s %s",
			     is_dir ? "directory":"file",
			     rk->rk_conf.ssl.ca_location);
		
		r = SSL_CTX_load_verify_locations(ctx,
						  !is_dir ?
						  rk->rk_conf.ssl.
						  ca_location : NULL,
						  is_dir ?
						  rk->rk_conf.ssl.
						  ca_location : NULL);

		if (r != 1)
			goto fail;
	}

	if (rk->rk_conf.ssl.cert_location) {
		rd_kafka_dbg(rk, SECURITY, "SSL",
			     "Loading certificate from file %s",
			     rk->rk_conf.ssl.cert_location);

		r = SSL_CTX_use_certificate_chain_file(ctx,
						       rk->rk_conf.ssl.cert_location);

		if (r != 1)
			goto fail;
	}

	if (rk->rk_conf.ssl.key_location) {
		rd_kafka_dbg(rk, SECURITY, "SSL",
			     "Loading private key file from %s",
			     rk->rk_conf.ssl.key_location);

		r = SSL_CTX_use_PrivateKey_file(ctx,
						rk->rk_conf.ssl.key_location,
						SSL_FILETYPE_PEM);
		if (r != 1)
			goto fail;
	}


	SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);

	rk->rk_conf.ssl.ctx = ctx;
	return 0;

 fail:
	rd_kafka_ssl_error(rk, NULL, errstr, errstr_size);
	SSL_CTX_free(ctx);

	return -1;
}
示例#11
0
static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
    SSL_CTX *ctx = NULL;
    unsigned long error;

    switch (type) {
#ifdef RADPROT_TLS
    case RAD_TLS:
	ctx = SSL_CTX_new(TLSv1_method());
	break;
#endif
#ifdef RADPROT_DTLS
    case RAD_DTLS:
	ctx = SSL_CTX_new(DTLSv1_method());
	SSL_CTX_set_read_ahead(ctx, 1);
	break;
#endif
    }
    if (!ctx) {
	debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
	while ((error = ERR_get_error()))
	    debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
	return NULL;
    }
#ifdef DEBUG
	SSL_CTX_set_info_callback(ctx, ssl_info_callback);
#endif

    if (conf->certkeypwd) {
	SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd);
	SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
    }
    if (conf->certfile || conf->certkeyfile) {
	if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) ||
	    !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) ||
	    !SSL_CTX_check_private_key(ctx)) {
	    while ((error = ERR_get_error()))
		debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
	    debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name);
	    SSL_CTX_free(ctx);
	    return NULL;
	}
    }

    if (conf->policyoids) {
	if (!conf->vpm) {
	    conf->vpm = createverifyparams(conf->policyoids);
	    if (!conf->vpm) {
		debug(DBG_ERR, "tlscreatectx: Failed to add policyOIDs in TLS context %s", conf->name);
		SSL_CTX_free(ctx);
		return NULL;
	    }
	}
    }

    if (conf->cacertfile != NULL || conf->cacertpath != NULL)
        if (!tlsaddcacrl(ctx, conf)) {
            if (conf->vpm) {
                X509_VERIFY_PARAM_free(conf->vpm);
                conf->vpm = NULL;
            }
            SSL_CTX_free(ctx);
            return NULL;
        }

    debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name);
    return ctx;
}
示例#12
0
int
mowgli_vio_openssl_default_listen(mowgli_vio_t *vio, int backlog)
{
	return_val_if_fail(vio, -255);

	mowgli_ssl_connection_t *connection = vio->privdata;
	const int fd = mowgli_vio_getfd(vio);

	vio->error.op = MOWGLI_VIO_ERR_OP_LISTEN;

#ifndef MOWGLI_HAVE_OPENSSL_TLS_METHOD_API
	connection->ssl_context = SSL_CTX_new(SSLv23_server_method());
#else
	connection->ssl_context = SSL_CTX_new(TLS_server_method());
#endif

	if (connection->ssl_context == NULL)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

#ifndef MOWGLI_HAVE_OPENSSL_TLS_METHOD_API
#  ifdef SSL_OP_NO_SSLv2
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_NO_SSLv2);
#  endif
#  ifdef SSL_OP_NO_SSLv3
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_NO_SSLv3);
#  endif
#endif

	connection->ssl_handle = SSL_new(connection->ssl_context);

	if (connection->ssl_handle == NULL)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	SSL_set_accept_state(connection->ssl_handle);
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_DH_USE);

#ifdef OPENSSL_EC_AVAILABLE
#  ifdef MOWGLI_HAVE_OPENSSL_ECDH_AUTO
	SSL_CTX_set_ecdh_auto(connection->ssl_context, 1);
#  else

	EC_KEY *ec_key_p256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

	if (ec_key_p256 != NULL)
	{
		SSL_CTX_set_tmp_ecdh(connection->ssl_context, ec_key_p256);
		EC_KEY_free(ec_key_p256);
		ec_key_p256 = NULL;
	}

#  endif
#  ifdef SSL_OP_SINGLE_ECDH_USE
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_ECDH_USE);
#  endif
#endif

	if (connection->settings.password_func)
	{
		SSL_CTX_set_default_passwd_cb(connection->ssl_context, connection->settings.password_func);
		SSL_CTX_set_default_passwd_cb_userdata(connection->ssl_context, vio->userdata);
	}

	if (SSL_CTX_use_certificate_file(connection->ssl_context, connection->settings.cert_path, SSL_FILETYPE_PEM) != 1)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	if (SSL_CTX_use_PrivateKey_file(connection->ssl_context, connection->settings.privatekey_path, SSL_FILETYPE_PEM) != 1)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	if (listen(fd, backlog) != 0)
		return mowgli_vio_err_errcode(vio, strerror, errno);

	if (!SSL_set_fd(connection->ssl_handle, fd))
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISSERVER, true);
	vio->error.op = MOWGLI_VIO_ERR_OP_NONE;

	return 0;
}
示例#13
0
int main(int argc, char **argv)
{
    SSL_library_init();
    SSL_load_error_strings();

    BIO * bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

    /* Set up a SIGPIPE handler */
    signal(SIGPIPE, SIG_IGN);

    /* Create our context*/
    SSL_CTX * ctx = SSL_CTX_new(SSLv23_method());

    /* Load our keys and certificates*/
    if(!(SSL_CTX_use_certificate_chain_file(ctx, "ftests/fixtures/rdpproxy-cert.pem")))
    {
        BIO_printf(bio_err, "Can't read certificate file\n");
        ERR_print_errors(bio_err);
        exit(0);
    }

    SSL_CTX_set_default_passwd_cb(ctx, password_cb0);
    SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast<char *>("inquisition"));
    if(!(SSL_CTX_use_PrivateKey_file(ctx, "ftests/fixtures/rdpproxy-key.pem", SSL_FILETYPE_PEM)))
    {
        BIO_printf(bio_err,"Can't read key file\n");
        ERR_print_errors(bio_err);
        exit(0);
    }

    DH *ret=nullptr;
    BIO *bio;

    if ((bio=BIO_new_file("ftests/fixtures/dh1024.pem","r")) == nullptr){
        BIO_printf(bio_err,"Couldn't open DH file\n");
        ERR_print_errors(bio_err);
        exit(0);
    }

    ret=PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr);
    BIO_free(bio);
    if(SSL_CTX_set_tmp_dh(ctx, ret)<0)
    {
        BIO_printf(bio_err,"Couldn't set DH parameters\n");
        ERR_print_errors(bio_err);
        exit(0);
    }


    union
    {
      struct sockaddr s;
      struct sockaddr_storage ss;
      struct sockaddr_in s4;
      struct sockaddr_in6 s6;
    } ucs;
    memset(&ucs, 0, sizeof(ucs));

    int val=1;

    int sock = socket(AF_INET, SOCK_STREAM,0);
    if(sock < 0) {
        fprintf(stderr, "Failed to make socket\n");
        exit(0);
    }

    memset(&ucs.s4, 0, sizeof(ucs));
    ucs.s4.sin_addr.s_addr = INADDR_ANY;
    ucs.s4.sin_family = AF_INET;
    ucs.s4.sin_port = htons(4433);
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, &val,sizeof(val));

    int bind_res = bind(sock,&ucs.s,  sizeof(ucs));
    if(bind_res < 0){
        fprintf(stderr, "Failed to bind\n");
        exit(0);
    }
    listen(sock,5);

    while(1){
      int s = accept(sock,nullptr,nullptr);
      if(s < 0){
        fprintf(stderr,"Problem accepting\n");
        exit(0);
      }

     pid_t pid = fork();

     if(pid){
       close(s);
     }
     else {
        rdp_serve(ctx, s, bio_err);
        exit(0);
      }
    }
    SSL_CTX_free(ctx);
    exit(0);
  }
示例#14
0
文件: tls.cpp 项目: 151706061/DVTK-1
bool TLS_SOCKET_CLASS::openSslInitialize()

//  DESCRIPTION     : Called to initialize the OpenSSL library for this session.
//  PRECONDITIONS   :
//  POSTCONDITIONS  :
//  EXCEPTIONS      : 
//  NOTES           : 
//<<===========================================================================
{
	int verify_mode;
	long ssl_options;

	openSslM_ptr = OPENSSL_CLASS::getInstance();
	if (openSslM_ptr == NULL)
	{
		if (loggerM_ptr)
		{
			loggerM_ptr->text(LOG_ERROR, 1, "OpenSSL library not initialized when initializing Secure Socket");
		}
		return false;
	}

	// setup the connection factory for this session
	if (tlsVersionM == TLS_VERSION_TLSv1)
	{
		ctxM_ptr = SSL_CTX_new(TLSv1_method());
	}
	else if (tlsVersionM == TLS_VERSION_SSLv3)
	{
		ctxM_ptr = SSL_CTX_new(SSLv3_method());
	}
	else
	{
		ctxM_ptr = SSL_CTX_new(SSLv23_method());
	}

	if (ctxM_ptr == NULL)
	{
		openSslError("initializing connection factory");
		return false;
	}

	SSL_CTX_set_default_passwd_cb(ctxM_ptr, OPENSSL_CLASS::openSslPasswordCallback);
	char *password = new char[certificateFilePasswordM.length() + 1]; // create a buffer to store the password
																	  // this is freed in the destructor
	strcpy(password, certificateFilePasswordM.c_str());
	SSL_CTX_set_default_passwd_cb_userdata(ctxM_ptr, (void *)password);

	if (SSL_CTX_load_verify_locations(ctxM_ptr, certificateFilenameM.c_str(), NULL) != 1)
	{
		openSslError("loading trusted certificate file");
	}

	SSL_CTX_set_client_CA_list(ctxM_ptr, SSL_load_client_CA_file(certificateFilenameM.c_str()));
	ERR_clear_error(); // the last call leaves an error in the stack

	if (!readCredentials(ctxM_ptr))
	{
		openSslError("loading credentials");
	}

	if (checkRemoteCertificateM)
	{
		verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
	}
	else
	{
		verify_mode = SSL_VERIFY_NONE;
	}
	SSL_CTX_set_verify(ctxM_ptr, verify_mode, openSslVerifyCallback);

	if ((loggerM_ptr != NULL) && ((loggerM_ptr->getLogMask() & LOG_DEBUG) != 0))
	{
		SSL_CTX_set_msg_callback(ctxM_ptr, openSslMsgCallback);
		// the 'this' pointer needed by openSslMsgCallback and openSslVerfyCallback must be set by 
		// SSL_set_msg_callback_arg for each SSL created
	}

	ssl_options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE;
	if (tlsVersionM.find(TLS_VERSION_SSLv2) == string::npos)
	{
		ssl_options |= SSL_OP_NO_SSLv2;
	}
	if (tlsVersionM.find(TLS_VERSION_SSLv3) == string::npos)
	{
		ssl_options |= SSL_OP_NO_SSLv3;
	}
	if (tlsVersionM.find(TLS_VERSION_TLSv1) == string::npos)
	{
		ssl_options |= SSL_OP_NO_TLSv1;
	}
	SSL_CTX_set_options(ctxM_ptr, ssl_options);

	SSL_CTX_set_timeout(ctxM_ptr, tlsCacheTimeoutM);
	SSL_CTX_set_session_id_context(ctxM_ptr, (const unsigned char *)"DVT", 3);
	if (cacheTlsSessionsM)
	{
		SSL_CTX_set_session_cache_mode(ctxM_ptr, SSL_SESS_CACHE_BOTH);
	}
	else
	{
		SSL_CTX_set_session_cache_mode(ctxM_ptr, SSL_SESS_CACHE_OFF);
	}

	SSL_CTX_set_tmp_dh_callback(ctxM_ptr, OPENSSL_CLASS::tmpDhCallback);

	if (SSL_CTX_set_cipher_list(ctxM_ptr, cipherListM.c_str()) != 1)
	{
		openSslError("initializing cipher list (no valid ciphers)");
	}
	
	return true;
}
示例#15
0
/* Create a socket and connect it to 'ip' on port 'port'.
 * Returns -1 on failure (ip is NULL, socket creation/connection error)
 * Returns sock number on success.
 */
int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port)
{
	int sock = INVALID_SOCKET;
#ifndef WIN32
	int opt;
#endif
	struct addrinfo hints;
	struct addrinfo *ainfo, *rp;
	int s;
#ifdef WIN32
	uint32_t val = 1;
#endif
#ifdef WITH_TLS
	int ret;
	BIO *bio;
#endif

	if(!mosq || !host || !port) return MOSQ_ERR_INVAL;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_ADDRCONFIG;
	hints.ai_socktype = SOCK_STREAM;

	s = getaddrinfo(host, NULL, &hints, &ainfo);
	if(s) return MOSQ_ERR_UNKNOWN;

	for(rp = ainfo; rp != NULL; rp = rp->ai_next){
		sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if(sock == INVALID_SOCKET) continue;
		
		if(rp->ai_family == PF_INET){
			((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port);
		}else if(rp->ai_family == PF_INET6){
			((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port);
		}else{
			continue;
		}
		if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1){
			break;
		}

#ifdef WIN32
		errno = WSAGetLastError();
#endif
		COMPAT_CLOSE(sock);
	}
	if(!rp){
		return MOSQ_ERR_ERRNO;
	}
	freeaddrinfo(ainfo);

	/* Set non-blocking */
#ifndef WIN32
	opt = fcntl(sock, F_GETFL, 0);
	if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){
#ifdef WITH_TLS
		if(mosq->ssl){
			SSL_shutdown(mosq->ssl);
			SSL_free(mosq->ssl);
			mosq->ssl = NULL;
		}
		if(mosq->ssl_ctx){
			SSL_CTX_free(mosq->ssl_ctx);
			mosq->ssl_ctx = NULL;
		}
#endif
		COMPAT_CLOSE(sock);
		return MOSQ_ERR_ERRNO;
	}
#else
	if(ioctlsocket(sock, FIONBIO, &val)){
		errno = WSAGetLastError();
#ifdef WITH_TLS
		if(mosq->ssl){
			SSL_shutdown(mosq->ssl);
			SSL_free(mosq->ssl);
			mosq->ssl = NULL;
		}
		if(mosq->ssl_ctx){
			SSL_CTX_free(mosq->ssl_ctx);
			mosq->ssl_ctx = NULL;
		}
#endif
		COMPAT_CLOSE(sock);
		return MOSQ_ERR_ERRNO;
	}
#endif

#ifdef WITH_TLS
	if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
		if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
			if(!mosq->ssl_ctx){
				_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}else{
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_INVAL;
		}

		if(mosq->tls_ciphers){
			ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers);
			if(ret == 0){
				_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers);
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}
		if(mosq->tls_cafile || mosq->tls_capath){
			ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
			if(ret == 0){
#ifdef WITH_BROKER
				if(mosq->tls_cafile && mosq->tls_capath){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
				}else if(mosq->tls_cafile){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
				}else{
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
				}
#else
				if(mosq->tls_cafile && mosq->tls_capath){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
				}else if(mosq->tls_cafile){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
				}else{
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
				}
#endif
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
			if(mosq->tls_cert_reqs == 0){
				SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL);
			}else{
				SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, NULL);
			}

			if(mosq->tls_pw_callback){
				SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback);
				SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq);
			}

			if(mosq->tls_certfile){
				ret = SSL_CTX_use_certificate_file(mosq->ssl_ctx, mosq->tls_certfile, SSL_FILETYPE_PEM);
				if(ret != 1){
#ifdef WITH_BROKER
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile);
#else
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile);
#endif
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
			}
			if(mosq->tls_keyfile){
				ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM);
				if(ret != 1){
#ifdef WITH_BROKER
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile);
#else
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile);
#endif
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
				ret = SSL_CTX_check_private_key(mosq->ssl_ctx);
				if(ret != 1){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent.");
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
			}
#ifdef WITH_TLS_PSK
		}else if(mosq->tls_psk){
			SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback);
#endif
		}

		mosq->ssl = SSL_new(mosq->ssl_ctx);
		if(!mosq->ssl){
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}
		SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq);
		bio = BIO_new_socket(sock, BIO_NOCLOSE);
		if(!bio){
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}
		SSL_set_bio(mosq->ssl, bio, bio);

		ret = SSL_connect(mosq->ssl);
		if(ret != 1){
			ret = SSL_get_error(mosq->ssl, ret);
			if(ret == SSL_ERROR_WANT_READ){
				mosq->want_read = true;
			}else if(ret == SSL_ERROR_WANT_WRITE){
				mosq->want_write = true;
			}else{
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}
	}
#endif

	mosq->sock = sock;

	return MOSQ_ERR_SUCCESS;
}
示例#16
0
int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
{
	int rc = 1;
	char* ciphers = NULL;

	FUNC_ENTRY;
	if (net->ctx == NULL)
		if ((net->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)	/* SSLv23 for compatibility with SSLv2, SSLv3 and TLSv1 */
		{
			SSLSocket_error("SSL_CTX_new", NULL, net->socket, rc);
			goto exit;
		}

	if (opts->keyStore)
	{
		if ((rc = SSL_CTX_use_certificate_chain_file(net->ctx, opts->keyStore)) != 1)
		{
			SSLSocket_error("SSL_CTX_use_certificate_chain_file", NULL, net->socket, rc);
			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 */
		}

		if (opts->privateKey == NULL)
			opts->privateKey = opts->keyStore;   /* the privateKey can be included in the 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);
        }

		/* support for ASN.1 == DER format? DER can contain only one certificate? */
		if ((rc = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM)) != 1)
		{
			SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc);
			goto free_ctx;
		}
	}

	if (opts->trustStore)
	{
		if ((rc = SSL_CTX_load_verify_locations(net->ctx, opts->trustStore, NULL)) != 1)
		{
			SSLSocket_error("SSL_CTX_load_verify_locations", NULL, net->socket, rc);
			goto free_ctx;
		}
	}
	else if ((rc = SSL_CTX_set_default_verify_paths(net->ctx)) != 1)
	{
		SSLSocket_error("SSL_CTX_set_default_verify_paths", NULL, net->socket, rc);
		goto free_ctx;
	}

	if (opts->enabledCipherSuites == NULL)
        ciphers = "DEFAULT";
    else
        ciphers = opts->enabledCipherSuites;

	if ((rc = SSL_CTX_set_cipher_list(net->ctx, ciphers)) != 1)
	{
		SSLSocket_error("SSL_CTX_set_cipher_list", NULL, net->socket, rc);
		goto free_ctx;
	}

	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;
}
示例#17
0
static void setup_ssl(tcptest_t *item)
{
	static int ssl_init_complete = 0;
	struct servent *sp;
	char portinfo[100];
	X509 *peercert;
	char *certcn, *certstart, *certend;
	int err;
	strbuffer_t *sslinfo;
	char msglin[2048];

	item->sslrunning = 1;

	if (!ssl_init_complete) {
		/* Setup entropy */
		if (RAND_status() != 1) {
			char path[PATH_MAX];	/* Path for the random file */

			/* load entropy from files */
			RAND_load_file(RAND_file_name(path, sizeof (path)), -1);

			/* load entropy from egd sockets */
			RAND_egd("/var/run/egd-pool");
			RAND_egd("/dev/egd-pool");
			RAND_egd("/etc/egd-pool");
			RAND_egd("/var/spool/prngd/pool");

			/* shuffle $RANDFILE (or ~/.rnd if unset) */
			RAND_write_file(RAND_file_name(path, sizeof (path)));
			if (RAND_status() != 1) {
				errprintf("Failed to find enough entropy on your system");
				item->errcode = CONTEST_ESSL;
				return;
			}
		}

		SSL_load_error_strings();
		SSL_library_init();
		ssl_init_complete = 1;
	}

	if (item->sslctx == NULL) {
		switch (item->ssloptions->sslversion) {
		  case SSLVERSION_V2:
			item->sslctx = SSL_CTX_new(SSLv2_client_method()); break;
		  case SSLVERSION_V3:
			item->sslctx = SSL_CTX_new(SSLv3_client_method()); break;
		  case SSLVERSION_TLS1:
			item->sslctx = SSL_CTX_new(TLSv1_client_method()); break;
		  default:
			item->sslctx = SSL_CTX_new(SSLv23_client_method()); break;
		}

		if (!item->sslctx) {
			char sslerrmsg[256];

			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Cannot create SSL context - IP %s, service %s: %s\n", 
				   inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg);
			item->sslrunning = 0;
			item->errcode = CONTEST_ESSL;
			return;
		}

		/* Workaround SSL bugs */
		SSL_CTX_set_options(item->sslctx, SSL_OP_ALL);
		SSL_CTX_set_quiet_shutdown(item->sslctx, 1);

		/* Limit set of ciphers, if user wants to */
		if (item->ssloptions->cipherlist) 
			SSL_CTX_set_cipher_list(item->sslctx, item->ssloptions->cipherlist);

		if (item->ssloptions->clientcert) {
			int status;
			char certfn[PATH_MAX];

			SSL_CTX_set_default_passwd_cb(item->sslctx, cert_password_cb);
			SSL_CTX_set_default_passwd_cb_userdata(item->sslctx, item);

			sprintf(certfn, "%s/certs/%s", xgetenv("XYMONHOME"), item->ssloptions->clientcert);
			status = SSL_CTX_use_certificate_chain_file(item->sslctx, certfn);
			if (status == 1) {
				status = SSL_CTX_use_PrivateKey_file(item->sslctx, certfn, SSL_FILETYPE_PEM);
			}

			if (status != 1) {
				char sslerrmsg[256];

				ERR_error_string(ERR_get_error(), sslerrmsg);
				errprintf("Cannot load SSL client certificate/key %s: %s\n", 
					  item->ssloptions->clientcert, sslerrmsg);
				item->sslrunning = 0;
				item->errcode = CONTEST_ESSL;
				return;
			}
		}
	}

	if (item->ssldata == NULL) {
		item->ssldata = SSL_new(item->sslctx);
		if (!item->ssldata) {
			char sslerrmsg[256];

			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("SSL_new failed - IP %s, service %s: %s\n", 
				   inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg);
			item->sslrunning = 0;
			SSL_CTX_free(item->sslctx);
			item->errcode = CONTEST_ESSL;
			return;
		}

		/* Verify that the client certificate is working */
		if (item->ssloptions->clientcert) {
			X509 *x509;

			x509 = SSL_get_certificate(item->ssldata);
			if(x509 != NULL) {
				EVP_PKEY *pktmp = X509_get_pubkey(x509);
				EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(item->ssldata));
				EVP_PKEY_free(pktmp);
			}

			if (!SSL_CTX_check_private_key(item->sslctx)) {
				errprintf("Private/public key mismatch for certificate %s\n", item->ssloptions->clientcert);
				item->sslrunning = 0;
				item->errcode = CONTEST_ESSL;
				return;
			}
		}

		/* SSL setup is done. Now attach the socket FD to the SSL protocol handler */
		if (SSL_set_fd(item->ssldata, item->fd) != 1) {
			char sslerrmsg[256];

			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Could not initiate SSL on connection - IP %s, service %s: %s\n", 
				   inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg);
			item->sslrunning = 0;
			SSL_free(item->ssldata); 
			SSL_CTX_free(item->sslctx);
			item->errcode = CONTEST_ESSL;
			return;
		}
	}

	sp = getservbyport(item->addr.sin_port, "tcp");
	if (sp) {
		sprintf(portinfo, "%s (%d/tcp)", sp->s_name, item->addr.sin_port);
	}
	else {
		sprintf(portinfo, "%d/tcp", item->addr.sin_port);
	}
	if ((err = SSL_connect(item->ssldata)) != 1) {
		char sslerrmsg[256];

		switch (SSL_get_error (item->ssldata, err)) {
		  case SSL_ERROR_WANT_READ:
		  case SSL_ERROR_WANT_WRITE:
			item->sslrunning = SSLSETUP_PENDING;
			break;
		  case SSL_ERROR_SYSCALL:
			ERR_error_string(ERR_get_error(), sslerrmsg);
			/* Filter out the bogus SSL error */
			if (strstr(sslerrmsg, "error:00000000:") == NULL) {
				errprintf("IO error in SSL_connect to %s on host %s: %s\n",
					  portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg);
			}
			item->errcode = CONTEST_ESSL;
			item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
			break;
		  case SSL_ERROR_SSL:
			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Unspecified SSL error in SSL_connect to %s on host %s: %s\n",
				  portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg);
			item->errcode = CONTEST_ESSL;
			item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
			break;
		  default:
			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Unknown error %d in SSL_connect to %s on host %s: %s\n",
				  err, portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg);
			item->errcode = CONTEST_ESSL;
			item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
			break;
		}

		return;
	}

	/* If we get this far, the SSL handshake has completed. So grab the certificate */
	peercert = SSL_get_peer_certificate(item->ssldata);
	if (!peercert) {
		errprintf("Cannot get peer certificate for %s on host %s\n",
			  portinfo, inet_ntoa(item->addr.sin_addr));
		item->errcode = CONTEST_ESSL;
		item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
		return;
	}

	sslinfo = newstrbuffer(0);

	certcn = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
	certstart = strdup(xymon_ASN1_UTCTIME(X509_get_notBefore(peercert)));
	certend = strdup(xymon_ASN1_UTCTIME(X509_get_notAfter(peercert)));

	snprintf(msglin, sizeof(msglin),
		"Server certificate:\n\tsubject:%s\n\tstart date: %s\n\texpire date:%s\n", 
		certcn, certstart, certend);
	addtobuffer(sslinfo, msglin);
	item->certsubject = strdup(certcn);
	item->certexpires = sslcert_expiretime(certend);
	xfree(certcn); xfree(certstart); xfree(certend);
	X509_free(peercert);

	/* We list the available ciphers in the SSL cert data */
	{
		int i;
		STACK_OF(SSL_CIPHER) *sk;

		addtobuffer(sslinfo, "\nAvailable ciphers:\n");
		sk = SSL_get_ciphers(item->ssldata);
		for (i=0; i<sk_SSL_CIPHER_num(sk); i++) {
			int b1, b2;
			char *cph;

			b1 = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(sk,i), &b2);
			cph = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk,i));
			snprintf(msglin, sizeof(msglin), "Cipher %d: %s (%d bits)\n", i, cph, b1);
			addtobuffer(sslinfo, msglin);

			if ((item->mincipherbits == 0) || (b1 < item->mincipherbits)) item->mincipherbits = b1;
		}
	}

	item->certinfo = grabstrbuffer(sslinfo);
}
示例#18
0
apn_return apn_ssl_connect(apn_ctx_t *const ctx) {
    assert(ctx);

    SSL_CTX *ssl_ctx = NULL;
    if (NULL == (ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) {
        apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL context: %s",
                  ERR_error_string(ERR_get_error(), NULL));
        return APN_ERROR;
    }

    SSL_CTX_set_ex_data(ssl_ctx, 0, ctx);
    SSL_CTX_set_info_callback(ssl_ctx, __apn_ssl_info_callback);

    X509 *cert = NULL;

    if (ctx->pkcs12_file && ctx->pkcs12_pass) {
        FILE *pkcs12_file = NULL;
#ifdef _WIN32
        fopen_s(&pkcs12_file, ctx->pkcs12_file, "r");
#else
        pkcs12_file = fopen(ctx->pkcs12_file, "r");
#endif
        if (!pkcs12_file) {
            char *error = apn_error_string(errno);
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to open file %s: %s (errno: %d)", ctx->pkcs12_file, error,
                      errno);
            free(error);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12;
            return APN_ERROR;
        }

        PKCS12 *pkcs12_cert = NULL;
        d2i_PKCS12_fp(pkcs12_file, &pkcs12_cert);
        fclose(pkcs12_file);

        EVP_PKEY *private_key = NULL;

        if (!PKCS12_parse(pkcs12_cert, ctx->pkcs12_pass, &private_key, &cert, NULL)) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            PKCS12_free(pkcs12_cert);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12;
            return APN_ERROR;
        }
        PKCS12_free(pkcs12_cert);

        if (!SSL_CTX_use_certificate(ssl_ctx, cert)) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            X509_free(cert);
            EVP_PKEY_free(private_key);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12;
            return APN_ERROR;
        }

        if (!SSL_CTX_use_PrivateKey(ssl_ctx, private_key)) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            X509_free(cert);
            EVP_PKEY_free(private_key);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12;
            return APN_ERROR;
        }
        EVP_PKEY_free(private_key);
    } else {
        FILE *cert_file = NULL;
#ifdef _WIN32
        fopen_s(&cert_file, ctx->certificate_file, "r");
#else
        cert_file = fopen(ctx->certificate_file, "r");
#endif
        if (!cert_file) {
            char *error = apn_error_string(errno);
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to open file %s: %s (errno: %d)", ctx->pkcs12_file, error,
                      errno);
            free(error);
            X509_free(cert);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE;
            return APN_ERROR;
        }

        cert = PEM_read_X509(cert_file, NULL, NULL, NULL);
        if (!cert) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified certificate: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            SSL_CTX_free(ssl_ctx);
            fclose(cert_file);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE;
            return EXIT_FAILURE;
        }
        fclose(cert_file);

        if (!SSL_CTX_use_certificate(ssl_ctx, cert)) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified certificate: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            X509_free(cert);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE;
            return APN_ERROR;
        }

        SSL_CTX_set_default_passwd_cb(ssl_ctx, __apn_ssl_password_callback);
        char *password = NULL;
        if (ctx->private_key_pass) {
            password = apn_strndup(ctx->private_key_pass, strlen(ctx->private_key_pass));
            if (!password) {
                X509_free(cert);
                SSL_CTX_free(ssl_ctx);
                return APN_ERROR;
            }
            SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, password);
        } else {
            SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, NULL);
        }

        if (!SSL_CTX_use_PrivateKey_file(ssl_ctx, ctx->private_key_file, SSL_FILETYPE_PEM)) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified private key: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            apn_strfree(&password);
            X509_free(cert);
            SSL_CTX_free(ssl_ctx);
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PRIVATE_KEY;
            return APN_ERROR;
        }

        apn_strfree(&password);

        if (!SSL_CTX_check_private_key(ssl_ctx)) {
            apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified private key: %s",
                      ERR_error_string(ERR_get_error(), NULL));
            errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PRIVATE_KEY;
            X509_free(cert);
            SSL_CTX_free(ssl_ctx);
            return APN_ERROR;
        }
    }

    if(cert) {
        char *subject = __apn_cert_subject_string(cert);
        apn_log(ctx, APN_LOG_LEVEL_INFO, "Local certificate subject: %s", subject);

        char *issuer = __apn_cert_issuer_string(cert);
        apn_log(ctx, APN_LOG_LEVEL_INFO, "Local certificate issuer: %s", issuer);

        free(subject);
        free(issuer);

        char *cn = __apn_cert_subject_value_by_nib(cert, __APN_X509_ENTRY_CN);
        X509_free(cert);
        if(cn) {
            uint8_t invalid_cert = 0;
            if(apn_mode(ctx) == APN_MODE_PRODUCTION && 0 != strncmp("Apple Production", cn, 16)) {
                invalid_cert = 1;
                apn_log(ctx, APN_LOG_LEVEL_ERROR, "Invalid certificate. You are using a PRODUCTION mode, but certificate was created for usage in SANDBOX");
            } else if (apn_mode(ctx) == APN_MODE_SANDBOX && 0 != strncmp("Apple Development", cn, 17)) {
                invalid_cert = 1;
                apn_log(ctx, APN_LOG_LEVEL_ERROR, "Invalid certificate. You are using a SANDBOX mode, but certificate was created for usage in PRODUCTION");
            }
            free(cn);
            if(1 == invalid_cert) {
                SSL_CTX_free(ssl_ctx);
                errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE;
                return APN_ERROR;
            }
        }
    }

    ctx->ssl = SSL_new(ssl_ctx);
    SSL_CTX_free(ssl_ctx);

    if (!ctx->ssl) {
        apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL");
        errno = APN_ERR_UNABLE_TO_ESTABLISH_SSL_CONNECTION;
        return APN_ERROR;
    }

    int ret = 0;

    if (-1 == (ret = SSL_set_fd(ctx->ssl, ctx->sock))) {
        apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to attach socket to SSL: SSL_set_fd() failed (%d)",
                  SSL_get_error(ctx->ssl, ret));
        errno = APN_ERR_UNABLE_TO_ESTABLISH_SSL_CONNECTION;
        return APN_ERROR;
    }

    if (1 > (ret = SSL_connect(ctx->ssl))) {
        char *error = apn_error_string(errno);
        apn_log(ctx, APN_LOG_LEVEL_ERROR,
                  "Could not initialize SSL connection: SSL_connect() failed: %s, %s (errno: %d):",
                  ERR_error_string((unsigned long) SSL_get_error(ctx->ssl, ret), NULL), error, errno);
        free(error);
        return APN_ERROR;
    }
    apn_log(ctx, APN_LOG_LEVEL_INFO, "SSL connection has been established");

    X509 *remote_cert = SSL_get_peer_certificate(ctx->ssl);
    if (remote_cert) {
        char *subject = __apn_cert_subject_string(remote_cert);
        apn_log(ctx, APN_LOG_LEVEL_INFO, "Remote certificate subject: %s", subject);

        char *issuer = __apn_cert_issuer_string(remote_cert);
        apn_log(ctx, APN_LOG_LEVEL_INFO, "Remote certificate issuer: %s", issuer);

        free(subject);
        free(issuer);
        X509_free(remote_cert);
    }
    return APN_SUCCESS;
}
示例#19
0
BOOL create_ssl(int sockfd, 
    const char* ca_crt_root,
    const char* ca_crt_server,
    const char* ca_password,
    const char* ca_key_server,
    BOOL enableclientcacheck,
    SSL** pp_ssl, SSL_CTX** pp_ssl_ctx)
{
    int ssl_rc = -1;
    BOOL b_ssl_accepted;
    X509* client_cert;
	SSL_METHOD* meth = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x010100000L
    meth = (SSL_METHOD*)TLS_server_method();
#else
    meth = (SSL_METHOD*)SSLv23_server_method();
#endif /* OPENSSL_VERSION_NUMBER */
	*pp_ssl_ctx = SSL_CTX_new(meth);
	if(!*pp_ssl_ctx)
	{
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
		goto clean_ssl3;
	}

	if(enableclientcacheck)
	{
    	SSL_CTX_set_verify(*pp_ssl_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
    	SSL_CTX_set_verify_depth(*pp_ssl_ctx, 4);
	}
	
	SSL_CTX_load_verify_locations(*pp_ssl_ctx, ca_crt_root, NULL);
	if(SSL_CTX_use_certificate_file(*pp_ssl_ctx, ca_crt_server, SSL_FILETYPE_PEM) <= 0)
	{
		CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
		goto clean_ssl3;
	}

	SSL_CTX_set_default_passwd_cb_userdata(*pp_ssl_ctx, (char*)ca_password);
	if(SSL_CTX_use_PrivateKey_file(*pp_ssl_ctx, ca_key_server, SSL_FILETYPE_PEM) <= 0)
	{
		CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
		goto clean_ssl3;

	}
	if(!SSL_CTX_check_private_key(*pp_ssl_ctx))
	{
		CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(),NULL));
		goto clean_ssl3;
	}
	
	ssl_rc = SSL_CTX_set_cipher_list(*pp_ssl_ctx, "ALL");
    if(ssl_rc == 0)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_CTX_set_cipher_list: %s", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl3;
    }
	SSL_CTX_set_mode(*pp_ssl_ctx, SSL_MODE_AUTO_RETRY);

	*pp_ssl = SSL_new(*pp_ssl_ctx);
	if(!*pp_ssl)
	{
		CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_new: %s", ERR_error_string(ERR_get_error(),NULL));
		goto clean_ssl2;
	}
	ssl_rc = SSL_set_fd(*pp_ssl, sockfd);
    if(ssl_rc == 0)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_set_fd: %s", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl2;
    }
    ssl_rc = SSL_set_cipher_list(*pp_ssl, "ALL");
    if(ssl_rc == 0)
    {
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_set_cipher_list: %s", ERR_error_string(ERR_get_error(),NULL));
        goto clean_ssl2;
    }
    ssl_rc = SSL_accept(*pp_ssl);
	if(ssl_rc < 0)
	{
        CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
		uTrace.Write(Trace_Error, "SSL_accept: %s", ERR_error_string(ERR_get_error(),NULL));
		goto clean_ssl2;
	}
    else if(ssl_rc = 0)
	{
		goto clean_ssl1;
	}

    b_ssl_accepted = TRUE;
    
    if(enableclientcacheck)
    {
        ssl_rc = SSL_get_verify_result(*pp_ssl);
        if(ssl_rc != X509_V_OK)
        {
            CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
            uTrace.Write(Trace_Error, "SSL_get_verify_result: %s", ERR_error_string(ERR_get_error(),NULL));
            goto clean_ssl1;
        }
    }
        
	if(enableclientcacheck)
	{
		X509* client_cert;
		client_cert = SSL_get_peer_certificate(*pp_ssl);
		if (client_cert != NULL)
		{
			X509_free (client_cert);
		}
		else
		{
			CUplusTrace uTrace(SSLERR_LOGNAME, SSLERR_LCKNAME);
            uTrace.Write(Trace_Error, "SSL_get_peer_certificate: %s", ERR_error_string(ERR_get_error(),NULL));
			goto clean_ssl1;
		}
	}

    return TRUE;

clean_ssl1:
    if(*pp_ssl && b_ssl_accepted)
    {
		SSL_shutdown(*pp_ssl);
        b_ssl_accepted = FALSE;
    }
clean_ssl2:
    if(*pp_ssl)
    {
		SSL_free(*pp_ssl);
        *pp_ssl = NULL;
    }
clean_ssl3:
    if(*pp_ssl_ctx)
    {
		SSL_CTX_free(*pp_ssl_ctx);
        *pp_ssl_ctx = NULL;
    }
    return FALSE;
}
示例#20
0
retcode_t tb_initSSL(Socket_t    S, 
										 enum ssl_mode  mode,       // SSL_CLIENT | SSL_SERVER
										 ssl_meth_t  method,     // SSL1 | SSL2 | SSL3 | TLS1
										 char      * CA_path,
										 char      * CA_file,
										 char      * cert,
										 char      * pwd,
										 char      * cipher) {
	SSL_METHOD * meth;
	sock_ssl_t m;

	tb_info("tb_initSSL in\n");

	if(!TB_VALID(S, TB_SOCKET)) {
		set_tb_errno(TB_ERR_INVALID_TB_OBJECT);
		return TB_ERR;
	}
	if(XSock(S)->ssl != NULL ) {
		tb_warn("tb_initSSL: Socket_t allready SSL initialized\n");
		set_tb_errno(TB_ERR_ALLREADY);
		return TB_ERR;
	}

	m = tb_xcalloc(1, sizeof(struct sock_ssl));
	XSock(S)->ssl = m;
	m->ssl_method = method;

	m->mode = method;


	if( CA_path ) m->CA_path = tb_xstrdup(CA_path);
	if( CA_file ) m->CA_file = tb_xstrdup(CA_file);
	if( cert ) 		m->cert    = tb_xstrdup(cert);
	if( pwd ) 		m->pwd     = tb_xstrdup(pwd);		
	if( cipher ) 	m->cipher  = tb_xstrdup(cipher);
	

	__tb_init_SSL_once();

	switch (m->ssl_method) {
  case 1:
		meth = (mode == SSL_CLIENT) ? SSLv23_client_method() : SSLv23_server_method();
    break;
  case 2:
		meth = (mode == SSL_CLIENT) ? SSLv2_client_method() : SSLv2_server_method();
    break;
  case 3:
		meth = (mode == SSL_CLIENT) ? SSLv3_client_method() : SSLv3_server_method();
    break;
  case 4:
		meth = (mode == SSL_CLIENT) ? TLSv1_client_method() : TLSv1_server_method();
    break;
	default:
		meth = NULL;
		goto err;
  }


	if (!(m->ctx = SSL_CTX_new(meth))) {
    tb_warn("tb_initSSL: Cannot create new SSL context\n");
    ERR_print_errors_fp(stderr);
		XSock(S)->status = TB_BROKEN;
		return TB_ERR; 
  }

	if(tb_errorlevel == TB_DEBUG) SSL_CTX_set_info_callback(m->ctx,info_cb);

  if(m->pwd) {
		SSL_CTX_set_default_passwd_cb(m->ctx, pass_cb);
		SSL_CTX_set_default_passwd_cb_userdata(m->ctx, S);
	}
	

	if(m->cert ) {
		if(SSL_CTX_use_certificate_file(m->ctx, m->cert, SSL_FILETYPE_PEM) <= 0) {
			ERR_print_errors_fp(stderr);
			goto err;
		}
		if (SSL_CTX_use_PrivateKey_file(m->ctx, m->cert, SSL_FILETYPE_PEM) <= 0) {
			tb_error("tb_initSSL: Unable to get private key from '%s'\n", 
							 m->cert);
			ERR_print_errors_fp(stderr);
			goto err;
		}
		tb_info("privkey loaded\n");		
		if (!SSL_CTX_check_private_key(m->ctx)) {
			tb_error("tb_initSSL: Private key does not match the certificate public key\n");
			goto err;
		}
		tb_info("tb_initSSL: privkey validated\n");
		tb_info("tb_initSSL: certificate loaded\n");
	}

	if(mode == SSL_CLIENT) {
		SSL_CTX_set_session_cache_mode(m->ctx, SSL_SESS_CACHE_CLIENT);
	} else {
		SSL_CTX_set_session_cache_mode(m->ctx, SSL_SESS_CACHE_SERVER);
		SSL_CTX_set_session_id_context(m->ctx,  "try this one", 12);
	}

  if(m->CA_file || m->CA_path) {
		tb_info("tb_initSSL: loading CAs ...\n");
    if(!SSL_CTX_load_verify_locations(m->ctx, m->CA_file, m->CA_path)) {
			XSock(S)->status = TB_BROKEN;
      tb_warn("tb_initSSL: Cannot load verify locations %s and %s\n",
              m->CA_file, m->CA_path);
      ERR_print_errors_fp(stderr);
			goto err;
    }
		tb_info("tb_initSSL: CA  <%s/%s> loaded\n", m->CA_path, m->CA_file);
		SSL_CTX_set_verify(m->ctx, SSL_VERIFY_PEER, verify_cb);
		SSL_CTX_set_default_verify_paths(m->ctx);
  }

 /* Create and configure SSL connection. */

  if (!(m->cx = (SSL *)SSL_new(m->ctx))) {
    tb_warn("tb_initSSL: Cannot create new SSL context\n");
    ERR_print_errors_fp(stderr);
		goto err;
  }
	tb_info("tb_initSSL: ssl ctx initialized\n");

  /* Use OpenSSL ciphers -v to see the cipher strings and their SSL
   * versions, key exchange, authentication, encryption, and message
   * digest algorithms, and key length restrictions.  See the OpenSSL
   * for the syntax to combine ciphers, e.g. !SSLv2:RC4-MD5:RC4-SHA.
   * If you don't specify anything, you get the same as "DEFAULT", which
   * means "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP".
   */
  if(m->cipher) {
    if(!SSL_CTX_set_cipher_list(m->ctx, m->cipher)) {
      tb_warn("tb_inittSSL: Cannot use cipher list %s\n", m->cipher);
			goto err;
    }
		tb_info("tb_initSSL: cipher set to <%s>\n", m->cipher);
	}


	tb_info("tb_initSSL out\n");
	return TB_OK;

 err:
	// fixme: context not totally freed (CA_path, pwd ...)
	SSL_CTX_free(m->ctx);
	m->ctx = NULL;
	XSock(S)->status = TB_BROKEN;
	return TB_ERR;
}
MMGConnectionError MMGSSLConnection::OpenConnection(void)
{
	// If already connected, bye bye
	if (this->IsConnected())
		return MMGConnectionError::MMGAlreadyConnected;

    // Create a SSL context
	this->_sslCtx = SSL_CTX_new(this->_sslMethod);
	if (NULL == this->_sslCtx)
	{
		MMG_ERRLOG("[!] Failed to create a SSL context\n");
		return MMGConnectionError::MMGSSLContextCreateFail;
	}

	// Load the client certificate into the SSL context
	if (SSL_CTX_use_certificate_file(this->_sslCtx, this->_certFile.c_str(), SSL_FILETYPE_PEM) <= 0)
	{
		MMG_ERRLOG("[!] Cannot use certificate file <%s>\n", this->_certFile.c_str());
		ERR_print_errors_fp(stderr);
		return MMGConnectionError::MMGSSLInvalidCertificateFile;
	}

    // Load the private-key corresponding to the client certificate
	if (!this->_keyPassword.empty())
		SSL_CTX_set_default_passwd_cb_userdata(this->_sslCtx, (void*)this->_keyPassword.c_str());
	if (SSL_CTX_use_PrivateKey_file(this->_sslCtx, this->_keyFile.c_str(), SSL_FILETYPE_PEM) <= 0)
	{
		MMG_ERRLOG("[!] Cannot use private key file <%s>\n", this->_keyFile.c_str());
		ERR_print_errors_fp(stderr);
		return MMGConnectionError::MMGSSLInvalidPrivateKeyFile;
	}

	// Load the CA
	if (SSL_CTX_load_verify_locations(this->_sslCtx, NULL, this->_certsPath.c_str()) <= 0)
	{
        MMG_ERRLOG("[!] Failed to set CA location...\n");
        ERR_print_errors_fp(stderr);
		return MMGConnectionError::MMGSSLInvalidCALocation;
	}

	// Check if the client certificate and private-key matches
	if (!SSL_CTX_check_private_key(this->_sslCtx))
	{
		MMG_ERRLOG("[!] Private key does not match the certificate public key\n");
		return MMGConnectionError::MMGSSLInvalidPrivateKeyPair;
	}

    // Set up a TCP socket
	this->_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (-1 == this->_socket)
	{
		MMG_ERRLOG("[!] Failed to create socket\n");
		return MMGConnectionError::MMGSocketError;
	}

	memset(&this->_addr, 0x00, sizeof(this->_addr));
	this->_addr.sin_family = AF_INET;
	this->_addr.sin_port = htons(this->_port);
	this->_hostent = gethostbyname(this->_hostname.c_str());
	if (this->_hostent)
	{
		// Take the first IP
		struct in_addr* address = (struct in_addr*)this->_hostent->h_addr_list[0];
		this->_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address));
	}
    else
	{
		MMG_ERRLOG("Could not resolve hostname %s\n", this->_hostname.c_str());
		return MMGConnectionError::MMGHostError;
	}

	// Establish a TCP/IP connection to the SSL client
	int err = connect(this->_socket, (struct sockaddr*)&this->_addr, sizeof(this->_addr));
	if (-1 == err)
	{
		MMG_ERRLOG("Could not connect\n");
		return MMGConnectionError::MMGConnectError;
	}

    // Create a SSL structure
	this->_ssl = SSL_new(this->_sslCtx);
	if (NULL == this->_ssl)
	{
		MMG_ERRLOG("Could not get SSL Socket\n");
		return MMGConnectionError::MMGSSLError;
	}

	// Assign the socket into the SSL structure (SSL and socket without BIO)
	SSL_set_fd(this->_ssl, this->_socket);

	// Perform SSL Handshake on the SSL client
	err = SSL_connect(this->_ssl);
	if (err <= 0)
	{
		MMG_ERRLOG("Could not connect to SSL Server\n");
		return MMGConnectionError::MMGSSLConnectError;
	}
	return MMGConnectionError::MMGNoError;
}
示例#22
0
文件: tls.c 项目: kaija/libre
/**
 * Allocate a new TLS context
 *
 * @param tlsp    Pointer to allocated TLS context
 * @param method  TLS method
 * @param keyfile Optional private key file
 * @param pwd     Optional password
 *
 * @return 0 if success, otherwise errorcode
 */
int tls_alloc(struct tls **tlsp, enum tls_method method, const char *keyfile,
	      const char *pwd)
{
	struct tls *tls;
	int r, err;

	if (!tlsp)
		return EINVAL;

	tls = mem_zalloc(sizeof(*tls), destructor);
	if (!tls)
		return ENOMEM;

	if (!tlsg.up) {
#ifdef SIGPIPE
		/* Set up a SIGPIPE handler */
		(void)signal(SIGPIPE, sigpipe_handle);
#endif

		SSL_library_init();
		tlsg.up = true;
	}

	if (tlsg.tlsc++ == 0) {
		DEBUG_INFO("error strings loaded\n");
		SSL_load_error_strings();
	}

	switch (method) {

	case TLS_METHOD_SSLV23:
		tls->ctx = SSL_CTX_new(SSLv23_method());
		break;

#ifdef USE_OPENSSL_DTLS
	case TLS_METHOD_DTLSV1:
		tls->ctx = SSL_CTX_new(DTLSv1_method());
		break;
#endif

	default:
		DEBUG_WARNING("tls method %d not supported\n", method);
		err = ENOSYS;
		goto out;
	}

	if (!tls->ctx) {
		err = ENOMEM;
		goto out;
	}

#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
	SSL_CTX_set_verify_depth(tls->ctx, 1);
#endif

	if (method == TLS_METHOD_DTLSV1) {
		SSL_CTX_set_read_ahead(tls->ctx, 1);
	}

	/* Load our keys and certificates */
	if (keyfile) {
		if (pwd) {
			err = str_dup(&tls->pass, pwd);
			if (err)
				goto out;

			SSL_CTX_set_default_passwd_cb(tls->ctx, password_cb);
			SSL_CTX_set_default_passwd_cb_userdata(tls->ctx, tls);
		}

		r = SSL_CTX_use_certificate_chain_file(tls->ctx, keyfile);
		if (r <= 0) {
			DEBUG_WARNING("Can't read certificate file: %s (%d)\n",
				      keyfile, r);
			err = EINVAL;
			goto out;
		}

		r = SSL_CTX_use_PrivateKey_file(tls->ctx, keyfile,
						SSL_FILETYPE_PEM);
		if (r <= 0) {
			DEBUG_WARNING("Can't read key file: %s (%d)\n",
				      keyfile, r);
			err = EINVAL;
			goto out;
		}
	}

	err = 0;
 out:
	if (err)
		mem_deref(tls);
	else
		*tlsp = tls;

	return err;
}
示例#23
0
static
int cert_stuff( struct connectdata *conn,
				SSL_CTX* ctx,
				char *cert_file,
				const char *cert_type,
				char *key_file,
				const char *key_type ) {
	struct SessionHandle *data = conn->data;
	int file_type;

	if ( cert_file != NULL ) {
		SSL *ssl;
		X509 *x509;

		if ( data->set.key_passwd ) {
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
			/*
			 * If password has been given, we store that in the global
			 * area (*shudder*) for a while:
			 */
			size_t len = strlen( data->set.key_passwd );
			if ( len < sizeof( global_passwd ) ) {
				memcpy( global_passwd, data->set.key_passwd, len + 1 );
			}
#else
			/*
			 * We set the password in the callback userdata
			 */
			SSL_CTX_set_default_passwd_cb_userdata( ctx,
													data->set.key_passwd );
#endif
			/* Set passwd callback: */
			SSL_CTX_set_default_passwd_cb( ctx, passwd_callback );
		}

		file_type = do_file_type( cert_type );

#define SSL_CLIENT_CERT_ERR	\
	"unable to use client certificate (no key found or wrong pass phrase?)"

		switch ( file_type ) {
		case SSL_FILETYPE_PEM:
			/* SSL_CTX_use_certificate_chain_file() only works on PEM files */
			if ( SSL_CTX_use_certificate_chain_file( ctx,
													 cert_file ) != 1 ) {
				failf( data, SSL_CLIENT_CERT_ERR );
				return 0;
			}
			break;

		case SSL_FILETYPE_ASN1:
			/* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
			   we use the case above for PEM so this can only be performed with
			   ASN1 files. */
			if ( SSL_CTX_use_certificate_file( ctx,
											   cert_file,
											   file_type ) != 1 ) {
				failf( data, SSL_CLIENT_CERT_ERR );
				return 0;
			}
			break;
		case SSL_FILETYPE_ENGINE:
			failf( data, "file type ENG for certificate not implemented" );
			return 0;

		default:
			failf( data, "not supported file type '%s' for certificate", cert_type );
			return 0;
		}

		file_type = do_file_type( key_type );

		switch ( file_type ) {
		case SSL_FILETYPE_PEM:
			if ( key_file == NULL ) {
				/* cert & key can only be in PEM case in the same file */
				key_file = cert_file;
			}
		case SSL_FILETYPE_ASN1:
			if ( SSL_CTX_use_PrivateKey_file( ctx, key_file, file_type ) != 1 ) {
				failf( data, "unable to set private key file: '%s' type %s\n",
					   key_file, key_type ? key_type : "PEM" );
				return 0;
			}
			break;
		case SSL_FILETYPE_ENGINE:
#ifdef HAVE_OPENSSL_ENGINE_H
			{                   /* XXXX still needs some work */
				EVP_PKEY *priv_key = NULL;
				if ( conn && conn->data && conn->data->engine ) {
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
					UI_METHOD *ui_method = UI_OpenSSL();
#endif
					if ( !key_file || !key_file[0] ) {
						failf( data, "no key set to load from crypto engine\n" );
						return 0;
					}
					/* the typecast below was added to please mingw32 */
					priv_key = (EVP_PKEY *)
							   ENGINE_load_private_key( conn->data->engine,key_file,
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
														ui_method,
#endif
														data->set.key_passwd );
					if ( !priv_key ) {
						failf( data, "failed to load private key from crypto engine\n" );
						return 0;
					}
					if ( SSL_CTX_use_PrivateKey( ctx, priv_key ) != 1 ) {
						failf( data, "unable to set private key\n" );
						EVP_PKEY_free( priv_key );
						return 0;
					}
					EVP_PKEY_free( priv_key ); /* we don't need the handle any more... */
				} else {
					failf( data, "crypto engine not set, can't load private key\n" );
					return 0;
				}
			}
			break;
#else
			failf( data, "file type ENG for private key not supported\n" );
			return 0;
#endif
		default:
			failf( data, "not supported file type for private key\n" );
			return 0;
		}

		ssl = SSL_new( ctx );
		x509 = SSL_get_certificate( ssl );

		/* This version was provided by Evan Jordan and is supposed to not
		   leak memory as the previous version: */
		if ( x509 != NULL ) {
			EVP_PKEY *pktmp = X509_get_pubkey( x509 );
			EVP_PKEY_copy_parameters( pktmp,SSL_get_privatekey( ssl ) );
			EVP_PKEY_free( pktmp );
		}

		SSL_free( ssl );

		/* If we are using DSA, we can copy the parameters from
		 * the private key */


		/* Now we know that a key and cert have been set against
		 * the SSL context */
		if ( !SSL_CTX_check_private_key( ctx ) ) {
			failf( data, "Private key does not match the certificate public key" );
			return( 0 );
		}
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
		/* erase it now */
		memset( global_passwd, 0, sizeof( global_passwd ) );
#endif
	}
	return( 1 );
}
示例#24
0
gboolean fbConnSpecInitTLS(
    fbConnSpec_t        *spec,
    gboolean            passive,
    GError              **err)
{
    const SSL_METHOD    *tlsmeth = NULL;
    SSL_CTX             *ssl_ctx = NULL;
    gboolean            ok = TRUE;

    /* Initialize the library and error strings */
    SSL_library_init();
    SSL_load_error_strings();

    /*
     * Select a TLS method based on passivity and transport.
     * Shortcircuit on no TLS initialization necessary for sockets.
     */
    switch (spec->transport) {
#if FB_ENABLE_SCTP
    case FB_SCTP:
#endif
    case FB_TCP:
    case FB_UDP:
        return TRUE;
#if HAVE_OPENSSL_DTLS_SCTP
    case FB_DTLS_SCTP:
        tlsmeth = passive ? DTLSv1_server_method() : DTLSv1_client_method();
        break;
#endif
    case FB_TLS_TCP:
        tlsmeth = passive ? TLSv1_server_method() : TLSv1_client_method();
        break;
#if HAVE_OPENSSL_DTLS
    case FB_DTLS_UDP:
        tlsmeth = passive ? DTLSv1_server_method() : DTLSv1_client_method();
        break;
#endif
    default:
        g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_IMPL,
                    "Unsupported TLS method.");
        return FALSE;
    }

    /* Verify we have all the files we need */
    g_assert(spec->ssl_ca_file);
    g_assert(spec->ssl_cert_file);
    g_assert(spec->ssl_key_file);

    /* nuke the old context if there is one */
    if (spec->vssl_ctx) {
        SSL_CTX_free((SSL_CTX *)spec->vssl_ctx);
        spec->vssl_ctx = NULL;
    }

    /* create an SSL_CTX object */
    ssl_ctx = SSL_CTX_new(tlsmeth);

    if (!ssl_ctx) {
        g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN,
                    "Cannot create SSL context: %s",
                    ERR_error_string(ERR_get_error(), NULL));
        while (ERR_get_error());
        ok = FALSE;
        goto end;
    }

    /* Set up password callback */
    SSL_CTX_set_default_passwd_cb(ssl_ctx, fbConnSpecGetTLSPassword);
    SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, spec->ssl_key_pass);

    /* Load CA certificate */
    if (SSL_CTX_load_verify_locations(ssl_ctx,
                                      spec->ssl_ca_file, NULL) != 1) {
        ok = FALSE;
        g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN,
                    "Failed to load certificate authority file %s: %s",
                    spec->ssl_ca_file, ERR_error_string(ERR_get_error(), NULL));
        while (ERR_get_error());
        goto end;
    }

    /* Load certificate */
    if (SSL_CTX_use_certificate_chain_file(ssl_ctx,
                                           spec->ssl_cert_file) != 1) {
        ok = FALSE;
        g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN,
                    "Failed to load certificate file %s: %s",
                    spec->ssl_cert_file,
                    ERR_error_string(ERR_get_error(), NULL));
        while (ERR_get_error());
        goto end;
    }

    /* Load private key */
    if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
                                    spec->ssl_key_file,
                                    SSL_FILETYPE_PEM) != 1) {
        ok = FALSE;
        g_set_error(err, FB_ERROR_DOMAIN, FB_ERROR_CONN,
                    "Failed to load private key file %s: %s",
                    spec->ssl_key_file,
                    ERR_error_string(ERR_get_error(), NULL));
        while (ERR_get_error());
        goto end;
    }

    /* Require verification */
    SSL_CTX_set_verify(ssl_ctx,
                       SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                       fbConnSpecVerifyTLSCert);

    /* Stash SSL context in specifier */
    spec->vssl_ctx = ssl_ctx;

end:
    /* free incomplete SSL context */
    if (!ok) SSL_CTX_free(ssl_ctx);
    return ok;
}
示例#25
0
/* Create a socket and connect it to 'ip' on port 'port'.
 * Returns -1 on failure (ip is NULL, socket creation/connection error)
 * Returns sock number on success.
 */
int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking)
{
	int sock = INVALID_SOCKET;
	int rc;
#ifdef WITH_TLS
	int ret;
	BIO *bio;
#endif

	if(!mosq || !host || !port) return MOSQ_ERR_INVAL;

#ifdef WITH_TLS
	if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
		blocking = true;
	}
#endif

	rc = _mosquitto_try_connect(host, port, &sock, bind_address, blocking);
	if(rc != MOSQ_ERR_SUCCESS) return rc;

#ifdef WITH_TLS
	if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
		if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1.2")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
		}else if(!strcmp(mosq->tls_version, "tlsv1.1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_1_client_method());
		}else if(!strcmp(mosq->tls_version, "tlsv1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
		}else{
			_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version);
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_INVAL;
		}
#else
		if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
		}else{
			_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version);
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_INVAL;
		}
#endif
		if(!mosq->ssl_ctx){
			_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}

#if OPENSSL_VERSION_NUMBER >= 0x10000000
		/* Disable compression */
		SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
			/* Use even less memory per SSL connection. */
			SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif

		if(mosq->tls_ciphers){
			ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers);
			if(ret == 0){
				_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers);
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}
		if(mosq->tls_cafile || mosq->tls_capath){
			ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
			if(ret == 0){
#ifdef WITH_BROKER
				if(mosq->tls_cafile && mosq->tls_capath){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
				}else if(mosq->tls_cafile){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
				}else{
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
				}
#else
				if(mosq->tls_cafile && mosq->tls_capath){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
				}else if(mosq->tls_cafile){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
				}else{
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
				}
#endif
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
			if(mosq->tls_cert_reqs == 0){
				SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL);
			}else{
				SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, _mosquitto_server_certificate_verify);
			}

			if(mosq->tls_pw_callback){
				SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback);
				SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq);
			}

			if(mosq->tls_certfile){
				ret = SSL_CTX_use_certificate_chain_file(mosq->ssl_ctx, mosq->tls_certfile);
				if(ret != 1){
#ifdef WITH_BROKER
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile);
#else
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile);
#endif
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
			}
			if(mosq->tls_keyfile){
				ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM);
				if(ret != 1){
#ifdef WITH_BROKER
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile);
#else
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile);
#endif
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
				ret = SSL_CTX_check_private_key(mosq->ssl_ctx);
				if(ret != 1){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent.");
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
			}
#ifdef REAL_WITH_TLS_PSK
		}else if(mosq->tls_psk){
			SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback);
#endif
		}

		mosq->ssl = SSL_new(mosq->ssl_ctx);
		if(!mosq->ssl){
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}
		SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq);
		bio = BIO_new_socket(sock, BIO_NOCLOSE);
		if(!bio){
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}
		SSL_set_bio(mosq->ssl, bio, bio);

		ret = SSL_connect(mosq->ssl);
		if(ret != 1){
			ret = SSL_get_error(mosq->ssl, ret);
			if(ret == SSL_ERROR_WANT_READ){
				mosq->want_read = true;
			}else if(ret == SSL_ERROR_WANT_WRITE){
				mosq->want_write = true;
			}else{
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}
	}
#endif

	mosq->sock = sock;

	return MOSQ_ERR_SUCCESS;
}
示例#26
0
bool SSLSocket::Initialize()
{
	//Initializing OpenSSL
	SSL_load_error_strings();
	SSL_library_init();
	OpenSSL_add_all_algorithms();
	//Initializing SSL context and SSL method in this case I use SSLv23_client_method (Negotiate highest available SSL / TLS version)
	sslContext = SSL_CTX_new(SSLv23_client_method()); 
	if (sslContext == nullptr)
	{
		LOGI("SSL_CTX_new error");
		LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
		return false;
	}
	//Configure SSL_CTX
	//Load the certificateAuthority (trustStore)
	if (NetworkSecurityOptions::certificateAuthority.empty() != SSL_SUCCESS)
	{
		if (!SSL_CTX_load_verify_locations(sslContext, NetworkSecurityOptions::certificateAuthority.c_str(), nullptr))
		{
			LOGI("SSL_CTX_load_verify_locations error");
			LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
			SSL_CTX_free(sslContext);
			sslContext = nullptr;
			return false;
		}
	}
	else if (SSL_CTX_set_default_verify_paths(sslContext) != SSL_SUCCESS)
	{
		LOGI("SSL_CTX_set_default_verify_paths error");
		LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
		SSL_CTX_free(sslContext);
		sslContext = nullptr;
		return false;
	}
	//Load the client's certificate (keyStore)
	if (!NetworkSecurityOptions::clientCertificate.empty())
	{
		if (SSL_CTX_use_certificate_file(sslContext, NetworkSecurityOptions::clientCertificate.c_str(), SSL_FILETYPE_PEM) != SSL_SUCCESS)
		{
			LOGI("SSL_CTX_use_certificate_file error");
			LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
			SSL_CTX_free(sslContext);
			sslContext = nullptr;
			return false;
		}
		std::string clientPrivateKey;
		if (NetworkSecurityOptions::clientPrivateKey.empty())
		{
			clientPrivateKey = NetworkSecurityOptions::clientCertificate; //The client's private key is in client certificate
		}
		else
		{
			clientPrivateKey = NetworkSecurityOptions::clientPrivateKey; //Load client's private key if it is not included in client's certificate (keyStore)
		}
		//Load private key password if it's exist
		//Note you should call these function before calling SSL_CTX_use_PrivateKey_file 
		if (!NetworkSecurityOptions::clientPrivateKeyPassword.empty())
		{
			SSL_CTX_set_default_passwd_cb(sslContext, PemPasswordCallback);
			SSL_CTX_set_default_passwd_cb_userdata(sslContext, (void*)NetworkSecurityOptions::clientPrivateKeyPassword.c_str());
		}
		if (SSL_CTX_use_PrivateKey_file(sslContext, clientPrivateKey.c_str(), SSL_FILETYPE_PEM) != SSL_SUCCESS)
		{
			LOGI("SSL_CTX_use_PrivateKey_file error");
			LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
			SSL_CTX_free(sslContext);
			sslContext = nullptr;
			return false;
		}
	}
	// Set list of cipher
	if (SSL_CTX_set_cipher_list(sslContext, "DEFAULT") != SSL_SUCCESS)
	{
		LOGI("SSL_CTX_set_cipher_list error");
		LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
		SSL_CTX_free(sslContext);
		sslContext = nullptr;
		return false;
	}
	SSL_CTX_set_mode(sslContext, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
	if (NetworkSecurityOptions::enableServerCertificate)
	{
		SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, nullptr);
		SSL_CTX_set_verify_depth(sslContext, 1);
	}
	ssl = SSL_new(sslContext);
	if (ssl == nullptr)
	{
		LOGI("SSL_new error");
		LOGI("%s\n", ERR_error_string(ERR_get_error(), NULL));
		SSL_CTX_free(sslContext);
		sslContext = nullptr;
		return false;
	}
	return true;
}
示例#27
0
int tnet_transport_tls_set_certs(tnet_transport_handle_t *handle, const char* ca, const char* pbk, const char* pvk, tsk_bool_t verify)
{
    tnet_transport_t *transport = handle;
    static const char* ssl_password = tsk_null;
    
    if (!transport) {
        TSK_DEBUG_ERROR("Invalid parameter");
        return -1;
    }
    
    tsk_strupdate(&transport->tls.ca, ca);
    tsk_strupdate(&transport->tls.pvk, pvk);
    tsk_strupdate(&transport->tls.pbk, pbk);
    transport->tls.verify = verify;
    
#if HAVE_OPENSSL
    {
        int32_t i, ret;
        SSL_CTX* contexts[3] = { tsk_null };
        
        /* init DTLS/TLS contexts */
        if ((ret = _tnet_transport_ssl_init(transport))){
            return ret;
        }
        
        if (transport->tls.enabled){
            contexts[0] = transport->tls.ctx_client;
            contexts[1] = transport->tls.ctx_server;
        }
        if (transport->dtls.enabled){
            contexts[2] = transport->dtls.ctx;
            /* Reset fingerprints */
            memset(transport->dtls.fingerprints, 0, sizeof(transport->dtls.fingerprints));
        }
        
        for (i = 0; i < sizeof(contexts) / sizeof(contexts[0]); ++i){
            if (!contexts[i]){
                continue;
            }
            SSL_CTX_set_verify(contexts[i], transport->tls.verify ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : SSL_VERIFY_NONE, tsk_null);
            if (!tsk_strnullORempty(transport->tls.pbk) || !tsk_strnullORempty(transport->tls.pvk) || !tsk_strnullORempty(transport->tls.ca)){
                /* Sets Public key (cert) */
                if (!tsk_strnullORempty(transport->tls.pbk) && (ret = SSL_CTX_use_certificate_file(contexts[i], transport->tls.pbk, SSL_FILETYPE_PEM)) != 1) {
                    TSK_DEBUG_ERROR("SSL_CTX_use_certificate_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null));
                    return -3;
                }
                /*Sets the password of the private key*/
                if (!tsk_strnullORempty(ssl_password)){
                    SSL_CTX_set_default_passwd_cb_userdata(contexts[i], (void*)ssl_password);
                }
                
                /* Sets Private key (cert) */
                if (!tsk_strnullORempty(transport->tls.pvk) && (ret = SSL_CTX_use_PrivateKey_file(contexts[i], transport->tls.pvk, SSL_FILETYPE_PEM)) != 1) {
                    TSK_DEBUG_ERROR("SSL_CTX_use_PrivateKey_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null));
                    return -4;
                }
                /* Checks private key */
                if (!tsk_strnullORempty(transport->tls.pvk) && SSL_CTX_check_private_key(contexts[i]) == 0) {
                    TSK_DEBUG_ERROR("SSL_CTX_check_private_key failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null));
                    return -5;
                }
                /* Sets trusted CAs and CA file */
                if (!tsk_strnullORempty(transport->tls.ca) && (ret = SSL_CTX_load_verify_locations(contexts[i], transport->tls.ca, /*tlsdir_cas*/tsk_null)) != 1) {
                    TSK_DEBUG_ERROR("SSL_CTX_load_verify_locations failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null));
                    return -5;
                }
            }
        }
    }
#endif /* HAVE_OPENSSL */
    
    return 0;
}
示例#28
0
static int ma_tls_set_certs(MYSQL *mysql)
{
  char *certfile= mysql->options.ssl_cert,
       *keyfile= mysql->options.ssl_key;
  
  /* add cipher */
  if ((mysql->options.ssl_cipher && 
        mysql->options.ssl_cipher[0] != 0) &&
      SSL_CTX_set_cipher_list(SSL_context, mysql->options.ssl_cipher) == 0)
    goto error;

  /* ca_file and ca_path */
  if (SSL_CTX_load_verify_locations(SSL_context, 
                                    mysql->options.ssl_ca,
                                    mysql->options.ssl_capath) == 0)
  {
    if (mysql->options.ssl_ca || mysql->options.ssl_capath)
      goto error;
    if (SSL_CTX_set_default_verify_paths(SSL_context) == 0)
      goto error;
  }

  if (keyfile && !certfile)
    certfile= keyfile;
  if (certfile && !keyfile)
    keyfile= certfile;

  /* set cert */
  if (certfile  && certfile[0] != 0)  
    if (SSL_CTX_use_certificate_file(SSL_context, certfile, SSL_FILETYPE_PEM) != 1)
      goto error; 

  /* If the private key file is encrypted, we need to register a callback function
   * for providing password. */
  if (OPT_HAS_EXT_VAL(mysql, tls_pw))
  {
    SSL_CTX_set_default_passwd_cb_userdata(SSL_context, (void *)mysql->options.extension->tls_pw);
    SSL_CTX_set_default_passwd_cb(SSL_context, ma_tls_get_password);
  }

  if (keyfile && keyfile[0])
  {
    if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1)
    {
      unsigned long err= ERR_peek_error();
      if (!(ERR_GET_LIB(err) == ERR_LIB_X509 &&
	  ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE))
        goto error;
    }
  }
  if (OPT_HAS_EXT_VAL(mysql, tls_pw))
  {
    SSL_CTX_set_default_passwd_cb_userdata(SSL_context, NULL);
    SSL_CTX_set_default_passwd_cb(SSL_context, NULL);
  }
  /* verify key */
  if (certfile && !SSL_CTX_check_private_key(SSL_context))
    goto error;
  
  if (mysql->options.extension &&
      (mysql->options.extension->ssl_crl || mysql->options.extension->ssl_crlpath))
  {
    X509_STORE *certstore;

    if ((certstore= SSL_CTX_get_cert_store(SSL_context)))
    {
      if (X509_STORE_load_locations(certstore, mysql->options.extension->ssl_crl,
                                               mysql->options.extension->ssl_crlpath) == 0)
        goto error;

      X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
    }
  }
  return 0;

error:
  ma_tls_set_error(mysql);
  return 1;
}
示例#29
0
int sslctx_init()
{
#if 0
    BIO *bio = NULL;
    X509 *cert = NULL;
    STACK_OF(X509) *ca = NULL;
    EVP_PKEY *pkey =NULL;
    PKCS12* p12 = NULL;
    X509_STORE *store =NULL;
    int error_code =0;
#endif

    int ret =0;
    print_client_cert(CERT_PATH);
    //registers the libssl error strings
    SSL_load_error_strings();

    //registers the available SSL/TLS ciphers and digests
    SSL_library_init();

    //creates a new SSL_CTX object as framework to establish TLS/SSL
    g_sslctx = SSL_CTX_new(SSLv23_client_method());
    if(g_sslctx == NULL){
        ret = -1;
        goto end;
    }

    //passwd is supplied to protect the private key,when you want to read key
    SSL_CTX_set_default_passwd_cb_userdata(g_sslctx,"1111");

    //set cipher ,when handshake client will send the cipher list to server
    SSL_CTX_set_cipher_list(g_sslctx,"HIGH:MEDIA:LOW:!DH");
    //SSL_CTX_set_cipher_list(g_sslctx,"AES128-SHA");

    //set verify ,when recive the server certificate and verify it
    //and verify_cb function will deal the result of verification
    SSL_CTX_set_verify(g_sslctx, SSL_VERIFY_PEER, verify_cb);

    //sets the maximum depth for the certificate chain verification that shall
    //be allowed for ctx
    SSL_CTX_set_verify_depth(g_sslctx, 10);

    //load the certificate for verify server certificate, CA file usually load
    SSL_CTX_load_verify_locations(g_sslctx,CAFILE, NULL);

    //load user certificate,this cert will be send to server for server verify
    if(SSL_CTX_use_certificate_file(g_sslctx,CERT_PATH,SSL_FILETYPE_PEM) <= 0){
        printf("certificate file error!\n");
        ret = -1;
        goto end;
    }
    //load user private key
    if(SSL_CTX_use_PrivateKey_file(g_sslctx,KEY_PATH,SSL_FILETYPE_PEM) <= 0){
        printf("privatekey file error!\n");
        ret = -1;
        goto end;
    }
    if(!SSL_CTX_check_private_key(g_sslctx)){
        printf("Check private key failed!\n");
        ret = -1;
        goto end;
    }

end:
    return ret;
}
示例#30
0
SSL *SSL_new_from_context(SSL_CTX *ctx, stream *stream) /* {{{ */
{
    zval **val = NULL;
    char *cafile = NULL;
    char *capath = NULL;
    char *certfile = NULL;
    char *cipherlist = NULL;
    int ok = 1;

    ERR_clear_error();

    /* look at context options in the stream and set appropriate verification flags */
    if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) {

        /* turn on verification callback */
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);

        /* CA stuff */
        GET_VER_OPT_STRING("cafile", cafile);
        GET_VER_OPT_STRING("capath", capath);

        if (cafile || capath) {
            if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) {
                error_docref(NULL, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath);
                return NULL;
            }
        }

        if (GET_VER_OPT("verify_depth")) {
            convert_to_long_ex(val);
            SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val));
        }
    } else {
        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
    }

    /* callback for the passphrase (for localcert) */
    if (GET_VER_OPT("passphrase")) {
        SSL_CTX_set_default_passwd_cb_userdata(ctx, stream);
        SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
    }

    GET_VER_OPT_STRING("ciphers", cipherlist);
    if (!cipherlist) {
        cipherlist = "DEFAULT";
    }
    if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) {
        return NULL;
    }

    GET_VER_OPT_STRING("local_cert", certfile);
    if (certfile) {
        X509 *cert = NULL;
        EVP_PKEY *key = NULL;
        SSL *tmpssl;
        char resolved_path_buff[MAXPATHLEN];
        const char * private_key = NULL;

        if (VCWD_REALPATH(certfile, resolved_path_buff)) {
            /* a certificate to use for authentication */
            if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) {
                error_docref(NULL, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile);
                return NULL;
            }
            GET_VER_OPT_STRING("local_pk", private_key);

            if (private_key) {
                char resolved_path_buff_pk[MAXPATHLEN];
                if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) {
                    if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) {
                        error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk);
                        return NULL;
                    }
                }
            } else {
                if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
                    error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff);
                    return NULL;
                }
            }

            tmpssl = SSL_new(ctx);
            cert = SSL_get_certificate(tmpssl);

            if (cert) {
                key = X509_get_pubkey(cert);
                EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
                EVP_PKEY_free(key);
            }
            SSL_free(tmpssl);

            if (!SSL_CTX_check_private_key(ctx)) {
                error_docref(NULL, E_WARNING, "Private key does not match certificate!");
            }
        }
    }
    if (ok) {
        SSL *ssl = SSL_new(ctx);

        if (ssl) {
            /* map SSL => stream */
            SSL_set_ex_data(ssl, ssl_stream_data_index, stream);
        }
        return ssl;
    }

    return NULL;
}