OCSP through an outbound explicit proxy
Hey DC community, Kevin Stewart here with a fun little project I'd like to share.
There have been countless questions about this over the years: how to pass LTM or APM OCSP requests through an out...
Published Dec 05, 2017
Version 1.0Kevin_Stewart
Employee
Joined March 16, 2006
Kevin_Stewart
Employee
Joined March 16, 2006
Piotr_Biesiada
Nov 08, 2019Nimbostratus
Hi,
small improvement about issuer object length in Application iRule
when CLIENTSSL_CLIENTCERT {
## Get the SHA1 hash of the DER-formatted issuer value
## X509 certificates are ASN.1-formatted, which is not easy to parse.
## Based on RFC5280 (https://tools.ietf.org/html/rfc5280), the issuer field is a mandatory value in the X509 certificate
## that comes directly after the signature algorithmIdentifier value. So we'll start by finding the object identifier (OID)
## of the signature algorithm, and then walk down the ASN.1 blob to the next item, which is the issuer.
if { [SSL::cert count] > 0 } {
if { [catch {
## sigAlg OID (1.2.840.113549.1.1.5) = sha1WithRSAEncryption = HEX \x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05
## sigAlg OID (1.2.840.113549.1.1.11) = sha256WithRSAEncryption = HEX \x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B
## Find the initial offset at the position of sigAlg OID in the certificate
## Here's an online tool to convert OID to Hex: https://misc.daniel-marschall.de/asn.1/oid-converter/online.php
# do not care about last byte x05 or x0B
if { [expr [set offset [string first \x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01 [SSL::cert 0]]] > 100] } {
log local0. "ERR:SigAlg-unknown"
}
## Offset this position by the size of the sigAlg
#13 bytes, size of this ASN.1 object
set newoffset [expr {$offset + 13}]
## Get the length of the issuer value - ASN.1 values start with a type and a length, so this extracts the length value.
binary scan [string range [SSL::cert 0] ${newoffset} [expr {$newoffset + 5}]] c1c1c1c1 type issuer_len_dec issuer_len_dec_ext1 issuer_len_dec_ext2
#RFC https://tools.ietf.org/html/rfc5280 p.124 issuer length could be more than 256 bytes (322 + asn1 encoding)
#c1 is signed byte, we need to & 0xFF
set issuer_len_dec [expr {$issuer_len_dec & 0xff}]
#x81
if {${issuer_len_dec} == 129 } {
set issuer_len_dec_ext1 [expr {$issuer_len_dec_ext1 & 0xff}]
set issuer_len_dec [expr {$issuer_len_dec_ext1 + 1}]
} elseif { ${issuer_len_dec} == 130 } {
#x82
set issuer_len_dec_ext1 [expr {$issuer_len_dec_ext1 & 0xff}]
set issuer_len_dec_ext2 [expr {$issuer_len_dec_ext2 & 0xff}]
set issuer_len_dec [expr { $issuer_len_dec_ext1 << 8 + $issuer_len_dec_ext2 + 2} ]
}
## SHA1-encode the DER-formatted issuer value - this is the value that will be present in an OCSP request
binary scan [sha1 [string range [SSL::cert 0] ${newoffset} [expr {${newoffset} + ${issuer_len_dec} + 1}]]] H* issuer_hash
## Store the SHA1 issuer hash:cert serial in a short-lived table with the AIA URL
set AIA [findstr [X509::extensions [SSL::cert 0]] "OCSP - URI:" 11 "\n"]
#remove : from serial
set serial [string map { ":" "" } [X509::serial_number [SSL::cert 0]]]
table set -subtable OCSP_AIA "${issuer_hash}:${serial}" "${AIA}" 300 300
} error]
} {
log local0. "error = $error"
}
}
}