X509: *Attribute() functions may now handle single values.

This commit is contained in:
Patrick Monnerat 2012-11-14 16:33:32 +01:00
parent ac8d0172eb
commit a61d7ba29b

View File

@ -69,6 +69,14 @@ define('FILE_X509_DN_OPENSSL', 3); // OpenSSL compatible array.
define('FILE_X509_DN_CANON', 4); // Canonical ASN.1 RDNs string. define('FILE_X509_DN_CANON', 4); // Canonical ASN.1 RDNs string.
define('FILE_X509_DN_HASH', 5); // Name hash for file indexing. define('FILE_X509_DN_HASH', 5); // Name hash for file indexing.
/**
* Attribute value disposition.
* If disposition is >= 0, this is the index of the target value.
*/
define('FILE_X509_ATTR_ALL', -1); // All attribute values (array).
define('FILE_X509_ATTR_APPEND', -2); // Add a value.
define('FILE_X509_ATTR_REPLACE', -3); // Clear first, then add a value.
/** /**
* Pure-PHP X.509 Parser * Pure-PHP X.509 Parser
* *
@ -2888,10 +2896,10 @@ class File_X509 {
); );
// Copy extensions from CSR. // Copy extensions from CSR.
$csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest'); $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);
if (!empty($csrexts)) { if (!empty($csrexts)) {
$this->CurrentCert['tbsCertificate']['extensions'] = $csrexts[0]; $this->currentCert['tbsCertificate']['extensions'] = $csrexts;
} }
} }
@ -3502,10 +3510,11 @@ class File_X509 {
* Remove a CSR attribute. * Remove a CSR attribute.
* *
* @param String $id * @param String $id
* @param Integer $disposition optional
* @access public * @access public
* @return Boolean * @return Boolean
*/ */
function removeAttribute($id) function removeAttribute($id, $disposition = FILE_X509_ATTR_ALL)
{ {
$attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes'); $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes');
@ -3514,10 +3523,31 @@ class File_X509 {
} }
$result = false; $result = false;
foreach ($attributes as $key => $value) { foreach ($attributes as $key => $attribute) {
if ($value['type'] == $id) { if ($attribute['type'] == $id) {
unset($attributes[$key]); $n = count($attribute['value']);
$result = true; switch (true) {
case $disposition == FILE_X509_ATTR_APPEND:
case $disposition == FILE_X509_ATTR_REPLACE:
return false;
case $disposition >= $n;
case $disposition >= $n;
$disposition -= $n;
break;
case $disposition == FILE_X509_ATTR_ALL:
case $n == 1:
unset($attributes[$key]);
$result = true;
break;
default:
unset($attributes[$key]['value'][$disposition]);
$attributes[$key]['value'] = array_values($attributes[$key]['value']);
$result = true;
break;
}
if ($result && $disposition != FILE_X509_ATTR_ALL) {
break;
}
} }
} }
@ -3526,16 +3556,17 @@ class File_X509 {
} }
/** /**
* Get a CRL attribute * Get a CSR attribute
* *
* Returns the attribute if it exists and false if not * Returns the attribute if it exists and false if not
* *
* @param String $id * @param String $id
* @param Integer $disposition optional
* @param Array $csr optional * @param Array $csr optional
* @access public * @access public
* @return Mixed * @return Mixed
*/ */
function getAttribute($id, $csr = NULL) function getAttribute($id, $disposition = FILE_X509_ATTR_ALL, $csr = NULL)
{ {
if (empty($csr)) { if (empty($csr)) {
$csr = $this->currentCert; $csr = $this->currentCert;
@ -3547,9 +3578,21 @@ class File_X509 {
return false; return false;
} }
foreach ($attributes as $key => $value) { foreach ($attributes as $key => $attribute) {
if ($value['type'] == $id) { if ($attribute['type'] == $id) {
return $value['value']; $n = count($attribute['value']);
switch (true) {
case $disposition == FILE_X509_ATTR_APPEND:
case $disposition == FILE_X509_ATTR_REPLACE:
return false;
case $disposition == FILE_X509_ATTR_ALL:
return $attribute['value'];
case $disposition >= $n:
$disposition -= $n;
break;
default:
return $attribute['value'][$disposition];
}
} }
} }
@ -3586,11 +3629,11 @@ class File_X509 {
* *
* @param String $id * @param String $id
* @param Mixed $value * @param Mixed $value
* @param Boolean $replace optional * @param Boolean $disposition optional
* @access public * @access public
* @return Boolean * @return Boolean
*/ */
function setAttribute($id, $value, $replace = true) function setAttribute($id, $value, $disposition = FILE_X509_ATTR_ALL)
{ {
$attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true); $attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
@ -3598,20 +3641,42 @@ class File_X509 {
return false; return false;
} }
$newattr = array('type' => $id, 'value' => $value); switch ($disposition) {
case FILE_X509_ATTR_REPLACE:
$disposition = FILE_X509_ATTR_APPEND;
case FILE_X509_ATTR_ALL:
$this->removeAttribute($id);
break;
}
foreach ($attributes as $key => $value) { foreach ($attributes as $key => $attribute) {
if ($value['type'] == $id) { if ($attribute['type'] == $id) {
if (!$replace) { $n = count($attribute['value']);
return false; switch (true) {
case $disposition == FILE_X509_ATTR_APPEND:
$last = $key;
break;
case $disposition >= $n;
$disposition -= $n;
break;
default:
$attributes[$key]['value'][$disposition] = $value;
return true;
} }
$attributes[$key] = $newattr;
return true;
} }
} }
$attributes[] = $newattr; switch (true) {
case $disposition >= 0:
return false;
case isset($last):
$attributes[$last]['value'][] = $value;
break;
default:
$attributes[] = array('type' => $id, 'value' => $disposition == FILE_X509_ATTR_ALL ? $value: array($value));
break;
}
return true; return true;
} }