Closed Bug 421724 Opened 16 years ago Closed 16 years ago

client x509 certificate with "SSLVerifyClient optional_no_ca" in Apache - second access after 15 seconds produces SSL renegotiate error/blank page

Categories

(NSS :: Libraries, defect)

3.11.9
x86
All
defect
Not set
major

Tracking

(Not tracked)

RESOLVED INVALID

People

(Reporter: petr.bug, Unassigned)

References

()

Details

(Keywords: conversion, dataloss)

Attachments

(4 files)

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12

If Firefox provides personal certificate to Apache site with "SSLVerifyClient optional_no_ca" TLS option and re-visits the page after >15 seconds then Firefox fails to establish TLS connection and displays empty page. UI reports no error, sniffer sees encrypted TLS alert from client.
Everything is fine if user keeps refreshing within <15 seconds.


Reproducible: Always

Steps to Reproduce:
1. Install Apache, setup HTTPS functionality. Tested on apache-2.2.3.

2. Open https://localhost/. Firefox will ask about unknown server certificate.

3. Choose Remember forever. (Actually not needed). A https page appears.

4. Edit Apache's .htaccess and add "SSLVerifyClient optional_no_ca" option. Reload Apache.

5. Create user certificate, for example by commands
$ openssl genrsa 1024 > ks.pem
$ openssl req -x509 -new -key ks.pem >> ks.pem
$ openssl pkcs12 -export -in ks.pem -inkey ks.pem -out ks.p12 

6. Import the certificate to Firefox: Preferences, Advanced, Security, Certificates, Personal, Import

7. Open the https:// page again. Firefox ask whether to supply the user certificate. Press OK. The page will appear.

8. Wait <15 seconds and hit Reload. The page will reload normally. Repeat if you like.

9. Wait >15 seconds and hit Reload.


Actual Results:  
Firefox will display blank page (no HTML), script at server was not executed.
Network sniffer captured this TLS communication:
1) Firefox: Client Hello,
2) Apache: Server Hello, Change Cipher Spec, Encrypted Handshake Message

3) Firefox: Change Cipher Spec, Encrypted Handshake Message, Application Data
4) Firefox: Encrypted Alert
5) Firefox: closes TCP connection


Expected Results:  
Firefox should
a) reload the page or
b) ask user if to provide the user certificate again and then reload the page.



After step 9 wait 2-5 minutes for Firefox to recover. Otherwise any attempt to reload will produce blank page again. (I was not able to figure out the exact timing.)



Opera and Internet Explorer behave as expected.

Apache documentation (http://httpd.apache.org/docs/2.0/mod/mod_ssl.html#sslverifyclient) says "SSLVerifyClient optional_no_ca" is not interesting option. However it still should work as it is needed when decision about allowing particular client (authorisation) is done by application script while server's TLS layer does only authentication.
Assignee: nobody → kengert
Component: Password Manager → Security: PSM
Product: Firefox → Core
QA Contact: password.manager → psm
Added sample personal certificate with private key (use empty passphrase on import) using the recipe in bug report that demonstrates the issue.

The bug can be also reproduced on https://artax.karlin.mff.cuni.cz/~hluzp1am/ssl-cert-test/ - the server settings were applied.

Also reproducible on Firefox (Swiftfox) 3.0b5pre.
This bug is also breaking submitting a web form when a user certificate is requested in apache in a directory context.   The server reports a 403 error with 0 bytes transferred, and in the error log claims that a renegotiate was rejected by the client...

If you post the form quickly enough (<15 seconds), it works.
So we've implemented a workaround for this; we put a little page up which refreshes every 10 seconds with a Refresh: tag, and we put an iframe that
points to that page on the web form.  Now the page works, even if the user takes between 15 seconds and 5 minutes to submit the form.

Please fix this so we can get rid of this ad-hockery.
Just a few more details on how this looks on the server side.  Apache logs in access_log:
bel-kwinith.dhcp.fnal.gov 131.225.82.108 - [04/Sep/2008:11:16:30 -0500] "POST /c
gi-bin/remedy/Helpdesk.pl HTTP/1.1" 403 - "https://computing.fnal.gov/cgi-bin/re
medy/Helpdesk.pl" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008052
912 Firefox/3.0" computing.fnal.gov
bel-kwinith.dhcp.fnal.gov 131.225.82.108 - [04/Sep/2008:11:16:37 -0500] "POST /c
gi-bin/remedy/Helpdesk.pl HTTP/1.1" 403 - "https://computing.fnal.gov/cgi-bin/re
medy/Helpdesk.pl" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008052
912 Firefox/3.0" computing.fnal.gov
bel-kwinith.dhcp.fnal.gov 131.225.82.108 - [04/Sep/2008:11:16:47 -0500] "GET /cg
i-bin/remedy/Helpdesk.pl HTTP/1.1" 200 56083 "-" "Mozilla/5.0 (X11; U; Linux i68
6; en-US; rv:1.9) Gecko/2008052912 Firefox/3.0" computing.fnal.gov

Note the POST response "403 -" -- error code 403 and nothing transfered.

Simultaneously in error_log:
[Thu Sep 04 11:16:30 2008] [error] Re-negotiation handshake failed: Not accepted
 by client!?
[Thu Sep 04 11:16:37 2008] [error] Re-negotiation handshake failed: Not accepted
 by client!?

We've worked around it using the following Perl cgi-script:
-----------------------
#!/usr/bin/env perl

print <<EOF
Refresh: 10;https://computing.fnal.gov/cgi-bin/remedy/refresh.pl
Content-type: text/html
Conent-length: 37

<html>
<body>
&nbsp;
</body>
</html>
EOF

----------------------

Which refreshes every 10 seconds; you put 

<iframe src="/cgi-bin/remedy/refresh.pl" width="1" height="1" frameborder="0"></iframe>

in your forms to to keep the ssl connection active and avoid the errors.
Just to comply to the letter of the FAQ: I have confirmed this bug on:

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008070206 Firefox/3.0.1

on:
 * Scientific Linux Fermi LTS release 4.2 (Wilson)
 * Scientific Linux SLF release 5.0 (Lederman)
This should have keywords "conversion" and possibly "dataloss", as it makes Firefox quite broken for folks using x509 certificate authentication, and it tends to trigger when people filled out a medium sized form, without giving a clear indication that anything is wrong.
Hello,

It would be very helpful if someone could fix this bug. Without it, I am unable to
fill out a web form. No error is generated when I connect to the particular
web form with a kca using x509 certificate authentication.  thanks
Severity: normal → major
Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: conversion, dataloss
Summary: personal certificate with "SSLVerifyClient optional_no_ca" in Apache - reload after 15 seconds produces blank page → client x509 certificate with "SSLVerifyClient optional_no_ca" in Apache - second access after 15 seconds produces SSL renegotiate error/blank page
NSS team: Is this a bug at the SSL/TLS handshake or session cache level?
Assignee: kaie → nobody
Component: Security: PSM → Libraries
Product: Core → NSS
QA Contact: psm → libraries
Version: unspecified → 3.11.9
I'm not convinced there's any NSS bug here at all.  Until there is hard 
evidence to the contrary, the NSS team will not presume that this is 
an NSS bug.  There is surely a bug somewhere, but the assumption that it 
is in NSS is not yet supported by evidence.

Steps to reproduce that say "setup your own apache server" or 
"run openssl" get ignored by the NSS team.  

Try using ssltap to capture one or more SSL connections that exhibit
this behavior.  google for ssltap.
(In reply to comment #10)
> Steps to reproduce that say "setup your own apache server" or 
> "run openssl" get ignored by the NSS team.  

Nelson, what's wrong with that exactly? I'm sure Kai and others do run Apache servers for testing. Apache still commands a majority share of all web servers used at the Internet, I think it appropriate to look into problems users are facing in conjunction with Apache and Mozilla products, EVEN if the problem proves in the end not to be that of NSS. This specially when they are trying to implement client certificate authentication - something you certainly support.
(In reply to comment #10)
> Try using ssltap to capture one or more SSL connections that exhibit
> this behavior.  google for ssltap.

I have read ssltap's documentation on [1] but I do not see how to instruct ssltap to send browser any SSL options. I expect ssltap is not useful for this bug.

I can provide you with network traffic dump from Wireshark. This will show what SSL/TLS parameters does Apache's "SSLVerifyClient" affect and perhaps allow other way to reproduce the bug.
Or I can record packet captures with "SSLVerifyClient optional_no_ca" (which does produce the bug) and with "SSLVerifyClient optional" (which does not) and report their differences on protocol level if you want.

(I have ssltap from package libnss3-tools-3.11.5-3 (Debian).)
[1] http://www.mozilla.org/projects/security/pki/nss/tools/ssltap.html
I don't want any wireshark output.  ssltap is just what you need.
Petr, Wireshark output will not help us, because that will be encrypted/unreadable bytes.

I guess we need a high level explanation of what ssltap is and does, maybe as part of an FAQ section on a NSS wiki page somewhere.


Say you usually connect
  browser -> server

You can use ssltap to setup this chain:

  browser -> ssltap-server-process -> server

You configure ssltap to listen on a port, you configure ssltap to connect to your destination server. You instruct the browser to connect to the ip address (often localhost) and port number where your ssltap process is listening.

You could run ssltap on the server, then you'll avoid hostname-mismatch errors.

You can run ssltap locally, but then you have to use an override/exception in the browser to allow the mismatch.

When you do all of the above, you can use ssltap to produce a log file. There is an option to do SSL protocol decoding, you should use it.

The resulting log file will display the protocol conversation between server and client in human readable form.
Just a note, AFAIK (I have never tried my self) Wireshark can be configured with the server private key and you can see the traffic decrypted. In this situation I presume you have access to that key?
http://wiki.wireshark.org/SSL, chapter "RSA keys list"
(In reply to comment #10)
The "run openssl" shows how _I_ did reproduce the bug. Anyone can create self-signed key in way they like but some other way may not reproduce the bug.

(In reply to comment #14)
> Petr, Wireshark output will not help us, because that will be
> encrypted/unreadable bytes.

You are right. I forgot Apache's SSLVerifyClient takes effect when encryption is already established.

> ...
> You can use ssltap to setup this chain:
>   browser -> ssltap-server-process -> server
> ...

I figured this out. However since connection to Apache does not use SSL, the SSLVerifyClient on Apache does have effect. Unless there is a way to mimic Apache's SSLVerifyClient option using ssltap I can not reproduce this using ssltap. Summary: We need more powerful tool.

I remind that this bug lists URL where you can experience the bug yourself and try your own tools.

I have tested only self-signed certificates (I do not know how to create CA signed - too lazy to learn).

(In reply to comment #15)
Unfortunately I do not have operational web server of my own in these days. It would take a while to create one since I do not know how to use openssl. (I'll be grateful for link to click-and-forget wrapper.)
(In reply to comment #17)
-...the SSLVerifyClient on Apache does have effect.
+...the SSLVerifyClient on Apache does not have effect.
Typo, sorry.
Petr, you can find the ssltap manual page at
http://www.mozilla.org/projects/security/pki/nss/tools/ssltap.html
In reply to comment 17
> However since connection to Apache does not use SSL, 
I think you believe that the connection from SSLTAP to the apache server
would not use SSL.  That belief is mistaken.  Please try it.
(In reply to comment #20)
> In reply to comment 17
> > However since connection to Apache does not use SSL, 
> I think you believe that the connection from SSLTAP to the apache server
> would not use SSL.  That belief is mistaken.  Please try it.

Yes, that is what I really thought. Ok, I will try it.

However Firefox keeps displaying
"localhost has sent invalid or illegal message. Error code: -12263" (just a rough translation).

I will look at that matter tomorrow.
ssltap documentation: I found what led me into believing ssltap's outgoing connections can not be encrypted. Attached patch tries to remove the confusion.
Attachment #341828 - Attachment mime type: text/x-log → text/plain
Attachment #341829 - Attachment mime type: text/x-log → text/plain
A side-by-side comparison of the two attached ssltap outputs plains shows
what's going on.  Here is a high level summary of each of them.

Success:

- Client and server do a handshake
- client sends http request to server
- server requests another handhshake (a renegotiation)
- client and server do a second handshake, in which the server requests
  client authentication and the client authenticates with a certificate
- server sends big long response to client's original https request

Failure:

- Client and server do a handshake, a "restart" handshake in which the 
  client requests that they resume the previously authenticated session.
  The server agrees, and completes the restart handshake.
- client sends http request to server
- Server immediately drops the connection, without a proper SSL close_notify.

In short: This is a server bug.  In comment 2, you wrote that:
> the error log claims that a renegotiate was rejected by the client...
but the ssltap output shows clearly that no renegotiate request was 
sent by the server.  The client did not reject a renegotiate request,
because no renegotiate request was sent.  

No client bug is shown in these outputs.  This is not a client bug.
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: