30-Oct-2020
13:12
- last edited on
04-Jun-2023
21:12
by
JimmyPackets
I have an IRule below that I'm working on. My intent is to enforce client certificate authentication on two URI's only and if any client certificate errors should result in a redirect to a custom error page. The VS has a SSL profile set to 'ignore' client certificates. This rule successfully processes the first two 'If' statements. The problem is that the custom error page is not displayed. Any help would be appreciated.
when HTTP_REQUEST {
if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
return
} else {
if { ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
SSL::session invalidate
SSL::authenticate always
SSL::authenticate depth 9
SSL::cert mode require
set cmd "SSL::profile /Common/require_clientssl"
eval $cmd
SSL::renegotiate
} else {
if {[SSL::verify_result] == 0 }{
return
} else {
HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache
}
}
}
}
I have another rule that meets two of the three requirements. With the VS SSL profile set to 'request' client certs. This rule does provide a custom error page when Cert errors occur on the two named URI's. But it also results in a certificate prompt for users who access other URI's due to the default SSL profile setting.
when HTTP_REQUEST {
if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
return
} else {
if {[SSL::verify_result] == 0 }{
return
} else {
HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache
}
}
}
Solved! Go to Solution.
01-Nov-2020
13:48
- last edited on
04-Jun-2023
21:12
by
JimmyPackets
Your HTTP::respond 302 is in the else clause of your second if statement.
It is never reached.
when HTTP_REQUEST {
if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
# This path has no client-authentication
return
} else {
# perform client-authentication if the uri matches
if { ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
SSL::session invalidate
SSL::authenticate always
SSL::authenticate depth 9
SSL::cert mode require
set cmd "SSL::profile /Common/require_clientssl"
eval $cmd
SSL::renegotiate
} else {
# we cannot execute this path because of the first *if* statement
if {[SSL::verify_result] == 0 }{
return
} else {
HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache
}
}
}
}
Try something like
when HTTP_REQUEST {
if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
# we don't need to renegotiate with client-authentication
return
} else {
# we do need to renegotiate with client-authentication
SSL::session invalidate
SSL::authenticate always
SSL::authenticate depth 9
SSL::cert mode require
set cmd "SSL::profile /Common/require_clientssl"
eval $cmd
SSL::renegotiate
# check if renegotiation with client-auth succeeded
if {[SSL::verify_result] == 0 }{
return
} else {
HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache
}
}
}
but I haven't tested this to check ...
01-Nov-2020
13:48
- last edited on
04-Jun-2023
21:12
by
JimmyPackets
Your HTTP::respond 302 is in the else clause of your second if statement.
It is never reached.
when HTTP_REQUEST {
if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
# This path has no client-authentication
return
} else {
# perform client-authentication if the uri matches
if { ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
SSL::session invalidate
SSL::authenticate always
SSL::authenticate depth 9
SSL::cert mode require
set cmd "SSL::profile /Common/require_clientssl"
eval $cmd
SSL::renegotiate
} else {
# we cannot execute this path because of the first *if* statement
if {[SSL::verify_result] == 0 }{
return
} else {
HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache
}
}
}
}
Try something like
when HTTP_REQUEST {
if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} {
# we don't need to renegotiate with client-authentication
return
} else {
# we do need to renegotiate with client-authentication
SSL::session invalidate
SSL::authenticate always
SSL::authenticate depth 9
SSL::cert mode require
set cmd "SSL::profile /Common/require_clientssl"
eval $cmd
SSL::renegotiate
# check if renegotiation with client-auth succeeded
if {[SSL::verify_result] == 0 }{
return
} else {
HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache
}
}
}
but I haven't tested this to check ...
02-Nov-2020 09:23
Thank you that was it! I also had to change the cert mode to 'request'.