You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Gordon Sim <gs...@redhat.com> on 2011/06/17 21:02:33 UTC

Re: EXTERNAL authentication and peer certificates

On 04/18/2011 05:23 PM, Gordon Sim wrote:
> On 04/14/2011 12:46 PM, Gordon Sim wrote:
>> On 04/13/2011 07:36 PM, Jakub Scholz wrote:
>>> Due to the points above, I would prefer to use a solution, when the
>>> client generates an self signed certificate with the assigned username
>>> in certificate subject and delivers the public key to me. I will check
>>> that the username in the certificate is as assigned to the client and
>>> load the public key into the certificate database as a peer (flags p
>>> or P - as they are supported by the certutil tool). Then, when the
>>> client connects, his key is verified not against the CA public key,
>>> but against the public key of his own certificate. And since the
>>> certificate is loaded as peer and not trusted CA, the client cannot
>>> use any other certificates signed by the original certificate to
>>> connect. As far as I understood from the NSS documentation, this is
>>> exactly how the peer certificates should be used. However, the broker
>>> seems to be accepting only the trusted CA certificates and ignoring
>>> the peer certificates :-(.
>>
>> Hmm, I hadn't tried that configuration before but I see what you mean.
>> The client seems happy with having the servers certificate imported as a
>> peer certificate, but not vice versa. I'll see if I can dig into this a
>> little further.
>
> NSS is apparently unable to support this. I.e. a certificate can't be
> marked trusted for SSL client authentication, only for server client
> authentication or as a CA (or for email or code signing outside of SSL).

Good news and bad news on this. Bad news is that I was wrong :-(

However the good news is that I believe it *does* works as you want! Not 
sure what I did wrong the first time, but I have it working now.

Here is what I did (from a Qpid cpp build directory):

(1) create and initialise a certificate database for both client and server:

mkdir server_db client_db
certutil -N -d client_db/
certutil -N -d server_db/

(2) create self signed certificates for client and server:

certutil -S -n my-user -s "CN=my-user" -x -t "P,," -d client_db -f 
password.file
certutil -S -n localhost -s "CN=localhost" -x -t "P,," -d server_db -f 
password.file

(3) import public part of server certificate as trusted peer into 
client's certificate database:

certutil -L -n localhost -d server_db/ -a -o server_db/localhost.crt
certutil -A -n localhost -d client_db/ -i server_db/localhost.crt -t 'P,,'

(4) import public part of client certificate as trusted peer into 
server's certificate database:

certutil -L -n my-user -d client_db/ -a -o client_db/my-user.crt
certutil -A -n my-user -d server_db/ -i client_db/my-user.crt -t 'P,,'

(5) if there is no CA trusted certificate in the servers database you 
get an error -12199: "No certificate authority is trusted for SSL client 
authentication.". We can workaround that by importing a dummy CA and 
destroying the private key so it can never be used.

mkdir dummy_ca_db
certutil -N -d dummy_ca_db/ -f password.file
certutil -S -n dummy -s "CN=dummy" -x -t "T,," -d dummy_ca_db/ -f 
password.file
certutil -L -n dummy -d dummy_ca_db/ -a -o server_db/dummy-ca.crt
certutil -A -n dummy -d server_db/ -i server_db/dummy-ca.crt -t 'T,,'
rm -rf dummy_ca_db/

(6) You can list the contents of each certificate directory:

For certutil -L -d client_db I see:

my-user                                                      Pu,u,u
localhost                                                    P,,

For certutil -L -d server_db I see:

localhost                                                    Pu,u,u
my-user                                                      P,,
dummy                                                        T,,

(7) Now we can start qpidd using the server certificate database:

./src/qpidd --load-module ./src/.libs/ssl.so --ssl-cert-db 
$(pwd)/server_db --ssl-cert-password-file password.file --ssl-cert-name 
localhost --ssl-require-client-authentication --ssl-sasl-no-dict 
--log-enable info+ --log-enable trace+:amqp_0_10

(8) and we can run a client test program that will be authenticated 
using SSL:

export QPID_LOAD_MODULE=$(pwd)/src/.libs/sslconnector.so
export QPID_SSL_CERT_DB=$(pwd)/client_db/
export QPID_SSL_CERT_NAME=my-user
export QPID_SSL_CERT_PASSWORD_FILE=$(pwd)/password.file

./src/tests/qpid-perftest --count 10 --port 5671 --protocol ssl --broker 
localhost

In the broker logs if you used the same settings as me you'll then see:

2011-06-17 19:52:38 trace RECV [127.0.0.1:5671-127.0.0.1:40844]: 
Frame[BEbe; channel=0; {ConnectionStartOkBody: 
client-properties={qpid.client_pid:F4:int32(26212),qpid.client_ppid:F4:int32(25501),qpid.client_process:V2:15:str16(lt-qpid-perftes),qpid.session_flow:F4:int32(1)}; 
mechanism=EXTERNAL; response=xxxxxx; locale=en_US; }]
2011-06-17 19:52:38 info 127.0.0.1:5671-127.0.0.1:40844 SASL: 
Authentication succeeded for: my-user@QPID

Validating that EXTERNAL was used and the identity has been taken from 
the clients certificate.

Does this work for you?

I hope this clears things up a little. Many apologies for the 
misinformation earlier. I'm not entirely sure how I managed to get the 
same error as you reported. One possibility is that I forgot to set the 
QPID_SSL_CERT_NAME for the client - that certainly gives the error code 
reported.



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscribe@qpid.apache.org


Re: EXTERNAL authentication and peer certificates

Posted by Jakub Scholz <ja...@scholz.cz>.
Hi Gordon,

Thanks for the time you are spending on this issue. I tried it and it
really seems to work. The problem seems to be caused by the Java API,
which I and my colleagues were probably using to check whether the
"Trusted Peer" certificates works or not.

When running the Java program with the SSL debug, the Java client
seems to receive a list of all trusted CA from the broker. And if he
doesn't find the username of the certificate it has in the keystore on
the list it received (which it doesn't unless it is loaded as a CA),
then it doesn't continue. so it seems to be an Java related issue
only. An workaround which seems to help with this issue is creating an
CA certificate with the same username, loading it into the certificate
database and deleting the private key (similarly as described by you
in step 5). Then the username appears in the list and the Java API can
use the Trusted Peer certificate to connect.

The C++ and Python API don't seem to be working with the list of
trusted CA from the broker and are able to log in even without the CA
certificate. I didn't checked the .NET API yet.

Thanks & Regards
Jakub

On Fri, Jun 17, 2011 at 21:02, Gordon Sim <gs...@redhat.com> wrote:
> On 04/18/2011 05:23 PM, Gordon Sim wrote:
>>
>> On 04/14/2011 12:46 PM, Gordon Sim wrote:
>>>
>>> On 04/13/2011 07:36 PM, Jakub Scholz wrote:
>>>>
>>>> Due to the points above, I would prefer to use a solution, when the
>>>> client generates an self signed certificate with the assigned username
>>>> in certificate subject and delivers the public key to me. I will check
>>>> that the username in the certificate is as assigned to the client and
>>>> load the public key into the certificate database as a peer (flags p
>>>> or P - as they are supported by the certutil tool). Then, when the
>>>> client connects, his key is verified not against the CA public key,
>>>> but against the public key of his own certificate. And since the
>>>> certificate is loaded as peer and not trusted CA, the client cannot
>>>> use any other certificates signed by the original certificate to
>>>> connect. As far as I understood from the NSS documentation, this is
>>>> exactly how the peer certificates should be used. However, the broker
>>>> seems to be accepting only the trusted CA certificates and ignoring
>>>> the peer certificates :-(.
>>>
>>> Hmm, I hadn't tried that configuration before but I see what you mean.
>>> The client seems happy with having the servers certificate imported as a
>>> peer certificate, but not vice versa. I'll see if I can dig into this a
>>> little further.
>>
>> NSS is apparently unable to support this. I.e. a certificate can't be
>> marked trusted for SSL client authentication, only for server client
>> authentication or as a CA (or for email or code signing outside of SSL).
>
> Good news and bad news on this. Bad news is that I was wrong :-(
>
> However the good news is that I believe it *does* works as you want! Not
> sure what I did wrong the first time, but I have it working now.
>
> Here is what I did (from a Qpid cpp build directory):
>
> (1) create and initialise a certificate database for both client and server:
>
> mkdir server_db client_db
> certutil -N -d client_db/
> certutil -N -d server_db/
>
> (2) create self signed certificates for client and server:
>
> certutil -S -n my-user -s "CN=my-user" -x -t "P,," -d client_db -f
> password.file
> certutil -S -n localhost -s "CN=localhost" -x -t "P,," -d server_db -f
> password.file
>
> (3) import public part of server certificate as trusted peer into client's
> certificate database:
>
> certutil -L -n localhost -d server_db/ -a -o server_db/localhost.crt
> certutil -A -n localhost -d client_db/ -i server_db/localhost.crt -t 'P,,'
>
> (4) import public part of client certificate as trusted peer into server's
> certificate database:
>
> certutil -L -n my-user -d client_db/ -a -o client_db/my-user.crt
> certutil -A -n my-user -d server_db/ -i client_db/my-user.crt -t 'P,,'
>
> (5) if there is no CA trusted certificate in the servers database you get an
> error -12199: "No certificate authority is trusted for SSL client
> authentication.". We can workaround that by importing a dummy CA and
> destroying the private key so it can never be used.
>
> mkdir dummy_ca_db
> certutil -N -d dummy_ca_db/ -f password.file
> certutil -S -n dummy -s "CN=dummy" -x -t "T,," -d dummy_ca_db/ -f
> password.file
> certutil -L -n dummy -d dummy_ca_db/ -a -o server_db/dummy-ca.crt
> certutil -A -n dummy -d server_db/ -i server_db/dummy-ca.crt -t 'T,,'
> rm -rf dummy_ca_db/
>
> (6) You can list the contents of each certificate directory:
>
> For certutil -L -d client_db I see:
>
> my-user                                                      Pu,u,u
> localhost                                                    P,,
>
> For certutil -L -d server_db I see:
>
> localhost                                                    Pu,u,u
> my-user                                                      P,,
> dummy                                                        T,,
>
> (7) Now we can start qpidd using the server certificate database:
>
> ./src/qpidd --load-module ./src/.libs/ssl.so --ssl-cert-db $(pwd)/server_db
> --ssl-cert-password-file password.file --ssl-cert-name localhost
> --ssl-require-client-authentication --ssl-sasl-no-dict --log-enable info+
> --log-enable trace+:amqp_0_10
>
> (8) and we can run a client test program that will be authenticated using
> SSL:
>
> export QPID_LOAD_MODULE=$(pwd)/src/.libs/sslconnector.so
> export QPID_SSL_CERT_DB=$(pwd)/client_db/
> export QPID_SSL_CERT_NAME=my-user
> export QPID_SSL_CERT_PASSWORD_FILE=$(pwd)/password.file
>
> ./src/tests/qpid-perftest --count 10 --port 5671 --protocol ssl --broker
> localhost
>
> In the broker logs if you used the same settings as me you'll then see:
>
> 2011-06-17 19:52:38 trace RECV [127.0.0.1:5671-127.0.0.1:40844]: Frame[BEbe;
> channel=0; {ConnectionStartOkBody:
> client-properties={qpid.client_pid:F4:int32(26212),qpid.client_ppid:F4:int32(25501),qpid.client_process:V2:15:str16(lt-qpid-perftes),qpid.session_flow:F4:int32(1)};
> mechanism=EXTERNAL; response=xxxxxx; locale=en_US; }]
> 2011-06-17 19:52:38 info 127.0.0.1:5671-127.0.0.1:40844 SASL: Authentication
> succeeded for: my-user@QPID
>
> Validating that EXTERNAL was used and the identity has been taken from the
> clients certificate.
>
> Does this work for you?
>
> I hope this clears things up a little. Many apologies for the misinformation
> earlier. I'm not entirely sure how I managed to get the same error as you
> reported. One possibility is that I forgot to set the QPID_SSL_CERT_NAME for
> the client - that certainly gives the error code reported.
>
>
>
> ---------------------------------------------------------------------
> Apache Qpid - AMQP Messaging Implementation
> Project:      http://qpid.apache.org
> Use/Interact: mailto:users-subscribe@qpid.apache.org
>
>

---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscribe@qpid.apache.org