diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php index d6fc3ceb8fe6e9258688bef16c8fceff073a613f..bcc6649d5be8e3d4aa21e4d9a234daf84fec5c26 100644 --- a/lib/SimpleSAML/Utilities.php +++ b/lib/SimpleSAML/Utilities.php @@ -524,130 +524,10 @@ class SimpleSAML_Utilities { /** - * Validate a certificate against a CA file, by using the builtin - * openssl_x509_checkpurpose function - * - * @param string $certificate The certificate, in PEM format. - * @param string $caFile File with trusted certificates, in PEM-format. - * @return boolean|string TRUE on success, or a string with error messages if it failed. - * @deprecated This method will be removed in SSP 2.0. - */ - private static function validateCABuiltIn($certificate, $caFile) { - assert('is_string($certificate)'); - assert('is_string($caFile)'); - - /* Clear openssl errors. */ - while(openssl_error_string() !== FALSE); - - $res = openssl_x509_checkpurpose($certificate, X509_PURPOSE_ANY, array($caFile)); - - $errors = ''; - /* Log errors. */ - while( ($error = openssl_error_string()) !== FALSE) { - $errors .= ' [' . $error . ']'; - } - - if($res !== TRUE) { - return $errors; - } - - return TRUE; - } - - - /** - * 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. - * - * @param string $certificate The certificate, in PEM format. - * @param string $caFile File with trusted certificates, in PEM-format. - * @return boolean|string TRUE on success, a string with error messages on failure. - * @deprecated This method will be removed in SSP 2.0. - */ - private static function validateCAExec($certificate, $caFile) { - assert('is_string($certificate)'); - assert('is_string($caFile)'); - - $command = array( - 'openssl', 'verify', - '-CAfile', $caFile, - '-purpose', 'any', - ); - - $cmdline = ''; - foreach($command as $c) { - $cmdline .= escapeshellarg($c) . ' '; - } - - $cmdline .= '2>&1'; - $descSpec = array( - 0 => array('pipe', 'r'), - 1 => array('pipe', 'w'), - ); - $process = proc_open($cmdline, $descSpec, $pipes); - if (!is_resource($process)) { - throw new Exception('Failed to execute verification command: ' . $cmdline); - } - - if (fwrite($pipes[0], $certificate) === FALSE) { - throw new Exception('Failed to write certificate for verification.'); - } - fclose($pipes[0]); - - $out = ''; - while (!feof($pipes[1])) { - $line = trim(fgets($pipes[1])); - if(strlen($line) > 0) { - $out .= ' [' . $line . ']'; - } - } - fclose($pipes[1]); - - $status = proc_close($process); - if ($status !== 0 || $out !== ' [stdin: OK]') { - return $out; - } - - return TRUE; - } - - - /** - * 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. - * - * @param string $certificate The certificate, in PEM format. - * @param string $caFile File with trusted certificates, in PEM-format. * @deprecated This method will be removed in SSP 2.0. */ public static function validateCA($certificate, $caFile) { - assert('is_string($certificate)'); - assert('is_string($caFile)'); - - if (!file_exists($caFile)) { - throw new Exception('Could not load CA file: ' . $caFile); - } - - SimpleSAML_Logger::debug('Validating certificate against CA file: ' . var_export($caFile, TRUE)); - - $resBuiltin = self::validateCABuiltIn($certificate, $caFile); - if ($resBuiltin !== TRUE) { - SimpleSAML_Logger::debug('Failed to validate with internal function: ' . var_export($resBuiltin, TRUE)); - - $resExternal = self::validateCAExec($certificate, $caFile); - if ($resExternal !== TRUE) { - SimpleSAML_Logger::debug('Failed to validate with external function: ' . var_export($resExternal, TRUE)); - throw new Exception('Could not verify certificate against CA file "' - . $caFile . '". Internal result:' . $resBuiltin . - ' External result:' . $resExternal); - } - } - - SimpleSAML_Logger::debug('Successfully validated certificate.'); + SimpleSAML_XML_Validator::validateCertificate($certificate, $caFile); } diff --git a/lib/SimpleSAML/XML/Validator.php b/lib/SimpleSAML/XML/Validator.php index c9736363bc1d201e8e531df5db8d91a7f3918888..b9a9dfdb29f707d1b27cbf591daea3450495e0e0 100644 --- a/lib/SimpleSAML/XML/Validator.php +++ b/lib/SimpleSAML/XML/Validator.php @@ -289,7 +289,134 @@ class SimpleSAML_XML_Validator { throw new Exception('Key used to sign the message was not an X509 certificate.'); } - SimpleSAML_Utilities::validateCA($this->x509Certificate, $caFile); + self::validateCertificate($this->x509Certificate, $caFile); + } + + /** + * Validate a certificate against a CA file, by using the builtin + * openssl_x509_checkpurpose function + * + * @param string $certificate The certificate, in PEM format. + * @param string $caFile File with trusted certificates, in PEM-format. + * @return boolean|string TRUE on success, or a string with error messages if it failed. + * @deprecated + */ + private static function validateCABuiltIn($certificate, $caFile) { + assert('is_string($certificate)'); + assert('is_string($caFile)'); + + /* Clear openssl errors. */ + while(openssl_error_string() !== FALSE); + + $res = openssl_x509_checkpurpose($certificate, X509_PURPOSE_ANY, array($caFile)); + + $errors = ''; + /* Log errors. */ + while( ($error = openssl_error_string()) !== FALSE) { + $errors .= ' [' . $error . ']'; + } + + if($res !== TRUE) { + return $errors; + } + + return TRUE; + } + + + /** + * 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. + * + * @param string $certificate The certificate, in PEM format. + * @param string $caFile File with trusted certificates, in PEM-format. + * @return boolean|string TRUE on success, a string with error messages on failure. + * @deprecated + */ + private static function validateCAExec($certificate, $caFile) { + assert('is_string($certificate)'); + assert('is_string($caFile)'); + + $command = array( + 'openssl', 'verify', + '-CAfile', $caFile, + '-purpose', 'any', + ); + + $cmdline = ''; + foreach($command as $c) { + $cmdline .= escapeshellarg($c) . ' '; + } + + $cmdline .= '2>&1'; + $descSpec = array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + ); + $process = proc_open($cmdline, $descSpec, $pipes); + if (!is_resource($process)) { + throw new Exception('Failed to execute verification command: ' . $cmdline); + } + + if (fwrite($pipes[0], $certificate) === FALSE) { + throw new Exception('Failed to write certificate for verification.'); + } + fclose($pipes[0]); + + $out = ''; + while (!feof($pipes[1])) { + $line = trim(fgets($pipes[1])); + if(strlen($line) > 0) { + $out .= ' [' . $line . ']'; + } + } + fclose($pipes[1]); + + $status = proc_close($process); + if ($status !== 0 || $out !== ' [stdin: OK]') { + return $out; + } + + return TRUE; + } + + + /** + * 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. + * + * @param string $certificate The certificate, in PEM format. + * @param string $caFile File with trusted certificates, in PEM-format. + * @deprecated + */ + public static function validateCertificate($certificate, $caFile) { + assert('is_string($certificate)'); + assert('is_string($caFile)'); + + if (!file_exists($caFile)) { + throw new Exception('Could not load CA file: ' . $caFile); + } + + SimpleSAML_Logger::debug('Validating certificate against CA file: ' . var_export($caFile, TRUE)); + + $resBuiltin = self::validateCABuiltIn($certificate, $caFile); + if ($resBuiltin !== TRUE) { + SimpleSAML_Logger::debug('Failed to validate with internal function: ' . var_export($resBuiltin, TRUE)); + + $resExternal = self::validateCAExec($certificate, $caFile); + if ($resExternal !== TRUE) { + SimpleSAML_Logger::debug('Failed to validate with external function: ' . var_export($resExternal, TRUE)); + throw new Exception('Could not verify certificate against CA file "' + . $caFile . '". Internal result:' . $resBuiltin . + ' External result:' . $resExternal); + } + } + + SimpleSAML_Logger::debug('Successfully validated certificate.'); } }