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:[email protected]

Reply via email to