OpenSMTPD Mail won't send from client, reason=ca-failure - openbsd

Any time I attempt to send mail from my mail client (In this case, thunderbird), it comes up with an arbitrary error for why it couldn't send the email (The error doesn't matter, as it simply is telling me that the connection got dropped). When I run tail -f /var/log/maillog I see:
smtp disconnected reason=ca-failure
I can't seem to find anywhere online talking about this and how to fix it.
I've attempted to use several different matching keys and certificates, locally sourced (openssl) and from letsencrypt. OpenSMTP accepts all of these no problem. I have also went as far as to specify the root CA certificate for letsencrypt with their certificates.

Did you define the mail hostname for the OpenSMTPD server?
This file is supposed to be found in /etc/mail/mailname, and it should match the pkiname thats in the smtpd.conf file "pki 'hostname' cert /etc/letsencrypt/live/www.domain.com/cert.pem"
I spent an hour or two fighting with this.
This is defined in the manual:
pki pkiname cert certfile
Associate certificate file certfile with host pkiname, and use that file to prove the identity of the mail server to clients. pkiname
is the server's name, derived from the default hostname or set using
either /etc/mail/mailname or using the hostname directive. If a
fallback certificate or SNI is wanted, the ‘*’ wildcard may be used as
pkiname.
A certificate chain may be created by appending one or many certificates, including a Certificate Authority certificate, to certfile. The creation of certificates is documented in starttls(8).

Related

Nifi: how to make ListenHTTP work with SSL

Objective
Because of Nifi integration with other tools through HTTP, I have to make ListenHTTP processor public facing. API Gateway on all 3 environments is too expensive for me. So I closed all VM ingress ports (except the one needed for ListenHTTP) for outer networks.
Issue
My configuration of ListenHTTP with StandardRestrictedSSLContextService doesn't work. Without SSL it worked, but was unsecure.
user$ curl -X POST -H "Content-Type: application/json" --data "test" https://localhost:7070/test
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
.....
user$ curl -X POST -H "Content-Type: application/json" --data "test" --cacert cacerts.jks https://localhost:7070/test
curl: (77) error setting certificate verify locations:
CAfile: cacerts.jks
CApath: none
Question
How to make ListenHTTP work with SSL certificates? What am I doing wrong?
More detailed questions:
Should I copy cacerts.jsk to the machine from which I issue the query? As far as I understand, StandardRestrictedSSLContextService will verify if the client has certificate in TrustStore.
If I need to protect only a single port with ListenHTTP processor - then I don't need nifi.security.needClientAuth property or all environment variables defined at "Standalone Instance, Two-Way SSL" section, right? I'm little bit confused because both Docker Image and StandardRestrictedSSLContextService contains the same configs, i.e. KEYSTORE_TYPE.
Already done
I have a general idea about KeyStore & TrustStore from this question and the documentation.
I have launched Nifi Docker container v1.10.0 with up & running ListenHTTP processor on 7070 port.
I have created keystore.jks and cacerts.jks files due to the instruction inside Nifi container.
I have configured ListenHTTP to use StandardRestrictedSSLContextService controller with the following configs:
.
The SSLContextService you're using probably doesn't contain a certificate which is signed by a publicly-accessible certificate authority (CA) like (for explanation purposes only; not endorsement) Comodo, Verisign, Let's Encrypt, etc.
Certificates signed by those CAs are generally trusted automatically by arbitrary clients because whoever builds the client (Java, Google/Microsoft/Mozilla/Apple for a browser, Microsoft/Apple/Linux Distro for the OS) has preemptively included those top-level public certs in the truststore of the client. The truststore you created cacerts.jks is in Java Keystore format, which curl doesn't happen to understand. You can export the public certificate from that keystore to a standalone file in PEM format using the commands here, but that will only solve the immediate problem of allowing curl with an arbitrary truststore to connect.
If you want generic external clients to be able to connect over TLS, you'll need to use a certificate in NiFi's keystore that is signed by a well-known CA. You can use any commercial CA for this purpose, but Let's Encrypt does offer this service for free and is very widely used. Once you are using a certificate signed by a CA, any* client will be able to connect.
If this is for internal/enterprise use only, and all allowed clients are controllable by you, then you can use a self-signed certificate (like you are doing now if you followed Simon's instructions), and export the public certificate to whatever format your other clients need in order to establish trust with this particular server. Theoretically, you could also enforce that each client attempting to connect also needs to present a certificate that the server (NiFi) can verify -- this is called mutual-authentication TLS and adds another layer of security because only authenticated clients will be able to make requests to this server. If you choose to do so, that's when the SSLContextService in ListenHTTP would need a truststore component as well.
Without knowing your explicit situation, I would heavily recommend option 1 (the signed cert).

How to implement valid https in web2py

I am using the following web2py slice in attempt to use https for a service worker function in a page.
http://www.web2pyslices.com/slice/show/1507/generate-ssl-self-signed-certificate-and-key-enable-https-encryption-in-web2py
I have tried opening web2py with the following line (with and without [-i IP and -p PORT]):
python web2py.py -c myPath/ssl_certificate.crt -k myPath/ssl_self_signed.key -i 127.0.0.1 -p 8000
but https is declared 'not private' and is crossed out. Because of this, I am getting a SSL certificate error when the registration of the service worker is attempted.
Please indicate what is going wrong or whether more information is needed
You mention "https is declared 'not private' and is crossed out". This has to do with browsers disliking not trusted (self-signed) certificates, because that's what trust is all about. If any hacker could just make up a certificate and the https client wouldn't respond with at least a frown, you could still be hacked or sniffed without noticing. Since you don't mention any other error, I assume you get otherwise valid results from the web2py server?
If so, you have setup your self-signed certificate well. If you don't get any valid html response (outside your browsers complaint, of course), you still have an issue with the setup.
If your service worker won't accept the certificate, what you can do (in a test environment at least) is import the self-signed certificate into the machine or service worker certificate repository. The process differs per OS and version.
Hope this helps. If it doesn't, please provide more detail.
The best way to use ssl with web2py is use of the deployment recipes with prodution-grade webservers like apache, nginx or Lighttpd.
Any of the mentioned scripts create a self-signed certificate, and then, you have to fix the generated server config files to a real certificate.
You can buy a real ssl certificate from any of many resellers or get for free from Let's Encript, if you have a real IP, like in a VPS or server.
A simple way to fix the config files is create a simbolic link from the real certificate to the one mentioned in the server config file.
To just test your service worker in your machine or a internal test server, just use a non-ssl port, or like Remco sugested, import the self-signed certificate to client environment.

Importing Pem/der certificate into kdb file

I have an IBM HTTP Server and Server [X] ,
I need to create secure connection [SSL] :
by creating KDB file : ibmhttpserverkey.kdb in IBM HTTP Server using iKeyman utility and importing Server[X]'s certificates [cert.PEM] or [cert.der] in ibmhttpserverkey.kdb
it's do-able or not?
I have tried a lot and every time it returns "Error Handshake, no certificate found" even if i installed it using certification manager!
You should be able to import certificates from other key file types such as a p12 database or another kdb. After doing the import check the personal certificates using IKEYMAN to see if the certificate is there. If you then see the "Error Handshake, no certificate found" in the IHS error log it may be you have not specified the certificate to be the default. Also check the VirtualHost entry for port 443 (or whatever ssl port is used) and see if an SSLServerCert directive is defined. This directive can be used to point at a label that identifies the needed certificate. The no certificate found message means that IHS opened the kdb defined by the keyfile directive and could not find either a default certificate or one that is specified using the SSLServerCert directive.
Guide to setting up SSL within IHS:
http://www-01.ibm.com/support/docview.wss?uid=swg21179559

Security & TLS handshake when client is authenticated

In a TLS handshake configured with a client authentication, there is a step where the server receives the client's certificate and choose to trust it or not (for instance, in Java it is done via a TrustManager).
I would like to know if the eventual "trust failure" message from the server is sent before or after the server made sure that the client really own that public key (for example, by receiving first some messages from the handshake encoded with the client's private key).
The purpose of my question is to see if it is possible for a third party to check if the server trust a client, by pretending to be this client and by using his public key.
Note: The risk is real when TLS is used in a context with specific security requirements. For instance, let's suppose a P2P application which uses TLS between peers, and which use the TrustManager as a way to authenticate peers from his contact list. This contact list is supposed to be private. An ISP can list the IPs with who a node communicates, then get his public certificate by starting a TLS handshake with it, then he can try to connect each another nodes on the IP list. In the end, the ISP can get a big part of the contact list which was supposed to be private.
OpenSSL verifies the client certificate, too, immediately upon receiving it in the Client Certificate message.
But it is as Eugene says, if the server sends meaningful alerts, then it does not matter if you send bad_certificate right away or only after having verified the signature in the Certificate Verify message. This would only prevent someone from finding out whether a certificate is trusted or not if they additionally send a malformed signature (e.g. by using the wrong key). But if a server were implemented that way, all you had to do is sign your Certificate Verify message with a private key you just generated. Then the signature will be valid and the server will then dutifully validate the certificate you sent, revealing the same information as before.
To mitigate this situation you would really have to use a customized server that does not send the corresponding alert at all, but rather something less revealing.
This depends on implementation. Our implementation sends the error immediately, as for other implementations - I guess most do the same.
However it doesn't matter: the server sends specific error code (BadCertificate) if the certificate is not valid, so no matter when this code is sent, the attacker would know that the certificate has not been accepted. Protecting the server from this attack would require the server send a different error code and this would confuse legitimate clients.
The risk (or unpleasant consequences) of detecting that the certificate is accepted by the server or not is questionable. If this matters to you, you can change the error code and build your custom version of OpenSSL or other SSL server module you use.

SSL Authentication with Certificates: Should the Certificates have a hostname?

Quick Version of Question
Gmail, TD (Canadian Bank), Royal Bank (Canadian Bank) all use ssl. When you inspect their certificates they all have
Common Name (CN) mail.google.com
Or more generally:
Common Name (CN) <url>
Is this needed to prevent man in the middle attacks?
Summary
JBoss allows clients and servers to authenticate using certificates and ssl. One thing that seems strange is that you are not required to give your hostname on the certificate.
I think that this means if Server B is in your truststore, Sever B can pretend to be any server that they want.
(And likewise: if Client B is in your truststore...)
Am I missing something here?
Authentication Steps
(Summary of Wikipeida Page)
Client Server
=================================================================================================
1) Client sends Client Hello
ENCRIPTION: None
- highest TLS protocol supported
- random number
- list of cipher suites
- compression methods
2) Sever Hello
ENCRIPTION: None
- highest TLS protocol supported
- random number
- choosen cipher suite
- choosen compression method
3) Certificate Message
ENCRIPTION: None
-
4) ServerHelloDone
ENCRIPTION: None
5) Certificate Message
ENCRIPTION: None
6) ClientKeyExchange Message
ENCRIPTION: server's public key => only server can read
=> if sever can read this he must own the certificate
- may contain a PreMasterSecerate, public key or nothing (depends on cipher)
7) CertificateVerify Message
ENCRIPTION: clients private key
- purpose is to prove to the server that client owns the cert
8) BOTH CLIENT AND SERVER:
- use random numbers and PreMasterSecret to compute a common secerate
9) Finished message
- contains a has and MAC over previous handshakes
(to ensure that those unincripted messages did not get broken)
10) Finished message
- samething
Sever Knows
The client has the public key for the sent certificate (step 7)
The client's certificate is valid because either:
it has been signed by a CA (verisign)
it has been self-signed BUT it is in the server's truststore
It is not a replay attack because presumably the random number (step 1 or 2) is sent with each message
Client Knows
The server has the public key for the sent certificate (step 6 with step 8)
The server's certificate is valid
because either:
it has been signed by a CA (verisign)
it has been self-signed BUT it is in the client's truststore
It is not a replay attack because presumably the random number (step 1 or 2)
is sent with each message
Potential Problem
Suppose the client's truststore has certs in it:
Server A
Server B (malicous)
Server A has hostname www.A.com
Server B has hostname www.B.com
Suppose: The client tries to connect to Server A but Server B launches a man in the middle attack.
Since server B:
has a public key for the certificate that will be sent to the client
has a "valid certificate" (a cert in the truststore)
And since:
certificates do not have a hostname feild in them
It seems like Server B can pretend to be Server A easily.
Is there something that I am missing?
Can you point to some text that says JBoss doesn't need a hostname in the cert, or is it simply your observation? I assume by 'hostname' you mean the Common Name (CN) or Distinguished Name (DN)??
Normally an application should check an X.509 cert for:
Valid date range
Usage (eg; server auth)
Chains to a trusted root
CN == DNS name of target host (it might be another name, not just DNS)
Not revoked (using a CRL or OCSP)
Technically, an app can choose to ignore any of these and simply indicate that all is well with the cert.... but that's bad :)
I think you're missing something, but I'm not sure if I understand your reasoning.
However, when server B tries to launch a man in the middle attack, you say that it has a public key. This is true, but to setup a ssl connection, you should also have a private key belonging to that public key. Moreover, the certificate used is coupled to the dns name (in case of https). So a client tries to connect to A, he types in www.a.com. Since we assume that B does not know the private key of A, he will have another keypair. He could never receive a valid (i.e. trusted) certificate from a major CA that is coupled to a domain he does not own.
So B could never get a certificate with common name www.A.com, for this reason, B could not perform a man in the middle attack.

Resources