diff options
-rw-r--r-- | ajax/settings.php | 276 | ||||
-rw-r--r-- | appinfo/app.php | 40 | ||||
-rw-r--r-- | appinfo/info.xml | 49 | ||||
-rw-r--r-- | appinfo/routes.php | 9 | ||||
-rw-r--r-- | appinfo/update.php | 71 | ||||
-rw-r--r-- | css/settings.css | 15 | ||||
-rw-r--r-- | img/app-dark.svg | 3 | ||||
-rw-r--r-- | img/screenshot.png (renamed from screenshot.png) | bin | 24828 -> 24828 bytes | |||
-rw-r--r-- | js/settings.js | 195 | ||||
-rw-r--r-- | lib/PasswordHash.php | 467 | ||||
-rw-r--r-- | lib/Settings/Admin.php | 123 | ||||
-rw-r--r-- | lib/Settings/Section.php | 75 | ||||
-rw-r--r-- | lib/drupal.php | 651 | ||||
-rw-r--r-- | lib/group_sql.php | 80 | ||||
-rw-r--r-- | lib/helper.php | 226 | ||||
-rw-r--r-- | lib/user_sql.php | 828 | ||||
-rw-r--r-- | templates/admin.php | 408 |
17 files changed, 1714 insertions, 1802 deletions
diff --git a/ajax/settings.php b/ajax/settings.php index 77de46f..ed0f406 100644 --- a/ajax/settings.php +++ b/ajax/settings.php @@ -1,7 +1,7 @@ <?php /** - * ownCloud - user_sql + * Nextcloud - user_sql * * @author Andreas Böhler and contributors * @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at> @@ -21,22 +21,22 @@ * */ - /** - * This is the AJAX portion of the settings page. - * - * It can: - * - Verify the connection settings - * - Load autocomplete values for tables - * - Load autocomplete values for columns - * - Save settings for a given domain - * - Load settings for a given domain - * - * It always returns JSON encoded responses - */ - +/** + * This is the AJAX portion of the settings page. + * + * It can: + * - Verify the connection settings + * - Load autocomplete values for tables + * - Load autocomplete values for columns + * - Save settings for a given domain + * - Load settings for a given domain + * + * It always returns JSON encoded responses + */ + namespace OCA\user_sql; -// Init owncloud +// Init Nextcloud // Check if we are a user \OCP\User::checkAdminUser(); @@ -50,53 +50,49 @@ $helper = new \OCA\user_sql\lib\Helper; $l = \OC::$server->getL10N('user_sql'); -$params = $helper -> getParameterArray(); +$params = $helper->getParameterArray(); $response = new \OCP\AppFramework\Http\JSONResponse(); // Check if the request is for us -if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POST['function']) && isset($_POST['domain'])) -{ +if (isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POST['function']) && isset($_POST['domain'])) { $domain = $_POST['domain']; - switch($_POST['function']) - { + switch ($_POST['function']) { // Save the settings for the given domain to the database case 'saveSettings': - $parameters = array('host' => $_POST['sql_hostname'], + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], 'tablePrefix' => '' ); - + // Check if the table exists - if(!$helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('The selected SQL table '.$_POST['sql_table'].' does not exist!')))); + if (!$helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('The selected SQL table ' . $_POST['sql_table'] . ' does not exist!')) + )); break; } - if(!empty($_POST['sql_group_table']) && !$helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_group_table'])) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('The selected SQL table '.$_POST['sql_group_table'].' does not exist!')))); + if (!empty($_POST['sql_group_table']) && !$helper->verifyTable($parameters, $_POST['sql_driver'], + $_POST['sql_group_table'])) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('The selected SQL table ' . $_POST['sql_group_table'] . ' does not exist!')) + )); break; } - + // Retrieve all column settings $columns = array(); $group_columns = array(); - foreach($params as $param) - { - if(strpos($param, 'col_') === 0) - { - if(isset($_POST[$param]) && $_POST[$param] !== '') - { - if(strpos($param, 'col_group_') === 0) - { + foreach ($params as $param) { + if (strpos($param, 'col_') === 0) { + if (isset($_POST[$param]) && $_POST[$param] !== '') { + if (strpos($param, 'col_group_') === 0) { $group_columns[] = $_POST[$param]; - } - else - { + } else { $columns[] = $_POST[$param]; } } @@ -105,97 +101,85 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS // Check if the columns exist $status = $helper->verifyColumns($parameters, $_POST['sql_driver'], $_POST['sql_table'], $columns); - if(!empty($_POST['sql_group_table']) && $status === true) - { - $status = $helper->verifyColumns($parameters, $_POST['sql_driver'], $_POST['sql_group_table'], $group_columns); + if (!empty($_POST['sql_group_table']) && $status === true) { + $status = $helper->verifyColumns($parameters, $_POST['sql_driver'], $_POST['sql_group_table'], + $group_columns); } - if($status !== true) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('The selected SQL column(s) do(es) not exist: '.$status)))); + if ($status !== true) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('The selected SQL column(s) do(es) not exist: ' . $status)) + )); break; } // If we reach this point, all settings have been verified - foreach($params as $param) - { + foreach ($params as $param) { // Special handling for checkbox fields - if(isset($_POST[$param])) - { - if($param === 'set_strip_domain') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_'.$domain, 'true'); - } - elseif($param === 'set_allow_pwchange') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_'.$domain, 'true'); - } - elseif($param === 'set_active_invert') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_'.$domain, 'true'); - } - elseif($param === 'set_enable_gethome') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_'.$domain, 'true'); + if (isset($_POST[$param])) { + if ($param === 'set_strip_domain') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_' . $domain, 'true'); + } elseif ($param === 'set_allow_pwchange') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_' . $domain, 'true'); + } elseif ($param === 'set_active_invert') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_' . $domain, 'true'); + } elseif ($param === 'set_enable_gethome') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_' . $domain, 'true'); + } else { + \OC::$server->getConfig()->setAppValue('user_sql', $param . '_' . $domain, $_POST[$param]); } - else - { - \OC::$server->getConfig()->setAppValue('user_sql', $param.'_'.$domain, $_POST[$param]); - } - } else - { - if($param === 'set_strip_domain') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_'.$domain, 'false'); - } - elseif($param === 'set_allow_pwchange') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_'.$domain, 'false'); - } - elseif($param === 'set_active_invert') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_'.$domain, 'false'); - } - elseif($param === 'set_enable_gethome') - { - \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_'.$domain, 'false'); + } else { + if ($param === 'set_strip_domain') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_strip_domain_' . $domain, 'false'); + } elseif ($param === 'set_allow_pwchange') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_allow_pwchange_' . $domain, 'false'); + } elseif ($param === 'set_active_invert') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_active_invert_' . $domain, 'false'); + } elseif ($param === 'set_enable_gethome') { + \OC::$server->getConfig()->setAppValue('user_sql', 'set_enable_gethome_' . $domain, 'false'); } } } - $response->setData(array('status' => 'success', - 'data' => array('message' => $l -> t('Application settings successfully stored.')))); - break; + $response->setData(array( + 'status' => 'success', + 'data' => array('message' => $l->t('Application settings successfully stored.')) + )); + break; // Load the settings for a given domain case 'loadSettingsForDomain': $retArr = array(); - foreach($params as $param) - { - $retArr[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param.'_'.$domain, ''); + foreach ($params as $param) { + $retArr[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param . '_' . $domain, ''); } - $response->setData(array('status' => 'success', - 'settings' => $retArr)); - break; + $response->setData(array( + 'status' => 'success', + 'settings' => $retArr + )); + break; // Try to verify the database connection settings case 'verifySettings': $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); - if(!isset($_POST['sql_driver'])) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Error connecting to database: No driver specified.')))); + if (!isset($_POST['sql_driver'])) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Error connecting to database: No driver specified.')) + )); break; } - if(($_POST['sql_hostname'] === '') || ($_POST['sql_database'] === '')) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Error connecting to database: You must specify at least host and database')))); + if (($_POST['sql_hostname'] === '') || ($_POST['sql_database'] === '')) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Error connecting to database: You must specify at least host and database')) + )); break; } - $parameters = array('host' => $_POST['sql_hostname'], + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], @@ -203,22 +187,25 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS ); try { - $conn = $cm -> getConnection($_POST['sql_driver'], $parameters); - $response->setData(array('status' => 'success', - 'data' => array('message' => $l -> t('Successfully connected to database')))); - } - catch(\Exception $e) - { - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Error connecting to database: ').$e->getMessage()))); + $conn = $cm->getConnection($_POST['sql_driver'], $parameters); + $response->setData(array( + 'status' => 'success', + 'data' => array('message' => $l->t('Successfully connected to database')) + )); + } catch (\Exception $e) { + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Error connecting to database: ') . $e->getMessage()) + )); } - break; + break; // Get the autocompletion values for a column case 'getColumnAutocomplete': - - - $parameters = array('host' => $_POST['sql_hostname'], + + + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], @@ -231,28 +218,30 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS $sql_table = $_POST['sql_table']; } - if($helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) + if ($helper->verifyTable($parameters, $_POST['sql_driver'], $_POST['sql_table'])) { $columns = $helper->getColumns($parameters, $_POST['sql_driver'], $sql_table); - else + } else { $columns = array(); - + } + $search = $_POST['request']; $ret = array(); - foreach($columns as $name) - { - if(($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) - { - $ret[] = array('label' => $name, - 'value' => $name); + foreach ($columns as $name) { + if (($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) { + $ret[] = array( + 'label' => $name, + 'value' => $name + ); } } - $response -> setData($ret); - break; + $response->setData($ret); + break; // Get the autocompletion values for a table case 'getTableAutocomplete': - $parameters = array('host' => $_POST['sql_hostname'], + $parameters = array( + 'host' => $_POST['sql_hostname'], 'password' => $_POST['sql_password'], 'user' => $_POST['sql_username'], 'dbname' => $_POST['sql_database'], @@ -263,23 +252,24 @@ if(isset($_POST['appname']) && ($_POST['appname'] === 'user_sql') && isset($_POS $search = $_POST['request']; $ret = array(); - foreach($tables as $name) - { - if(($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) - { - $ret[] = array('label' => $name, - 'value' => $name); + foreach ($tables as $name) { + if (($search === '') || ($search === 'search') || (strpos($name, $search) === 0)) { + $ret[] = array( + 'label' => $name, + 'value' => $name + ); } } - $response -> setData($ret); - break; + $response->setData($ret); + break; } -} else -{ +} else { // If the request was not for us, set an error message - $response->setData(array('status' => 'error', - 'data' => array('message' => $l -> t('Not submitted for us.')))); + $response->setData(array( + 'status' => 'error', + 'data' => array('message' => $l->t('Not submitted for us.')) + )); } // Return the JSON array diff --git a/appinfo/app.php b/appinfo/app.php index df34741..b984edd 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -1,31 +1,31 @@ <?php /** -* ownCloud - user_sql -* -* @author Andreas Böhler -* @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at> -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library 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 library. If not, see <http://www.gnu.org/licenses/>. -* -*/ + * Nextcloud - user_sql + * + * @author Andreas Böhler + * @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + * + */ require_once(__DIR__ . '/../lib/user_sql.php'); require_once __DIR__ . '/../lib/group_sql.php'; + $backend = new \OCA\user_sql\OC_USER_SQL; $group_backend = new \OCA\user_sql\OC_GROUP_SQL; \OC::$server->getUserManager()->registerBackend($backend); \OC::$server->getGroupManager()->addBackend($group_backend); -?> diff --git a/appinfo/info.xml b/appinfo/info.xml index 1c5d6bf..fa70152 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -1,27 +1,28 @@ <?xml version="1.0"?> <info> - <id>user_sql</id> - <name>SQL user backend</name> - <summary>Authenticate Users by SQL</summary> - <description>Authenticate Users by SQL</description> - <version>3.1.0</version> - <licence>agpl</licence> - <author>Andreas Boehler <dev (at) aboehler (dot) at ></author> - <namespace>user_sql</namespace> - <bugs>https://github.com/nextcloud/user_sql/issues</bugs> - <repository>https://github.com/nextcloud/user_sql</repository> - <screenshot>https://raw.githubusercontent.com/nextcloud/user_sql/v2.4.0/screenshot.png</screenshot> - <types> - <authentication/> - </types> - <category>auth</category> - <dependencies> - <nextcloud min-version="12" max-version="13"/> - <database>mysql</database> - <database>pgsql</database> - </dependencies> - <settings> - <admin>\OCA\user_sql\Settings\Admin</admin> - <admin-section>OCA\user_sql\Settings\Section</admin-section> - </settings> + <id>user_sql</id> + <name>SQL User Backend</name> + <summary>Authenticate Users by SQL</summary> + <description>Authenticate users and retrieve their groups from external database by native SQL queries.</description> + <version>4.0.0-dev</version> + <licence>agpl</licence> + <author>Andreas Boehler <dev (at) aboehler (dot) at ></author> + <namespace>user_sql</namespace> + <bugs>https://github.com/nextcloud/user_sql/issues</bugs> + <repository>https://github.com/nextcloud/user_sql</repository> + <screenshot>https://raw.githubusercontent.com/nextcloud/user_sql/v4.0.0/img/screenshot.png</screenshot> + <types> + <authentication/> + </types> + <category>auth</category> + <dependencies> + <php min-version="5.4"/> + <nextcloud min-version="12" max-version="13"/> + <database>mysql</database> + <database>pgsql</database> + </dependencies> + <settings> + <admin>\OCA\user_sql\Settings\Admin</admin> + <admin-section>OCA\user_sql\Settings\Section</admin-section> + </settings> </info> diff --git a/appinfo/routes.php b/appinfo/routes.php index afb4fea..1617c63 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,8 +1,9 @@ <?php /** -* Copyright (c) 2015, Andreas Böhler <dev@aboehler.at> -* This file is licensed under the Affero General Public License version 3 or later. -* See the COPYING-README file. -*/ + * Copyright (c) 2015, Andreas Böhler <dev@aboehler.at> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + /** @var $this \OCP\Route\IRouter */ $this->create('user_sql_ajax_settings', 'ajax/settings.php')->actionInclude('user_sql/ajax/settings.php'); diff --git a/appinfo/update.php b/appinfo/update.php deleted file mode 100644 index 6312a16..0000000 --- a/appinfo/update.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/** - * ownCloud - user_sql - * - * @author Andreas Böhler and contributors - * @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library 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 library. If not, see <http://www.gnu.org/licenses/>. - * - */ - -$installedVersion = \OC::$server->getConfig()->getAppValue('user_sql', 'installed_version'); - -$params = array('sql_host' => 'sql_hostname', - 'sql_user' => 'sql_username', - 'sql_database' => 'sql_database', - 'sql_password' => 'sql_password', - 'sql_table' => 'sql_table', - 'sql_column_username' => 'col_username', - 'sql_column_password' => 'col_password', - 'sql_type' => 'sql_driver', - 'sql_column_active' => 'col_active', - 'strip_domain' => 'set_strip_domain', - 'default_domain' => 'set_default_domain', - 'crypt_type' => 'set_crypt_type', - 'sql_column_displayname' => 'col_displayname', - 'allow_password_change' => 'set_allow_pwchange', - 'sql_column_active_invert' => 'set_active_invert', - 'sql_column_email' => 'col_email', - 'mail_sync_mode' => 'set_mail_sync_mode' - ); - -$delParams = array('domain_settings', - 'map_array', - 'domain_array' - ); - -if(version_compare($installedVersion, '1.99', '<')) -{ - foreach($params as $oldPar => $newPar) - { - $val = \OC::$server->getConfig()->getAppValue('user_sql', $oldPar); - if(($oldPar === 'strip_domain') || ($oldPar === 'allow_password_change') || ($oldPar === 'sql_column_active_invert')) - { - if($val) - $val = 'true'; - else - $val = 'false'; - } - if($val) - \OC::$server->getConfig()->setAppValue('user_sql', $newPar.'_default', $val); - \OC::$server->getConfig()->deleteAppValue('user_sql', $oldPar); - } - - foreach($delParams as $param) - { - \OC::$server->getConfig()->deleteAppValue('user_sql', $param); - } -} diff --git a/css/settings.css b/css/settings.css index 87f19b7..0f90ec3 100644 --- a/css/settings.css +++ b/css/settings.css @@ -1,15 +1,18 @@ .statusmessage { - background-color: #DDDDFF; + background-color: #DDDDFF; } + .errormessage { - background-color: #FFDDDD; + background-color: #FFDDDD; } + .successmessage { - background-color: #DDFFDD; + background-color: #DDFFDD; } -.statusmessage,.errormessage,.successmessage{ - display:none; - padding: 1px; + +.statusmessage, .errormessage, .successmessage { + display: none; + padding: 1px; } #sql-1 p label:first-child, diff --git a/img/app-dark.svg b/img/app-dark.svg index 54939fa..24168c8 100644 --- a/img/app-dark.svg +++ b/img/app-dark.svg @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.0" viewBox="0 0 16 16"> - <path style="block-progression:tb;color:#000000;text-transform:none;text-indent:0" fill="#000" d="m8.4036 1c-1.7312 0-3.1998 1.2661-3.1998 2.9 0.012287 0.51643 0.058473 1.1532 0.36664 2.5v0.033333l0.033328 0.033333c0.098928 0.28338 0.24289 0.44549 0.4333 0.66666s0.41742 0.48149 0.63328 0.69999c0.025397 0.025708 0.041676 0.041633 0.066656 0.066677 0.04281 0.18631 0.094672 0.38681 0.13332 0.56666 0.10284 0.47851 0.092296 0.81737 0.066668 0.93332-0.74389 0.26121-1.6694 0.57228-2.4998 0.93332-0.46622 0.2027-0.8881 0.3837-1.2332 0.59999-0.34513 0.2163-0.68837 0.37971-0.79994 0.86666-0.16004 0.63293-0.19866 0.7539-0.39997 1.5333-0.027212 0.20914 0.083011 0.42961 0.26665 0.53333 1.5078 0.81451 3.824 1.1423 6.1329 1.1333s4.6066-0.35609 6.0662-1.1333c0.11739-0.07353 0.14304-0.10869 0.13332-0.2333-0.04365-0.68908-0.08154-1.3669-0.13332-1.7666-0.01807-0.09908-0.06492-0.19275-0.13332-0.26666-0.46366-0.5537-1.1564-0.89218-1.9665-1.2333-0.7396-0.31144-1.6067-0.63486-2.4665-0.99999-0.048123-0.10721-0.095926-0.41912 0-0.89999 0.025759-0.12912 0.066096-0.26742 0.099994-0.4 0.0808-0.090507 0.14378-0.16447 0.23332-0.26666 0.19096-0.21796 0.39614-0.44661 0.56662-0.66666s0.30996-0.40882 0.39997-0.66666l0.03333-0.033333c0.34839-1.4062 0.34857-1.9929 0.36664-2.5v-0.033333c0-1.6339-1.4686-2.9-3.1998-2.9z"/> + <path style="block-progression:tb;color:#000000;text-transform:none;text-indent:0" fill="#000" + d="m8.4036 1c-1.7312 0-3.1998 1.2661-3.1998 2.9 0.012287 0.51643 0.058473 1.1532 0.36664 2.5v0.033333l0.033328 0.033333c0.098928 0.28338 0.24289 0.44549 0.4333 0.66666s0.41742 0.48149 0.63328 0.69999c0.025397 0.025708 0.041676 0.041633 0.066656 0.066677 0.04281 0.18631 0.094672 0.38681 0.13332 0.56666 0.10284 0.47851 0.092296 0.81737 0.066668 0.93332-0.74389 0.26121-1.6694 0.57228-2.4998 0.93332-0.46622 0.2027-0.8881 0.3837-1.2332 0.59999-0.34513 0.2163-0.68837 0.37971-0.79994 0.86666-0.16004 0.63293-0.19866 0.7539-0.39997 1.5333-0.027212 0.20914 0.083011 0.42961 0.26665 0.53333 1.5078 0.81451 3.824 1.1423 6.1329 1.1333s4.6066-0.35609 6.0662-1.1333c0.11739-0.07353 0.14304-0.10869 0.13332-0.2333-0.04365-0.68908-0.08154-1.3669-0.13332-1.7666-0.01807-0.09908-0.06492-0.19275-0.13332-0.26666-0.46366-0.5537-1.1564-0.89218-1.9665-1.2333-0.7396-0.31144-1.6067-0.63486-2.4665-0.99999-0.048123-0.10721-0.095926-0.41912 0-0.89999 0.025759-0.12912 0.066096-0.26742 0.099994-0.4 0.0808-0.090507 0.14378-0.16447 0.23332-0.26666 0.19096-0.21796 0.39614-0.44661 0.56662-0.66666s0.30996-0.40882 0.39997-0.66666l0.03333-0.033333c0.34839-1.4062 0.34857-1.9929 0.36664-2.5v-0.033333c0-1.6339-1.4686-2.9-3.1998-2.9z"/> </svg> diff --git a/screenshot.png b/img/screenshot.png Binary files differindex fd2ed67..fd2ed67 100644 --- a/screenshot.png +++ b/img/screenshot.png diff --git a/js/settings.js b/js/settings.js index f9f6b44..4b63b53 100644 --- a/js/settings.js +++ b/js/settings.js @@ -2,63 +2,57 @@ // declare namespace var user_sql = user_sql || -{ -}; + {}; /** * init admin settings view */ -user_sql.adminSettingsUI = function() -{ +user_sql.adminSettingsUI = function () { - if($('#sqlDiv').length > 0) - { + if ($('#sqlDiv').length > 0) { // enable tabs on settings page $('#sqlDiv').tabs(); - + // Attach auto-completion to all column fields $('#col_username, #col_password, #col_displayname, #col_active, #col_email, #col_gethome').autocomplete({ - source: function(request, response) - { + source: function (request, response) { var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'getColumnAutocomplete' }); - + post.push({ name: 'domain', value: domain }); - + post.push({ name: 'request', value: request.term }); - + // Ajax foobar $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, response, 'json'); }, minLength: 0, - open: function() { + open: function () { $(this).attr('state', 'open'); }, - close: function() { + close: function () { $(this).attr('state', 'closed'); } - }).focus(function() { - if($(this).attr('state') != 'open') - { - $(this).autocomplete("search"); - } + }).focus(function () { + if ($(this).attr('state') != 'open') { + $(this).autocomplete("search"); + } }); // Attach auto-completion to all group column fields $('#col_group_name, #col_group_username').autocomplete({ - source: function(request, response) - { + source: function (request, response) { var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); @@ -86,71 +80,67 @@ user_sql.adminSettingsUI = function() $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, response, 'json'); }, minLength: 0, - open: function() { + open: function () { $(this).attr('state', 'open'); }, - close: function() { + close: function () { $(this).attr('state', 'closed'); } - }).focus(function() { - if($(this).attr('state') != 'open') - { - $(this).autocomplete("search"); - } + }).focus(function () { + if ($(this).attr('state') != 'open') { + $(this).autocomplete("search"); + } }); - + // Attach auto-completion to all table fields $('#sql_table, #sql_group_table').autocomplete({ - source: function(request, response) - { + source: function (request, response) { var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'getTableAutocomplete' }); - + post.push({ name: 'domain', value: domain }); - + post.push({ name: 'request', value: request.term }); - + // Ajax foobar $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, response, 'json'); }, minLength: 0, - open: function() { + open: function () { $(this).attr('state', 'open'); }, - close: function() { + close: function () { $(this).attr('state', 'closed'); } - }).focus(function() { - if($(this).attr('state') != 'open') - { - $(this).autocomplete("search"); - } + }).focus(function () { + if ($(this).attr('state') != 'open') { + $(this).autocomplete("search"); + } }); - + // Verify the SQL database settings - $('#sqlVerify').click(function(event) - { + $('#sqlVerify').click(function (event) { event.preventDefault(); var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'verifySettings' }); - + post.push({ name: 'domain', value: domain @@ -161,39 +151,34 @@ user_sql.adminSettingsUI = function() $('#sql_error_message').hide(); $('#sql_update_message').hide(); // Ajax foobar - $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data) - { + $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function (data) { $('#sql_verify_message').hide(); - if(data.status == 'success') - { + if (data.status == 'success') { $('#sql_success_message').html(data.data.message); $('#sql_success_message').show(); - window.setTimeout(function() - { + window.setTimeout(function () { $('#sql_success_message').hide(); }, 10000); - } else - { + } else { $('#sql_error_message').html(data.data.message); $('#sql_error_message').show(); } }, 'json'); return false; - }); + }); // Save the settings for a domain - $('#sqlSubmit').click(function(event) - { + $('#sqlSubmit').click(function (event) { event.preventDefault(); var post = $('#sqlForm').serializeArray(); var domain = $('#sql_domain_chooser option:selected').val(); - + post.push({ name: 'function', value: 'saveSettings' }); - + post.push({ name: 'domain', value: domain @@ -204,19 +189,15 @@ user_sql.adminSettingsUI = function() $('#sql_verify_message').hide(); $('#sql_error_message').hide(); // Ajax foobar - $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data) - { + $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function (data) { $('#sql_update_message').hide(); - if(data.status == 'success') - { + if (data.status == 'success') { $('#sql_success_message').html(data.data.message); $('#sql_success_message').show(); - window.setTimeout(function() - { + window.setTimeout(function () { $('#sql_success_message').hide(); }, 10000); - } else - { + } else { $('#sql_error_message').html(data.data.message); $('#sql_error_message').show(); } @@ -225,45 +206,39 @@ user_sql.adminSettingsUI = function() }); // Attach event handler to the domain chooser - $('#sql_domain_chooser').change(function() { - user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val()); + $('#sql_domain_chooser').change(function () { + user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val()); }); - - $('#set_gethome_mode').change(function() { - user_sql.setGethomeMode(); + + $('#set_gethome_mode').change(function () { + user_sql.setGethomeMode(); }); - - $('#set_enable_gethome').change(function() { + + $('#set_enable_gethome').change(function () { user_sql.setGethomeMode(); }); } }; -user_sql.setGethomeMode = function() -{ +user_sql.setGethomeMode = function () { var enabled = $('#set_enable_gethome').prop('checked'); - if(enabled) - { + if (enabled) { $('#set_gethome_mode').prop('disabled', false); var val = $('#set_gethome_mode option:selected').val(); - if(val === 'query') - { + if (val === 'query') { $('#set_gethome').prop('disabled', true); $('#col_gethome').prop('disabled', false); } - else if(val === 'static') - { + else if (val === 'static') { $('#set_gethome').prop('disabled', false); $('#col_gethome').prop('disabled', true); } - else - { + else { $('#set_gethome').prop('disabled', true); $('#col_gethome').prop('disabled', true); } } - else - { + else { $('#set_gethome_mode').prop('disabled', true); $('#set_gethome').prop('disabled', true); $('#col_gethome').prop('disabled', true); @@ -274,8 +249,7 @@ user_sql.setGethomeMode = function() * Load the settings for the selected domain * @param string domain The domain to load */ -user_sql.loadDomainSettings = function(domain) -{ +user_sql.loadDomainSettings = function (domain) { $('#sql_success_message').hide(); $('#sql_error_message').hide(); $('#sql_verify_message').hide(); @@ -294,49 +268,40 @@ user_sql.loadDomainSettings = function(domain) value: domain } ]; - $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function(data) - { + $.post(OC.filePath('user_sql', 'ajax', 'settings.php'), post, function (data) { $('#sql_loading_message').hide(); - if(data.status == 'success') - { - for(key in data.settings) - { - if(key == 'set_strip_domain') - { - if(data.settings[key] == 'true') + if (data.status == 'success') { + for (key in data.settings) { + if (key == 'set_strip_domain') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else if(key == 'set_allow_pwchange') - { - if(data.settings[key] == 'true') + else if (key == 'set_allow_pwchange') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else if(key == 'set_active_invert') - { - if(data.settings[key] == 'true') + else if (key == 'set_active_invert') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else if(key == 'set_enable_gethome') - { - if(data.settings[key] == 'true') + else if (key == 'set_enable_gethome') { + if (data.settings[key] == 'true') $('#' + key).prop('checked', true); else $('#' + key).prop('checked', false); } - else - { + else { $('#' + key).val(data.settings[key]); } } } - else - { + else { $('#sql_error_message').html(data.data.message); $('#sql_error_message').show(); } @@ -346,10 +311,8 @@ user_sql.loadDomainSettings = function(domain) }; // Run our JS if the SQL settings are present -$(document).ready(function() -{ - if($('#sqlDiv')) - { +$(document).ready(function () { + if ($('#sqlDiv')) { user_sql.adminSettingsUI(); user_sql.loadDomainSettings($('#sql_domain_chooser option:selected').val()); user_sql.setGethomeMode(); diff --git a/lib/PasswordHash.php b/lib/PasswordHash.php index e363656..c414ad3 100644 --- a/lib/PasswordHash.php +++ b/lib/PasswordHash.php @@ -24,230 +24,245 @@ # Obviously, since this code is in the public domain, the above are not # requirements (there can be none), but merely suggestions. # -class PasswordHash { - var $itoa64; - var $iteration_count_log2; - var $portable_hashes; - var $random_state; - - function __construct($iteration_count_log2, $portable_hashes) - { - $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - - if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) - $iteration_count_log2 = 8; - $this->iteration_count_log2 = $iteration_count_log2; - - $this->portable_hashes = $portable_hashes; - - $this->random_state = microtime(); - if (function_exists('getmypid')) - $this->random_state .= getmypid(); - } - - function get_random_bytes($count) - { - $output = ''; - if (is_readable('/dev/urandom') && - ($fh = @fopen('/dev/urandom', 'rb'))) { - $output = fread($fh, $count); - fclose($fh); - } - - if (strlen($output) < $count) { - $output = ''; - for ($i = 0; $i < $count; $i += 16) { - $this->random_state = - md5(microtime() . $this->random_state); - $output .= - pack('H*', md5($this->random_state)); - } - $output = substr($output, 0, $count); - } - - return $output; - } - - function encode64($input, $count) - { - $output = ''; - $i = 0; - do { - $value = ord($input[$i++]); - $output .= $this->itoa64[$value & 0x3f]; - if ($i < $count) - $value |= ord($input[$i]) << 8; - $output .= $this->itoa64[($value >> 6) & 0x3f]; - if ($i++ >= $count) - break; - if ($i < $count) - $value |= ord($input[$i]) << 16; - $output .= $this->itoa64[($value >> 12) & 0x3f]; - if ($i++ >= $count) - break; - $output .= $this->itoa64[($value >> 18) & 0x3f]; - } while ($i < $count); - - return $output; - } - - function gensalt_private($input) - { - $output = '$P$'; - $output .= $this->itoa64[min($this->iteration_count_log2 + - ((PHP_VERSION >= '5') ? 5 : 3), 30)]; - $output .= $this->encode64($input, 6); - - return $output; - } - - function crypt_private($password, $setting) - { - $output = '*0'; - if (substr($setting, 0, 2) === $output) - $output = '*1'; - - $id = substr($setting, 0, 3); - # We use "$P$", phpBB3 uses "$H$" for the same thing - if ($id !== '$P$' && $id !== '$H$') - return $output; - - $count_log2 = strpos($this->itoa64, $setting[3]); - if ($count_log2 < 7 || $count_log2 > 30) - return $output; - - $count = 1 << $count_log2; - - $salt = substr($setting, 4, 8); - if (strlen($salt) !== 8) - return $output; - - # We're kind of forced to use MD5 here since it's the only - # cryptographic primitive available in all versions of PHP - # currently in use. To implement our own low-level crypto - # in PHP would result in much worse performance and - # consequently in lower iteration counts and hashes that are - # quicker to crack (by non-PHP code). - if (PHP_VERSION >= '5') { - $hash = md5($salt . $password, TRUE); - do { - $hash = md5($hash . $password, TRUE); - } while (--$count); - } else { - $hash = pack('H*', md5($salt . $password)); - do { - $hash = pack('H*', md5($hash . $password)); - } while (--$count); - } - - $output = substr($setting, 0, 12); - $output .= $this->encode64($hash, 16); - - return $output; - } - - function gensalt_extended($input) - { - $count_log2 = min($this->iteration_count_log2 + 8, 24); - # This should be odd to not reveal weak DES keys, and the - # maximum valid value is (2**24 - 1) which is odd anyway. - $count = (1 << $count_log2) - 1; - - $output = '_'; - $output .= $this->itoa64[$count & 0x3f]; - $output .= $this->itoa64[($count >> 6) & 0x3f]; - $output .= $this->itoa64[($count >> 12) & 0x3f]; - $output .= $this->itoa64[($count >> 18) & 0x3f]; - - $output .= $this->encode64($input, 3); - - return $output; - } - - function gensalt_blowfish($input) - { - # This one needs to use a different order of characters and a - # different encoding scheme from the one in encode64() above. - # We care because the last character in our encoded string will - # only represent 2 bits. While two known implementations of - # bcrypt will happily accept and correct a salt string which - # has the 4 unused bits set to non-zero, we do not want to take - # chances and we also do not want to waste an additional byte - # of entropy. - $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - - $output = '$2a$'; - $output .= chr(ord('0') + $this->iteration_count_log2 / 10); - $output .= chr(ord('0') + $this->iteration_count_log2 % 10); - $output .= '$'; - - $i = 0; - do { - $c1 = ord($input[$i++]); - $output .= $itoa64[$c1 >> 2]; - $c1 = ($c1 & 0x03) << 4; - if ($i >= 16) { - $output .= $itoa64[$c1]; - break; - } - - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 4; - $output .= $itoa64[$c1]; - $c1 = ($c2 & 0x0f) << 2; - - $c2 = ord($input[$i++]); - $c1 |= $c2 >> 6; - $output .= $itoa64[$c1]; - $output .= $itoa64[$c2 & 0x3f]; - } while (1); - - return $output; - } - - function HashPassword($password) - { - $random = ''; - - if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { - $random = $this->get_random_bytes(16); - $hash = - crypt($password, $this->gensalt_blowfish($random)); - if (strlen($hash) === 60) - return $hash; - } - - if (CRYPT_EXT_DES === 1 && !$this->portable_hashes) { - if (strlen($random) < 3) - $random = $this->get_random_bytes(3); - $hash = - crypt($password, $this->gensalt_extended($random)); - if (strlen($hash) === 20) - return $hash; - } - - if (strlen($random) < 6) - $random = $this->get_random_bytes(6); - $hash = - $this->crypt_private($password, - $this->gensalt_private($random)); - if (strlen($hash) === 34) - return $hash; - - # Returning '*' on error is safe here, but would _not_ be safe - # in a crypt(3)-like function used _both_ for generating new - # hashes and for validating passwords against existing hashes. - return '*'; - } - - function CheckPassword($password, $stored_hash) - { - $hash = $this->crypt_private($password, $stored_hash); - if ($hash[0] === '*') - $hash = crypt($password, $stored_hash); - - return $hash === $stored_hash; - } +class PasswordHash +{ + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; + + function __construct($iteration_count_log2, $portable_hashes) + { + $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) { + $iteration_count_log2 = 8; + } + $this->iteration_count_log2 = $iteration_count_log2; + + $this->portable_hashes = $portable_hashes; + + $this->random_state = microtime(); + if (function_exists('getmypid')) { + $this->random_state .= getmypid(); + } + } + + function get_random_bytes($count) + { + $output = ''; + if (is_readable('/dev/urandom') && + ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } + + if (strlen($output) < $count) { + $output = ''; + for ($i = 0; $i < $count; $i += 16) { + $this->random_state = + md5(microtime() . $this->random_state); + $output .= + pack('H*', md5($this->random_state)); + } + $output = substr($output, 0, $count); + } + + return $output; + } + + function encode64($input, $count) + { + $output = ''; + $i = 0; + do { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + if ($i < $count) { + $value |= ord($input[$i]) << 8; + } + $output .= $this->itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) { + break; + } + if ($i < $count) { + $value |= ord($input[$i]) << 16; + } + $output .= $this->itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) { + break; + } + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; + } + + function gensalt_private($input) + { + $output = '$P$'; + $output .= $this->itoa64[min($this->iteration_count_log2 + + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; + $output .= $this->encode64($input, 6); + + return $output; + } + + function crypt_private($password, $setting) + { + $output = '*0'; + if (substr($setting, 0, 2) === $output) { + $output = '*1'; + } + + $id = substr($setting, 0, 3); + # We use "$P$", phpBB3 uses "$H$" for the same thing + if ($id !== '$P$' && $id !== '$H$') { + return $output; + } + + $count_log2 = strpos($this->itoa64, $setting[3]); + if ($count_log2 < 7 || $count_log2 > 30) { + return $output; + } + + $count = 1 << $count_log2; + + $salt = substr($setting, 4, 8); + if (strlen($salt) !== 8) { + return $output; + } + + # We're kind of forced to use MD5 here since it's the only + # cryptographic primitive available in all versions of PHP + # currently in use. To implement our own low-level crypto + # in PHP would result in much worse performance and + # consequently in lower iteration counts and hashes that are + # quicker to crack (by non-PHP code). + if (PHP_VERSION >= '5') { + $hash = md5($salt . $password, true); + do { + $hash = md5($hash . $password, true); + } while (--$count); + } else { + $hash = pack('H*', md5($salt . $password)); + do { + $hash = pack('H*', md5($hash . $password)); + } while (--$count); + } + + $output = substr($setting, 0, 12); + $output .= $this->encode64($hash, 16); + + return $output; + } + + function gensalt_extended($input) + { + $count_log2 = min($this->iteration_count_log2 + 8, 24); + # This should be odd to not reveal weak DES keys, and the + # maximum valid value is (2**24 - 1) which is odd anyway. + $count = (1 << $count_log2) - 1; + + $output = '_'; + $output .= $this->itoa64[$count & 0x3f]; + $output .= $this->itoa64[($count >> 6) & 0x3f]; + $output .= $this->itoa64[($count >> 12) & 0x3f]; + $output .= $this->itoa64[($count >> 18) & 0x3f]; + + $output .= $this->encode64($input, 3); + + return $output; + } + + function gensalt_blowfish($input) + { + # This one needs to use a different order of characters and a + # different encoding scheme from the one in encode64() above. + # We care because the last character in our encoded string will + # only represent 2 bits. While two known implementations of + # bcrypt will happily accept and correct a salt string which + # has the 4 unused bits set to non-zero, we do not want to take + # chances and we also do not want to waste an additional byte + # of entropy. + $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + $output = '$2a$'; + $output .= chr(ord('0') + $this->iteration_count_log2 / 10); + $output .= chr(ord('0') + $this->iteration_count_log2 % 10); + $output .= '$'; + + $i = 0; + do { + $c1 = ord($input[$i++]); + $output .= $itoa64[$c1 >> 2]; + $c1 = ($c1 & 0x03) << 4; + if ($i >= 16) { + $output .= $itoa64[$c1]; + break; + } + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 4; + $output .= $itoa64[$c1]; + $c1 = ($c2 & 0x0f) << 2; + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 6; + $output .= $itoa64[$c1]; + $output .= $itoa64[$c2 & 0x3f]; + } while (1); + + return $output; + } + + function HashPassword($password) + { + $random = ''; + + if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { + $random = $this->get_random_bytes(16); + $hash = + crypt($password, $this->gensalt_blowfish($random)); + if (strlen($hash) === 60) { + return $hash; + } + } + + if (CRYPT_EXT_DES === 1 && !$this->portable_hashes) { + if (strlen($random) < 3) { + $random = $this->get_random_bytes(3); + } + $hash = + crypt($password, $this->gensalt_extended($random)); + if (strlen($hash) === 20) { + return $hash; + } + } + + if (strlen($random) < 6) { + $random = $this->get_random_bytes(6); + } + $hash = + $this->crypt_private($password, + $this->gensalt_private($random)); + if (strlen($hash) === 34) { + return $hash; + } + + # Returning '*' on error is safe here, but would _not_ be safe + # in a crypt(3)-like function used _both_ for generating new + # hashes and for validating passwords against existing hashes. + return '*'; + } + + function CheckPassword($password, $stored_hash) + { + $hash = $this->crypt_private($password, $stored_hash); + if ($hash[0] === '*') { + $hash = crypt($password, $stored_hash); + } + + return $hash === $stored_hash; + } } - -?> diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index cf11109..bf6f5b1 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -28,73 +28,76 @@ use OCP\Defaults; use OCP\IConfig; use OCP\IL10N; use OCP\Settings\ISettings; -use OCA\user_sql\lib\Helper; -class Admin implements ISettings { - /** @var IL10N */ - private $l10n; - /** @var Defaults */ - private $defaults; - /** @var IConfig */ - private $config; +class Admin implements ISettings +{ + /** @var IL10N */ + private $l10n; + /** @var Defaults */ + private $defaults; + /** @var IConfig */ + private $config; - /** - * @param IL10N $l10n - * @param Defaults $defaults - * @param IConfig $config - */ - public function __construct(IL10N $l10n, - Defaults $defaults, - IConfig $config) { - $this->l10n = $l10n; - $this->defaults = $defaults; - $this->config = $config; - $this->helper = new \OCA\user_sql\lib\Helper(); - $this->params = $this->helper->getParameterArray(); - $this->settings = $this->helper -> loadSettingsForDomain('default'); - } + /** + * @param IL10N $l10n + * @param Defaults $defaults + * @param IConfig $config + */ + public function __construct( + IL10N $l10n, + Defaults $defaults, + IConfig $config + ) { + $this->l10n = $l10n; + $this->defaults = $defaults; + $this->config = $config; + $this->helper = new \OCA\user_sql\lib\Helper(); + $this->params = $this->helper->getParameterArray(); + $this->settings = $this->helper->loadSettingsForDomain('default'); + } - /** - * @return TemplateResponse - */ - public function getForm() { + /** + * @return TemplateResponse + */ + public function getForm() + { - $type = $this->config->getAppValue('user_sql', 'type'); - $trusted_domains = \OC::$server->getConfig()->getSystemValue('trusted_domains'); - $inserted = array('default'); - array_splice($trusted_domains, 0, 0, $inserted); + $type = $this->config->getAppValue('user_sql', 'type'); + $trusted_domains = \OC::$server->getConfig()->getSystemValue('trusted_domains'); + $inserted = array('default'); + array_splice($trusted_domains, 0, 0, $inserted); - $params = [ - 'type' => $type, - ]; - $params['allowed_domains']= array_unique($trusted_domains); + $params = [ + 'type' => $type, + ]; + $params['allowed_domains'] = array_unique($trusted_domains); - foreach($this->params as $key) - { - $value = $this->settings[$key]; - $params[$key]=$value; - } + foreach ($this->params as $key) { + $value = $this->settings[$key]; + $params[$key] = $value; + } - $params["config"]=$this->config; - return new TemplateResponse('user_sql', 'admin', $params); - } + $params["config"] = $this->config; + return new TemplateResponse('user_sql', 'admin', $params); + } - /** - * @return string the section ID, e.g. 'sharing' - */ - public function getSection() { - return 'usersql'; - } - - /** - * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. - * - * keep the server setting at the top, right after "server settings" - */ - public function getPriority() { - return 0; - } + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() + { + return 'user_sql'; + } + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * keep the server setting at the top, right after "server settings" + */ + public function getPriority() + { + return 0; + } } diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php index 091f8f2..9d6ba23 100644 --- a/lib/Settings/Section.php +++ b/lib/Settings/Section.php @@ -27,42 +27,49 @@ use OCP\IL10N; use OCP\Settings\IIconSection; use OCP\IURLGenerator; -class Section implements IIconSection { - /** @var IL10N */ - private $l; +class Section implements IIconSection +{ + /** @var IL10N */ + private $l; - /** - * @param IL10N $l - */ - public function __construct(IURLGenerator $url,IL10N $l) { - $this->l = $l; - $this->url = $url; - } + /** + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) + { + $this->l = $l; + $this->url = $url; + } - /** - * {@inheritdoc} - */ - public function getID() { - return 'usersql'; - } + /** + * {@inheritdoc} + */ + public function getID() + { + return 'user_sql'; + } - /** - * {@inheritdoc} - */ - public function getName() { - return $this->l->t('User SQL'); - } + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->l->t('User SQL'); + } - /** - * {@inheritdoc} - */ - public function getPriority() { - return 75; - } - /** - * {@inheritdoc} - */ - public function getIcon() { - return $this->url->imagePath('user_sql', 'app-dark.svg'); - } + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 75; + } + + /** + * {@inheritdoc} + */ + public function getIcon() + { + return $this->url->imagePath('user_sql', 'app-dark.svg'); + } } diff --git a/lib/drupal.php b/lib/drupal.php index 4c7e0a4..3b07cda 100644 --- a/lib/drupal.php +++ b/lib/drupal.php @@ -1,321 +1,330 @@ -<?php
-
-/**
- * @file
- * Secure password hashing functions for user authentication.
- * Adopted from Drupal 7.x WD 2018-01-04
- *
- * Based on the Portable PHP password hashing framework.
- * @see http://www.openwall.com/phpass/
- *
- * An alternative or custom version of this password hashing API may be
- * used by setting the variable password_inc to the name of the PHP file
- * containing replacement user_hash_password(), user_check_password(), and
- * user_needs_new_hash() functions.
- */
-
-/**
- * The standard log2 number of iterations for password stretching. This should
- * increase by 1 every Drupal version in order to counteract increases in the
- * speed and power of computers available to crack the hashes.
- */
-define('HASH_COUNT', 15);
-
-/**
- * The minimum allowed log2 number of iterations for password stretching.
- */
-define('MIN_HASH_COUNT', 7);
-
-/**
- * The maximum allowed log2 number of iterations for password stretching.
- */
-define('MAX_HASH_COUNT', 30);
-
-/**
- * The expected (and maximum) number of characters in a hashed password.
- */
-define('HASH_LENGTH', 55);
-
-/**
- * Returns a string for mapping an int to the corresponding base 64 character.
- */
-function _password_itoa64() {
- return './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
-}
-
-/**
- * Encodes bytes into printable base 64 using the *nix standard from crypt().
- *
- * @param $input
- * The string containing bytes to encode.
- * @param $count
- * The number of characters (bytes) to encode.
- *
- * @return
- * Encoded string
- */
-function _password_base64_encode($input, $count) {
- $output = '';
- $i = 0;
- $itoa64 = _password_itoa64();
- do {
- $value = ord($input[$i++]);
- $output .= $itoa64[$value & 0x3f];
- if ($i < $count) {
- $value |= ord($input[$i]) << 8;
- }
- $output .= $itoa64[($value >> 6) & 0x3f];
- if ($i++ >= $count) {
- break;
- }
- if ($i < $count) {
- $value |= ord($input[$i]) << 16;
- }
- $output .= $itoa64[($value >> 12) & 0x3f];
- if ($i++ >= $count) {
- break;
- }
- $output .= $itoa64[($value >> 18) & 0x3f];
- } while ($i < $count);
-
- return $output;
-}
-/**
- * Returns a string of highly randomized bytes (over the full 8-bit range).
- *
- * This function is better than simply calling mt_rand() or any other built-in
- * PHP function because it can return a long string of bytes (compared to < 4
- * bytes normally from mt_rand()) and uses the best available pseudo-random
- * source.
- *
- * @param $count
- * The number of characters (bytes) to return in the string.
- */
-
- function _random_bytes($count) {
- // $random_state does not use static as it stores random bytes.
- static $random_state, $bytes, $has_openssl;
-
- $missing_bytes = $count - strlen($bytes);
-
- if ($missing_bytes > 0) {
- // PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes()
- // locking on Windows and rendered it unusable.
- if (!isset($has_openssl)) {
- $has_openssl = version_compare(PHP_VERSION, '5.3.4', '>=') && function_exists('openssl_random_pseudo_bytes');
- }
-
- // openssl_random_pseudo_bytes() will find entropy in a system-dependent
- // way.
- if ($has_openssl) {
- $bytes .= openssl_random_pseudo_bytes($missing_bytes);
- }
-
- // Else, read directly from /dev/urandom, which is available on many *nix
- // systems and is considered cryptographically secure.
- elseif ($fh = @fopen('/dev/urandom', 'rb')) {
- // PHP only performs buffered reads, so in reality it will always read
- // at least 4096 bytes. Thus, it costs nothing extra to read and store
- // that much so as to speed any additional invocations.
- $bytes .= fread($fh, max(4096, $missing_bytes));
- fclose($fh);
- }
-
- // If we couldn't get enough entropy, this simple hash-based PRNG will
- // generate a good set of pseudo-random bytes on any system.
- // Note that it may be important that our $random_state is passed
- // through hash() prior to being rolled into $output, that the two hash()
- // invocations are different, and that the extra input into the first one -
- // the microtime() - is prepended rather than appended. This is to avoid
- // directly leaking $random_state via the $output stream, which could
- // allow for trivial prediction of further "random" numbers.
- if (strlen($bytes) < $count) {
- // Initialize on the first call. The contents of $_SERVER includes a mix of
- // user-specific and system information that varies a little with each page.
- if (!isset($random_state)) {
- $random_state = print_r($_SERVER, TRUE);
- if (function_exists('getmypid')) {
- // Further initialize with the somewhat random PHP process ID.
- $random_state .= getmypid();
- }
- $bytes = '';
- }
-
- do {
- $random_state = hash('sha256', microtime() . mt_rand() . $random_state);
- $bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
- }
- while (strlen($bytes) < $count);
- }
- }
- $output = substr($bytes, 0, $count);
- $bytes = substr($bytes, $count);
- return $output;
-}
-
-/**
- * Generates a random base 64-encoded salt prefixed with settings for the hash.
- *
- * Proper use of salts may defeat a number of attacks, including:
- * - The ability to try candidate passwords against multiple hashes at once.
- * - The ability to use pre-hashed lists of candidate passwords.
- * - The ability to determine whether two users have the same (or different)
- * password without actually having to guess one of the passwords.
- *
- * @param $count_log2
- * Integer that determines the number of iterations used in the hashing
- * process. A larger value is more secure, but takes more time to complete.
- *
- * @return
- * A 12 character string containing the iteration count and a random salt.
- */
-function _password_generate_salt($count_log2) {
- $output = '$S$';
- // Ensure that $count_log2 is within set bounds.
- $count_log2 = _password_enforce_log2_boundaries($count_log2);
- // We encode the final log2 iteration count in base 64.
- $itoa64 = _password_itoa64();
- $output .= $itoa64[$count_log2];
- // 6 bytes is the standard salt for a portable phpass hash.
- $output .= _password_base64_encode(_random_bytes(6), 6);
- return $output;
-}
-
-/**
- * Ensures that $count_log2 is within set bounds.
- *
- * @param $count_log2
- * Integer that determines the number of iterations used in the hashing
- * process. A larger value is more secure, but takes more time to complete.
- *
- * @return
- * Integer within set bounds that is closest to $count_log2.
- */
-function _password_enforce_log2_boundaries($count_log2) {
- if ($count_log2 < MIN_HASH_COUNT) {
- return MIN_HASH_COUNT;
- }
- elseif ($count_log2 > MAX_HASH_COUNT) {
- return MAX_HASH_COUNT;
- }
-
- return (int) $count_log2;
-}
-
-/**
- * Hash a password using a secure stretched hash.
- *
- * By using a salt and repeated hashing the password is "stretched". Its
- * security is increased because it becomes much more computationally costly
- * for an attacker to try to break the hash by brute-force computation of the
- * hashes of a large number of plain-text words or strings to find a match.
- *
- * @param $algo
- * The string name of a hashing algorithm usable by hash(), like 'sha256'.
- * @param $password
- * Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to hash.
- * @param $setting
- * An existing hash or the output of _password_generate_salt(). Must be
- * at least 12 characters (the settings and salt).
- *
- * @return
- * A string containing the hashed password (and salt) or FALSE on failure.
- * The return string will be truncated at DRUPAL_HASH_LENGTH characters max.
- */
-function _password_crypt($algo, $password, $setting) {
- // Prevent DoS attacks by refusing to hash large passwords.
- if (strlen($password) > 512) {
- return FALSE;
- }
- // The first 12 characters of an existing hash are its setting string.
- $setting = substr($setting, 0, 12);
-
- if ($setting[0] != '$' || $setting[2] != '$') {
- return FALSE;
- }
- $count_log2 = _password_get_count_log2($setting);
- // Hashes may be imported from elsewhere, so we allow != DRUPAL_HASH_COUNT
- if ($count_log2 < MIN_HASH_COUNT || $count_log2 > MAX_HASH_COUNT) {
- return FALSE;
- }
- $salt = substr($setting, 4, 8);
- // Hashes must have an 8 character salt.
- if (strlen($salt) != 8) {
- return FALSE;
- }
-
- // Convert the base 2 logarithm into an integer.
- $count = 1 << $count_log2;
-
- // We rely on the hash() function being available in PHP 5.2+.
- $hash = hash($algo, $salt . $password, TRUE);
- do {
- $hash = hash($algo, $hash . $password, TRUE);
- } while (--$count);
-
- $len = strlen($hash);
- $output = $setting . _password_base64_encode($hash, $len);
- // _password_base64_encode() of a 16 byte MD5 will always be 22 characters.
- // _password_base64_encode() of a 64 byte sha512 will always be 86 characters.
- $expected = 12 + ceil((8 * $len) / 6);
- return (strlen($output) == $expected) ? substr($output, 0, HASH_LENGTH) : FALSE;
-}
-
-/**
- * Parse the log2 iteration count from a stored hash or setting string.
- */
-function _password_get_count_log2($setting) {
- $itoa64 = _password_itoa64();
- return strpos($itoa64, $setting[3]);
-}
-
-/**
- * Hash a password using a secure hash.
- *
- * @param $password
- * A plain-text password.
- * @param $count_log2
- * Optional integer to specify the iteration count. Generally used only during
- * mass operations where a value less than the default is needed for speed.
- *
- * @return
- * A string containing the hashed password (and a salt), or FALSE on failure.
- */
-function user_hash_password($password, $count_log2 = 0) {
- if (empty($count_log2)) {
- // Use the standard iteration count.
- $count_log2 = variable_get('password_count_log2', DRUPAL_HASH_COUNT);
- }
- return _password_crypt('sha512', $password, _password_generate_salt($count_log2));
-}
-
-/**
- * Check whether a plain text password matches a stored hashed password.
- *
- * @param $password
- * A plain-text password
- * @param $hashpass
- *
- * @return
- * TRUE or FALSE.
- */
-function user_check_password($password, $hashpass) {
- $stored_hash = $hashpass;
- $type = substr($stored_hash, 0, 3);
- switch ($type) {
- case '$S$':
- // A normal Drupal 7 password using sha512.
- $hash = _password_crypt('sha512', $password, $stored_hash);
- break;
- case '$H$':
- // phpBB3 uses "$H$" for the same thing as "$P$".
- case '$P$':
- // A phpass password generated using md5. This is an
- // imported password or from an earlier Drupal version.
- $hash = _password_crypt('md5', $password, $stored_hash);
- break;
- default:
- return FALSE;
- }
- return ($hash && $stored_hash == $hash);
-}
\ No newline at end of file +<?php + +/** + * @file + * Secure password hashing functions for user authentication. + * Adopted from Drupal 7.x WD 2018-01-04 + * + * Based on the Portable PHP password hashing framework. + * @see http://www.openwall.com/phpass/ + * + * An alternative or custom version of this password hashing API may be + * used by setting the variable password_inc to the name of the PHP file + * containing replacement user_hash_password(), user_check_password(), and + * user_needs_new_hash() functions. + */ + +/** + * The standard log2 number of iterations for password stretching. This should + * increase by 1 every Drupal version in order to counteract increases in the + * speed and power of computers available to crack the hashes. + */ +define('HASH_COUNT', 15); + +/** + * The minimum allowed log2 number of iterations for password stretching. + */ +define('MIN_HASH_COUNT', 7); + +/** + * The maximum allowed log2 number of iterations for password stretching. + */ +define('MAX_HASH_COUNT', 30); + +/** + * The expected (and maximum) number of characters in a hashed password. + */ +define('HASH_LENGTH', 55); + +/** + * Returns a string for mapping an int to the corresponding base 64 character. + */ +function _password_itoa64() +{ + return './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; +} + +/** + * Encodes bytes into printable base 64 using the *nix standard from crypt(). + * + * @param $input + * The string containing bytes to encode. + * @param $count + * The number of characters (bytes) to encode. + * + * @return + * Encoded string + */ +function _password_base64_encode($input, $count) +{ + $output = ''; + $i = 0; + $itoa64 = _password_itoa64(); + do { + $value = ord($input[$i++]); + $output .= $itoa64[$value & 0x3f]; + if ($i < $count) { + $value |= ord($input[$i]) << 8; + } + $output .= $itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) { + break; + } + if ($i < $count) { + $value |= ord($input[$i]) << 16; + } + $output .= $itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) { + break; + } + $output .= $itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; +} + +/** + * Returns a string of highly randomized bytes (over the full 8-bit range). + * + * This function is better than simply calling mt_rand() or any other built-in + * PHP function because it can return a long string of bytes (compared to < 4 + * bytes normally from mt_rand()) and uses the best available pseudo-random + * source. + * + * @param $count + * The number of characters (bytes) to return in the string. + */ + +function _random_bytes($count) +{ + // $random_state does not use static as it stores random bytes. + static $random_state, $bytes, $has_openssl; + + $missing_bytes = $count - strlen($bytes); + + if ($missing_bytes > 0) { + // PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes() + // locking on Windows and rendered it unusable. + if (!isset($has_openssl)) { + $has_openssl = version_compare(PHP_VERSION, '5.3.4', + '>=') && function_exists('openssl_random_pseudo_bytes'); + } + + // openssl_random_pseudo_bytes() will find entropy in a system-dependent + // way. + if ($has_openssl) { + $bytes .= openssl_random_pseudo_bytes($missing_bytes); + } + + // Else, read directly from /dev/urandom, which is available on many *nix + // systems and is considered cryptographically secure. + elseif ($fh = @fopen('/dev/urandom', 'rb')) { + // PHP only performs buffered reads, so in reality it will always read + // at least 4096 bytes. Thus, it costs nothing extra to read and store + // that much so as to speed any additional invocations. + $bytes .= fread($fh, max(4096, $missing_bytes)); + fclose($fh); + } + + // If we couldn't get enough entropy, this simple hash-based PRNG will + // generate a good set of pseudo-random bytes on any system. + // Note that it may be important that our $random_state is passed + // through hash() prior to being rolled into $output, that the two hash() + // invocations are different, and that the extra input into the first one - + // the microtime() - is prepended rather than appended. This is to avoid + // directly leaking $random_state via the $output stream, which could + // allow for trivial prediction of further "random" numbers. + if (strlen($bytes) < $count) { + // Initialize on the first call. The contents of $_SERVER includes a mix of + // user-specific and system information that varies a little with each page. + if (!isset($random_state)) { + $random_state = print_r($_SERVER, true); + if (function_exists('getmypid')) { + // Further initialize with the somewhat random PHP process ID. + $random_state .= getmypid(); + } + $bytes = ''; + } + + do { + $random_state = hash('sha256', microtime() . mt_rand() . $random_state); + $bytes .= hash('sha256', mt_rand() . $random_state, true); + } while (strlen($bytes) < $count); + } + } + $output = substr($bytes, 0, $count); + $bytes = substr($bytes, $count); + return $output; +} + +/** + * Generates a random base 64-encoded salt prefixed with settings for the hash. + * + * Proper use of salts may defeat a number of attacks, including: + * - The ability to try candidate passwords against multiple hashes at once. + * - The ability to use pre-hashed lists of candidate passwords. + * - The ability to determine whether two users have the same (or different) + * password without actually having to guess one of the passwords. + * + * @param $count_log2 + * Integer that determines the number of iterations used in the hashing + * process. A larger value is more secure, but takes more time to complete. + * + * @return + * A 12 character string containing the iteration count and a random salt. + */ +function _password_generate_salt($count_log2) +{ + $output = '$S$'; + // Ensure that $count_log2 is within set bounds. + $count_log2 = _password_enforce_log2_boundaries($count_log2); + // We encode the final log2 iteration count in base 64. + $itoa64 = _password_itoa64(); + $output .= $itoa64[$count_log2]; + // 6 bytes is the standard salt for a portable phpass hash. + $output .= _password_base64_encode(_random_bytes(6), 6); + return $output; +} + +/** + * Ensures that $count_log2 is within set bounds. + * + * @param $count_log2 + * Integer that determines the number of iterations used in the hashing + * process. A larger value is more secure, but takes more time to complete. + * + * @return + * Integer within set bounds that is closest to $count_log2. + */ +function _password_enforce_log2_boundaries($count_log2) +{ + if ($count_log2 < MIN_HASH_COUNT) { + return MIN_HASH_COUNT; + } elseif ($count_log2 > MAX_HASH_COUNT) { + return MAX_HASH_COUNT; + } + + return (int)$count_log2; +} + +/** + * Hash a password using a secure stretched hash. + * + * By using a salt and repeated hashing the password is "stretched". Its + * security is increased because it becomes much more computationally costly + * for an attacker to try to break the hash by brute-force computation of the + * hashes of a large number of plain-text words or strings to find a match. + * + * @param $algo + * The string name of a hashing algorithm usable by hash(), like 'sha256'. + * @param $password + * Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to hash. + * @param $setting + * An existing hash or the output of _password_generate_salt(). Must be + * at least 12 characters (the settings and salt). + * + * @return + * A string containing the hashed password (and salt) or FALSE on failure. + * The return string will be truncated at DRUPAL_HASH_LENGTH characters max. + */ +function _password_crypt($algo, $password, $setting) +{ + // Prevent DoS attacks by refusing to hash large passwords. + if (strlen($password) > 512) { + return false; + } + // The first 12 characters of an existing hash are its setting string. + $setting = substr($setting, 0, 12); + + if ($setting[0] != '$' || $setting[2] != '$') { + return false; + } + $count_log2 = _password_get_count_log2($setting); + // Hashes may be imported from elsewhere, so we allow != DRUPAL_HASH_COUNT + if ($count_log2 < MIN_HASH_COUNT || $count_log2 > MAX_HASH_COUNT) { + return false; + } + $salt = substr($setting, 4, 8); + // Hashes must have an 8 character salt. + if (strlen($salt) != 8) { + return false; + } + + // Convert the base 2 logarithm into an integer. + $count = 1 << $count_log2; + + // We rely on the hash() function being available in PHP 5.2+. + $hash = hash($algo, $salt . $password, true); + do { + $hash = hash($algo, $hash . $password, true); + } while (--$count); + + $len = strlen($hash); + $output = $setting . _password_base64_encode($hash, $len); + // _password_base64_encode() of a 16 byte MD5 will always be 22 characters. + // _password_base64_encode() of a 64 byte sha512 will always be 86 characters. + $expected = 12 + ceil((8 * $len) / 6); + return (strlen($output) == $expected) ? substr($output, 0, HASH_LENGTH) : false; +} + +/** + * Parse the log2 iteration count from a stored hash or setting string. + */ +function _password_get_count_log2($setting) +{ + $itoa64 = _password_itoa64(); + return strpos($itoa64, $setting[3]); +} + +/** + * Hash a password using a secure hash. + * + * @param $password + * A plain-text password. + * @param $count_log2 + * Optional integer to specify the iteration count. Generally used only during + * mass operations where a value less than the default is needed for speed. + * + * @return + * A string containing the hashed password (and a salt), or FALSE on failure. + */ +function user_hash_password($password, $count_log2 = 0) +{ + if (empty($count_log2)) { + // Use the standard iteration count. + $count_log2 = variable_get('password_count_log2', DRUPAL_HASH_COUNT); + } + return _password_crypt('sha512', $password, _password_generate_salt($count_log2)); +} + +/** + * Check whether a plain text password matches a stored hashed password. + * + * @param $password + * A plain-text password + * @param $hashpass + * + * @return + * TRUE or FALSE. + */ +function user_check_password($password, $hashpass) +{ + $stored_hash = $hashpass; + $type = substr($stored_hash, 0, 3); + switch ($type) { + case '$S$': + // A normal Drupal 7 password using sha512. + $hash = _password_crypt('sha512', $password, $stored_hash); + break; + case '$H$': + // phpBB3 uses "$H$" for the same thing as "$P$". + case '$P$': + // A phpass password generated using md5. This is an + // imported password or from an earlier Drupal version. + $hash = _password_crypt('md5', $password, $stored_hash); + break; + default: + return false; + } + return ($hash && $stored_hash == $hash); +} diff --git a/lib/group_sql.php b/lib/group_sql.php index b0c1c06..8d06cd0 100644 --- a/lib/group_sql.php +++ b/lib/group_sql.php @@ -2,7 +2,6 @@ namespace OCA\user_sql; -use \OCA\user_sql\lib\Helper; use OCP\Util; class OC_GROUP_SQL extends \OC_Group_Backend implements \OCP\GroupInterface @@ -12,85 +11,78 @@ class OC_GROUP_SQL extends \OC_Group_Backend implements \OCP\GroupInterface public function __construct() { - $this -> helper = new \OCA\user_sql\lib\Helper(); + $this->helper = new \OCA\user_sql\lib\Helper(); $domain = \OC::$server->getRequest()->getServerHost(); - $this -> settings = $this -> helper -> loadSettingsForDomain($domain); - $this -> helper -> connectToDb($this -> settings); + $this->settings = $this->helper->loadSettingsForDomain($domain); + $this->helper->connectToDb($this->settings); return false; } - public function getUserGroups($uid) { - if(empty($this -> settings['sql_group_table'])) - { + public function getUserGroups($uid) + { + if (empty($this->settings['sql_group_table'])) { Util::writeLog('OC_USER_SQL', "Group table not configured", Util::DEBUG); return []; } - $rows = $this -> helper -> runQuery('getUserGroups', array('uid' => $uid), false, true); - if($rows === false) - { + $rows = $this->helper->runQuery('getUserGroups', array('uid' => $uid), false, true); + if ($rows === false) { Util::writeLog('OC_USER_SQL', "Found no group", Util::DEBUG); return []; } $groups = array(); - foreach($rows as $row) - { - $groups[] = $row[$this -> settings['col_group_name']]; - } + foreach ($rows as $row) { + $groups[] = $row[$this->settings['col_group_name']]; + } return $groups; } - public function getGroups($search = '', $limit = null, $offset = null) { - if(empty($this -> settings['sql_group_table'])) - { + public function getGroups($search = '', $limit = null, $offset = null) + { + if (empty($this->settings['sql_group_table'])) { return []; } - $search = "%".$search."%"; - $rows = $this -> helper -> runQuery('getGroups', array('search' => $search), false, true, array('limit' => $limit, 'offset' => $offset)); - if($rows === false) - { + $search = "%" . $search . "%"; + $rows = $this->helper->runQuery('getGroups', array('search' => $search), false, true, + array('limit' => $limit, 'offset' => $offset)); + if ($rows === false) { return []; - } + } $groups = array(); - foreach($rows as $row) - { - $groups[] = $row[$this -> settings['col_group_name']]; - } + foreach ($rows as $row) { + $groups[] = $row[$this->settings['col_group_name']]; + } return $groups; } - public function usersInGroup($gid, $search = '', $limit = null, $offset = null) { - if(empty($this -> settings['sql_group_table'])) - { + public function usersInGroup($gid, $search = '', $limit = null, $offset = null) + { + if (empty($this->settings['sql_group_table'])) { Util::writeLog('OC_USER_SQL', "Group table not configured", Util::DEBUG); return []; } - $rows = $this -> helper -> runQuery('getGroupUsers', array('gid' => $gid), false, true); - if($rows === false) - { + $rows = $this->helper->runQuery('getGroupUsers', array('gid' => $gid), false, true); + if ($rows === false) { Util::writeLog('OC_USER_SQL', "Found no users for group", Util::DEBUG); return []; } $users = array(); - foreach($rows as $row) - { - $users[] = $row[$this -> settings['col_group_username']]; - } + foreach ($rows as $row) { + $users[] = $row[$this->settings['col_group_username']]; + } return $users; } - public function countUsersInGroup($gid, $search = '') { - if(empty($this -> settings['sql_group_table'])) - { + public function countUsersInGroup($gid, $search = '') + { + if (empty($this->settings['sql_group_table'])) { return 0; } - $search = "%".$search."%"; - $count = $this -> helper -> runQuery('countUsersInGroup', array('gid' => $gid, 'search' => $search)); - if($count === false) - { + $search = "%" . $search . "%"; + $count = $this->helper->runQuery('countUsersInGroup', array('gid' => $gid, 'search' => $search)); + if ($count === false) { return 0; } else { return intval(reset($count)); } } } -?> diff --git a/lib/helper.php b/lib/helper.php index 0c0f782..b455e0a 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -1,7 +1,7 @@ <?php /** - * nextCloud - user_sql + * Nextcloud - user_sql * * @author Andreas Böhler and contributors * @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at> @@ -22,10 +22,12 @@ */ namespace OCA\user_sql\lib; + use OCP\IConfig; use OCP\Util; -class Helper { +class Helper +{ protected $db; protected $db_conn; @@ -85,15 +87,13 @@ class Helper { { Util::writeLog('OC_USER_SQL', "Trying to load settings for domain: " . $domain, Util::DEBUG); $settings = array(); - $sql_host = \OC::$server->getConfig()->getAppValue('user_sql', 'sql_hostname_'.$domain, ''); - if($sql_host === '') - { + $sql_host = \OC::$server->getConfig()->getAppValue('user_sql', 'sql_hostname_' . $domain, ''); + if ($sql_host === '') { $domain = 'default'; } - $params = $this -> getParameterArray(); - foreach($params as $param) - { - $settings[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param.'_'.$domain, ''); + $params = $this->getParameterArray(); + foreach ($params as $param) { + $settings[$param] = \OC::$server->getConfig()->getAppValue('user_sql', $param . '_' . $domain, ''); } Util::writeLog('OC_USER_SQL', "Loaded settings for domain: " . $domain, Util::DEBUG); return $settings; @@ -111,159 +111,157 @@ class Helper { public function runQuery($type, $params, $execOnly = false, $fetchArray = false, $limits = array()) { Util::writeLog('OC_USER_SQL', "Entering runQuery for type: " . $type, Util::DEBUG); - if(!$this -> db_conn) + if (!$this->db_conn) { return false; + } - switch($type) - { + switch ($type) { case 'getHome': - $query = "SELECT ".$this->settings['col_gethome']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - break; + $query = "SELECT " . $this->settings['col_gethome'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'getMail': - $query = "SELECT ".$this->settings['col_email']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - break; + $query = "SELECT " . $this->settings['col_email'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'setMail': - $query = "UPDATE ".$this->settings['sql_table']." SET ".$this->settings['col_email']." = :currMail WHERE ".$this->settings['col_username']." = :uid"; - break; + $query = "UPDATE " . $this->settings['sql_table'] . " SET " . $this->settings['col_email'] . " = :currMail WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'getPass': - $query = "SELECT ".$this->settings['col_password']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT " . $this->settings['col_password'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'setPass': - $query = "UPDATE ".$this->settings['sql_table']." SET ".$this->settings['col_password']." = :enc_password WHERE ".$this->settings['col_username'] ." = :uid"; - break; + $query = "UPDATE " . $this->settings['sql_table'] . " SET " . $this->settings['col_password'] . " = :enc_password WHERE " . $this->settings['col_username'] . " = :uid"; + break; case 'getRedmineSalt': - $query = "SELECT salt FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username'] ." = :uid;"; - break; + $query = "SELECT salt FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid;"; + break; case 'countUsers': - $query = "SELECT COUNT(*) FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username'] ." LIKE :search"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT COUNT(*) FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " LIKE :search"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'getUsers': - $query = "SELECT ".$this->settings['col_username']." FROM ".$this->settings['sql_table']; - $query .= " WHERE ".$this->settings['col_username']." LIKE :search"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - $query .= " ORDER BY ".$this->settings['col_username']; - break; + $query = "SELECT " . $this->settings['col_username'] . " FROM " . $this->settings['sql_table']; + $query .= " WHERE " . $this->settings['col_username'] . " LIKE :search"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + $query .= " ORDER BY " . $this->settings['col_username']; + break; case 'userExists': - $query = "SELECT ".$this->settings['col_username']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT " . $this->settings['col_username'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'getDisplayName': - $query = "SELECT ".$this->settings['col_displayname']." FROM ".$this->settings['sql_table']." WHERE ".$this->settings['col_username']." = :uid"; - if($this -> settings['col_active'] !== '') - $query .= " AND " .($this -> settings['set_active_invert'] === 'true' ? "NOT " : "" ) . $this -> settings['col_active']; - break; + $query = "SELECT " . $this->settings['col_displayname'] . " FROM " . $this->settings['sql_table'] . " WHERE " . $this->settings['col_username'] . " = :uid"; + if ($this->settings['col_active'] !== '') { + $query .= " AND " . ($this->settings['set_active_invert'] === 'true' ? "NOT " : "") . $this->settings['col_active']; + } + break; case 'mysqlEncryptSalt': $query = "SELECT ENCRYPT(:pw, :salt);"; - break; + break; case 'mysqlEncrypt': $query = "SELECT ENCRYPT(:pw);"; - break; + break; case 'mysqlPassword': $query = "SELECT PASSWORD(:pw);"; - break; + break; case 'getUserGroups': - $query = "SELECT ".$this->settings['col_group_name']." FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_username']." = :uid"; - break; + $query = "SELECT " . $this->settings['col_group_name'] . " FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_username'] . " = :uid"; + break; case 'getGroups': - $query = "SELECT distinct ".$this->settings['col_group_name']." FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_name']." LIKE :search"; - break; + $query = "SELECT distinct " . $this->settings['col_group_name'] . " FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_name'] . " LIKE :search"; + break; case 'getGroupUsers': - $query = "SELECT distinct ".$this->settings['col_group_username']." FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_name']." = :gid"; - break; + $query = "SELECT distinct " . $this->settings['col_group_username'] . " FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_name'] . " = :gid"; + break; case 'countUsersInGroup': - $query = "SELECT count(".$this->settings['col_group_username'].") FROM ".$this->settings['sql_group_table']." WHERE ".$this->settings['col_group_name']." = :gid AND ".$this->settings['col_group_username']." LIKE :search"; - break; + $query = "SELECT count(" . $this->settings['col_group_username'] . ") FROM " . $this->settings['sql_group_table'] . " WHERE " . $this->settings['col_group_name'] . " = :gid AND " . $this->settings['col_group_username'] . " LIKE :search"; + break; } - if(isset($limits['limit']) && $limits['limit'] !== null) - { + if (isset($limits['limit']) && $limits['limit'] !== null) { $limit = intval($limits['limit']); - $query .= " LIMIT ".$limit; + $query .= " LIMIT " . $limit; } - if(isset($limits['offset']) && $limits['offset'] !== null) - { + if (isset($limits['offset']) && $limits['offset'] !== null) { $offset = intval($limits['offset']); - $query .= " OFFSET ".$offset; + $query .= " OFFSET " . $offset; } Util::writeLog('OC_USER_SQL', "Preparing query: $query", Util::DEBUG); - $result = $this -> db -> prepare($query); - foreach($params as $param => $value) - { - $result -> bindValue(":".$param, $value); + $result = $this->db->prepare($query); + foreach ($params as $param => $value) { + $result->bindValue(":" . $param, $value); } Util::writeLog('OC_USER_SQL', "Executing query...", Util::DEBUG); - if(!$result -> execute()) - { - $err = $result -> errorInfo(); + if (!$result->execute()) { + $err = $result->errorInfo(); Util::writeLog('OC_USER_SQL', "Query failed: " . $err[2], Util::DEBUG); return false; } - if($execOnly === true) - { + if ($execOnly === true) { return true; } Util::writeLog('OC_USER_SQL', "Fetching result...", Util::DEBUG); - if($fetchArray === true) - $row = $result -> fetchAll(); - else - $row = $result -> fetch(); + if ($fetchArray === true) { + $row = $result->fetchAll(); + } else { + $row = $result->fetch(); + } - if(!$row) - { + if (!$row) { return false; } return $row; } /** - * Connect to the database using ownCloud's DBAL + * Connect to the database using Nextcloud's DBAL * @param array $settings The settings for the connection * @return bool */ public function connectToDb($settings) { - $this -> settings = $settings; + $this->settings = $settings; $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); - $parameters = array('host' => $this -> settings['sql_hostname'], - 'password' => $this -> settings['sql_password'], - 'user' => $this -> settings['sql_username'], - 'dbname' => $this -> settings['sql_database'], - 'tablePrefix' => '' - ); - try - { - $this -> db = $cm -> getConnection($this -> settings['sql_driver'], $parameters); - $this -> db -> query("SET NAMES 'UTF8'"); - $this -> db_conn = true; + $parameters = array( + 'host' => $this->settings['sql_hostname'], + 'password' => $this->settings['sql_password'], + 'user' => $this->settings['sql_username'], + 'dbname' => $this->settings['sql_database'], + 'tablePrefix' => '' + ); + try { + $this->db = $cm->getConnection($this->settings['sql_driver'], $parameters); + $this->db->query("SET NAMES 'UTF8'"); + $this->db_conn = true; return true; - } - catch (\Exception $e) - { - Util::writeLog('OC_USER_SQL', 'Failed to connect to the database: ' . $e -> getMessage(), Util::ERROR); - $this -> db_conn = false; + } catch (\Exception $e) { + Util::writeLog('OC_USER_SQL', 'Failed to connect to the database: ' . $e->getMessage(), Util::ERROR); + $this->db_conn = false; return false; } } @@ -275,24 +273,24 @@ class Helper { * @param string $table The table name to check * @param array $cols The columns to check * @param array True if found, otherwise false + * @return bool|string */ public function verifyColumns($parameters, $sql_driver, $table, $cols) { $columns = $this->getColumns($parameters, $sql_driver, $table); $res = true; $err = ''; - foreach($cols as $col) - { - if(!in_array($col, $columns, true)) - { + foreach ($cols as $col) { + if (!in_array($col, $columns, true)) { $res = false; - $err .= $col.' '; + $err .= $col . ' '; } } - if($res) + if ($res) { return true; - else + } else { return $err; + } } /** @@ -301,6 +299,7 @@ class Helper { * @param string $sql_driver The SQL driver to use * @param string $table The table name to check * @param array True if found, otherwise false + * @return bool */ public function verifyTable($parameters, $sql_driver, $table) { @@ -320,8 +319,8 @@ class Helper { { $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); try { - $conn = $cm -> getConnection($sql_driver, $parameters); - $platform = $conn -> getDatabasePlatform(); + $conn = $cm->getConnection($sql_driver, $parameters); + $platform = $conn->getDatabasePlatform(); $queryTables = $platform->getListTablesSQL(); $queryViews = $platform->getListViewsSQL($parameters['dbname']); @@ -339,9 +338,7 @@ class Helper { $ret[] = $name; } return $ret; - } - catch(\Exception $e) - { + } catch (\Exception $e) { return array(); } } @@ -404,13 +401,12 @@ class Helper { { $cm = new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()); try { - $conn = $cm -> getConnection($sql_driver, $parameters); - $platform = $conn -> getDatabasePlatform(); - $query = $platform -> getListTableColumnsSQL($table); - $result = $conn -> executeQuery($query); + $conn = $cm->getConnection($sql_driver, $parameters); + $platform = $conn->getDatabasePlatform(); + $query = $platform->getListTableColumnsSQL($table); + $result = $conn->executeQuery($query); $ret = array(); - while($row = $result -> fetch()) - { + while ($row = $result->fetch()) { switch ($sql_driver) { case 'mysql': $name = $row['Field']; @@ -424,12 +420,8 @@ class Helper { $ret[] = $name; } return $ret; - } - catch(\Exception $e) - { + } catch (\Exception $e) { return array(); } } - - } diff --git a/lib/user_sql.php b/lib/user_sql.php index 936dfbb..b696027 100644 --- a/lib/user_sql.php +++ b/lib/user_sql.php @@ -1,7 +1,7 @@ <?php /** - * nextCloud - user_sql + * Nextcloud - user_sql * * @author Andreas Böhler and contributors * @copyright 2012-2015 Andreas Böhler <dev (at) aboehler (dot) at> @@ -28,30 +28,31 @@ */ namespace OCA\user_sql; + use OC\User\Backend; -use \OCA\user_sql\lib\Helper; use OCP\IConfig; use OCP\IUser; use OCP\IUserSession; -use OCP\Notification\IManager as INotificationManager; use OCP\Util; -abstract class BackendUtility { +abstract class BackendUtility +{ protected $access; /** * constructor, make sure the subclasses call this one! * @param Access $access an instance of Access for LDAP interaction */ - public function __construct(Access $access) { + public function __construct(Access $access) + { $this->access = $access; } } class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, - \OCP\UserInterface + \OCP\UserInterface { protected $cache; protected $settings; @@ -66,26 +67,25 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function __construct() { $memcache = \OC::$server->getMemCacheFactory(); - if ( $memcache -> isAvailable()) - { - $this -> cache = $memcache -> create(); + if ($memcache->isAvailable()) { + $this->cache = $memcache->create(); } - $this -> helper = new \OCA\user_sql\lib\Helper(); + $this->helper = new \OCA\user_sql\lib\Helper(); $domain = \OC::$server->getRequest()->getServerHost(); - $this -> settings = $this -> helper -> loadSettingsForDomain($domain); - $this -> ocConfig = \OC::$server->getConfig(); - $this -> helper -> connectToDb($this -> settings); - $this -> session_cache_name = 'USER_SQL_CACHE'; + $this->settings = $this->helper->loadSettingsForDomain($domain); + $this->ocConfig = \OC::$server->getConfig(); + $this->helper->connectToDb($this->settings); + $this->session_cache_name = 'USER_SQL_CACHE'; return false; } /** - * Sync the user's E-Mail address with the address stored by ownCloud. + * Sync the user's E-Mail address with the address stored by Nextcloud. * We have three (four) sync modes: * - none: Does nothing - * - initial: Do the sync only once from SQL -> ownCloud - * - forcesql: The SQL database always wins and sync to ownCloud - * - forceoc: ownCloud always wins and syncs to SQL + * - initial: Do the sync only once from SQL -> Nextcloud + * - forcesql: The SQL database always wins and sync to Nextcloud + * - forceoc: Nextcloud always wins and syncs to SQL * * @param string $uid The user's ID to sync * @return bool Success or Fail @@ -93,56 +93,57 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, private function doEmailSync($uid) { Util::writeLog('OC_USER_SQL', "Entering doEmailSync for UID: $uid", - Util::DEBUG); - if($this -> settings['col_email'] === '') + Util::DEBUG); + if ($this->settings['col_email'] === '') { return false; + } - if($this -> settings['set_mail_sync_mode'] === 'none') + if ($this->settings['set_mail_sync_mode'] === 'none') { return false; + } $ocUid = $uid; - $uid = $this -> doUserDomainMapping($uid); + $uid = $this->doUserDomainMapping($uid); - $row = $this -> helper -> runQuery('getMail', array('uid' => $uid)); - if($row === false) - { + $row = $this->helper->runQuery('getMail', array('uid' => $uid)); + if ($row === false) { return false; } - $newMail = $row[$this -> settings['col_email']]; + $newMail = $row[$this->settings['col_email']]; - $currMail = $this->ocConfig->getUserValue( $ocUid, - 'settings', - 'email', ''); + $currMail = $this->ocConfig->getUserValue($ocUid, + 'settings', + 'email', ''); - switch($this -> settings['set_mail_sync_mode']) - { + switch ($this->settings['set_mail_sync_mode']) { case 'initial': - if($currMail === '') - $this->ocConfig->setUserValue( $ocUid, - 'settings', - 'email', - $newMail); + if ($currMail === '') { + $this->ocConfig->setUserValue($ocUid, + 'settings', + 'email', + $newMail); + } break; case 'forcesql': //if($currMail !== $newMail) - $this->ocConfig->setUserValue( $ocUid, - 'settings', - 'email', - $newMail); + $this->ocConfig->setUserValue($ocUid, + 'settings', + 'email', + $newMail); break; case 'forceoc': - if(($currMail !== '') && ($currMail !== $newMail)) - { - $row = $this -> helper -> runQuery('setMail', - array('uid' => $uid, - 'currMail' => $currMail) - , true); - - if($row === false) - { + if (($currMail !== '') && ($currMail !== $newMail)) { + $row = $this->helper->runQuery('setMail', + array( + 'uid' => $uid, + 'currMail' => $currMail + ) + , true); + + if ($row === false) { Util::writeLog('OC_USER_SQL', - "Could not update E-Mail address in SQL database!", - Util::ERROR); + "Could not update E-Mail address in SQL database!", + Util::ERROR); } } break; @@ -162,19 +163,17 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { $uid = trim($uid); - if($this -> settings['set_default_domain'] !== '') - { - Util::writeLog('OC_USER_SQL', "Append default domain: ". - $this -> settings['set_default_domain'], Util::DEBUG); - if(strpos($uid, '@') === false) - { - $uid .= "@" . $this -> settings['set_default_domain']; + if ($this->settings['set_default_domain'] !== '') { + Util::writeLog('OC_USER_SQL', "Append default domain: " . + $this->settings['set_default_domain'], Util::DEBUG); + if (strpos($uid, '@') === false) { + $uid .= "@" . $this->settings['set_default_domain']; } } $uid = strtolower($uid); Util::writeLog('OC_USER_SQL', 'Returning mapped UID: ' . $uid, - Util::DEBUG); + Util::DEBUG); return $uid; } @@ -186,12 +185,12 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function implementsActions($actions) { return (bool)((Backend::CHECK_PASSWORD - | Backend::GET_DISPLAYNAME - | Backend::COUNT_USERS - | ($this -> settings['set_allow_pwchange'] === 'true' ? - Backend::SET_PASSWORD : 0) - | ($this -> settings['set_enable_gethome'] === 'true' ? - Backend::GET_HOME : 0) + | Backend::GET_DISPLAYNAME + | Backend::COUNT_USERS + | ($this->settings['set_allow_pwchange'] === 'true' ? + Backend::SET_PASSWORD : 0) + | ($this->settings['set_enable_gethome'] === 'true' ? + Backend::GET_HOME : 0) ) & $actions); } @@ -212,47 +211,46 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function getHome($uid) { Util::writeLog('OC_USER_SQL', "Entering getHome for UID: $uid", - Util::DEBUG); + Util::DEBUG); - if($this -> settings['set_enable_gethome'] !== 'true') + if ($this->settings['set_enable_gethome'] !== 'true') { return false; + } - $uidMapped = $this -> doUserDomainMapping($uid); + $uidMapped = $this->doUserDomainMapping($uid); $home = false; - switch($this->settings['set_gethome_mode']) - { + switch ($this->settings['set_gethome_mode']) { case 'query': Util::writeLog('OC_USER_SQL', - "getHome with Query selected, running Query...", - Util::DEBUG); - $row = $this -> helper -> runQuery('getHome', - array('uid' => $uidMapped)); - if($row === false) - { + "getHome with Query selected, running Query...", + Util::DEBUG); + $row = $this->helper->runQuery('getHome', + array('uid' => $uidMapped)); + if ($row === false) { Util::writeLog('OC_USER_SQL', - "Got no row, return false", - Util::DEBUG); + "Got no row, return false", + Util::DEBUG); return false; } - $home = $row[$this -> settings['col_gethome']]; - break; + $home = $row[$this->settings['col_gethome']]; + break; case 'static': Util::writeLog('OC_USER_SQL', - "getHome with static selected", - Util::DEBUG); - $home = $this -> settings['set_gethome']; + "getHome with static selected", + Util::DEBUG); + $home = $this->settings['set_gethome']; $home = str_replace('%ud', $uidMapped, $home); $home = str_replace('%u', $uid, $home); $home = str_replace('%d', - $this -> settings['set_default_domain'], - $home); - break; + $this->settings['set_default_domain'], + $home); + break; } Util::writeLog('OC_USER_SQL', - "Returning getHome for UID: $uid with Home $home", - Util::DEBUG); + "Returning getHome for UID: $uid with Home $home", + Util::DEBUG); return $home; } @@ -264,8 +262,8 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { // Can't create user Util::writeLog('OC_USER_SQL', - 'Not possible to create local users from web'. - ' frontend using SQL user backend', Util::ERROR); + 'Not possible to create local users from web' . + ' frontend using SQL user backend', Util::ERROR); return false; } @@ -277,7 +275,7 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function deleteUser($uid) { // Can't delete user - Util::writeLog('OC_USER_SQL', 'Not possible to delete local users'. + Util::writeLog('OC_USER_SQL', 'Not possible to delete local users' . ' from web frontend using SQL user backend', Util::ERROR); return false; } @@ -286,7 +284,7 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, * Set (change) a user password * This can be enabled/disabled in the settings (set_allow_pwchange) * - * @param string $uid The user ID + * @param string $uid The user ID * @param string $password The user's new password * @return bool The return status */ @@ -295,109 +293,87 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, // Update the user's password - this might affect other services, that // use the same database, as well Util::writeLog('OC_USER_SQL', "Entering setPassword for UID: $uid", - Util::DEBUG); + Util::DEBUG); - if($this -> settings['set_allow_pwchange'] !== 'true') + if ($this->settings['set_allow_pwchange'] !== 'true') { return false; + } - $uid = $this -> doUserDomainMapping($uid); + $uid = $this->doUserDomainMapping($uid); - $row = $this -> helper -> runQuery('getPass', array('uid' => $uid)); - if($row === false) - { + $row = $this->helper->runQuery('getPass', array('uid' => $uid)); + if ($row === false) { return false; } - $old_password = $row[$this -> settings['col_password']]; + $old_password = $row[$this->settings['col_password']]; // Added and disabled updating passwords for Drupal 7 WD 2018-01-04 - if($this -> settings['set_crypt_type'] === 'drupal') - { + if ($this->settings['set_crypt_type'] === 'drupal') { return false; - } - elseif($this -> settings['set_crypt_type'] === 'joomla2') - { - if(!class_exists('\PasswordHash')) + } elseif ($this->settings['set_crypt_type'] === 'joomla2') { + if (!class_exists('\PasswordHash')) { require_once('PasswordHash.php'); + } $hasher = new \PasswordHash(10, true); - $enc_password = $hasher -> HashPassword($password); + $enc_password = $hasher->HashPassword($password); } // Redmine stores the salt separatedly, this doesn't play nice with // the way we check passwords - elseif($this -> settings['set_crypt_type'] === 'redmine') - { - $salt = $this -> helper -> runQuery('getRedmineSalt', - array('uid' => $uid)); - if(!$salt) + elseif ($this->settings['set_crypt_type'] === 'redmine') { + $salt = $this->helper->runQuery('getRedmineSalt', + array('uid' => $uid)); + if (!$salt) { return false; - $enc_password = sha1($salt['salt'].sha1($password)); + } + $enc_password = sha1($salt['salt'] . sha1($password)); - } - elseif($this -> settings['set_crypt_type'] === 'sha1') - { + } elseif ($this->settings['set_crypt_type'] === 'sha1') { $enc_password = sha1($password); - } - elseif($this -> settings['set_crypt_type'] === 'system') - { - $prefix=substr($old_password,0,2); - if ($prefix==="$2") + } elseif ($this->settings['set_crypt_type'] === 'system') { + $prefix = substr($old_password, 0, 2); + if ($prefix === "$2") { + $enc_password = $this->pw_hash($password); + } else { + if (($prefix === "$1") or ($prefix[0] != "$")) //old md5 or DES { - $enc_password = $this->pw_hash($password); + //Update encryption algorithm + $prefix = "$6"; //change to sha512 } - else - { - if (($prefix==="$1") or ($prefix[0] != "$")) //old md5 or DES - { - //Update encryption algorithm - $prefix="$6"; //change to sha512 - } - - $newsalt=$this->create_systemsalt(); - $enc_password=crypt($password,$prefix ."$" . $newsalt); + + $newsalt = $this->create_systemsalt(); + $enc_password = crypt($password, $prefix . "$" . $newsalt); } - } - elseif($this -> settings['set_crypt_type'] === 'password_hash') - { - $enc_password = $this->pw_hash($password); - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5') - { - $enc_password = '{MD5}'.OC_USER_SQL::hex_to_base64(md5($password)); - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5raw') - { - $enc_password = '{MD5RAW}'.md5($password); - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha1') - { - $enc_password = '{SHA}'.OC_USER_SQL::hex_to_base64(sha1($password)); - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha256') - { - $enc_password = '{SHA256}'.OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)); - } - else - { - $enc_password = $this -> pacrypt($password, $old_password); - } - $res = $this -> helper -> runQuery('setPass', - array('uid' => $uid, 'enc_password' => $enc_password), - true); - if($res === false) - { + } elseif ($this->settings['set_crypt_type'] === 'password_hash') { + $enc_password = $this->pw_hash($password); + } elseif ($this->settings['set_crypt_type'] === 'courier_md5') { + $enc_password = '{MD5}' . OC_USER_SQL::hex_to_base64(md5($password)); + } elseif ($this->settings['set_crypt_type'] === 'courier_md5raw') { + $enc_password = '{MD5RAW}' . md5($password); + } elseif ($this->settings['set_crypt_type'] === 'courier_sha1') { + $enc_password = '{SHA}' . OC_USER_SQL::hex_to_base64(sha1($password)); + } elseif ($this->settings['set_crypt_type'] === 'courier_sha256') { + $enc_password = '{SHA256}' . OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)); + } else { + $enc_password = $this->pacrypt($password, $old_password); + } + $res = $this->helper->runQuery('setPass', + array('uid' => $uid, 'enc_password' => $enc_password), + true); + if ($res === false) { Util::writeLog('OC_USER_SQL', "Could not update password!", - Util::ERROR); + Util::ERROR); return false; } Util::writeLog('OC_USER_SQL', - "Updated password successfully, return true", - Util::DEBUG); + "Updated password successfully, return true", + Util::DEBUG); return true; } /** * Check if the password is correct - * @param string $uid The username + * @param string $uid The username * @param string $password The password * @return bool true/false * @@ -406,94 +382,75 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function checkPassword($uid, $password) { Util::writeLog('OC_USER_SQL', - "Entering checkPassword() for UID: $uid", - Util::DEBUG); + "Entering checkPassword() for UID: $uid", + Util::DEBUG); - $uid = $this -> doUserDomainMapping($uid); + $uid = $this->doUserDomainMapping($uid); - $row = $this -> helper -> runQuery('getPass', array('uid' => $uid)); - if($row === false) - { - Util::writeLog('OC_USER_SQL', "Got no row, return false", Util::DEBUG); - return false; - } - $db_pass = $row[$this -> settings['col_password']]; + $row = $this->helper->runQuery('getPass', array('uid' => $uid)); + if ($row === false) { + Util::writeLog('OC_USER_SQL', "Got no row, return false", Util::DEBUG); + return false; + } + $db_pass = $row[$this->settings['col_password']]; Util::writeLog('OC_USER_SQL', "Encrypting and checking password", - Util::DEBUG); + Util::DEBUG); // Added handling for Drupal 7 passwords WD 2018-01-04 - if($this -> settings['set_crypt_type'] === 'drupal') - { - if(!function_exists('user_check_password')) + if ($this->settings['set_crypt_type'] === 'drupal') { + if (!function_exists('user_check_password')) { require_once('drupal.php'); + } $ret = user_check_password($password, $db_pass); } // Joomla 2.5.18 switched to phPass, which doesn't play nice with the // way we check passwords - elseif($this -> settings['set_crypt_type'] === 'joomla2') - { - if(!class_exists('\PasswordHash')) + elseif ($this->settings['set_crypt_type'] === 'joomla2') { + if (!class_exists('\PasswordHash')) { require_once('PasswordHash.php'); + } $hasher = new \PasswordHash(10, true); - $ret = $hasher -> CheckPassword($password, $db_pass); - } - elseif($this -> settings['set_crypt_type'] === 'password_hash') - { - $ret = password_verify($password,$db_pass); + $ret = $hasher->CheckPassword($password, $db_pass); + } elseif ($this->settings['set_crypt_type'] === 'password_hash') { + $ret = password_verify($password, $db_pass); } // Redmine stores the salt separatedly, this doesn't play nice with the // way we check passwords - elseif($this -> settings['set_crypt_type'] === 'redmine') - { - $salt = $this -> helper -> runQuery('getRedmineSalt', - array('uid' => $uid)); - if(!$salt) + elseif ($this->settings['set_crypt_type'] === 'redmine') { + $salt = $this->helper->runQuery('getRedmineSalt', + array('uid' => $uid)); + if (!$salt) { return false; - $ret = sha1($salt['salt'].sha1($password)) === $db_pass; - } - - elseif($this -> settings['set_crypt_type'] == 'sha1') - { - $ret = $this->hash_equals(sha1($password) , $db_pass); - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5') - { - $ret = '{MD5}'.OC_USER_SQL::hex_to_base64(md5($password)) === $db_pass; - } - elseif($this -> settings['set_crypt_type'] === 'courier_md5raw') - { - $ret = '{MD5RAW}'.md5($password) === $db_pass; - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha1') - { - $ret = '{SHA}'.OC_USER_SQL::hex_to_base64(sha1($password)) === $db_pass; - } - elseif($this -> settings['set_crypt_type'] === 'courier_sha256') - { - $ret = '{SHA256}'.OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)) === $db_pass; - } else - - { - // $ret = $this -> pacrypt($password, $db_pass) === $db_pass; - $ret = $this->hash_equals($this -> pacrypt($password, $db_pass), - $db_pass); - } - if($ret) - { + } + $ret = sha1($salt['salt'] . sha1($password)) === $db_pass; + } elseif ($this->settings['set_crypt_type'] == 'sha1') { + $ret = $this->hash_equals(sha1($password), $db_pass); + } elseif ($this->settings['set_crypt_type'] === 'courier_md5') { + $ret = '{MD5}' . OC_USER_SQL::hex_to_base64(md5($password)) === $db_pass; + } elseif ($this->settings['set_crypt_type'] === 'courier_md5raw') { + $ret = '{MD5RAW}' . md5($password) === $db_pass; + } elseif ($this->settings['set_crypt_type'] === 'courier_sha1') { + $ret = '{SHA}' . OC_USER_SQL::hex_to_base64(sha1($password)) === $db_pass; + } elseif ($this->settings['set_crypt_type'] === 'courier_sha256') { + $ret = '{SHA256}' . OC_USER_SQL::hex_to_base64(hash('sha256', $password, false)) === $db_pass; + } else { + // $ret = $this -> pacrypt($password, $db_pass) === $db_pass; + $ret = $this->hash_equals($this->pacrypt($password, $db_pass), + $db_pass); + } + if ($ret) { Util::writeLog('OC_USER_SQL', - "Passwords matching, return true", - Util::DEBUG); - if($this -> settings['set_strip_domain'] === 'true') - { + "Passwords matching, return true", + Util::DEBUG); + if ($this->settings['set_strip_domain'] === 'true') { $uid = explode("@", $uid); $uid = $uid[0]; } return $uid; - } else - { + } else { Util::writeLog('OC_USER_SQL', - "Passwords do not match, return false", - Util::DEBUG); + "Passwords do not match, return false", + Util::DEBUG); return false; } } @@ -505,68 +462,64 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function countUsers() { Util::writeLog('OC_USER_SQL', "Entering countUsers()", - Util::DEBUG); + Util::DEBUG); - $search = "%".$this -> doUserDomainMapping(""); - $userCount = $this -> helper -> runQuery('countUsers', - array('search' => $search)); - if($userCount === false) - { + $search = "%" . $this->doUserDomainMapping(""); + $userCount = $this->helper->runQuery('countUsers', + array('search' => $search)); + if ($userCount === false) { $userCount = 0; - } - else { + } else { $userCount = reset($userCount); } - Util::writeLog('OC_USER_SQL', "Return usercount: ".$userCount, - Util::DEBUG); + Util::writeLog('OC_USER_SQL', "Return usercount: " . $userCount, + Util::DEBUG); return $userCount; } /** * Get a list of all users * @param string $search The search term (can be empty) - * @param int $limit The search limit (can be null) - * @param int $offset The search offset (can be null) + * @param int $limit The search limit (can be null) + * @param int $offset The search offset (can be null) * @return array with all uids */ public function getUsers($search = '', $limit = null, $offset = null) { Util::writeLog('OC_USER_SQL', - "Entering getUsers() with Search: $search, ". - "Limit: $limit, Offset: $offset", Util::DEBUG); + "Entering getUsers() with Search: $search, " . + "Limit: $limit, Offset: $offset", Util::DEBUG); $users = array(); - if($search !== '') - { - $search = "%".$this -> doUserDomainMapping($search."%")."%"; - } - else - { - $search = "%".$this -> doUserDomainMapping("")."%"; - } - - $rows = $this -> helper -> runQuery('getUsers', - array('search' => $search), - false, - true, - array('limit' => $limit, - 'offset' => $offset)); - if($rows === false) + if ($search !== '') { + $search = "%" . $this->doUserDomainMapping($search . "%") . "%"; + } else { + $search = "%" . $this->doUserDomainMapping("") . "%"; + } + + $rows = $this->helper->runQuery('getUsers', + array('search' => $search), + false, + true, + array( + 'limit' => $limit, + 'offset' => $offset + )); + if ($rows === false) { return array(); + } - foreach($rows as $row) - { - $uid = $row[$this -> settings['col_username']]; - if($this -> settings['set_strip_domain'] === 'true') - { + foreach ($rows as $row) { + $uid = $row[$this->settings['col_username']]; + if ($this->settings['set_strip_domain'] === 'true') { $uid = explode("@", $uid); $uid = $uid[0]; } $users[] = strtolower($uid); } Util::writeLog('OC_USER_SQL', "Return list of results", - Util::DEBUG); + Util::DEBUG); return $users; } @@ -579,36 +532,34 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { $cacheKey = 'sql_user_exists_' . $uid; - $cacheVal = $this -> getCache ($cacheKey); + $cacheVal = $this->getCache($cacheKey); Util::writeLog('OC_USER_SQL', - "userExists() for UID: $uid cacheVal: $cacheVal", - Util::DEBUG); - if(!is_null($cacheVal)) + "userExists() for UID: $uid cacheVal: $cacheVal", + Util::DEBUG); + if (!is_null($cacheVal)) { return (bool)$cacheVal; + } Util::writeLog('OC_USER_SQL', - "Entering userExists() for UID: $uid", - Util::DEBUG); + "Entering userExists() for UID: $uid", + Util::DEBUG); // Only if the domain is removed for internal user handling, // we should add the domain back when checking existance - if($this -> settings['set_strip_domain'] === 'true') - { - $uid = $this -> doUserDomainMapping($uid); + if ($this->settings['set_strip_domain'] === 'true') { + $uid = $this->doUserDomainMapping($uid); } - $exists = (bool)$this -> helper -> runQuery('userExists', - array('uid' => $uid));; - $this -> setCache ($cacheKey, $exists, 60); + $exists = (bool)$this->helper->runQuery('userExists', + array('uid' => $uid));; + $this->setCache($cacheKey, $exists, 60); - if(!$exists) - { + if (!$exists) { Util::writeLog('OC_USER_SQL', - "Empty row, user does not exists, return false", - Util::DEBUG); + "Empty row, user does not exists, return false", + Util::DEBUG); return false; - } else - { + } else { Util::writeLog('OC_USER_SQL', "User exists, return true", Util::DEBUG); return true; @@ -624,45 +575,41 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, public function getDisplayName($uid) { Util::writeLog('OC_USER_SQL', - "Entering getDisplayName() for UID: $uid", - Util::DEBUG); + "Entering getDisplayName() for UID: $uid", + Util::DEBUG); - $this -> doEmailSync($uid); - $uid = $this -> doUserDomainMapping($uid); + $this->doEmailSync($uid); + $uid = $this->doUserDomainMapping($uid); - if(!$this -> userExists($uid)) - { + if (!$this->userExists($uid)) { return false; } - $row = $this -> helper -> runQuery('getDisplayName', - array('uid' => $uid)); + $row = $this->helper->runQuery('getDisplayName', + array('uid' => $uid)); - if(!$row) - { + if (!$row) { Util::writeLog('OC_USER_SQL', - "Empty row, user has no display name or ". - "does not exist, return false", - Util::DEBUG); + "Empty row, user has no display name or " . + "does not exist, return false", + Util::DEBUG); return false; - } else - { + } else { Util::writeLog('OC_USER_SQL', - "User exists, return true", - Util::DEBUG); - $displayName = $row[$this -> settings['col_displayname']]; - return $displayName; ; + "User exists, return true", + Util::DEBUG); + $displayName = $row[$this->settings['col_displayname']]; + return $displayName;; } return false; } public function getDisplayNames($search = '', $limit = null, $offset = null) { - $uids = $this -> getUsers($search, $limit, $offset); + $uids = $this->getUsers($search, $limit, $offset); $displayNames = array(); - foreach($uids as $uid) - { - $displayNames[$uid] = $this -> getDisplayName($uid); + foreach ($uids as $uid) { + $displayNames[$uid] = $this->getDisplayName($uid); } return $displayNames; } @@ -686,109 +633,90 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, * salt used - hence * the second parameter ($pw_db), which is the existing hash from the DB. * - * @param string $pw cleartext password - * @param string $pw_db encrypted password from database + * @param string $pw cleartext password + * @param string $pw_db encrypted password from database * @return string encrypted password. */ private function pacrypt($pw, $pw_db = "") { Util::writeLog('OC_USER_SQL', "Entering private pacrypt()", - Util::DEBUG); + Util::DEBUG); $pw = stripslashes($pw); $password = ""; $salt = ""; - if($this -> settings['set_crypt_type'] === 'md5crypt') - { + if ($this->settings['set_crypt_type'] === 'md5crypt') { $split_salt = preg_split('/\$/', $pw_db); - if(isset($split_salt[2])) - { + if (isset($split_salt[2])) { $salt = $split_salt[2]; } - $password = $this -> md5crypt($pw, $salt); - } elseif($this -> settings['set_crypt_type'] === 'md5') - { + $password = $this->md5crypt($pw, $salt); + } elseif ($this->settings['set_crypt_type'] === 'md5') { $password = md5($pw); - } elseif($this -> settings['set_crypt_type'] === 'system') - { + } elseif ($this->settings['set_crypt_type'] === 'system') { // We never generate salts, as user creation is not allowed here $password = crypt($pw, $pw_db); - } elseif($this -> settings['set_crypt_type'] === 'cleartext') - { + } elseif ($this->settings['set_crypt_type'] === 'cleartext') { $password = $pw; } // See // https://sourceforge.net/tracker/?func=detail&atid=937966&aid=1793352&group_id=191583 // this is apparently useful for pam_mysql etc. - elseif($this -> settings['set_crypt_type'] === 'mysql_encrypt') - { - if($pw_db !== "") - { + elseif ($this->settings['set_crypt_type'] === 'mysql_encrypt') { + if ($pw_db !== "") { $salt = substr($pw_db, 0, 2); - $row = $this -> helper -> runQuery('mysqlEncryptSalt', - array('pw' => $pw, 'salt' => $salt)); - } else - { - $row = $this -> helper -> runQuery('mysqlEncrypt', - array('pw' => $pw)); + $row = $this->helper->runQuery('mysqlEncryptSalt', + array('pw' => $pw, 'salt' => $salt)); + } else { + $row = $this->helper->runQuery('mysqlEncrypt', + array('pw' => $pw)); } - if($row === false) - { + if ($row === false) { return false; } $password = $row[0]; - } elseif($this -> settings['set_crypt_type'] === 'mysql_password') - { - $row = $this -> helper -> runQuery('mysqlPassword', - array('pw' => $pw)); + } elseif ($this->settings['set_crypt_type'] === 'mysql_password') { + $row = $this->helper->runQuery('mysqlPassword', + array('pw' => $pw)); - if($row === false) - { + if ($row === false) { return false; } $password = $row[0]; - } - - // The following is by Frédéric France - elseif($this -> settings['set_crypt_type'] === 'joomla') - { + } // The following is by Frédéric France + elseif ($this->settings['set_crypt_type'] === 'joomla') { $split_salt = preg_split('/:/', $pw_db); - if(isset($split_salt[1])) - { + if (isset($split_salt[1])) { $salt = $split_salt[1]; } $password = ($salt) ? md5($pw . $salt) : md5($pw); $password .= ':' . $salt; - } - - elseif($this-> settings['set_crypt_type'] === 'ssha256') - { + } elseif ($this->settings['set_crypt_type'] === 'ssha256') { $salted_password = base64_decode( - preg_replace('/{SSHA256}/i','',$pw_db)); - $salt = substr($salted_password,-(strlen($salted_password)-32)); - $password = $this->ssha256($pw,$salt); - } else - { + preg_replace('/{SSHA256}/i', '', $pw_db)); + $salt = substr($salted_password, -(strlen($salted_password) - 32)); + $password = $this->ssha256($pw, $salt); + } else { Util::writeLog('OC_USER_SQL', - "unknown/invalid crypt_type settings: ". - $this->settings['set_crypt_type'], - Util::ERROR); + "unknown/invalid crypt_type settings: " . + $this->settings['set_crypt_type'], + Util::ERROR); die('unknown/invalid Encryption type setting: ' . - $this -> settings['set_crypt_type']); + $this->settings['set_crypt_type']); } Util::writeLog('OC_USER_SQL', "pacrypt() done, return", - Util::DEBUG); + Util::DEBUG); return $password; } /** * md5crypt * Creates MD5 encrypted password - * @param string $pw The password to encrypt - * @param string $salt The salt to use + * @param string $pw The password to encrypt + * @param string $salt The salt to use * @param string $magic ? * @return string The encrypted password */ @@ -797,75 +725,72 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, { $MAGIC = "$1$"; - if($magic === "") + if ($magic === "") { $magic = $MAGIC; - if($salt === "") - $salt = $this -> create_md5salt(); + } + if ($salt === "") { + $salt = $this->create_md5salt(); + } $slist = explode("$", $salt); - if($slist[0] === "1") + if ($slist[0] === "1") { $salt = $slist[1]; + } $salt = substr($salt, 0, 8); $ctx = $pw . $magic . $salt; - $final = $this -> pahex2bin(md5($pw . $salt . $pw)); + $final = $this->pahex2bin(md5($pw . $salt . $pw)); - for($i = strlen($pw); $i > 0; $i -= 16) - { - if($i > 16) - { + for ($i = strlen($pw); $i > 0; $i -= 16) { + if ($i > 16) { $ctx .= substr($final, 0, 16); - } else - { + } else { $ctx .= substr($final, 0, $i); } } $i = strlen($pw); - while($i > 0) - { - if($i & 1) + while ($i > 0) { + if ($i & 1) { $ctx .= chr(0); - else + } else { $ctx .= $pw[0]; - $i = $i>>1; + } + $i = $i >> 1; } - $final = $this -> pahex2bin(md5($ctx)); + $final = $this->pahex2bin(md5($ctx)); - for($i = 0; $i < 1000; $i++) - { + for ($i = 0; $i < 1000; $i++) { $ctx1 = ""; - if($i & 1) - { + if ($i & 1) { $ctx1 .= $pw; - } else - { + } else { $ctx1 .= substr($final, 0, 16); } - if($i % 3) + if ($i % 3) { $ctx1 .= $salt; - if($i % 7) + } + if ($i % 7) { $ctx1 .= $pw; - if($i & 1) - { + } + if ($i & 1) { $ctx1 .= substr($final, 0, 16); - } else - { + } else { $ctx1 .= $pw; } - $final = $this -> pahex2bin(md5($ctx1)); + $final = $this->pahex2bin(md5($ctx1)); } $passwd = ""; - $passwd .= $this -> to64(((ord($final[0])<<16) | - (ord($final[6])<<8) | (ord($final[12]))), 4); - $passwd .= $this -> to64(((ord($final[1])<<16) | - (ord($final[7])<<8) | (ord($final[13]))), 4); - $passwd .= $this -> to64(((ord($final[2])<<16) | - (ord($final[8])<<8) | (ord($final[14]))), 4); - $passwd .= $this -> to64(((ord($final[3])<<16) | - (ord($final[9])<<8) | (ord($final[15]))), 4); - $passwd .= $this -> to64(((ord($final[4])<<16) | - (ord($final[10])<<8) | (ord($final[5]))), 4); - $passwd .= $this -> to64(ord($final[11]), 2); + $passwd .= $this->to64(((ord($final[0]) << 16) | + (ord($final[6]) << 8) | (ord($final[12]))), 4); + $passwd .= $this->to64(((ord($final[1]) << 16) | + (ord($final[7]) << 8) | (ord($final[13]))), 4); + $passwd .= $this->to64(((ord($final[2]) << 16) | + (ord($final[8]) << 8) | (ord($final[14]))), 4); + $passwd .= $this->to64(((ord($final[3]) << 16) | + (ord($final[9]) << 8) | (ord($final[15]))), 4); + $passwd .= $this->to64(((ord($final[4]) << 16) | + (ord($final[10]) << 8) | (ord($final[5]))), 4); + $passwd .= $this->to64(ord($final[11]), 2); return "$magic$salt\$$passwd"; } @@ -875,20 +800,20 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function create_md5salt() { - srand((double) microtime() * 1000000); + srand((double)microtime() * 1000000); $salt = substr(md5(rand(0, 9999999)), 0, 8); return $salt; } /** * Encrypt using SSHA256 algorithm - * @param string $pw The password + * @param string $pw The password * @param string $salt The salt to use * @return string The hashed password, prefixed by {SSHA256} */ private function ssha256($pw, $salt) { - return '{SSHA256}'.base64_encode(hash('sha256',$pw.$salt,true).$salt); + return '{SSHA256}' . base64_encode(hash('sha256', $pw . $salt, true) . $salt); } /** @@ -898,15 +823,12 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function pahex2bin($str) { - if(function_exists('hex2bin')) - { + if (function_exists('hex2bin')) { return hex2bin($str); - } else - { + } else { $len = strlen($str); $nstr = ""; - for($i = 0; $i < $len; $i += 2) - { + for ($i = 0; $i < $len; $i += 2) { $num = sscanf(substr($str, $i, 2), "%x"); $nstr .= chr($num[0]); } @@ -919,36 +841,33 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function to64($v, $n) { - $ITOA64 = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + $ITOA64 = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; $ret = ""; - while(($n - 1) >= 0) - { + while (($n - 1) >= 0) { $n--; $ret .= $ITOA64[$v & 0x3f]; - $v = $v>>6; + $v = $v >> 6; } return $ret; } /** * Store a value in memcache or the session, if no memcache is available - * @param string $key The key + * @param string $key The key * @param mixed $value The value to store * @param int $ttl (optional) defaults to 3600 seconds. */ - private function setCache($key, $value, $ttl=3600) + private function setCache($key, $value, $ttl = 3600) { - if ($this -> cache === NULL) - { - $_SESSION[$this -> session_cache_name][$key] = array( + if ($this->cache === null) { + $_SESSION[$this->session_cache_name][$key] = array( 'value' => $value, 'time' => time(), 'ttl' => $ttl, ); - } else - { - $this -> cache -> set($key,$value,$ttl); + } else { + $this->cache->set($key, $value, $ttl); } } @@ -960,26 +879,22 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, */ private function getCache($key) { - $retVal = NULL; - if ($this -> cache === NULL) - { - if (isset($_SESSION[$this -> session_cache_name], - $_SESSION[$this -> session_cache_name][$key])) - { - $value = $_SESSION[$this -> session_cache_name][$key]; - if (time() < $value['time'] + $value['ttl']) - { + $retVal = null; + if ($this->cache === null) { + if (isset($_SESSION[$this->session_cache_name], + $_SESSION[$this->session_cache_name][$key])) { + $value = $_SESSION[$this->session_cache_name][$key]; + if (time() < $value['time'] + $value['ttl']) { $retVal = $value['value']; } } - } else - { - $retVal = $this -> cache -> get ($key); + } else { + $retVal = $this->cache->get($key); } return $retVal; } - private function create_systemsalt($length=20) + private function create_systemsalt($length = 20) { $fp = fopen('/dev/urandom', 'r'); $randomString = fread($fp, $length); @@ -991,31 +906,32 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, private function pw_hash($password) { $options = [ - 'cost' => 10, - ]; + 'cost' => 10, + ]; return password_hash($password, PASSWORD_BCRYPT, $options); } - function hash_equals( $a, $b ) { - $a_length = strlen( $a ); + function hash_equals($a, $b) + { + $a_length = strlen($a); - if ( $a_length !== strlen( $b ) ) { + if ($a_length !== strlen($b)) { return false; - } - $result = 0; + } + $result = 0; // Do not attempt to "optimize" this. - for ( $i = 0; $i < $a_length; $i++ ) { - $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] ); + for ($i = 0; $i < $a_length; $i++) { + $result |= ord($a[$i]) ^ ord($b[$i]); } - //Hide the length of the string - $additional_length=200-($a_length % 200); - $tmp=0; - $c="abCD"; - for ( $i = 0; $i < $additional_length; $i++ ) { - $tmp |= ord( $c[ 0 ] ) ^ ord( $c[ 0 ] ); + //Hide the length of the string + $additional_length = 200 - ($a_length % 200); + $tmp = 0; + $c = "abCD"; + for ($i = 0; $i < $additional_length; $i++) { + $tmp |= ord($c[0]) ^ ord($c[0]); } return $result === 0; @@ -1024,11 +940,9 @@ class OC_USER_SQL extends BackendUtility implements \OCP\IUserBackend, private static function hex_to_base64($hex) { $hex_chr = ''; - foreach(str_split($hex, 2) as $hexpair) - { + foreach (str_split($hex, 2) as $hexpair) { $hex_chr .= chr(hexdec($hexpair)); } return base64_encode($hex_chr); } - } diff --git a/templates/admin.php b/templates/admin.php index 4820559..5ff8a8e 100644 --- a/templates/admin.php +++ b/templates/admin.php @@ -1,181 +1,273 @@ <?php script('user_sql', 'settings'); style('user_sql', 'settings'); -$cfgClass = 'section'; +$cfgClass = 'section'; ?> <div class="<?php p($cfgClass); ?>"> <h2><?php p($l->t('SQL User Backend')); ?></h2> -<form id="sqlForm" action="#" method="post" class="<?php p($cfgClass); ?>"> - - <div id="sqlDiv" class="<?php p($cfgClass); ?>"> - <label for="sql_domain_chooser"><?php p($l -> t('Settings for Domain')) ?></label> - <select id="sql_domain_chooser" name="sql_domain_chooser"> - <?php foreach ($_['allowed_domains'] as $domain): ?> - <option value="<?php p($domain); ?>"><?php p($domain); ?></option> - <?php endforeach ?> - </select> - <ul> - <li><a id="sqlBasicSettings" href="#sql-1"><?php p($l -> t('Connection Settings')); ?></a></li> - <li><a id="sqlColSettings" href="#sql-2"><?php p($l -> t('Column Settings')); ?></a></li> - <li><a id="sqlEmailSettings" href="#sql-3"><?php p($l -> t('E-Mail Settings')); ?></a></li> - <li><a id="sqlDomainSettings" href="#sql-4"><?php p($l -> t('Domain Settings')); ?></a></li> - <li><a id="sqlGethomeSettings" href="#sql-5"><?php p($l -> t('getHome Settings')); ?></a></li> - <li><a id="sqlGroupsSettings" href="#sql-6"><?php p($l -> t('Groups Settings')); ?></a></li> - </ul> - - <fieldset id="sql-1"> - <p><label for="sql_driver"><?php p($l -> t('SQL Driver')); ?></label> - <?php $db_driver = array('mysql' => 'MySQL', 'pgsql' => 'PostgreSQL'); ?> - <select id="sql_driver" name="sql_driver"> - <?php + <form id="sqlForm" action="#" method="post" class="<?php p($cfgClass); ?>"> + + <div id="sqlDiv" class="<?php p($cfgClass); ?>"> + <label for="sql_domain_chooser"><?php p($l->t('Settings for Domain')) ?></label> + <select id="sql_domain_chooser" name="sql_domain_chooser"> + <?php foreach ($_['allowed_domains'] as $domain): ?> + <option value="<?php p($domain); ?>"><?php p($domain); ?></option> + <?php endforeach ?> + </select> + <ul> + <li><a id="sqlBasicSettings" href="#sql-1"><?php p($l->t('Connection Settings')); ?></a></li> + <li><a id="sqlColSettings" href="#sql-2"><?php p($l->t('Column Settings')); ?></a></li> + <li><a id="sqlEmailSettings" href="#sql-3"><?php p($l->t('E-Mail Settings')); ?></a></li> + <li><a id="sqlDomainSettings" href="#sql-4"><?php p($l->t('Domain Settings')); ?></a></li> + <li><a id="sqlGethomeSettings" href="#sql-5"><?php p($l->t('getHome Settings')); ?></a></li> + <li><a id="sqlGroupsSettings" href="#sql-6"><?php p($l->t('Groups Settings')); ?></a></li> + </ul> + + <fieldset id="sql-1"> + <p><label for="sql_driver"><?php p($l->t('SQL Driver')); ?></label> + <?php $db_driver = array('mysql' => 'MySQL', 'pgsql' => 'PostgreSQL'); ?> + <select id="sql_driver" name="sql_driver"> + <?php foreach ($db_driver as $driver => $name): //echo $_['sql_driver']; - if($_['sql_driver'] === $driver): ?> + if ($_['sql_driver'] === $driver): ?> <option selected="selected" value="<?php p($driver); ?>"><?php p($name); ?></option> <?php else: ?> <option value="<?php p($driver); ?>"><?php p($name); ?></option> <?php endif; endforeach; - ?> - </select> - </p> - - <p><label for="sql_hostname"><?php p($l -> t('Host')); ?></label><input type="text" id="sql_hostname" name="sql_hostname" value="<?php p($_['sql_hostname']); ?>"></p> - - <p><label for="sql_database"><?php p($l -> t('Database')); ?></label><input type="text" id="sql_database" name="sql_database" value="<?php p($_['sql_database']); ?>" /></p> - - <p><label for="sql_username"><?php p($l -> t('Username')); ?></label><input type="text" id="sql_username" name="sql_username" value="<?php p($_['sql_username']); ?>" /></p> - - <p><label for="sql_password"><?php p($l -> t('Password')); ?></label><input type="password" id="sql_password" name="sql_password" value="<?php p($_['sql_password']); ?>" /></p> - - <p><input type="submit" id="sqlVerify" value="<?php p($l -> t('Verify Settings')); ?>"></p> - - </fieldset> - <fieldset id="sql-2"> - <p><label for="sql_table"><?php p($l -> t('Table')); ?></label><input type="text" id="sql_table" name="sql_table" value="<?php p($_['sql_table']); ?>" /></p> - - <p><label for="col_username"><?php p($l -> t('Username Column')); ?></label><input type="text" id="col_username" name="col_username" value="<?php p($_['col_username']); ?>" /></p> - - <p><label for="col_password"><?php p($l -> t('Password Column')); ?></label><input type="text" id="col_password" name="col_password" value="<?php p($_['col_password']); ?>" /></p> - - <p><label for="set_allow_pwchange"><?php p($l -> t('Allow password changing (read README!)')); ?></label><input type="checkbox" id="set_allow_pwchange" name="set_allow_pwchange" value="1"<?php - if($_['set_allow_pwchange']) - p(' checked'); - ?>><br> - <em><?php p($l -> t('Allow changing passwords. Imposes a security risk if password salts are not recreated.')); ?></em></p> - <em><?php p($l -> t('Only the encryption types "System","password_hash" and "Joomla2" are safe.')); ?></em></p> - - <p><label for="col_displayname"><?php p($l -> t('Real Name Column')); ?></label><input type="text" id="col_displayname" name="col_displayname" value="<?php p($_['col_displayname']); ?>" /></p> - - <p><label for="set_crypt_type"><?php p($l -> t('Encryption Type')); ?></label> - <?php $crypt_types = array('drupal' => 'Drupal 7', 'md5' => 'MD5', 'md5crypt' => 'MD5 Crypt', 'cleartext' => 'Cleartext', 'mysql_encrypt' => 'mySQL ENCRYPT()', 'system' => 'System (crypt)', 'password_hash' => 'password_hash','mysql_password' => 'mySQL PASSWORD()', 'joomla' => 'Joomla MD5 Encryption', 'joomla2' => 'Joomla > 2.5.18 phpass', 'ssha256' => 'Salted SSHA256', 'redmine' => 'Redmine', 'sha1' => 'SHA1', 'courier_md5' => 'Courier base64-encoded MD5', 'courier_md5raw' => 'Courier hexadecimal MD5', 'courier_sha1' => 'Courier base64-encoded SHA1', 'courier_sha256' => 'Courier base64-encoded SHA256'); ?> - <select id="set_crypt_type" name="set_crypt_type"> - <?php + ?> + </select> + </p> + + <p><label for="sql_hostname"><?php p($l->t('Host')); ?></label><input type="text" id="sql_hostname" + name="sql_hostname" + value="<?php p($_['sql_hostname']); ?>"> + </p> + + <p><label for="sql_database"><?php p($l->t('Database')); ?></label><input type="text" id="sql_database" + name="sql_database" + value="<?php p($_['sql_database']); ?>"/> + </p> + + <p><label for="sql_username"><?php p($l->t('Username')); ?></label><input type="text" id="sql_username" + name="sql_username" + value="<?php p($_['sql_username']); ?>"/> + </p> + + <p><label for="sql_password"><?php p($l->t('Password')); ?></label><input type="password" + id="sql_password" + name="sql_password" + value="<?php p($_['sql_password']); ?>"/> + </p> + + <p><input type="submit" id="sqlVerify" value="<?php p($l->t('Verify Settings')); ?>"></p> + + </fieldset> + <fieldset id="sql-2"> + <p><label for="sql_table"><?php p($l->t('Table')); ?></label><input type="text" id="sql_table" + name="sql_table" + value="<?php p($_['sql_table']); ?>"/> + </p> + + <p><label for="col_username"><?php p($l->t('Username Column')); ?></label><input type="text" + id="col_username" + name="col_username" + value="<?php p($_['col_username']); ?>"/> + </p> + + <p><label for="col_password"><?php p($l->t('Password Column')); ?></label><input type="text" + id="col_password" + name="col_password" + value="<?php p($_['col_password']); ?>"/> + </p> + + <p> + <label for="set_allow_pwchange"><?php p($l->t('Allow password changing (read README!)')); ?></label><input + type="checkbox" id="set_allow_pwchange" name="set_allow_pwchange" value="1"<?php + if ($_['set_allow_pwchange']) { + p(' checked'); + } + ?>><br> + <em><?php p($l->t('Allow changing passwords. Imposes a security risk if password salts are not recreated.')); ?></em> + </p> + <em><?php p($l->t('Only the encryption types "System","password_hash" and "Joomla2" are safe.')); ?></em></p> + + <p><label for="col_displayname"><?php p($l->t('Real Name Column')); ?></label><input type="text" + id="col_displayname" + name="col_displayname" + value="<?php p($_['col_displayname']); ?>"/> + </p> + + <p><label for="set_crypt_type"><?php p($l->t('Encryption Type')); ?></label> + <?php $crypt_types = array( + 'drupal' => 'Drupal 7', + 'md5' => 'MD5', + 'md5crypt' => 'MD5 Crypt', + 'cleartext' => 'Cleartext', + 'mysql_encrypt' => 'mySQL ENCRYPT()', + 'system' => 'System (crypt)', + 'password_hash' => 'password_hash', + 'mysql_password' => 'mySQL PASSWORD()', + 'joomla' => 'Joomla MD5 Encryption', + 'joomla2' => 'Joomla > 2.5.18 phpass', + 'ssha256' => 'Salted SSHA256', + 'redmine' => 'Redmine', + 'sha1' => 'SHA1', + 'courier_md5' => 'Courier base64-encoded MD5', + 'courier_md5raw' => 'Courier hexadecimal MD5', + 'courier_sha1' => 'Courier base64-encoded SHA1', + 'courier_sha256' => 'Courier base64-encoded SHA256' + ); ?> + <select id="set_crypt_type" name="set_crypt_type"> + <?php foreach ($crypt_types as $driver => $name): //echo $_['set_crypt_type']; - if($_['set_crypt_type'] === $driver): ?> + if ($_['set_crypt_type'] === $driver): ?> <option selected="selected" value="<?php p($driver); ?>"><?php p($name); ?></option> <?php else: ?> <option value="<?php p($driver); ?>"><?php p($name); ?></option> <?php endif; endforeach; - ?> - </select> - </p> - - <p><label for="col_active"><?php p($l -> t('User Active Column')); ?></label><input type="text" id="col_active" name="col_active" value="<?php p($_['col_active']); ?>" /></p> - - <p><label for="set_active_invert"><?php p($l -> t('Invert Active Value')); ?></label><input type="checkbox" id="set_active_invert" name="set_active_invert" value="1"<?php - if($_['set_active_invert']) - p(' checked'); - ?> /><br> - <em><?php p($l -> t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?></em></p> - - </fieldset> - - <fieldset id="sql-3"> - - <p><label for="col_email"><?php p($l -> t('E-Mail Column')); ?></label><input type="text" id="col_email" name="col_email" value="<?php p($_['col_email']); ?>" /></p> - - <p><label for="set_mail_sync_mode"><?php p($l -> t('E-Mail address sync mode')); ?></label> - <?php $mail_modes = array('none' => 'No Synchronisation', 'initial' => 'Synchronise only once', 'forceoc' => 'Nextcloud always wins', 'forcesql' => 'SQL always wins'); ?> - <select id="set_mail_sync_mode" name="set_mail_sync_mode"> - <?php - foreach ($mail_modes as $mode => $name): - //echo $_['set_mail_sync_mode']; - if($_['set_mail_sync_mode'] === $mode): ?> - <option selected="selected" value="<?php p($mode); ?>"><?php p($name); ?></option> - <?php else: ?> - <option value="<?php p($mode); ?>"><?php p($name); ?></option> - <?php endif; - endforeach; - ?> - </select> - </p> - - </fieldset> - - <fieldset id="sql-4"> - - <p><label for="set_default_domain"><?php p($l -> t('Append Default Domain')); ?></label><input type="text" id="set_default_domain", name="set_default_domain" value="<?php p($_['set_default_domain']); ?>" /><br> - <em><?php p($l -> t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?></em> - </p> - - <p><label for="set_strip_domain"><?php p($l -> t('Strip Domain Part from Username')); ?></label><input type="checkbox" id="set_strip_domain" name="set_strip_domain" value="1"<?php - if($_['set_strip_domain']) - p(' checked'); - ?> /><br> - <em><?php p($l -> t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?></em></p> - - </fieldset> - - <fieldset id="sql-5"> - <p><label for="set_enable_gethome"><?php p($l -> t('Enable support for getHome()')); ?></label><input type="checkbox" id="set_enable_gethome", name="set_enable_gethome" value="1" <?php - if($_['set_enable_gethome']) - p(' checked'); - ?>/></p> - - <p><label for="set_gethome_mode"><?php p($l -> t('Method for getHome')); ?></label> - <?php $gethome_modes = array('query' => 'SQL Column', 'static' => 'Static (with Variables)'); ?> - <select id="set_gethome_mode" name="set_gethome_mode"> - <?php - foreach ($gethome_modes as $mode => $name): - //echo $_['set_mail_sync_mode']; - if($_['set_gethome_mode'] === $mode): ?> - <option selected="selected" value="<?php p($mode); ?>"><?php p($name); ?></option> - <?php else: ?> - <option value="<?php p($mode); ?>"><?php p($name); ?></option> - <?php endif; - endforeach; - ?> - </select> - </p> - - <p><label for="col_gethome"><?php p($l -> t('Home Column')); ?></label><input type="text" id="col_gethome" name="col_gethome" value="<?php p($_['col_gethome']); ?>"></p> - - <p><label for="set_gethome"><?php p($l -> t('Home Dir')); ?></label><input type="text" id="set_gethome" name="set_gethome" value="<?php p($_['set_gethome']); ?>"><br> - <em><?php p($l -> t('You can use the placeholders %%u to specify the user ID (before appending the default domain), %%ud to specify the user ID (after appending the default domain) and %%d to specify the default domain')); ?></em></p> - - </fieldset> - <fieldset id="sql-6"> - <p><label for="sql_group_table"><?php p($l -> t('Table')); ?></label><input type="text" id="sql_group_table" name="sql_group_table" value="<?php p($_['sql_group_table']); ?>" /></p> - - <p><label for="col_group_username"><?php p($l -> t('Username Column')); ?></label><input type="text" id="col_group_username" name="col_group_username" value="<?php p($_['col_group_username']); ?>" /></p> - - <p><label for="col_group_name"><?php p($l -> t('Group Name Column')); ?></label><input type="text" id="col_group_name" name="col_group_name" value="<?php p($_['col_group_name']); ?>" /></p> - - </fieldset> - - <input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>" id="requesttoken" /> - <input type="hidden" name="appname" value="user_sql" /> - <input id="sqlSubmit" type="submit" value="<?php p($l -> t('Save')); ?>" /> - <div id="sql_update_message" class="statusmessage"><?php p($l -> t('Saving...')); ?></div> - <div id="sql_loading_message" class="statusmessage"><?php p($l -> t('Loading...')); ?></div> - <div id="sql_verify_message" class="statusmessage"><?php p($l -> t('Verifying...')); ?></div> - <div id="sql_error_message" class="errormessage"></div> - <div id="sql_success_message" class="successmessage"></div> - </div> -</form> + ?> + </select> + </p> + + <p><label for="col_active"><?php p($l->t('User Active Column')); ?></label><input type="text" + id="col_active" + name="col_active" + value="<?php p($_['col_active']); ?>"/> + </p> + + <p><label for="set_active_invert"><?php p($l->t('Invert Active Value')); ?></label><input + type="checkbox" id="set_active_invert" name="set_active_invert" value="1"<?php + if ($_['set_active_invert']) { + p(' checked'); + } + ?> /><br> + <em><?php p($l->t("Invert the logic of the active column (for blocked users in the SQL DB)")); ?></em> + </p> + + </fieldset> + + <fieldset id="sql-3"> + + <p><label for="col_email"><?php p($l->t('E-Mail Column')); ?></label><input type="text" id="col_email" + name="col_email" + value="<?php p($_['col_email']); ?>"/> + </p> + + <p><label for="set_mail_sync_mode"><?php p($l->t('E-Mail address sync mode')); ?></label> + <?php $mail_modes = array( + 'none' => 'No Synchronisation', + 'initial' => 'Synchronise only once', + 'forceoc' => 'Nextcloud always wins', + 'forcesql' => 'SQL always wins' + ); ?> + <select id="set_mail_sync_mode" name="set_mail_sync_mode"> + <?php + foreach ($mail_modes as $mode => $name): + //echo $_['set_mail_sync_mode']; + if ($_['set_mail_sync_mode'] === $mode): ?> + <option selected="selected" value="<?php p($mode); ?>"><?php p($name); ?></option> + <?php else: ?> + <option value="<?php p($mode); ?>"><?php p($name); ?></option> + <?php endif; + endforeach; + ?> + </select> + </p> + + </fieldset> + + <fieldset id="sql-4"> + + <p><label for="set_default_domain"><?php p($l->t('Append Default Domain')); ?></label><input type="text" + id="set_default_domain" + , + name="set_default_domain" + value="<?php p($_['set_default_domain']); ?>"/><br> + <em><?php p($l->t('Append this string, e.g. a domain name, to each user name. The @-sign is automatically inserted.')); ?></em> + </p> + + <p><label for="set_strip_domain"><?php p($l->t('Strip Domain Part from Username')); ?></label><input + type="checkbox" id="set_strip_domain" name="set_strip_domain" value="1"<?php + if ($_['set_strip_domain']) { + p(' checked'); + } + ?> /><br> + <em><?php p($l->t("Strip Domain Part including @-sign from Username when logging in and retrieving username lists")); ?></em> + </p> + + </fieldset> + + <fieldset id="sql-5"> + <p><label for="set_enable_gethome"><?php p($l->t('Enable support for getHome()')); ?></label><input + type="checkbox" id="set_enable_gethome" , name="set_enable_gethome" value="1" <?php + if ($_['set_enable_gethome']) { + p(' checked'); + } + ?>/></p> + + <p><label for="set_gethome_mode"><?php p($l->t('Method for getHome')); ?></label> + <?php $gethome_modes = array('query' => 'SQL Column', 'static' => 'Static (with Variables)'); ?> + <select id="set_gethome_mode" name="set_gethome_mode"> + <?php + foreach ($gethome_modes as $mode => $name): + //echo $_['set_mail_sync_mode']; + if ($_['set_gethome_mode'] === $mode): ?> + <option selected="selected" value="<?php p($mode); ?>"><?php p($name); ?></option> + <?php else: ?> + <option value="<?php p($mode); ?>"><?php p($name); ?></option> + <?php endif; + endforeach; + ?> + </select> + </p> + + <p><label for="col_gethome"><?php p($l->t('Home Column')); ?></label><input type="text" id="col_gethome" + name="col_gethome" + value="<?php p($_['col_gethome']); ?>"> + </p> + + <p><label for="set_gethome"><?php p($l->t('Home Dir')); ?></label><input type="text" id="set_gethome" + name="set_gethome" + value="<?php p($_['set_gethome']); ?>"><br> + <em><?php p($l->t('You can use the placeholders %%u to specify the user ID (before appending the default domain), %%ud to specify the user ID (after appending the default domain) and %%d to specify the default domain')); ?></em> + </p> + + </fieldset> + <fieldset id="sql-6"> + <p><label for="sql_group_table"><?php p($l->t('Table')); ?></label><input type="text" + id="sql_group_table" + name="sql_group_table" + value="<?php p($_['sql_group_table']); ?>"/> + </p> + + <p><label for="col_group_username"><?php p($l->t('Username Column')); ?></label><input type="text" + id="col_group_username" + name="col_group_username" + value="<?php p($_['col_group_username']); ?>"/> + </p> + + <p><label for="col_group_name"><?php p($l->t('Group Name Column')); ?></label><input type="text" + id="col_group_name" + name="col_group_name" + value="<?php p($_['col_group_name']); ?>"/> + </p> + + </fieldset> + + <input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>" id="requesttoken"/> + <input type="hidden" name="appname" value="user_sql"/> + <input id="sqlSubmit" type="submit" value="<?php p($l->t('Save')); ?>"/> + <div id="sql_update_message" class="statusmessage"><?php p($l->t('Saving...')); ?></div> + <div id="sql_loading_message" class="statusmessage"><?php p($l->t('Loading...')); ?></div> + <div id="sql_verify_message" class="statusmessage"><?php p($l->t('Verifying...')); ?></div> + <div id="sql_error_message" class="errormessage"></div> + <div id="sql_success_message" class="successmessage"></div> + </div> + </form> </div> |