Aaron
Did try putting code tags in, but just kept breaking... I guess could be due to the HTML tags in the include page...
I tried adding your line to the RULE_INIT block, but got the following error:
Jan 18 13:57:24 tmm err tmm[9144]: 01220001:3: TCL error: /Common/Catch_SSL_Errors - can't read "failure_result": no such variable while executing "subst [ifile get error_page_html]"
Jan 18 13:57:24 tmm err tmm[9144]: 01220006:3: RULE_INIT for rule /Common/Catch_SSL_Errors failed
However that did send me in the right direction... I've kept the error_page variable in the HTTP_REQUEST block, and have wrapped it inside a 'subst' tag on the HTTP::respond lines... E.g:
HTTP::respond 403 content [subst $error_page] "Content-Type" "text/html" "Connection" "Close"
I did try the code without the SSL::cert count, and it returns a result code of 50 - 'X509_V_ERR_APPLICATION_VERIFICATION: application verification failure'. I chose to wrap it in a count as it gives me an easy way of picking out where they don't have a client cert, as that's our typical failure method. Plus it saves some processing time I guess...
Latest copy of the rule is below...
Going back to your suggestion of putting the 'ifile get' in the RULE_INIT section, are there any advantages/disadvantages of this?
Cheers
Gav
when RULE_INIT {
Debug Logging
set static::CatchSSLErrorsDebug 1
Get the Error Page HTML
set static::error_page [ifile get error_page_html]
}
v10.1 or higher
Redirect any client HTTP request with no client certificate or with a cert which is not correctly
validated against the trusted root certificate specified in the client SSL profile.
when HTTP_REQUEST priority 10 {
if {$static::CatchSSLErrorsDebug == 1} { log local0. "CatchSSLErrors HTTP Request:" }
Return the Logo if requested.
if { [HTTP::uri] ends_with "logo-act.png" } {
if {$static::CatchSSLErrorsDebug > 0} { log local0.info "Returning Logo..." }
HTTP::respond 200 content [ifile get act_logo_png] "Content-Type" "image/png" "Connection" "Close"
event disable
return
}
Hide the SSL:: command's from the iRule parser
so the iRule can be used on a non-client SSL VS
set cipher_cmd "SSL::cipher version"
set count_cmd "SSL::cert 0"
set verify_cmd "SSL::verify_result"
set failure_cmd "X509::verify_cert_error_string"
Get the error page
set error_page [ifile get error_page_html]
Check if the client used an SSL cipher and it's not "none"
if {not ([catch {eval $cipher_cmd} result]) && $result ne "none"}{
Client did use a cipher
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL Connection initiated... Verifying client certificate." }
catch {eval $count_cmd} count_result
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL::cert returned the following output... '$count_result'" }
if {$count_result ne ""} {
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "Client cert presented. Verifying..." }
catch {eval $verify_cmd} verify_result
if { $verify_result == 0 } {
Client Cert present and verified successfully.
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL::Verify_result was OK... '$verify_result' Continuing..." }
return
} else {
Client cert verification error.
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL::Verify_result was NOT OK... '$verify_result'" }
Get failure reason
catch {eval $failure_cmd $verify_result } failure_result
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "X509::verify_cert_error_string value is... '$failure_result'" }
HTTP::respond 403 content [subst $error_page] "Content-Type" "text/html" "Connection" "Close"
event disable
return
}
} else {
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "No Client cert presented. Returning error page..." }
Return failure page. No Client cert presented...
set failure_result "No client certificate present"
HTTP::respond 403 content [subst $error_page] "Content-Type" "text/html" "Connection" "Close"
event disable
return
}
} else {
Client did not use a cipher
if {$static::CatchSSLErrorsDebug == 1} { log local0.info "Non-SSL Connection initiated... Continuing..." }
return
}
}