haproxy (v0.61_9) generates a PHP error when a HAProxy Frontend is set to use a SSL Offloading Certificate that has multiple Common Names
-
The issue is for isolated cases and happens only when an SSL Offloading Certificate with multiple Common Names is set as part of an HAProxy Frontend.
How to reproduce?
Step1:
Generate a certificate that has multiple Common Names as part of the Certificate Subject.
Certificate Subject:- CN = mailedc.domain.zz
- CN = edcexch01.domain.zz
- CN = edcexch02.domain.zz
- CN = edcexch03.domain.zz
- CN = edcexch04.domain.zz
- OU = IT
- O = ORG
- L = Munich
- ST = Bavaria
- C = DE
Certificate Subject Alternative Name:
- DNS Name: mailedc.domain.zz
- DNS Name: edcexch01.domain.zz
- DNS Name: edcexch02.domain.zz
- DNS Name: edcexch03.domain.zz
- DNS Name: edcexch04.domain.zz
Step2:
Import the certificate in pfSense.Step3:
Define an HAProxy Frontend, and configure it to perform SSL Offloading. In the SSL Offloading section, select the certificate with multiple Common Names. Save.Step4:
Once you will be redirected to the /haproxy/haproxy_listeners.php page, an error will be shown for the newly created HAProxy Frontend.Step5:
Press the Apply Changes button. -> PHP Error will be thrown.How to rollback?
From the UI is impossible to revert the changes by re-editing the HAProxy Frontend entry. The only option is to restore via Config History.PHP error thrown
Fatal error: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, array given in /usr/local/pkg/haproxy/haproxy.inc:2722
Stack trace:
#0 /usr/local/pkg/haproxy/haproxy.inc(2722): substr(Array, 0, 2)
#1 /usr/local/pkg/haproxy/haproxy.inc(2769): haproxy_get_cert_acls(NULL)
#2 /usr/local/pkg/haproxy/haproxy.inc(1898): get_frontend_acls(Array)
#3 /usr/local/pkg/haproxy/haproxy.inc(1284): haproxy_writeconf('/var/etc/haprox...')
#4 /usr/local/www/haproxy/haproxy_listeners.php(97): haproxy_check_and_run(NULL, true)
#5 {main} thrown in /usr/local/pkg/haproxy/haproxy.inc on line 2722 PHP ERROR: Type: 1, File: /usr/local/pkg/haproxy/haproxy.inc, Line: 2722, Message: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, array given in /usr/local/pkg/haproxy/haproxy.inc:2722 Stack trace: #0 /usr/local/pkg/haproxy/haproxy.inc(2722): substr(Array, 0, 2) #1 /usr/local/pkg/haproxy/haproxy.inc(2769): haproxy_get_cert_acls(NULL) #2 /usr/local/pkg/haproxy/haproxy.inc(1898): get_frontend_acls(Array) #3 /usr/local/pkg/haproxy/haproxy.inc(1284): haproxy_writeconf('/var/etc/haprox...') #4 /usr/local/www/haproxy/haproxy_listeners.php(97): haproxy_check_and_run(NULL, true) #5 {main} thrownHow to fix?
Edit the /usr/local/pkg/haproxy/haproxy.inc file, line 2722, with PHP code that is handling certificates that have multiple Common Names.Example of code that is fixing the issue:
Replace line 2722 (the one with $is_wildcard = substr($cn_from_cert, 0, 2) == ".";*)
with:if(is_array($cert_cn)) { foreach($cert_cn as $cn_from_cert) { $is_wildcard = substr($cn_from_cert, 0, 2) == "*."; } } else { $is_wildcard = substr($cert_cn, 0, 2) == "*."; }
Crash reporter
14.0-CURRENT
FreeBSD 14.0-CURRENT #0 plus-RELENG_23_01-n256037-6e914874a5e: Fri Feb 10 20:30:29 UTC 2023 root@freebsd:/var/jenkins/workspace/pfSense-Plus-snapshots-23_01-main/obj/amd64/VDZvZksF/var/jenkins/workspace/pfSense-Plus-snapshots-23_01-main/sources/FreeBSCrash report details:
PHP Errors:
[11-Apr-2023 23:46:10 Europe/Berlin] PHP Fatal error: Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, array given in /usr/local/pkg/haproxy/haproxy.inc:2722
Stack trace:
#0 /usr/local/pkg/haproxy/haproxy.inc(2722): substr(Array, 0, 2)
#1 /usr/local/pkg/haproxy/haproxy.inc(2769): haproxy_get_cert_acls(NULL)
#2 /usr/local/www/haproxy/haproxy_listeners.php(332): get_frontend_acls(Array)
#3 {main}
thrown in /usr/local/pkg/haproxy/haproxy.inc on line 2722No FreeBSD crash data found.
-
@iftvio why/how are you creating a cert with multiple CN, that is borked out of the gate.. That is not a valid config.
A cert can contain 1 CN, be it a nonwildcard or wildcard.. If you want to add other fqdn to a cert that would be done via SAN, not CN.
So your issue is completely self inflicted and a non issue for people that don't shoot themselves in the foot and then find ways to fix it..
-
@johnpoz yeah Iām not sure how the cert even got created with multiple CNs.
More curious about that but everything you said is spot on. Leverage SAN entries for this -
@johnpoz said in haproxy (v0.61_9) generates a PHP error when a HAProxy Frontend is set to use a SSL Offloading Certificate that has multiple Common Names:
@iftvio why/how are you creating a cert with multiple CN, that is borked out of the gate.. That is not a valid config.
A cert can contain 1 CN.
I tend to disagree with you here. There is no rule regarding the number of CNs as part of a certificate. I haven't found any IEEE standard or RFC to enforce the "one CN" rule.
Let's have a look here -> https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6)Anyway, such kind of certificate is a valid certificate. You can generate it with an internal Certificate Authority solution. The today's internet browsers handle it without a problem.
The fact that this kind of certificate is not common is indeed a true aspect.
Before the common use of the Subject Alternative Names, some software solutions (currently legacy solutions) that were distributed across multiple hosts, used Common Names for validation (not the SAN). To make myself clear, we are talking about some legacy solutions.Indeed, such certificates are not today's norm today, but since the Certificate related standards don't impose the existence of a single Common Name as part of the Subject Name, please take into consideration that the code part of the HAProxy Package is not handling correctly such kind of certificates.
-
@iftvio CN is depreciated anyway rfc 2818 - again have no idea where you got such a cert or what CA would actually sign it or how you even requested via a CSR... CN has always been 1 name not multiple, where does is say you can have multiple CN values?
That pfsense told you you shot yourself in the foot with some borked up cert.. That cert is not a good cert to use..
-
@johnpoz said in haproxy (v0.61_9) generates a PHP error when a HAProxy Frontend is set to use a SSL Offloading Certificate that has multiple Common Names:
@iftvio CN is depreciated anyway rfc 2818 - again have no idea where you got such a cert or what CA would actually sign it or how you even requested via a CSR...
Let's read together and apply common sense of what is written in RFC 2818.
- "If a subjectAltName extension of type dNSName is present, that MUST be used as the identity."
Therefore, if a certificate has SAN defined, the software solutions that perform certificate validation MUST use SAN over any other identity definition. - "Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used."
So, if SAN is not defined, the next entry to extract the identity are the Common Names. The phrasing "(most specific)" implies the possibility of more than just one CN. - "Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead."
Deprecated means: although something is available or allowed, it is not recommended for future use (sunset phase before obsolete).
In other words, the authors of RFC 2818 are saying that it is still possible and valid to consume Common Name. They recommend the Certification Authorities to issue certificates with SAN, so that in time, certificates with Common Name(s) to sunset in a graceful way.
Long-story-short: As of today, having a certificate with multiple CNs and SAN is a valid certificate!
That is mostly because SAN became in time "the way" for reading the identity from a certificate.CN has always been 1 name not multiple
This statement is not correct.
Certificates with multiple CNs have been issued in the past, when this was the norm/practice (before updates like RFC 2818).
Some software solutions (currently legacy solutions) that were distributed across multiple hosts, used Common Names for validation. The implementation and certificate requirements impose rules like "despite wildcard, include additional CNs with the names of each front-end host".
That's why we had sometimes to request certificates like
CN = mailedc.domain.zz
CN = edcexch01.domain.zz
CN = edcexch02.domain.zz
CN = edcexch03.domain.zz
CN = edcexch04.domain.zzwhere does is say you can have multiple CN values?
The baseline is the RFC 5280 and the following updates. None of those RFCs specify any rule regarding the number of CNs in a certificate. In the absence of such rules, you are free to choose. That means it is possible to have multiple CNs in a certificate. Of course, combined with RFC 2818, it means a certificate with SAN and multiple CNs is a valid certificate. That's because nowadays, the majority of the software is relying on SAN, instead of CNs.
But old/legacy software is not updated anymore and remained with the validation logic from past (CNs).That pfSense told you you shot yourself in the foot with some borked up cert.. That cert is not a good cert to use..
pfSense is a software developed by people. It is as good as it was developed. Exceptional scenarios can still be met, where the software is behaving in an unexpected way. The fact, that you consider pfSense the source "of truth" is simply absurd.
Anyway, a certificate with multiple CNs and SAN, as of today, is still a valid certificate. The fact, that you haven't seen, or worked with such certificates, doesn't mean that you are right.
It is the second time when you mention the "shoot yourself ..." phrase .
Do you need some record player needle cartridges? - "If a subjectAltName extension of type dNSName is present, that MUST be used as the identity."
-
@iftvio Ok - lets say you create your multiple CN in your cert... When would these multiple be considered as valid?
Its only at most going to look at one of those when serving up https.. So while you might be able to get a way with creating a cert with multiple CN, its not valid for actual use anywhere..
There is flexibility in use, and then there is its not going to work anyway.. Be it not specific in the rfc or not... I am telling you from 30 years in doing this - multiple CN is not valid, its not..
-
Hello!
The propriety of multiple CNs in a cert notwithstanding, and not knowing exactly which version you are running or the intent of the original design goals with regards to handling multiple CNs, a quick code review of your suggested fix would indicate that it may not work in all situations.
Among the possible issues:
- $is_wildcard will be set based on the last CN checked in the array.
- str_replace will return an array when the subject ($cert_cn) parameter is an array, which will cause subsequent calls to substr that reference $cert_cn_regex to fail.
A quick hack might be to simply set $cert_cn to the first/last CN in the array, when present.
Of course, any code changes should be fully unit tested.
John