[BUGFIX] Check if OpenSSL works on every platform
[Packages/TYPO3.CMS.git] / typo3 / sysext / rsaauth / sv1 / backends / class.tx_rsaauth_php_backend.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009-2011 Dmitry Dulepov <dmitry@typo3.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25
26 /**
27 * This class contains a PHP OpenSSL backend for the TYPO3 RSA authentication
28 * service. See class tx_rsaauth_abstract_backend for the information on using
29 * backends.
30 *
31 * @author Dmitry Dulepov <dmitry@typo3.org>
32 * @package TYPO3
33 * @subpackage tx_rsaauth
34 */
35 class tx_rsaauth_php_backend extends tx_rsaauth_abstract_backend {
36
37 /**
38 * Creates a new public/private key pair using PHP OpenSSL extension.
39 *
40 * @return tx_rsaauth_keypair A new key pair or NULL in case of error
41 * @see tx_rsaauth_abstract_backend::createNewKeyPair()
42 */
43 public function createNewKeyPair() {
44 $result = NULL;
45 $privateKey = @openssl_pkey_new();
46 if ($privateKey) {
47 // Create private key as string
48 $privateKeyStr = '';
49 openssl_pkey_export($privateKey, $privateKeyStr);
50
51 // Prepare public key information
52 $exportedData = '';
53 $csr = openssl_csr_new(array(), $privateKey);
54 openssl_csr_export($csr, $exportedData, FALSE);
55
56 // Get public key (in fact modulus) and exponent
57 $publicKey = $this->extractPublicKeyModulus($exportedData);
58 $exponent = $this->extractExponent($exportedData);
59
60 // Create result object
61 $result = t3lib_div::makeInstance('tx_rsaauth_keypair');
62 /* @var $result tx_rsaauth_keypair */
63 $result->setExponent($exponent);
64 $result->setPrivateKey($privateKeyStr);
65 $result->setPublicKey($publicKey);
66
67 // Clean up all resources
68 openssl_free_key($privateKey);
69 }
70 return $result;
71 }
72
73 /**
74 * Decrypts data using the private key. This implementation uses PHP OpenSSL
75 * extension.
76 *
77 * @param string $privateKey The private key (obtained from a call to createNewKeyPair())
78 * @param string $data Data to decrypt (base64-encoded)
79 * @return string Decrypted data or NULL in case of a error
80 * @see tx_rsaauth_abstract_backend::decrypt()
81 */
82 public function decrypt($privateKey, $data) {
83 $result = '';
84 if (!@openssl_private_decrypt(base64_decode($data), $result, $privateKey)) {
85 $result = NULL;
86 }
87 return $result;
88 }
89
90 /**
91 * Checks if this backend is available for calling. In particular checks if
92 * PHP OpenSSl extension is installed and functional.
93 *
94 * @return void
95 * @see tx_rsaauth_abstract_backend::isAvailable()
96 */
97 public function isAvailable() {
98 $result = FALSE;
99 if (is_callable('openssl_pkey_new')) {
100 // PHP extension has to be configured properly. It
101 // can be installed and available but will not work unless
102 // properly configured. So we check if it works.
103 $testKey = @openssl_pkey_new();
104 if (is_resource($testKey)) {
105 openssl_free_key($testKey);
106 $result = TRUE;
107 }
108 }
109 return $result;
110 }
111
112 /**
113 * Extracts the exponent from the OpenSSL CSR
114 *
115 * @param string $data The result of openssl_csr_export()
116 * @return int The exponent as a number
117 */
118 protected function extractExponent($data) {
119 $index = strpos($data, 'Exponent: ');
120 // We do not check for '$index === FALSE' because the exponent is
121 // always there!
122 return intval(substr($data, $index + 10));
123 }
124
125 /**
126 * Extracts public key modulus from the OpenSSL CSR.
127 *
128 * @param string $data The result of openssl_csr_export()
129 * @return string Modulus as uppercase hex string
130 */
131 protected function extractPublicKeyModulus($data) {
132 $fragment = preg_replace('/.*Modulus.*?\n(.*)Exponent:.*/ms', '\1', $data);
133 $fragment = preg_replace('/[\s\n\r:]/', '', $fragment);
134 $result = trim(strtoupper(substr($fragment, 2)));
135
136 return $result;
137 }
138 }
139
140 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rsaauth/sv1/backends/class.tx_rsaauth_php_backend.php'])) {
141 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rsaauth/sv1/backends/class.tx_rsaauth_php_backend.php']);
142 }
143
144 ?>