ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
SimpleSAML\XML\Validator Class Reference
+ Collaboration diagram for SimpleSAML\XML\Validator:

Public Member Functions

 __construct ($xmlNode, $idAttribute=null, $publickey=false)
 This function initializes the validator. More...
 
 getX509Certificate ()
 Retrieve the X509 certificate which was used to sign the XML. More...
 
 validateFingerprint ($fingerprints)
 Validate the fingerprint of the certificate which was used to sign this document. More...
 
 isNodeValidated ($node)
 This function checks if the given XML node was signed. More...
 
 validateCA ($caFile)
 Validate the certificate used to sign the XML against a CA file. More...
 

Static Public Member Functions

static validateCertificate ($certificate, $caFile)
 Validate the certificate used to sign the XML against a CA file. More...
 

Static Private Member Functions

static calculateX509Fingerprint ($x509cert)
 Calculates the fingerprint of an X509 certificate. More...
 
static validateCertificateFingerprint ($certificate, $fingerprints)
 Helper function for validating the fingerprint. More...
 
static validateCABuiltIn ($certificate, $caFile)
 Validate a certificate against a CA file, by using the builtin openssl_x509_checkpurpose function. More...
 
static validateCAExec ($certificate, $caFile)
 Validate the certificate used to sign the XML against a CA file, by using the "openssl verify" command. More...
 

Private Attributes

 $x509Certificate
 
 $validNodes = null
 

Detailed Description

Definition at line 16 of file Validator.php.

Constructor & Destructor Documentation

◆ __construct()

SimpleSAML\XML\Validator::__construct (   $xmlNode,
  $idAttribute = null,
  $publickey = false 
)

This function initializes the validator.

This function accepts an optional parameter $publickey, which is the public key or certificate which should be used to validate the signature. This parameter can take the following values:

  • NULL/FALSE: No validation will be performed. This is the default.
  • A string: Assumed to be a PEM-encoded certificate / public key.
  • An array: Assumed to be an array returned by SimpleSAML_Utilities::loadPublicKey.
Parameters
\DOMNode$xmlNodeThe XML node which contains the Signature element.
string | array$idAttributeThe ID attribute which is used in node references. If this attribute is NULL (the default), then we will use whatever is the default ID. Can be eigther a string with one value, or an array with multiple ID attrbute names.
array | bool$publickeyThe public key / certificate which should be used to validate the XML node.
Exceptions

Definition at line 49 of file Validator.php.

References $certificate, array, and RobRichards\XMLSecLibs\XMLSecEnc\staticLocateKeyInfo().

50  {
51  assert('$xmlNode instanceof \DOMNode');
52 
53  if ($publickey === null) {
54  $publickey = false;
55  } elseif (is_string($publickey)) {
56  $publickey = array(
57  'PEM' => $publickey,
58  );
59  } else {
60  assert('$publickey === FALSE || is_array($publickey)');
61  }
62 
63  // Create an XML security object
64  $objXMLSecDSig = new XMLSecurityDSig();
65 
66  // Add the id attribute if the user passed in an id attribute
67  if ($idAttribute !== null) {
68  if (is_string($idAttribute)) {
69  $objXMLSecDSig->idKeys[] = $idAttribute;
70  } elseif (is_array($idAttribute)) {
71  foreach ($idAttribute as $ida) {
72  $objXMLSecDSig->idKeys[] = $ida;
73  }
74  }
75  }
76 
77  // Locate the XMLDSig Signature element to be used
78  $signatureElement = $objXMLSecDSig->locateSignature($xmlNode);
79  if (!$signatureElement) {
80  throw new \Exception('Could not locate XML Signature element.');
81  }
82 
83  // Canonicalize the XMLDSig SignedInfo element in the message
84  $objXMLSecDSig->canonicalizeSignedInfo();
85 
86  // Validate referenced xml nodes
87  if (!$objXMLSecDSig->validateReference()) {
88  throw new \Exception('XMLsec: digest validation failed');
89  }
90 
91 
92  // Find the key used to sign the document
93  $objKey = $objXMLSecDSig->locateKey();
94  if (empty($objKey)) {
95  throw new \Exception('Error loading key to handle XML signature');
96  }
97 
98  // Load the key data
99  if ($publickey !== false && array_key_exists('PEM', $publickey)) {
100  // We have PEM data for the public key / certificate
101  $objKey->loadKey($publickey['PEM']);
102  } else {
103  // No PEM data. Search for key in signature
104 
105  if (!XMLSecEnc::staticLocateKeyInfo($objKey, $signatureElement)) {
106  throw new \Exception('Error finding key data for XML signature validation.');
107  }
108 
109  if ($publickey !== false) {
110  /* $publickey is set, and should therefore contain one or more fingerprints.
111  * Check that the response contains a certificate with a matching
112  * fingerprint.
113  */
114  assert('is_array($publickey["certFingerprint"])');
115 
116  $certificate = $objKey->getX509Certificate();
117  if ($certificate === null) {
118  // Wasn't signed with an X509 certificate
119  throw new \Exception('Message wasn\'t signed with an X509 certificate,' .
120  ' and no public key was provided in the metadata.');
121  }
122 
123  self::validateCertificateFingerprint($certificate, $publickey['certFingerprint']);
124  // Key OK
125  }
126  }
127 
128  // Check the signature
129  if ($objXMLSecDSig->verify($objKey) !== 1) {
130  throw new \Exception("Unable to validate Signature");
131  }
132 
133  // Extract the certificate
134  $this->x509Certificate = $objKey->getX509Certificate();
135 
136  // Find the list of validated nodes
137  $this->validNodes = $objXMLSecDSig->getValidatedNodes();
138  }
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77
static staticLocateKeyInfo($objBaseKey=null, $node=null)
Definition: XMLSecEnc.php:410
Create styles array
The data for the language used.
+ Here is the call graph for this function:

Member Function Documentation

◆ calculateX509Fingerprint()

static SimpleSAML\XML\Validator::calculateX509Fingerprint (   $x509cert)
staticprivate

Calculates the fingerprint of an X509 certificate.

Parameters
string$x509certThe certificate as a base64-encoded string. The string may optionally be framed with '--—BEGIN CERTIFICATE--—' and '--—END CERTIFICATE--—'.
Returns
string The fingerprint as a 40-character lowercase hexadecimal number. NULL is returned if the argument isn't an X509 certificate.

Definition at line 163 of file Validator.php.

References $data.

164  {
165  assert('is_string($x509cert)');
166 
167  $lines = explode("\n", $x509cert);
168 
169  $data = '';
170 
171  foreach ($lines as $line) {
172  // Remove '\r' from end of line if present
173  $line = rtrim($line);
174  if ($line === '-----BEGIN CERTIFICATE-----') {
175  // Delete junk from before the certificate
176  $data = '';
177  } elseif ($line === '-----END CERTIFICATE-----') {
178  // Ignore data after the certificate
179  break;
180  } elseif ($line === '-----BEGIN PUBLIC KEY-----') {
181  // This isn't an X509 certificate
182  return null;
183  } else {
184  // Append the current line to the certificate data
185  $data .= $line;
186  }
187  }
188 
189  /* $data now contains the certificate as a base64-encoded string. The fingerprint
190  * of the certificate is the sha1-hash of the certificate.
191  */
192  return strtolower(sha1(base64_decode($data)));
193  }

◆ getX509Certificate()

SimpleSAML\XML\Validator::getX509Certificate ( )

Retrieve the X509 certificate which was used to sign the XML.

This function will return the certificate as a PEM-encoded string. If the XML wasn't signed by an X509 certificate, NULL will be returned.

Returns
string The certificate as a PEM-encoded string, or NULL if not signed with an X509 certificate.

Definition at line 149 of file Validator.php.

References SimpleSAML\XML\Validator\$x509Certificate.

150  {
151  return $this->x509Certificate;
152  }

◆ isNodeValidated()

SimpleSAML\XML\Validator::isNodeValidated (   $node)

This function checks if the given XML node was signed.

Parameters
\DOMNode$nodeThe XML node which we should verify that was signed.
Returns
bool TRUE if this node (or a parent node) was signed. FALSE if not.

Definition at line 275 of file Validator.php.

276  {
277  assert('$node instanceof \DOMNode');
278 
279  while ($node !== null) {
280  if (in_array($node, $this->validNodes, true)) {
281  return true;
282  }
283 
284  $node = $node->parentNode;
285  }
286 
287  /* Neither this node nor any of the parent nodes could be found in the list of
288  * signed nodes.
289  */
290  return false;
291  }

◆ validateCA()

SimpleSAML\XML\Validator::validateCA (   $caFile)

Validate the certificate used to sign the XML against a CA file.

This function throws an exception if unable to validate against the given CA file.

Parameters
string$caFileFile with trusted certificates, in PEM-format.
Exceptions

Definition at line 302 of file Validator.php.

303  {
304  assert('is_string($caFile)');
305 
306  if ($this->x509Certificate === null) {
307  throw new \Exception('Key used to sign the message was not an X509 certificate.');
308  }
309 
310  self::validateCertificate($this->x509Certificate, $caFile);
311  }

◆ validateCABuiltIn()

static SimpleSAML\XML\Validator::validateCABuiltIn (   $certificate,
  $caFile 
)
staticprivate

Validate a certificate against a CA file, by using the builtin openssl_x509_checkpurpose function.

Parameters
string$certificateThe certificate, in PEM format.
string$caFileFile with trusted certificates, in PEM-format.
Returns
boolean|string TRUE on success, or a string with error messages if it failed.
Deprecated:

Definition at line 322 of file Validator.php.

References $certificate, $error, $errors, $res, and array.

323  {
324  assert('is_string($certificate)');
325  assert('is_string($caFile)');
326 
327  // Clear openssl errors
328  while (openssl_error_string() !== false);
329 
330  $res = openssl_x509_checkpurpose($certificate, X509_PURPOSE_ANY, array($caFile));
331 
332  $errors = '';
333  // Log errors
334  while (($error = openssl_error_string()) !== false) {
335  $errors .= ' [' . $error . ']';
336  }
337 
338  if ($res !== true) {
339  return $errors;
340  }
341 
342  return true;
343  }
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77
$error
Definition: Error.php:17
foreach($_POST as $key=> $value) $res
Create styles array
The data for the language used.
$errors
Definition: index.php:6

◆ validateCAExec()

static SimpleSAML\XML\Validator::validateCAExec (   $certificate,
  $caFile 
)
staticprivate

Validate the certificate used to sign the XML against a CA file, by using the "openssl verify" command.

This function uses the openssl verify command to verify a certificate, to work around limitations on the openssl_x509_checkpurpose function. That function will not work on certificates without a purpose set.

Parameters
string$certificateThe certificate, in PEM format.
string$caFileFile with trusted certificates, in PEM-format.
Returns
bool|string TRUE on success, a string with error messages on failure.
Exceptions

Definition at line 359 of file Validator.php.

References $certificate, $out, and array.

360  {
361  assert('is_string($certificate)');
362  assert('is_string($caFile)');
363 
364  $command = array(
365  'openssl', 'verify',
366  '-CAfile', $caFile,
367  '-purpose', 'any',
368  );
369 
370  $cmdline = '';
371  foreach ($command as $c) {
372  $cmdline .= escapeshellarg($c) . ' ';
373  }
374 
375  $cmdline .= '2>&1';
376  $descSpec = array(
377  0 => array('pipe', 'r'),
378  1 => array('pipe', 'w'),
379  );
380  $process = proc_open($cmdline, $descSpec, $pipes);
381  if (!is_resource($process)) {
382  throw new \Exception('Failed to execute verification command: ' . $cmdline);
383  }
384 
385  if (fwrite($pipes[0], $certificate) === false) {
386  throw new \Exception('Failed to write certificate for verification.');
387  }
388  fclose($pipes[0]);
389 
390  $out = '';
391  while (!feof($pipes[1])) {
392  $line = trim(fgets($pipes[1]));
393  if (strlen($line) > 0) {
394  $out .= ' [' . $line . ']';
395  }
396  }
397  fclose($pipes[1]);
398 
399  $status = proc_close($process);
400  if ($status !== 0 || $out !== ' [stdin: OK]') {
401  return $out;
402  }
403 
404  return true;
405  }
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77
Create styles array
The data for the language used.

◆ validateCertificate()

static SimpleSAML\XML\Validator::validateCertificate (   $certificate,
  $caFile 
)
static

Validate the certificate used to sign the XML against a CA file.

This function throws an exception if unable to validate against the given CA file.

Parameters
string$certificateThe certificate, in PEM format.
string$caFileFile with trusted certificates, in PEM-format.
Exceptions

Definition at line 418 of file Validator.php.

References $certificate, and SimpleSAML\Logger\debug().

Referenced by SimpleSAML_Utilities\validateCA().

419  {
420  assert('is_string($certificate)');
421  assert('is_string($caFile)');
422 
423  if (!file_exists($caFile)) {
424  throw new \Exception('Could not load CA file: ' . $caFile);
425  }
426 
427  Logger::debug('Validating certificate against CA file: ' . var_export($caFile, true));
428 
429  $resBuiltin = self::validateCABuiltIn($certificate, $caFile);
430  if ($resBuiltin !== true) {
431  Logger::debug('Failed to validate with internal function: ' . var_export($resBuiltin, true));
432 
433  $resExternal = self::validateCAExec($certificate, $caFile);
434  if ($resExternal !== true) {
435  Logger::debug('Failed to validate with external function: ' . var_export($resExternal, true));
436  throw new \Exception('Could not verify certificate against CA file "'
437  . $caFile . '". Internal result:' . $resBuiltin .
438  ' External result:' . $resExternal);
439  }
440  }
441 
442  Logger::debug('Successfully validated certificate.');
443  }
static debug($string)
Definition: Logger.php:213
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateCertificateFingerprint()

static SimpleSAML\XML\Validator::validateCertificateFingerprint (   $certificate,
  $fingerprints 
)
staticprivate

Helper function for validating the fingerprint.

Checks the fingerprint of a certificate against an array of valid fingerprints. Will throw an exception if none of the fingerprints matches.

Parameters
string$certificateThe X509 certificate we should validate.
array$fingerprintsThe valid fingerprints.
Exceptions

Definition at line 206 of file Validator.php.

References $certificate.

207  {
208  assert('is_string($certificate)');
209  assert('is_array($fingerprints)');
210 
211  $certFingerprint = self::calculateX509Fingerprint($certificate);
212  if ($certFingerprint === null) {
213  // Couldn't calculate fingerprint from X509 certificate. Should not happen.
214  throw new \Exception('Unable to calculate fingerprint from X509' .
215  ' certificate. Maybe it isn\'t an X509 certificate?');
216  }
217 
218  foreach ($fingerprints as $fp) {
219  assert('is_string($fp)');
220 
221  if ($fp === $certFingerprint) {
222  // The fingerprints matched
223  return;
224  }
225  }
226 
227  // None of the fingerprints matched. Throw an exception describing the error.
228  throw new \Exception('Invalid fingerprint of certificate. Expected one of [' .
229  implode('], [', $fingerprints) . '], but got [' . $certFingerprint . ']');
230  }
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77

◆ validateFingerprint()

SimpleSAML\XML\Validator::validateFingerprint (   $fingerprints)

Validate the fingerprint of the certificate which was used to sign this document.

This function accepts either a string, or an array of strings as a parameter. If this is an array, then any string (certificate) in the array can match. If this is a string, then that string must match,

Parameters
string | array$fingerprintsThe fingerprints which should match. This can be a single string, or an array of fingerprints.
Exceptions

Definition at line 244 of file Validator.php.

References array.

245  {
246  assert('is_string($fingerprints) || is_array($fingerprints)');
247 
248  if ($this->x509Certificate === null) {
249  throw new \Exception('Key used to sign the message was not an X509 certificate.');
250  }
251 
252  if (!is_array($fingerprints)) {
253  $fingerprints = array($fingerprints);
254  }
255 
256  // Normalize the fingerprints
257  foreach ($fingerprints as &$fp) {
258  assert('is_string($fp)');
259 
260  // Make sure that the fingerprint is in the correct format
261  $fp = strtolower(str_replace(":", "", $fp));
262  }
263 
264  self::validateCertificateFingerprint($this->x509Certificate, $fingerprints);
265  }
Create styles array
The data for the language used.

Field Documentation

◆ $validNodes

SimpleSAML\XML\Validator::$validNodes = null
private

Definition at line 28 of file Validator.php.

◆ $x509Certificate

SimpleSAML\XML\Validator::$x509Certificate
private

Definition at line 23 of file Validator.php.

Referenced by SimpleSAML\XML\Validator\getX509Certificate().


The documentation for this class was generated from the following file: