From 511f55de3d1d504e4686f9d558a3c10709b413f8 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Fri, 2 Aug 2019 21:51:06 -0500 Subject: [PATCH] X509: fix issue with explicit time tags whose maps expect implicit --- phpseclib/File/ASN1.php | 14 ++++++++++++-- phpseclib/File/X509.php | 9 +++++++++ tests/Unit/File/ASN1Test.php | 29 +++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php index abab574a..1a79173d 100644 --- a/phpseclib/File/ASN1.php +++ b/phpseclib/File/ASN1.php @@ -787,7 +787,14 @@ class File_ASN1 case FILE_ASN1_TYPE_UTC_TIME: case FILE_ASN1_TYPE_GENERALIZED_TIME: if (class_exists('DateTime')) { - if (isset($mapping['implicit'])) { + // for explicitly tagged optional stuff + if (is_array($decoded['content'])) { + $decoded['content'] = $decoded['content'][0]['content']; + } + // for implicitly tagged optional stuff + // in theory, doing isset($mapping['implicit']) would work but malformed certs do exist + // in the wild that OpenSSL decodes without issue so we'll support them as well + if (!is_object($decoded['content'])) { $decoded['content'] = $this->_decodeDateTime($decoded['content'], $decoded['type']); } if (!$decoded['content']) { @@ -795,7 +802,10 @@ class File_ASN1 } return $decoded['content']->format($this->format); } else { - if (isset($mapping['implicit'])) { + if (is_array($decoded['content'])) { + $decoded['content'] = $decoded['content'][0]['content']; + } + if (!is_int($decoded['content'])) { $decoded['content'] = $this->_decodeUnixTime($decoded['content'], $decoded['type']); } return @date($this->format, $decoded['content']); diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php index 3a694f29..ccf964f5 100644 --- a/phpseclib/File/X509.php +++ b/phpseclib/File/X509.php @@ -982,6 +982,13 @@ class File_X509 'children' => $AccessDescription ); + $this->SubjectInfoAccessSyntax = array( + 'type' => FILE_ASN1_TYPE_SEQUENCE, + 'min' => 1, + 'max' => -1, + 'children' => $AccessDescription + ); + $this->SubjectAltName = $GeneralNames; $this->PrivateKeyUsagePeriod = array( @@ -1922,6 +1929,8 @@ class File_X509 return $this->ExtKeyUsageSyntax; case 'id-pe-authorityInfoAccess': return $this->AuthorityInfoAccessSyntax; + case 'id-pe-subjectInfoAccess': + return $this->SubjectInfoAccessSyntax; case 'id-ce-subjectAltName': return $this->SubjectAltName; case 'id-ce-subjectDirectoryAttributes': diff --git a/tests/Unit/File/ASN1Test.php b/tests/Unit/File/ASN1Test.php index 1a84035d..2f1131d5 100644 --- a/tests/Unit/File/ASN1Test.php +++ b/tests/Unit/File/ASN1Test.php @@ -363,4 +363,33 @@ class Unit_File_ASN1Test extends PhpseclibTestCase $this->assertSame(pack('H*', '6983f09da7ebcfdee0c7a1a7b2c0948cc8f9d776'), $new); $this->assertSame($orig, $asn1->_decodeOID($new)); } + + /** + * @group github1388 + */ + public function testExplicitImplicitDate() + { + $map = [ + 'type' => FILE_ASN1_TYPE_SEQUENCE, + 'children' => [ + 'notBefore' => [ + 'constant' => 0, + 'optional' => true, + 'implicit' => true, + 'type' => FILE_ASN1_TYPE_GENERALIZED_TIME], + 'notAfter' => [ + 'constant' => 1, + 'optional' => true, + 'implicit' => true, + 'type' => FILE_ASN1_TYPE_GENERALIZED_TIME] + ] + ]; + + $asn1 = new File_ASN1(); + $a = pack('H*', '3026a011180f32303137303432313039303535305aa111180f32303138303432313230353935395a'); + $a = $asn1->decodeBER($a); + $a = $asn1->asn1map($a[0], $map); + + $this->assertInternalType('array', $a); + } }