diff options
author | Robin Appelman <robin@icewind.nl> | 2018-04-13 16:39:27 +0200 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2018-04-17 13:46:36 +0200 |
commit | f399e1591f27495e5faf6507a1489c2265ef35fe (patch) | |
tree | 692eaa32a867b4725dfab7c941d29798ed2fa5ae /lib/private/Log/ExceptionSerializer.php | |
parent | 42b7dfe9ac84da2e3e2bda732b0e94c68df9d515 (diff) | |
download | nextcloud-server-f399e1591f27495e5faf6507a1489c2265ef35fe.tar.gz nextcloud-server-f399e1591f27495e5faf6507a1489c2265ef35fe.zip |
Log classnames of arguments in exception trace
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib/private/Log/ExceptionSerializer.php')
-rw-r--r-- | lib/private/Log/ExceptionSerializer.php | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php new file mode 100644 index 00000000000..be025cb9e52 --- /dev/null +++ b/lib/private/Log/ExceptionSerializer.php @@ -0,0 +1,140 @@ +<?php +/** + * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Log; + +use OC\HintException; + +class ExceptionSerializer { + const methodsWithSensitiveParameters = [ + // Session/User + 'completeLogin', + 'login', + 'checkPassword', + 'checkPasswordNoLogging', + 'loginWithPassword', + 'updatePrivateKeyPassword', + 'validateUserPass', + 'loginWithToken', + '{closure}', + + // TokenProvider + 'getToken', + 'isTokenPassword', + 'getPassword', + 'decryptPassword', + 'logClientIn', + 'generateToken', + 'validateToken', + + // TwoFactorAuth + 'solveChallenge', + 'verifyChallenge', + + // ICrypto + 'calculateHMAC', + 'encrypt', + 'decrypt', + + // LoginController + 'tryLogin', + 'confirmPassword', + + // LDAP + 'bind', + 'areCredentialsValid', + 'invokeLDAPMethod', + + // Encryption + 'storeKeyPair', + 'setupUser', + ]; + + private function filterTrace(array $trace) { + $sensitiveValues = []; + $trace = array_map(function (array $traceLine) use (&$sensitiveValues) { + foreach (self::methodsWithSensitiveParameters as $sensitiveMethod) { + if (strpos($traceLine['function'], $sensitiveMethod) !== false) { + $sensitiveValues = array_merge($sensitiveValues, $traceLine['args']); + $traceLine['args'] = ['*** sensitive parameters replaced ***']; + return $traceLine; + } + } + return $traceLine; + }, $trace); + return array_map(function (array $traceLine) use ($sensitiveValues) { + $traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues); + return $traceLine; + }, $trace); + } + + private function removeValuesFromArgs($args, $values) { + foreach ($args as &$arg) { + if (in_array($arg, $values, true)) { + $arg = '*** sensitive parameter replaced ***'; + } else if (is_array($arg)) { + $arg = $this->removeValuesFromArgs($arg, $values); + } + } + return $args; + } + + private function encodeTrace($trace) { + $filteredTrace = $this->filterTrace($trace); + return array_map(function (array $line) { + $line['args'] = array_map([$this, 'encodeArg'], $line['args']); + return $line; + }, $filteredTrace); + } + + private function encodeArg($arg) { + if (is_object($arg)) { + $data = get_object_vars($arg); + $data['__class__'] = get_class($arg); + return array_map([$this, 'encodeArg'], $data); + } else if (is_array($arg)) { + return array_map([$this, 'encodeArg'], $arg); + } else { + return $arg; + } + } + + public function serializeException(\Throwable $exception) { + $data = [ + 'Exception' => get_class($exception), + 'Message' => $exception->getMessage(), + 'Code' => $exception->getCode(), + 'Trace' => $this->encodeTrace($exception->getTrace()), + 'File' => $exception->getFile(), + 'Line' => $exception->getLine(), + ]; + + if ($exception instanceof HintException) { + $data['Hint'] = $exception->getHint(); + } + + if ($exception->getPrevious()) { + $data['Previous'] = $this->serializeException($exception->getPrevious()); + } + + return $data; + } +}
\ No newline at end of file |