I got it working !
Here is my solution. Questions 1 & 4 still
remain.
The additional module (ssl_error) also works, although I
need to fine-tune it.
Feel free to criticize and enhance.
Marc
-------------------
In 'ssl_hook_Access( )' (ssl_engine_kernel.c), the last line
can be replaced by:
{ /* MSTERN: SSL errors
trapping */
const char
*ssl_client_verify = ssl_var_lookup( r->pool, r->server, r->connection,
r, apr_pstrdup(r->pool, "SSL_CLIENT_VERIFY")
);
if ( ! ssl_client_verify )
{
ap_log_error(APLOG_MARK, APLOG_NOERRNO |
APLOG_DEBUG, 0, r->server, "Unable to get SSL Verification
STATUS");
return HTTP_INTERNAL_SERVER_ERROR;
/* cannot find ssl_var_lookup( ) */
}
if ( ! *ssl_client_verify ) return HTTP_INTERNAL_SERVER_ERROR; /* not in a SSL
session */
if ( strcmp(ssl_client_verify, "NONE") == 0 ) return HTTP_INTERNAL_SERVER_ERROR;
/* SSL negociation not finished */
ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r->server,
"Certificate Verification Status: %s",
ssl_client_verify);
if ( strcmp(ssl_client_verify,
"SUCCESS") == 0 ) return DECLINED;
if (
strncmp(ssl_client_verify, "GENEROUS", 8) == 0 ) return
DECLINED;
}
apr_table_setn(r->notes, "ssl-access-forbidden", "1");
{ /* Check if
mod_ssl_error is loaded */
extern
AP_DECLARE_DATA module
*ap_top_module;
module
*m;
for ( m = ap_top_module; m; m
= m->next
)
if (
strcmp(m->name, "mod_ssl_error.c") == 0 ) return
DECLINED;
}
return
HTTP_FORBIDDEN;
----- Original Message -----
Sent: Friday, April 29, 2005 12:26
PM
Subject: SSL error trapping
In case a SSL connection fails because a certificate is
expired, or a CRL is unavailable, etc., the browser receives a SSL error that
results in a cryptic technical error displayed to the user - sometimes only an
error number like in Firefox. In such a situation, the SSL connection could be
established, and a HTTP_FORBIDDEN (403) error returned. By adding another
module, It is even possible to trap the exact SSL error and redirect to a page
with the specific error message ("Your certificate is expired", "We cannot
check the validity of the certificate - retry later", ..).
I plan to add all of this, but I'd like to check with
everybody the best design and implementation.
Technical description (based on
2.0.54):
In ssl_io_filter_connect( (ssl_engine_io.c), we have 2 cases
(at line 1147 and 1173) where the connection may break because of certificates
verification/validation problem: ' return
ssl_filter_io_shutdown(filter_ctx, c, 1); '
If we do
not return, we can trap the error in 'ssl_hook_Access( )'
(ssl_engine_kernel.c).
At the end, instead of returning DECLINED, we have
to check the certification verification result, then return either DECLINED or
HTTP_FORBIDDEN.
This is quite generic; then we may use another module to
make redirections depending on the exact error.
Questions and choices:
1. Could this be accepted as a standard feature (thus for
everybody), or should I use
- a compilation flag
- a run-time directive
2. Does the other module trapping the 'hook_access' receive the control
in case of the previous module returns a HTTP_FORBIDDEN error ?
If not, we could detect at run-time that the trapping module is loaded
(how exactly ?), and, in this case, return DECLINED.
3. To check the certification verification
process, I can use the string "SSL_CLIENT_VERIFY", but isn't there any real
error code (int) available ? It would be cleaner to use the exact OpenSSL
error codes than a string. I cannot find this code, even inside
'ssl_hook_Access( )' in ssl_engine_kernel.c. Awk
...
4. Should this trapping be extended to other non fatal SSL
errors ? Is it also possible to trap fatal errors and redirect to HTTP
?
If you have other remarks or ideas, please tell
me.
Marc