How to enable ActiveMQ SSL authentication using C client - c++

I am trying to connect a C client with activeMQ using ssl.For this I created certificates using the following link.
Also I confiugured activeMQ with transport connectors as:
<transportConnector name="ssl" uri="mqtt+ssl://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
The portion of C client uisng SSL is as follows:
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
ssl_opts.enableServerCertAuth = 0;
conn_opts.ssl = &ssl_opts;
conn_opts.ssl->keyStore = "/home/user/certs/client-chain.pem";
conn_opts.ssl->privateKeyPassword = "password";
conn_opts.ssl->enabledCipherSuites = "DEFAULT";
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if ((rc = MQTTClient_connect(client, &conn_opts))!=MQTTCLIENT_SUCCESS)
{
printf("%d",rc);
}
But when I connect a C client to activeMQ I get connect failed return code -1 error...Kindly help me to fix this issue

Related

Golang Paho MQTT over Websocket

Hey I was trying to connect to AWS IoT Core via Golang Paho MQTT client. I tried the normal MQTT connection which was working without problems. Next I wanted to try the connection via MQTT over Websocket but could not find anything relating that in the Paho.Mqtt docs. How do I make the Websocket connection? I could post my code from my normal MQTT connection if necessary.
Edit, here is my code:
package main
import (
"crypto/tls"
"fmt"
"time"
MQTT "github.com/eclipse/paho.mqtt.golang"
)
type Message struct {
message string
}
/*var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
fmt.Printf("TOPIC: %s\n", msg.Topic())
fmt.Printf("MSG: %s\n", msg.Payload())
}*/
func main() {
cer, err := tls.LoadX509KeyPair("cd5a04e9fd9a094326c9ee0cdc1e1f7b2e3510a9e106968683d333a2a4344ca7-certificate.pem.crt",
"./cd5a04e9fd9a094326c9ee0cdc1e1f7b2e3510a9e106968683d333a2a4344ca7-private.pem.key")
check(err)
cid := "ClientID"
// AutoReconnect option is true by default
// CleanSession option is true by default
// KeepAlive option is 30 seconds by default
connOpts := MQTT.NewClientOptions() // This line is different, we use the constructor function instead of creating the instance ourselves.
connOpts.SetClientID(cid)
connOpts.SetMaxReconnectInterval(1 * time.Second)
connOpts.SetTLSConfig(&tls.Config{Certificates: []tls.Certificate{cer}})
host := "a2to6mbspmaw82-ats.iot.eu-west-1.amazonaws.com"
port := 443
brokerURL := fmt.Sprintf("wss://%s:%d", host, port)
connOpts.AddBroker(brokerURL)
mqttClient := MQTT.NewClient(connOpts)
if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
}
var message = "message from lap"
for message != "bye" {
token := mqttClient.Publish("some_topic", 0, false, message)
token.Wait()
message = "bye"
}
}
func check(err error) {
if err != nil {
panic(err)
}
}
From the Eclipse Paho GoLang page
The type of connection required is specified by the scheme of the
connection URL set in the ClientOptions struct, for example:
tcp://mqtt.eclipseprojects.io:1883 - connect to mqtt.eclipseprojects.io on port 1883 using plain TCP
ws://mqtt.eclipseprojects.io:1883 - connect to mqtt.eclipseprojects.io on port 1883 using WebSockets
tls://mqtt.eclipseprojects.io:8883 - connect to mqtt.eclipseprojects.io on port 8883 using TLS (ssl:// and tcps:// are
synonyms for tls://)
The second entry in the list suggests you just pas in the URL with the right schema ( ws:// or probably wss://)

Amazon root certificate pinning in Flutter, Dart

I'm using AWS CA to generate an SSL certificate for ElasticBeanstalk that I'm using in my Flutter app.
Based on the bets practices, I'm trying to pin HTTP client the Root certificate from Amazon Trusted Services
I face 2 issues with the Flutter HTTP client:
Whenever I try to load the certificate it crashes:
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: TlsException: Failure trusting builtin roots (OS Error: BAD_PKCS12_DATA(pkcs8_x509.c:657), errno = 0)
This is the certificate I use (one of five, I add them all):
final _awsRoot1 = _decodePEM("""-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----""");
And this is what I do to decode PEM :
Uint8List _decodePEM(pem) {
for (var s in _startsWith) {
if (pem.startsWith(s)) pem = pem.substring(s.length);
}
for (var s in _endsWith) {
if (pem.endsWith(s)) pem = pem.substring(0, pem.length - s.length);
}
pem = pem.replaceAll('\n', '');
pem = pem.replaceAll('\r', '');
return Uint8List.fromList(base64.decode(pem));
}
And add it via:
void certificatePinningPem(SecurityContext context) {
context.setTrustedCertificatesBytes(_awsRoot1);
context.setTrustedCertificatesBytes(_awsRoot2);
context.setTrustedCertificatesBytes(_awsRoot3);
context.setTrustedCertificatesBytes(_awsRoot4);
context.setTrustedCertificatesBytes(_awsRoot5);
}
I get the same exception when I read DER file :
final aws1 = await rootBundle.load('assets/cer/aws1.cer');
context.setTrustedCertificatesBytes(aws1.buffer.asUint8List());
PEM file from the connection is different
Despite that, when I use badCertificateCallback, pem file from the certificate doesn't match any of those five from repo So how to get Root certificate from connection?
httpClient.badCertificateCallback = (
X509Certificate certificate,
String host,
int port,
) {
print('Bad certificate: ${certificate.pem} for host $host:$port');
return false;
};
Any suggestion on how to properly do certificate pinning in Flutter with AWS Root certificates?
I found a few related threads but they don't really help, i.e. https://github.com/flutter/flutter/issues/39190#issuecomment-693315205

Client authentication (certificat + private key) using WinHttp

I'm trying to communicate in https with a server using the Win32 API.
Here is a very minimalist code :
HINTERNET ses = WinHttpOpen(L"test",WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS,0 ) ;
HINTERNET con = WinHttpConnect(ses,L"stackoverflow.com",INTERNET_DEFAULT_HTTPS_PORT,0 ) ;
HINTERNET req = WinHttpOpenRequest(con,L"GET",NULL,NULL,WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,WINHTTP_FLAG_SECURE ) ;
WinHttpSendRequest( req,WINHTTP_NO_ADDITIONAL_HEADERS,0,WINHTTP_NO_REQUEST_DATA,0,0,0 ) ;
WinHttpReceiveResponse( req,NULL ) ;
char buffer [10000] ;
unsigned long size ;
WinHttpReadData( req,reinterpret_cast<void*>( buffer ),sizeof( buffer )-1,&size ) ;
buffer[size] = 0 ;
cout << buffer << endl ;
As long as I communicate with a "classic" https server like stackoverflow.com everything goes well.
The problem is when I try to communicate with a server that requests an authentication of the client.
I have 3 .pem files : a certificate and a private key for my client, and a root certificate that authenticates my client certificate (i.e. a certificate chain of length 2).
For information, I can connect my server using this cULR command line :
curl https://my.server --cert Client_cert.pem --key Client_key.pem --cacert Root_cert.pem
So I kown it's possible!
Reading the win32 API documentation, I figured out that the key is to call
WinHttpSetOption but it's not clear between the options WINHTTP_OPTION_CLIENT_CERT_CONTEXT and WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST...
And I did not find out how to pass my data (cert+key files).
Any wise advice ?
Thanks in advance !

Secured SSL connection Error: unknown protocol | bad hostname lookup

Iam downloading RSS feed file (eg. https://tools.ietf.org/dailydose/dailydose_atom.xml) from server via HTTP.
First, i have to connect to the remote server via OpenSSL, as described here.
Unsecured version works just fine and i can connect and receive HTTP answer with feeds:
bio = BIO_new_connect("www.tools.ietf.org:80");
if(bio == NULL)
{
/* Handle the failure */
}
if(BIO_do_connect(bio) <= 0)
{
/* Handle failed connection */
}
Secured version:
BIO * m_bio;
SSL_CTX * m_ctx;
SSL * m_ssl;
SSL_library_init();
m_ctx = SSL_CTX_new(SSLv23_client_method());
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
SSL_CTX_set_default_verify_paths(m_ctx);
m_bio = BIO_new_ssl_connect(m_ctx);
BIO_get_ssl(m_bio, &m_ssl);
SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
BIO_set_conn_hostname(m_bio, "www.tools.ietf.org:80");
if (BIO_do_connect(m_bio) <= 0)
{
printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));
throw std::runtime_error("FEEDREADER: Connection failed.");
}
if(SSL_get_verify_result(m_ssl) != X509_V_OK)
{
throw std::runtime_error("FEEDREADER: Verification failed.");
}
Where do_connect fails with following error:
Error: unknown protocol
when i replace www.tools.ietf.org with http(s)://www.tools.ietf.org
another error appears:
Error: bad hostname lookup
But hostname & dns works well for unsecured version, so may somebody help me with this one ?
80 is the default HTTP port. 443 is the default HTTPS port.
bio = BIO_new_connect("www.tools.ietf.org:443");
BIO_set_conn_hostname(m_bio, "www.tools.ietf.org:443");

How to use NSS with Jetty?

I am trying to setup Jetty to use NSS as its cryptographic engine. I have gotten it to the point where the server starts BUT any client that tries to connect seems to hang in the browser.
The setup process / code I am following is as follows (32-bit Windows 1.6 JVM).
NSS Database Creation
modutil.exe -create -dbdir C:\nssdb
modutil.exe -create -fips true -dbdir C:\nssdb
modutil.exe -create -changepw "NSS FIPS 140-2 Certificate DB" -dbdir C:\nssdb
Load NSS into Java
String config = "name = NSS\n";
config += "nssLibraryDirectory = C:\\nss\\lib\n";
config += "nssSecmodDirectory = C:\\nssdb\n";
config += "nssDbMode = readWrite\n";
config += "nssModule = fips";
InputStream stream = new ByteArrayInputStream(config.getBytes("UTF-8"));
Provider nss = new sun.security.pkcs11.SunPKCS11(stream);
Security.addProvider(nss);
int sunJssePosition = -1;
int currentIndex = 0;
for (Provider provider : Security.getProviders()) {
if ("SunJSSE".equals(provider.getName())) {
sunJssePosition = currentIndex + 1;
break;
}
currentIndex++;
}
Security.removeProvider("SunJSSE");
Provider sunJsse = new com.sun.net.ssl.internal.ssl.Provider(nss);
if (sunJssePosition == -1) {
Security.addProvider(sunJsse);
} else {
Security.insertProviderAt(sunJsse, sunJssePosition);
}
NSS Self Sign Certificate Generation
C:\nss\bin\certutil.exe -S -n 127.0.0.1 -x -t "u,u,u" -s "CN=127.0.0.1, OU=Foo, O=Bar, L=City, ST=NY, C=US" -m 25001 -d C:\nssdb
Jetty Startup
KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, "SuperSecret");
//Start setting up Jetty
Server server = new Server();
SslContextFactory sslContextFactory = new SslContextFactory();
//sslContextFactory.setKeyStoreProvider("SunPKCS11-NSS");
sslContextFactory.setKeyStore(ks);
//sslContextFactory.setKeyStorePassword(new String("SuperSecret"));
SslSelectChannelConnector sslConnector = new SslSelectChannelConnector(sslContextFactory);
sslConnector.setPort(443);
server.addConnector(sslConnector);
WebAppContext context = new WebAppContext();
//Blah Blah Blah, setup Jetty
server.setHandler(context);
server.start();
server.join();
Any ideas?
Edit: This seems extremely odd but I can access the server using Internet Explorer just fine. Firefox seems to be the one having an issue.
I have solved the issue. It turns out there are severe bugs in the Java 6 SSL implementation. The solution? Switch to Java 7!