[TASK] Re-work/simplify copyright header in PHP files - Part 9
[Packages/TYPO3.CMS.git] / typo3 / sysext / rsaauth / Classes / Backend / CommandLineBackend.php
1 <?php
2 namespace TYPO3\CMS\Rsaauth\Backend;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * This class contains a OpenSSL backend for the TYPO3 RSA authentication
21 * service. It uses shell version of OpenSSL to perform tasks. See class
22 * \TYPO3\CMS\Rsaauth\Backend\AbstractBackend for the information on using backends.
23 *
24 * @author Dmitry Dulepov <dmitry@typo3.org>
25 */
26 class CommandLineBackend extends \TYPO3\CMS\Rsaauth\Backend\AbstractBackend {
27 /**
28 * @var integer
29 */
30 const DEFAULT_EXPONENT = 65537;
31
32 /**
33 * A path to the openssl binary or FALSE if the binary does not exist
34 *
35 * @var mixed
36 */
37 protected $opensslPath;
38
39 /**
40 * Temporary directory. It is best of it is outside of the web site root and
41 * not publicly readable.
42 * For now we use typo3temp/.
43 *
44 * @var string
45 */
46 protected $temporaryDirectory;
47
48 /**
49 * Creates an instance of this class. It obtains a path to the OpenSSL
50 * binary.
51 */
52 public function __construct() {
53 $this->opensslPath = \TYPO3\CMS\Core\Utility\CommandUtility::getCommand('openssl');
54 $this->temporaryDirectory = PATH_site . 'typo3temp';
55 // Get temporary directory from the configuration
56 $extconf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['rsaauth']);
57 if ($extconf['temporaryDirectory'] != '' && $extconf['temporaryDirectory'][0] == '/' && @is_dir($extconf['temporaryDirectory']) && is_writable($extconf['temporaryDirectory'])) {
58 $this->temporaryDirectory = $extconf['temporaryDirectory'];
59 }
60 }
61
62 /**
63 * Creates a new key pair for the encryption or gets the existing key pair (if one already has been generated).
64 *
65 * There should only be one key pair per request because the second private key would overwrites the first private
66 * key. So the submitting the form with the first public key would not work anymore.
67 *
68 * @return \TYPO3\CMS\Rsaauth\Keypair|NULL a key pair or NULL in case of error
69 */
70 public function createNewKeyPair() {
71 /** @var $keyPair \TYPO3\CMS\Rsaauth\Keypair */
72 $keyPair = GeneralUtility::makeInstance('TYPO3\\CMS\\Rsaauth\\Keypair');
73 if ($keyPair->isReady()) {
74 return $keyPair;
75 }
76
77 if ($this->opensslPath === FALSE) {
78 return NULL;
79 }
80
81 // Create a temporary file. Security: tempnam() sets permissions to 0600
82 $privateKeyFile = tempnam($this->temporaryDirectory, uniqid());
83
84 // Generate the private key.
85 //
86 // PHP generates 1024 bit key files. We force command line version
87 // to do the same and use the F4 (0x10001) exponent. This is the most
88 // secure.
89 $command = $this->opensslPath . ' genrsa -out ' . escapeshellarg($privateKeyFile) . ' 1024';
90 if (TYPO3_OS === 'WIN') {
91 $command .= ' 2>NUL';
92 } else {
93 $command .= ' 2>/dev/null';
94 }
95 \TYPO3\CMS\Core\Utility\CommandUtility::exec($command);
96 // Test that we got a private key
97 $privateKey = file_get_contents($privateKeyFile);
98 if (FALSE !== strpos($privateKey, 'BEGIN RSA PRIVATE KEY')) {
99 // Ok, we got the private key. Get the modulus.
100 $command = $this->opensslPath . ' rsa -noout -modulus -in ' . escapeshellarg($privateKeyFile);
101 $value = \TYPO3\CMS\Core\Utility\CommandUtility::exec($command);
102 if (substr($value, 0, 8) === 'Modulus=') {
103 $publicKey = substr($value, 8);
104
105 $keyPair->setExponent(self::DEFAULT_EXPONENT);
106 $keyPair->setPrivateKey($privateKey);
107 $keyPair->setPublicKey($publicKey);
108 }
109 } else {
110 $keyPair = NULL;
111 }
112
113 @unlink($privateKeyFile);
114 return $keyPair;
115 }
116
117 /**
118 * @param string $privateKey The private key (obtained from a call to createNewKeyPair())
119 * @param string $data Data to decrypt (base64-encoded)
120 * @return string Decrypted data or NULL in case of a error
121 * @see \TYPO3\CMS\Rsaauth\Backend\AbstractBackend::decrypt()
122 */
123 public function decrypt($privateKey, $data) {
124 // Key must be put to the file
125 $privateKeyFile = tempnam($this->temporaryDirectory, uniqid());
126 file_put_contents($privateKeyFile, $privateKey);
127 $dataFile = tempnam($this->temporaryDirectory, uniqid());
128 file_put_contents($dataFile, base64_decode($data));
129 // Prepare the command
130 $command = $this->opensslPath . ' rsautl -inkey ' . escapeshellarg($privateKeyFile) . ' -in ' . escapeshellarg($dataFile) . ' -decrypt';
131 // Execute the command and capture the result
132 $output = array();
133 \TYPO3\CMS\Core\Utility\CommandUtility::exec($command, $output);
134 // Remove the file
135 @unlink($privateKeyFile);
136 @unlink($dataFile);
137 return implode(LF, $output);
138 }
139
140 /**
141 * Checks if command line version of the OpenSSL is available and can be
142 * executed successfully.
143 *
144 * @return void
145 * @see \TYPO3\CMS\Rsaauth\Backend\AbstractBackend::isAvailable()
146 */
147 public function isAvailable() {
148 $result = FALSE;
149 if ($this->opensslPath) {
150 // If path exists, test that command runs and can produce output
151 $test = \TYPO3\CMS\Core\Utility\CommandUtility::exec($this->opensslPath . ' version');
152 $result = substr($test, 0, 8) == 'OpenSSL ';
153 }
154 return $result;
155 }
156
157 }