mirror of
https://github.com/phpseclib/phpseclib.git
synced 2025-02-05 13:28:27 +00:00
ASN1/X509: latch effective type of ANY fields as an additional indexing level.
This commit is contained in:
parent
9e803fe374
commit
340ee0cd2d
@ -195,6 +195,41 @@ class File_ASN1 {
|
|||||||
*/
|
*/
|
||||||
var $filters;
|
var $filters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type mapping table for the ANY type.
|
||||||
|
*
|
||||||
|
* Structured or unknown types are mapped to a FILE_ASN1_Element.
|
||||||
|
* Unambiguous types get the direct mapping (int/real/bool).
|
||||||
|
* Others are mapped as a choice, with an extra indexing level.
|
||||||
|
*
|
||||||
|
* @var Array
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $ANYmap = array(
|
||||||
|
FILE_ASN1_TYPE_BOOLEAN => true,
|
||||||
|
FILE_ASN1_TYPE_INTEGER => true,
|
||||||
|
FILE_ASN1_TYPE_BIT_STRING => 'bitString',
|
||||||
|
FILE_ASN1_TYPE_OCTET_STRING => 'octetString',
|
||||||
|
FILE_ASN1_TYPE_NULL => 'null',
|
||||||
|
FILE_ASN1_TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
|
||||||
|
FILE_ASN1_TYPE_REAL => true,
|
||||||
|
FILE_ASN1_TYPE_ENUMERATED => 'enumerated',
|
||||||
|
FILE_ASN1_TYPE_UTF8_STRING => 'utf8String',
|
||||||
|
FILE_ASN1_TYPE_NUMERIC_STRING => 'numericString',
|
||||||
|
FILE_ASN1_TYPE_PRINTABLE_STRING => 'printableString',
|
||||||
|
FILE_ASN1_TYPE_TELETEX_STRING => 'teletexString',
|
||||||
|
FILE_ASN1_TYPE_VIDEOTEX_STRING => 'videotexString',
|
||||||
|
FILE_ASN1_TYPE_IA5_STRING => 'ia5String',
|
||||||
|
FILE_ASN1_TYPE_UTC_TIME => 'utcTime',
|
||||||
|
FILE_ASN1_TYPE_GENERALIZED_TIME => 'generalTime',
|
||||||
|
FILE_ASN1_TYPE_GRAPHIC_STRING => 'graphicString',
|
||||||
|
FILE_ASN1_TYPE_VISIBLE_STRING => 'visibleString',
|
||||||
|
FILE_ASN1_TYPE_GENERAL_STRING => 'generalString',
|
||||||
|
FILE_ASN1_TYPE_UNIVERSAL_STRING => 'universalString',
|
||||||
|
//FILE_ASN1_TYPE_CHARACTER_STRING => 'characterString',
|
||||||
|
FILE_ASN1_TYPE_BMP_STRING => 'bmpString'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse BER-encoding
|
* Parse BER-encoding
|
||||||
*
|
*
|
||||||
@ -444,6 +479,16 @@ class File_ASN1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
|
case $mapping['type'] == FILE_ASN1_TYPE_ANY:
|
||||||
|
$intype = $decoded['type'];
|
||||||
|
if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || ($this->encoded[$decoded['start']] & 0x20)) {
|
||||||
|
return new File_ASN1_Element(substr($this->encoded, $decoded['start'], $decoded['length']));
|
||||||
|
}
|
||||||
|
$inmap = $this->ANYmap[$intype];
|
||||||
|
if (is_string($inmap)) {
|
||||||
|
return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case $mapping['type'] == FILE_ASN1_TYPE_CHOICE:
|
case $mapping['type'] == FILE_ASN1_TYPE_CHOICE:
|
||||||
foreach ($mapping['children'] as $key => $option) {
|
foreach ($mapping['children'] as $key => $option) {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
@ -459,7 +504,6 @@ class File_ASN1 {
|
|||||||
case isset($mapping['implicit']):
|
case isset($mapping['implicit']):
|
||||||
case isset($mapping['explicit']):
|
case isset($mapping['explicit']):
|
||||||
case $decoded['type'] == $mapping['type']:
|
case $decoded['type'] == $mapping['type']:
|
||||||
case $mapping['type'] == FILE_ASN1_TYPE_ANY:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -469,14 +513,6 @@ class File_ASN1 {
|
|||||||
$decoded['type'] = $mapping['type'];
|
$decoded['type'] = $mapping['type'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mapping['type'] == FILE_ASN1_TYPE_ANY) {
|
|
||||||
if ($decoded['type'] == FILE_ASN1_TYPE_SEQUENCE || $decoded['type'] == FILE_ASN1_TYPE_SET) {
|
|
||||||
// return $this->encode_der($decoded['content']);
|
|
||||||
//return serialize($decoded['content']);
|
|
||||||
return substr($this->encoded, $decoded['start'], $decoded['length']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($decoded['type']) {
|
switch ($decoded['type']) {
|
||||||
case FILE_ASN1_TYPE_SEQUENCE:
|
case FILE_ASN1_TYPE_SEQUENCE:
|
||||||
$map = array();
|
$map = array();
|
||||||
@ -920,14 +956,31 @@ class File_ASN1 {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FILE_ASN1_TYPE_ANY:
|
case FILE_ASN1_TYPE_ANY:
|
||||||
if (!isset($source)) {
|
$loc = $this->location;
|
||||||
if (isset($idx)) {
|
if (isset($idx)) {
|
||||||
array_pop($this->location);
|
array_pop($this->location);
|
||||||
}
|
}
|
||||||
return $this->_encode_der(NULL, array('type' => FILE_ASN1_TYPE_NULL));
|
|
||||||
|
switch (true) {
|
||||||
|
case !isset($source):
|
||||||
|
return $this->_encode_der(NULL, array('type' => FILE_ASN1_TYPE_NULL) + $mapping);
|
||||||
|
case is_int($source):
|
||||||
|
case is_object($source) && strtolower(get_class($source)) == 'math_biginteger':
|
||||||
|
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping);
|
||||||
|
case is_float($source):
|
||||||
|
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping);
|
||||||
|
case is_bool($source):
|
||||||
|
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping);
|
||||||
|
case is_array($source) && count($source) == 1:
|
||||||
|
$typename = implode('', array_keys($source));
|
||||||
|
$outtype = array_search($typename, $this->ANYmap, true);
|
||||||
|
if ($outtype !== false) {
|
||||||
|
return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$filters = $this->filters;
|
$filters = $this->filters;
|
||||||
foreach ($this->location as $part) {
|
foreach ($loc as $part) {
|
||||||
if (!isset($filters[$part])) {
|
if (!isset($filters[$part])) {
|
||||||
$filters = false;
|
$filters = false;
|
||||||
break;
|
break;
|
||||||
@ -935,13 +988,10 @@ class File_ASN1 {
|
|||||||
$filters = $filters[$part];
|
$filters = $filters[$part];
|
||||||
}
|
}
|
||||||
if ($filters === false) {
|
if ($filters === false) {
|
||||||
user_error('No filters defined for ' . implode('/', $this->location), E_USER_NOTICE);
|
user_error('No filters defined for ' . implode('/', $loc), E_USER_NOTICE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isset($idx)) {
|
return $this->_encode_der($source, $filters + $mapping);
|
||||||
array_pop($this->location);
|
|
||||||
}
|
|
||||||
return $this->_encode_der($source, $filters);
|
|
||||||
case FILE_ASN1_TYPE_NULL:
|
case FILE_ASN1_TYPE_NULL:
|
||||||
$value = '';
|
$value = '';
|
||||||
break;
|
break;
|
||||||
@ -953,6 +1003,9 @@ class File_ASN1 {
|
|||||||
case FILE_ASN1_TYPE_BMP_STRING:
|
case FILE_ASN1_TYPE_BMP_STRING:
|
||||||
case FILE_ASN1_TYPE_IA5_STRING:
|
case FILE_ASN1_TYPE_IA5_STRING:
|
||||||
case FILE_ASN1_TYPE_VISIBLE_STRING:
|
case FILE_ASN1_TYPE_VISIBLE_STRING:
|
||||||
|
case FILE_ASN1_TYPE_VIDEOTEX_STRING:
|
||||||
|
case FILE_ASN1_TYPE_GRAPHIC_STRING:
|
||||||
|
case FILE_ASN1_TYPE_GENERAL_STRING:
|
||||||
$value = $source;
|
$value = $source;
|
||||||
break;
|
break;
|
||||||
case FILE_ASN1_TYPE_BOOLEAN:
|
case FILE_ASN1_TYPE_BOOLEAN:
|
||||||
|
@ -2033,10 +2033,11 @@ class File_X509 {
|
|||||||
*
|
*
|
||||||
* @param String $propName
|
* @param String $propName
|
||||||
* @param Mixed $propValue
|
* @param Mixed $propValue
|
||||||
|
* @param String $type optional
|
||||||
* @access public
|
* @access public
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
function setDNProp($propName, $propValue)
|
function setDNProp($propName, $propValue, $type = 'utf8String')
|
||||||
{
|
{
|
||||||
if (empty($this->dn)) {
|
if (empty($this->dn)) {
|
||||||
$this->dn = array('rdnSequence' => array());
|
$this->dn = array('rdnSequence' => array());
|
||||||
@ -2046,13 +2047,17 @@ class File_X509 {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ((array) $propValue as $v)
|
foreach ((array) $propValue as $v) {
|
||||||
|
if (!is_array($v) && isset($type)) {
|
||||||
|
$v = array($type => $v);
|
||||||
|
}
|
||||||
$this->dn['rdnSequence'][] = array(
|
$this->dn['rdnSequence'][] = array(
|
||||||
array(
|
array(
|
||||||
'type' => $propName,
|
'type' => $propName,
|
||||||
'value'=> $v
|
'value'=> $v
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2088,10 +2093,12 @@ class File_X509 {
|
|||||||
* Get Distinguished Name properties
|
* Get Distinguished Name properties
|
||||||
*
|
*
|
||||||
* @param String $propName
|
* @param String $propName
|
||||||
|
* @param Array $dn optional
|
||||||
|
* @param Boolean $withType optional
|
||||||
* @return Mixed
|
* @return Mixed
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function getDNProp($propName, $dn = NULL)
|
function getDNProp($propName, $dn = NULL, $withType = false)
|
||||||
{
|
{
|
||||||
if (!isset($dn)) {
|
if (!isset($dn)) {
|
||||||
$dn = $this->dn;
|
$dn = $this->dn;
|
||||||
@ -2109,7 +2116,11 @@ class File_X509 {
|
|||||||
$result = array();
|
$result = array();
|
||||||
for ($i = 0; $i < count($dn); $i++) {
|
for ($i = 0; $i < count($dn); $i++) {
|
||||||
if ($dn[$i][0]['type'] == $propName) {
|
if ($dn[$i][0]['type'] == $propName) {
|
||||||
$result[] = $dn[$i][0]['value'];
|
$v = $dn[$i][0]['value'];
|
||||||
|
if (!$withType && is_array($v) && count($v) == 1) {
|
||||||
|
$v = array_pop($v);
|
||||||
|
}
|
||||||
|
$result[] = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2121,10 +2132,11 @@ class File_X509 {
|
|||||||
*
|
*
|
||||||
* @param Mixed $dn
|
* @param Mixed $dn
|
||||||
* @param Boolean $merge optional
|
* @param Boolean $merge optional
|
||||||
|
* @param String $type optional
|
||||||
* @access public
|
* @access public
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
function setDN($dn, $merge = false)
|
function setDN($dn, $merge = false, $type = 'utf8String')
|
||||||
{
|
{
|
||||||
if (!$merge) {
|
if (!$merge) {
|
||||||
$this->dn = NULL;
|
$this->dn = NULL;
|
||||||
@ -2137,8 +2149,8 @@ class File_X509 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handles stuff generated by openssl_x509_parse()
|
// handles stuff generated by openssl_x509_parse()
|
||||||
foreach ($dn as $type => $value) {
|
foreach ($dn as $prop => $value) {
|
||||||
if (!$this->setDNProp($type, $value)) {
|
if (!$this->setDNProp($prop, $value, $type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2148,9 +2160,9 @@ class File_X509 {
|
|||||||
// handles everything else
|
// handles everything else
|
||||||
$results = preg_split('#((?:^|, |/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
|
$results = preg_split('#((?:^|, |/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||||
for ($i = 1; $i < count($results); $i+=2) {
|
for ($i = 1; $i < count($results); $i+=2) {
|
||||||
$type = trim($results[$i], ', =/');
|
$prop = trim($results[$i], ', =/');
|
||||||
$value = $results[$i + 1];
|
$value = $results[$i + 1];
|
||||||
if (!$this->setDNProp($type, $value)) {
|
if (!$this->setDNProp($prop, $value, $type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2162,6 +2174,7 @@ class File_X509 {
|
|||||||
* Get the Distinguished Name for a certificates subject
|
* Get the Distinguished Name for a certificates subject
|
||||||
*
|
*
|
||||||
* @param Boolean $string optional
|
* @param Boolean $string optional
|
||||||
|
* @param Array $dn optional
|
||||||
* @access public
|
* @access public
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
*/
|
*/
|
||||||
@ -2177,11 +2190,11 @@ class File_X509 {
|
|||||||
|
|
||||||
$start = true;
|
$start = true;
|
||||||
foreach ($dn['rdnSequence'] as $field) {
|
foreach ($dn['rdnSequence'] as $field) {
|
||||||
$type = $field[0]['type'];
|
$prop = $field[0]['type'];
|
||||||
$value = $field[0]['value'];
|
$value = $field[0]['value'];
|
||||||
|
|
||||||
$delim = ', ';
|
$delim = ', ';
|
||||||
switch ($type) {
|
switch ($prop) {
|
||||||
case 'id-at-countryName':
|
case 'id-at-countryName':
|
||||||
$desc = 'C=';
|
$desc = 'C=';
|
||||||
break;
|
break;
|
||||||
@ -2209,12 +2222,15 @@ class File_X509 {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$delim = '/';
|
$delim = '/';
|
||||||
$desc = preg_replace('#.+-([^-]+)$#', '$1', $type) . '=';
|
$desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '=';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$start) {
|
if (!$start) {
|
||||||
$output.= $delim;
|
$output.= $delim;
|
||||||
}
|
}
|
||||||
|
if (is_array($value) && count($value) == 1) {
|
||||||
|
$value = array_pop($value); // Always strip data type.
|
||||||
|
}
|
||||||
$output.= $desc . $value;
|
$output.= $desc . $value;
|
||||||
$start = false;
|
$start = false;
|
||||||
}
|
}
|
||||||
@ -2254,28 +2270,30 @@ class File_X509 {
|
|||||||
* Get an individual Distinguished Name property for a certificates issuer
|
* Get an individual Distinguished Name property for a certificates issuer
|
||||||
*
|
*
|
||||||
* @param String $propName
|
* @param String $propName
|
||||||
|
* @param Boolean $withType optional
|
||||||
* @access public
|
* @access public
|
||||||
* @return Mixed
|
* @return Mixed
|
||||||
*/
|
*/
|
||||||
function getIssuerDNProp($propName)
|
function getIssuerDNProp($propName, $withType = false)
|
||||||
{
|
{
|
||||||
if (!isset($this->currentCert) || !is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
if (!isset($this->currentCert) || !is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer']);
|
return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alias of getDNProp()
|
* Alias of getDNProp()
|
||||||
*
|
*
|
||||||
* @param String $propName
|
* @param String $propName
|
||||||
|
* @param Boolean $withType optional
|
||||||
* @access public
|
* @access public
|
||||||
* @return Mixed
|
* @return Mixed
|
||||||
*/
|
*/
|
||||||
function getSubjectDNProp($propName)
|
function getSubjectDNProp($propName, $withType = false)
|
||||||
{
|
{
|
||||||
return $this->getDNProp($propName);
|
return $this->getDNProp($propName, NULL, $withType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user