diff --git a/settings.php b/settings.php
--- a/settings.php
+++ b/settings.php
@@ -1,60 +1,61 @@
*
* 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 .
*
*/
-$params = array('sql_host', 'sql_user', 'sql_database', 'sql_password', 'sql_table', 'sql_column_username', 'sql_column_password', 'sql_type', 'sql_column_active', 'strip_domain', 'default_domain');
+$params = array('sql_host', 'sql_user', 'sql_database', 'sql_password', 'sql_table', 'sql_column_username', 'sql_column_password', 'sql_type', 'sql_column_active', 'strip_domain', 'default_domain', 'crypt_type');
OCP\Util::addscript('user_sql', 'settings');
if ($_POST) {
foreach($params as $param){
if(isset($_POST[$param]))
{
OCP\Config::setAppValue('user_sql', $param, $_POST[$param]);
}
elseif($param == 'strip_domain')
{
OCP\Config::setAppValue('user_sql', $param, 0);
}
}
}
// fill template
$tmpl = new OCP\Template( 'user_sql', 'settings');
foreach($params as $param){
$value = htmlentities(OCP\Config::getAppValue('user_sql', $param,''));
$tmpl->assign($param, $value);
}
// settings with default values
$tmpl->assign( 'sql_host', OCP\Config::getAppValue('user_sql', 'sql_host', OC_USER_BACKEND_SQL_DEFAULT_HOST));
$tmpl->assign( 'sql_user', OCP\Config::getAppValue('user_sql', 'sql_user', OC_USER_BACKEND_SQL_DEFAULT_USER));
$tmpl->assign( 'sql_database', OCP\Config::getAppValue( 'user_sql', 'sql_database', OC_USER_BACKEND_SQL_DEFAULT_DB));
$tmpl->assign( 'sql_password', OCP\Config::getAppValue( 'user_sql', 'sql_password', OC_USER_BACKEND_SQL_DEFAULT_PASSWORD));
$tmpl->assign( 'sql_table', OCP\Config::getAppValue( 'user_sql', 'sql_table', OC_USER_BACKEND_SQL_DEFAULT_TABLE));
$tmpl->assign( 'sql_column_password', OCP\Config::getAppValue( 'user_sql', 'sql_column_password', OC_USER_BACKEND_SQL_DEFAULT_PW_COLUMN));
$tmpl->assign( 'sql_column_username', OCP\Config::getAppValue( 'user_sql', 'sql_column_username', OC_USER_BACKEND_SQL_DEFAULT_USER_COLUMN));
$tmpl->assign( 'sql_type', OCP\Config::getAppValue( 'user_sql', 'sql_type', OC_USER_BACKEND_SQL_DEFAULT_DRIVER));
$tmpl->assign( 'sql_column_active', OCP\Config::getAppValue( 'user_sql', 'sql_column_active', ''));
$tmpl->assign( 'strip_domain', OCP\Config::getAppValue( 'user_sql', 'strip_domain', 0));
$tmpl->assign( 'default_domain', OCP\Config::getAppValue( 'user_sql', 'default_domain', ''));
+$tmpl->assign( 'crypt_type', OCP\Config::getAppValue( 'user_sql', 'crypt_type', 'mysql_encrypt'));
return $tmpl->fetchPage();
diff --git a/templates/settings.php b/templates/settings.php
--- a/templates/settings.php
+++ b/templates/settings.php
@@ -1,32 +1,46 @@
diff --git a/user_sql.php b/user_sql.php
--- a/user_sql.php
+++ b/user_sql.php
@@ -1,235 +1,428 @@
*
* 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 .
*
*/
class OC_USER_SQL extends OC_User_Backend implements OC_User_Interface {
- // cached settings
- protected $sql_host;
- protected $sql_username;
- protected $sql_database;
- protected $sql_password;
- protected $sql_table;
- protected $sql_column_username;
- protected $sql_column_password;
- protected $sql_column_active;
- protected $sql_type;
- protected $db_conn;
- protected $db;
- protected $default_domain;
- protected $strip_domain;
+ // cached settings
+ protected $sql_host;
+ protected $sql_username;
+ protected $sql_database;
+ protected $sql_password;
+ protected $sql_table;
+ protected $sql_column_username;
+ protected $sql_column_password;
+ protected $sql_column_active;
+ protected $sql_type;
+ protected $db_conn;
+ protected $db;
+ protected $default_domain;
+ protected $strip_domain;
+ protected $crypt_type;
- public function __construct()
+ public function __construct()
+ {
+ $this->db_conn = false;
+ $this->sql_host = OCP\Config::getAppValue('user_sql', 'sql_host', '');
+ $this->sql_username = OCP\Config::getAppValue('user_sql', 'sql_user', '');
+ $this->sql_database = OCP\Config::getAppValue('user_sql', 'sql_database', '');
+ $this->sql_password = OCP\Config::getAppValue('user_sql', 'sql_password', '');
+ $this->sql_table = OCP\Config::getAppValue('user_sql', 'sql_table', '');
+ $this->sql_column_username = OCP\Config::getAppValue('user_sql', 'sql_column_username', '');
+ $this->sql_column_password = OCP\Config::getAppValue('user_sql', 'sql_column_password', '');
+ $this->sql_column_active = OCP\Config::getAppValue('user_sql', 'sql_column_active', '');
+ $this->sql_type = OCP\Config::getAppValue('user_sql', 'sql_type', '');
+ $this->default_domain = OCP\Config::getAppValue('user_sql', 'default_domain', '');
+ $this->strip_domain = OCP\Config::getAppValue('user_sql', 'strip_domain', 0);
+ $this->crypt_type = OCP\Config::getAppValue('user_sql', 'crypt_type', 'md5crypt');
+ $dsn = $this->sql_type.":host=".$this->sql_host.";dbname=".$this->sql_database;
+ try
+ {
+ $this->db = new PDO($dsn, $this->sql_username, $this->sql_password);
+ $this->db_conn = true;
+ }
+ catch (PDOException $e)
+ {
+ OC_Log::write('OC_USER_SQL', 'OC_USER_SQL, Failed to connect to the database: ' . $e->getMessage(), OC_Log::ERROR);
+ }
+ return false;
+ }
+
+ public function implementsAction($actions)
+ {
+ return (bool)((OC_USER_BACKEND_CHECK_PASSWORD) & $actions);
+ }
+
+ public function createUser() {
+ // Can't create user
+ OC_Log::write('OC_USER_SQL', 'Not possible to create local users from web frontend using SQL user backend', OC_Log::ERROR);
+ return false;
+ }
+
+ public function deleteUser( $uid )
+ {
+ // Can't delete user
+ OC_Log::write('OC_USER_SQL', 'Not possible to delete local users from web frontend using SQL user backend', OC_Log::ERROR);
+ return false;
+ }
+
+ public function setPassword ( $uid, $password ) {
+ // Update the user's password - this might affect other services, that user the same database, as well
+ if(!$this->db_conn)
{
- $this->db_conn = false;
- $this->sql_host = OCP\Config::getAppValue('user_sql', 'sql_host', '');
- $this->sql_username = OCP\Config::getAppValue('user_sql', 'sql_user', '');
- $this->sql_database = OCP\Config::getAppValue('user_sql', 'sql_database', '');
- $this->sql_password = OCP\Config::getAppValue('user_sql', 'sql_password', '');
- $this->sql_table = OCP\Config::getAppValue('user_sql', 'sql_table', '');
- $this->sql_column_username = OCP\Config::getAppValue('user_sql', 'sql_column_username', '');
- $this->sql_column_password = OCP\Config::getAppValue('user_sql', 'sql_column_password', '');
- $this->sql_column_active = OCP\Config::getAppValue('user_sql', 'sql_column_active', '');
- $this->sql_type = OCP\Config::getAppValue('user_sql', 'sql_type', '');
- $this->default_domain = OCP\Config::getAppValue('user_sql', 'default_domain', '');
- $this->strip_domain = OCP\Config::getAppValue('user_sql', 'strip_domain', 0);
- $dsn = $this->sql_type.":host=".$this->sql_host.";dbname=".$this->sql_database;
- try
- {
- $this->db = new PDO($dsn, $this->sql_username, $this->sql_password);
- $this->db_conn = true;
- }
- catch (PDOException $e)
- {
- OC_Log::write('OC_USER_SQL', 'OC_USER_SQL, Failed to connect to the database: ' . $e->getMessage(), OC_Log::ERROR);
- }
+ return false;
+ }
+ if($this->strip_domain)
+ {
+ $uid .= "@".$this->default_domain;
+ }
+ $query = "SELECT $this->sql_column_password FROM $this->sql_table WHERE $this->sql_column_username = '$uid'";
+ $result = $this->db->prepare($query);
+ if(!$result->execute())
+ {
+ return false;
+ }
+ $row = $result->fetch();
+ if(!$row)
+ {
+ return false;
+ }
+ $old_password = $row[$this->sql_column_password];
+ $enc_password = pacrypt($password, $old_password);
+ $query = "UPDATE $this->sql_table SET $this->sql_column_password = '$enc_password' WHERE $this->sql_column_username = '$uid'";
+ $result = $this->db->prepare($query);
+ if(!$result->execute())
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @brief Check if the password is correct
+ * @param $uid The username
+ * @param $password The password
+ * @returns true/false
+ *
+ * Check if the password is correct without logging in the user
+ */
+ public function checkPassword($uid, $password)
+ {
+ if(!$this->db_conn)
+ {
+ return false;
+ }
+ $suid = $uid;
+ if($this->strip_domain)
+ {
+ $suid = $uid."@".$this->default_domain;
+ }
+
+ $query = "SELECT $this->sql_column_username, $this->sql_column_password FROM $this->sql_table WHERE $this->sql_column_username = '$suid'";
+ if($this->sql_column_active != '')
+ $query .= " AND $this->sql_column_active = 1";
+ $result = $this->db->prepare($query);
+ if(!$result->execute())
+ {
+ return false;
+ }
+ $row = $result->fetch();
+ if(!$row)
+ {
+ return false;
+ }
+ if($this->pacrypt($password, $row[$this->sql_column_password]) == $row[$this->sql_column_password])
+ {
+ return $uid;
+ }
+ else
+ {
return false;
}
+ }
- public function implementsAction($actions)
- {
- return (bool)((OC_USER_BACKEND_CHECK_PASSWORD) & $actions);
- }
+ /**
+ * @brief Get a list of all users
+ * @returns array with all uids
+ *
+ * Get a list of all users.
+ */
- public function createUser() {
- // Can't create user
- OC_Log::write('OC_USER_SQL', 'Not possible to create local users from web frontend using SQL user backend', OC_Log::ERROR);
+ public function getUsers($search = '', $limit = null, $offset = null)
+ {
+ $users = array();
+ if(!$this->db_conn)
+ {
+ return false;
+ }
+ $query = "SELECT $this->sql_column_username FROM $this->sql_table";
+ if($search != '')
+ $query .= " WHERE $this->sql_column_username LIKE '%$search%'";
+ if($this->sql_column_active != '')
+ {
+ if($search != '')
+ $query .= " AND";
+ else
+ $query .= " WHERE";
+ $query .= " $this->sql_column_active = 1";
+ }
+ if($limit != null)
+ $query .= " LIMIT $limit";
+ if($offset != null)
+ $query .= " OFFSET $offset";
+ $result = $this->db->prepare($query);
+ if(!$result->execute())
+ {
+ return array();
+ }
+ while($row = $result->fetch())
+ {
+ $uid = $row[$this->sql_column_username];
+ if($this->strip_domain)
+ {
+ $uid = explode("@", $uid);
+ $uid = $uid[0];
+ }
+ $users[] = $uid;
+ }
+ return $users;
+ }
+
+ /**
+ * @brief check if a user exists
+ * @param string $uid the username
+ * @return boolean
+ */
+
+ public function userExists($uid)
+ {
+ if(!$this->db_conn)
+ {
return false;
}
-
- public function deleteUser( $uid )
+
+ if($this->strip_domain)
{
- // Can't delete user
- OC_Log::write('OC_USER_SQL', 'Not possible to delete local users from web frontend using SQL user backend', OC_Log::ERROR);
+ $uid .= "@".$this->default_domain;
+ }
+
+ $query = "SELECT $this->sql_column_username FROM $this->sql_table WHERE $this->sql_column_username = '$uid'";
+ if($this->sql_column_active != '')
+ $query .= " AND $this->sql_column_active = 1";
+ $result = $this->db->prepare($query);
+ if(!$result->execute())
+ {
+ return false;
+ }
+ $row = $result->fetch();
+ if(!$row)
+ {
return false;
}
+ else
+ {
+ return true;
+ }
- public function setPassword ( $uid, $password ) {
- // Update the user's password - this might affect other services, that user the same database, as well
+ }
+
+ /**
+ * The following functions were directly taken from PostfixAdmin and just slightly modified
+ * to suit our needs.
+ * Encrypt a password, using the apparopriate hashing mechanism as defined in
+ * config.inc.php ($this->crypt_type).
+ * When wanting to compare one pw to another, it's necessary to provide the salt used - hence
+ * the second parameter ($pw_db), which is the existing hash from the DB.
+ *
+ * @param string $pw
+ * @param string $encrypted password
+ * @return string encrypted password.
+ */
+ private function pacrypt ($pw, $pw_db="")
+ {
+ $pw = stripslashes($pw);
+ $password = "";
+ $salt = "";
+
+ if ($this->crypt_type == 'md5crypt') {
+ $split_salt = preg_split ('/\$/', $pw_db);
+ if (isset ($split_salt[2])) {
+ $salt = $split_salt[2];
+ }
+ $password = $this->md5crypt ($pw, $salt);
+ }
+
+ elseif ($this->crypt_type == 'md5') {
+ $password = md5($pw);
+ }
+
+ elseif ($this->crypt_type == 'system') {
+ if (preg_match("/\\$1\\$/", $pw_db)) {
+ $split_salt = preg_split ('/\$/', $pw_db);
+ $salt = "\$1\$${split_salt[2]}\$";
+ }
+ else {
+ if (strlen($pw_db) == 0) {
+ $salt = substr (md5 (mt_rand ()), 0, 2);
+ }
+ else {
+ $salt = substr ($pw_db, 0, 2);
+ }
+ }
+ $password = crypt ($pw, $salt);
+ }
+
+ elseif ($this->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->crypt_type == 'mysql_encrypt')
+ {
+ if ($pw_db!="") {
+ $salt=substr($pw_db,0,2);
+ $query = "SELECT ENCRYPT('".$pw."','".$salt."');";
+ } else {
+ $query = "SELECT ENCRYPT('".$pw."');";
+ }
+
if(!$this->db_conn)
{
return false;
}
- if($this->strip_domain)
- {
- $uid .= "@".$this->default_domain;
- }
- $query = "UPDATE $this->sql_table SET $this->sql_column_password = ENCRYPT('$password') WHERE $this->sql_column_username = '$uid'";
$result = $this->db->prepare($query);
if(!$result->execute())
{
return false;
}
- return true;
- }
-
- /**
- * @brief Check if the password is correct
- * @param $uid The username
- * @param $password The password
- * @returns true/false
- *
- * Check if the password is correct without logging in the user
- */
- public function checkPassword($uid, $password)
- {
- if(!$this->db_conn)
+ $row = $result->fetch();
+ if(!$row)
{
return false;
}
- $suid = $uid;
- if($this->strip_domain)
- {
- $suid = $uid."@".$this->default_domain;
- }
-
- $query = "SELECT $this->sql_column_username, $this->sql_column_password FROM $this->sql_table WHERE $this->sql_column_username = '$suid'";
- if($this->sql_column_active != '')
- $query .= " AND $this->sql_column_active = 1";
- $result = $this->db->prepare($query);
- if(!$result->execute())
- {
- return false;
- }
- $row = $result->fetch();
- if(!$row)
- {
- return false;
- }
- if(crypt($password, $row[$this->sql_column_password]) == $row[$this->sql_column_password])
- {
- return $uid;
- }
- else
- {
- return false;
- }
- }
+ $password = $row[0];
+ }
+
+ else {
+ die ('unknown/invalid $CONF["encrypt"] setting: ' . $this->crypt_type);
+ }
- /**
- * @brief Get a list of all users
- * @returns array with all uids
- *
- * Get a list of all users.
- */
+ return $password;
+ }
+
+ //
+ // md5crypt
+ // Action: Creates MD5 encrypted password
+ // Call: md5crypt (string cleartextpassword)
+ //
- public function getUsers($search = '', $limit = null, $offset = null)
- {
- $users = array();
- if(!$this->db_conn)
- {
- return false;
- }
- $query = "SELECT $this->sql_column_username FROM $this->sql_table";
- if($search != '')
- $query .= " WHERE $this->sql_column_username LIKE '%$search%'";
- if($this->sql_column_active != '')
- {
- if($search != '')
- $query .= " AND";
- else
- $query .= " WHERE";
- $query .= " $this->sql_column_active = 1";
- }
- if($limit != null)
- $query .= " LIMIT $limit";
- if($offset != null)
- $query .= " OFFSET $offset";
- $result = $this->db->prepare($query);
- if(!$result->execute())
- {
- return array();
- }
- while($row = $result->fetch())
- {
- $uid = $row[$this->sql_column_username];
- if($this->strip_domain)
- {
- $uid = explode("@", $uid);
- $uid = $uid[0];
- }
- $users[] = $uid;
- }
- return $users;
- }
+ function md5crypt ($pw, $salt="", $magic="")
+ {
+ $MAGIC = "$1$";
+
+ if ($magic == "") $magic = $MAGIC;
+ if ($salt == "") $salt = $this->create_salt ();
+ $slist = explode ("$", $salt);
+ if ($slist[0] == "1") $salt = $slist[1];
- /**
- * @brief check if a user exists
- * @param string $uid the username
- * @return boolean
- */
+ $salt = substr ($salt, 0, 8);
+ $ctx = $pw . $magic . $salt;
+ $final = $this->hex2bin (md5 ($pw . $salt . $pw));
- public function userExists($uid)
- {
- if(!$this->db_conn)
+ for ($i=strlen ($pw); $i>0; $i-=16)
+ {
+ if ($i > 16)
{
- return false;
- }
-
- if($this->strip_domain)
- {
- $uid .= "@".$this->default_domain;
- }
-
- $query = "SELECT $this->sql_column_username FROM $this->sql_table WHERE $this->sql_column_username = '$uid'";
- if($this->sql_column_active != '')
- $query .= " AND $this->sql_column_active = 1";
- $result = $this->db->prepare($query);
- if(!$result->execute())
- {
- return false;
- }
- $row = $result->fetch();
- if(!$row)
- {
- return false;
+ $ctx .= substr ($final,0,16);
}
else
{
- return true;
+ $ctx .= substr ($final,0,$i);
+ }
+ }
+ $i = strlen ($pw);
+
+ while ($i > 0)
+ {
+ if ($i & 1) $ctx .= chr (0);
+ else $ctx .= $pw[0];
+ $i = $i >> 1;
+ }
+ $final = $this->hex2bin (md5 ($ctx));
+
+ for ($i=0;$i<1000;$i++)
+ {
+ $ctx1 = "";
+ if ($i & 1)
+ {
+ $ctx1 .= $pw;
+ }
+ else
+ {
+ $ctx1 .= substr ($final,0,16);
+ }
+ if ($i % 3) $ctx1 .= $salt;
+ if ($i % 7) $ctx1 .= $pw;
+ if ($i & 1)
+ {
+ $ctx1 .= substr ($final,0,16);
}
+ else
+ {
+ $ctx1 .= $pw;
+ }
+ $final = $this->hex2bin (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);
+ return "$magic$salt\$$passwd";
+ }
- }
+ function create_salt ()
+ {
+ srand ((double) microtime ()*1000000);
+ $salt = substr (md5 (rand (0,9999999)), 0, 8);
+ return $salt;
+ }
+
+ function to64 ($v, $n)
+ {
+ $ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ $ret = "";
+ while (($n - 1) >= 0)
+ {
+ $n--;
+ $ret .= $ITOA64[$v & 0x3f];
+ $v = $v >> 6;
+ }
+ return $ret;
+ }
}
?>