3232final class SubjectCertificatePurposeValidator implements SubjectCertificateValidator
3333{
3434
35+ private const KEY_USAGE = 'id-ce-keyUsage ' ;
36+ private const KEY_USAGE_DIGITAL_SIGNATURE = 0 ;
37+ private const EXTENDED_KEY_USAGE = 'id-ce-extKeyUsage ' ;
3538 // oid 1.3.6.1.5.5.7.3.2
3639 private const EXTENDED_KEY_USAGE_CLIENT_AUTHENTICATION = "id-kp-clientAuth " ;
3740 private $ logger ;
@@ -51,15 +54,32 @@ public function __construct(LoggerInterface $logger = null)
5154 */
5255 public function validate (X509 $ subjectCertificate ): void
5356 {
54- $ usages = $ subjectCertificate ->getExtension (' id-ce-extKeyUsage ' );
55- if (!$ usages || empty ($ usages )) {
57+ $ keyUsage = $ subjectCertificate ->getExtension (self :: KEY_USAGE );
58+ if (!$ keyUsage || empty ($ keyUsage )) {
5659 throw new UserCertificateMissingPurposeException ();
5760 }
61+ if (!$ keyUsage [self ::KEY_USAGE_DIGITAL_SIGNATURE ] ) {
62+ throw new UserCertificateWrongPurposeException ();
63+ }
64+ $ usages = $ subjectCertificate ->getExtension (self ::EXTENDED_KEY_USAGE );
65+ if ($ this ->isExtendedKeyUsageAllowAllPurposes ($ usages )) {
66+ return ;
67+ }
5868 // Extended usages must contain TLS Web Client Authentication
59- if (!in_array ( self :: EXTENDED_KEY_USAGE_CLIENT_AUTHENTICATION , $ usages )) {
69+ if (!$ this -> isExtendedKeyUsageAllowClientAuthentication ( $ usages )) {
6070 throw new UserCertificateWrongPurposeException ();
6171 }
6272
6373 $ this ->logger ?->debug("User certificate can be used for client authentication. " );
6474 }
75+
76+ private function isExtendedKeyUsageAllowAllPurposes (mixed $ usages ): bool
77+ {
78+ return !$ usages || empty ($ usages );
79+ }
80+
81+ private function isExtendedKeyUsageAllowClientAuthentication (mixed $ usages ): bool
82+ {
83+ return in_array (self ::EXTENDED_KEY_USAGE_CLIENT_AUTHENTICATION , $ usages );
84+ }
6585}
0 commit comments