I have this error for webservice accessment with Gsoap.
We are doing test so no SSL certificate check is required.
But my client side, how can I bypass SSL check?
i'm using C++.
My error is
SOAP 1.2 fault SOAP-ENV:Sender[no subcode]
"OpenSSL not installed: recompile with -DWITH_OPENSSL"
Detail: [no detail]
This is the solution.
#include "calc.nsmap"
#include "soapcalcProxy.h" // generated with soapcpp2 -j calc.h
calcProxy calc("https-server-endpoint-URL");
double sum;
soap_ssl_init(); // init SSL (just need to do this once in an application)
// soap_ssl_no_init(); // or prevent init OpenSSL when already initialized elsewhere in an application
if (soap_ssl_client_context(calc.soap,
SOAP_SSL_DEFAULT,
NULL, // no keyfile
NULL, // no keyfile password
"cacerts.pem", // trusted certificates (or use self-signed cacert.pem)
NULL, // no capath to trusted certificates
NULL // no random data to seed randomness
))
{
calc.soap_stream_fault(std::cerr);
exit(EXIT_FAILURE);
}
if (calc.add(1.23, 4.56, sum) == SOAP_OK)
Related
I'm trying to implement MQTT in my program using M2MQTT v4.3.0.0 (github), but when I try to connect using signed certificates my code cannot establish a connection. I'm on a Windows 10 system, and using C# with .NET 4.8. The version of Mosquitto I have installed is 2.0.10.
To make the server certificate I followed this tutorial:
http://www.steves-internet-guide.com/mosquitto-tls/#server
To make the client certificate I followed this tutorial:
http://www.steves-internet-guide.com/creating-and-using-client-certificates-with-mqtt-and-mosquitto/
I also made a host name in my etc/hosts file for 127.0.0.1 that points to localhost.conrad.com.
The configuration for my Mosquitto Broker is:
bind_address localhost.conrad.com
port 8883
allow_anonymous true
cafile C:/mosquitto/certs/ca.crt
keyfile C:/mosquitto/certs/server.key
certfile C:/mosquitto/certs/server.crt
require_certificate true
tls_version tlsv1.2
log_dest file C:/mosquitto/log/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
I successfully tested that this configuration works using Mosquitto's command line publish tool with
mosquitto_pub --cafile C:\mosquitto\certs\ca.crt --cert C:\mosquitto\certs\client.crt --key C:\mosquitto\certs\client.key -d -h localhost.conrad.com -p 8883 -t herp/derp/test -m "hi"
I received this message after using the command.
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'herp/derp/test', ... (2 bytes))
Client (null) sending DISCONNECT
My Mosquitto log confirms a successful connection:
1621547553: New connection from 127.0.0.1:57874 on port 8883.
1621547553: New client connected from 127.0.0.1:57874 as auto-6A8387C3-E091-0EC6-CED7-0A78BAA63099 (p2, c1, k60).
1621547553: Client auto-6A8387C3-E091-0EC6-CED7-0A78BAA63099 disconnected.
However when I try to connect using M2MQTT I run into a problem when trying to connect using signed certificates. My code is as follows:
int securePort = 8883;
MqttClient client = null;
string subTopic1 = "herp/derp/test";
string subTopic2 = "herp/derp/test2";
X509Certificate caCert = new X509Certificate("C:/mosquitto/certs/ca.crt");
X509Certificate clientCert = new X509Certificate("C:/mosquitto/certs/client.crt");
string clientID = "TestClientID";
public MQTTTest()
{
try
{
client = new MqttClient("localhost.conrad.com", securePort, true, caCert, clientCert, MqttSslProtocols.TLSv1_2, RemoteCertificateValidationCallback);
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
client.MqttMsgPublished += client_MqttMsgPublished;
client.MqttMsgSubscribed += client_MqttMsgSubscribed;
client.ConnectionClosed += client_ConnectionClosed;
client.Connect(clientID, "", "", true, 1000);
client.Subscribe(new string[] { subTopic1, subTopic2 }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
I get the following exception when trying at client.Connect.
Exception message: "A call to SSPI failed, see inner exception."
Inner exception: "The message received was unexpected or badly formatted"
My Mosquitto logs show:
1621547793: New connection from 127.0.0.1:57896 on port 8883.
1621547793: OpenSSL Error[0]: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate
1621547793: Client <unknown> disconnected: protocol error.
I can establish insecure connections just fine. As it is written my code also connects when I set require_certificate to false in my Mosquitto config file; however I am worried that if require_certificate is set to false that I won't have the security I want. Any help would be greatly appreciated.
Thanks to Brits' comment I was able to figure it out (link to answer). I made a pfx certificate and used that instead of using a crt.
Instead of...
X509Certificate caCert = new X509Certificate("C:/mosquitto/certs/ca.crt");
X509Certificate clientCert = new X509Certificate("C:/mosquitto/certs/client.crt");
I used...
X509Certificate2 caCert = new X509Certificate2("C:/mosquitto/certs/ca.pfx", "password");
X509Certificate2 clientCert = new X509Certificate2("C:/mosquitto/certs/client.pfx", "password");
I am trying to make HTTPS calls to site that has 2 SSL certificates: a self-signed certificate and a certificate that was signed by the the first certificate. When I use an HttpClient to send a request to the site, the console logs an untrusted chain, shows both certificates, then print a long stack trace of that is caused by java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
I have installed both certificates on my phone and navigating Chrome to the site shows a trusted connection (it had an untrusted connection warning before I installed the certificates). I believe the issue is that the App refuses to trust self-signed certificates. I do not have access to the server and thus have no influence on its certificates, so installing a certificate signed by a trusted CA is not viable.
Solutions I've tried that have not worked.
ServicePointManager.ServerCertificateValidationCallback doesn't seem to run.
I have tried using my own function for ServicePointManager.ServerCertificateValidationCallback, but the delegate I give it never seems to run. I have the following code in my MainActivity.OnCreate method, but the console never logs the message:
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
Console.WriteLine($"****************************************************************************************************");
return true;
};
HttpClientHandler.ServerCertificateCustomValidationCallback throws an exception.
I have tried using an HttpClientHandler and settings its ServerCertificateCustomValidationCallback, but I just get the message:
System.NotImplementedException: The method or operation is not implemented. at System.Net.Http.HttpClientHandler.set_ServerCertificateCustomValidationCallback (System.Func`5[T1,T2,T3,T4,TResult] value).
Setup code:
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
HttpClient client = new HttpClient(handler);
I was able to get this to work in both Android and iOS.
iOS was easy, just override ServicePointManager.ServerCertificateValidationCallback:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
For Android I used Bruno Caceiro's answer from a similar question and a created Dependency Service.
In my Xamarin Forms project I added a simple interface:
public interface IHTTPClientHandlerCreationService
{
HttpClientHandler GetInsecureHandler();
}
And in my Xamarin Android project I implemented the interface:
[assembly: Dependency(typeof(HTTPClientHandlerCreationService_Android))]
namespace MyApp.Droid
{
public class HTTPClientHandlerCreationService_Android : CollateralUploader.Services.IHTTPClientHandlerCreationService
{
public HttpClientHandler GetInsecureHandler()
{
return new IgnoreSSLClientHandler();
}
}
internal class IgnoreSSLClientHandler : AndroidClientHandler
{
protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
{
return SSLCertificateSocketFactory.GetInsecure(1000, null);
}
protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
{
return new IgnoreSSLHostnameVerifier();
}
}
internal class IgnoreSSLHostnameVerifier : Java.Lang.Object, IHostnameVerifier
{
public bool Verify(string hostname, ISSLSession session)
{
return true;
}
}
}
Shared code to correctly set up the HttpClient:
switch (Device.RuntimePlatform)
{
case Device.Android:
this.httpClient = new HttpClient(DependencyService.Get<Services.IHTTPClientHandlerCreationService>().GetInsecureHandler());
break;
default:
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
this.httpClient = new HttpClient(new HttpClientHandler());
break;
}
My use case looks like I know the public certificates of my clients and only want to allow them. I have a go server based on gin and a TLS configuration in which I have assigned a method to the property "VerifyPeerCertificate".
The function looks like
func customVerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
if len(verifiedChains) < 1 {
return errors.New("Verified certificate chains is empty.")
}
if len(verifiedChains[0]) < 1 {
return errors.New("No certificates in certificate chains.")
}
if len(verifiedChains[0][0].Subject.CommonName) < 1 {
return errors.New("Common name can not be empty.")
}
fmt.Println(verifiedChains[0][0].Raw)
publicKeyDer, _ := x509.MarshalPKIXPublicKey(verifiedChains[0][0].PublicKey)
publicKeyBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: publicKeyDer,
}
publicKeyPem := string(pem.EncodeToMemory(&publicKeyBlock))
}
The problem is, however, that the string in the variable "publicKeyPem" does not look like the client public certificate I used to send the request to the server, it's also shorter in length.
A certificate is more than its public key. The entire x509.Certificate object represents the certificate presented by the client, the public key field is only the actual value of the public key.
If you want to compare certificates for strict equality, you should use the rawCerts [][]byte argument passed to your callback. This is mentioned in the tls.Config comments for VerifyPeerCertificate:
VerifyPeerCertificate, if not nil, is called after normal
certificate verification by either a TLS client or server. It
receives the raw ASN.1 certificates provided by the peer and also
any verified chains that normal processing found. If it returns a
non-nil error, the handshake is aborted and that error results.
Thanks to Marc, I know that I used the wrong variable. To convert the certificate as a string, as used by the client, use the following code
publicKeyBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: rawCerts[0],
}
publicKeyPem := string(pem.EncodeToMemory(&publicKeyBlock))
Problem with Poco library (poco-1.9.0-all) and OpenSSL (v1.1.0h from slproweb site).
I can't establish a secure connection with any site.
Simple code:
Poco::Net::initializeSSL();
Poco::Net::Context* pCtx = new Poco::Net::Context(Poco::Net::Context::Usage::TLSV1_2_CLIENT_USE, "", "cacert.pem", "", Poco::Net::Context::VerificationMode::VERIFY_RELAXED, 9, false);
Poco::Net::HTTPSClientSession cs("ya.ru", 443, pCtx);
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, "/?encoding=text", Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPResponse resp;
try
{
Poco::Net::WebSocket sock(cs, req, resp);
}
catch (Poco::Net::SSLException& e)
{
cout << "ssl exception: " << e.displayText() << endl;
}
catch (...)
{
}
I get a exception from the poco library: 'SSL Exception: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed'.
File cacert.pem downloaded from https://curl.haxx.se/docs/caextract.html
OpenSSL reads it without errors by SSL_CTX_use_certificate_chain_file function in Poco::Net::Context::init(const Params& params).
If I specify the verification mode VERIFY_NONE in Poco::Net::Context constructor - connection passes without problems.
Maybe I'm setting the wrong parameters in Poco::Net::Context constructor?
I have the same exception: SSL Exception: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed. Changing the order of constructor Poco::Net::Context constructor arguments helps:
Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "cacert.pem", Poco::Net::Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:#STRENGTH");
cacert.pem it is the root CA certificate file and should be passed as caLocation argument.
I'm experimenting with OSGi conditional permissions mechanism. More specifically, I'm trying to use org.osgi.service.condpermadmin.BundleSignerCondition to restrict which bundles can be started. Documentation I have states that in order to use this permission, I must specify the path to JKS keystores using org.osgi.framework.trust.repositories framework configuration property. However, the same documentation mentions that JKS mentioned in this property must not have a password. So the question is: how to create a JKS without a password? Keytool utility refuses to create JKS with blank password.
You cannot create a keystore with a blank password with keytool since a while, but you can still do it programmatically.
Read a cert like this:
private static Certificate readCert(String path) throws IOException, CertificateException {
try (FileInputStream fin = new FileInputStream(path)) {
return CertificateFactory.getInstance("X.509").generateCertificate(fin);
}
}
Than create the keystore with the empty password like this:
try {
// Reading the cert
Certificate cert = readCert("/tmp/cert.cert");
// Creating an empty JKS keystore
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
// Adding the cert to the keystore
keystore.setCertificateEntry("somecert", cert);
// Saving the keystore with a zero length password
FileOutputStream fout = new FileOutputStream("/tmp/keystore");
keystore.store(fout, new char[0]);
} catch (GeneralSecurityException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Run the command:
keytool -list -keystore keystore
It will ask for a password but you can simply push an enter. You will get the following warning, but the content of the keystore will be listed:
***************** WARNING WARNING WARNING *****************
* The integrity of the information stored in your keystore *
* has NOT been verified! In order to verify its integrity, *
* you must provide your keystore password. *
***************** WARNING WARNING WARNING *****************
This might work for you.