hedera-web/rest/core/account.php

248 lines
5.3 KiB
PHP
Executable File

<?php
class Account
{
static function trySync ($db, $userName, $password = NULL)
{
$isSync = $db->getValue (
'SELECT sync FROM account.user WHERE name = #',
[$userName]
);
if ($isSync)
return;
self::sync ($db, $userName, $password);
}
static function sync ($db, $userName, $password = NULL, $force = TRUE)
{
$hasAccount = $db->getValue (
'SELECT COUNT(*) > 0
FROM account.user u
JOIN account.account a ON u.id = a.id
WHERE u.name = #',
[$userName]
);
if ($hasAccount)
{
self::ldapSync ($db, $userName, $password);
self::sambaSync ($db, $userName, $password);
}
$db->query (
'UPDATE account.user SET sync = TRUE WHERE name = #',
[$userName]
);
}
/**
* Synchronizes the user credentials in the LDAP server.
*/
static function ldapSync ($db, $userName, $password)
{
if (empty ($password))
return;
// Gets LDAP configuration parameters
$conf = $db->getObject (
'SELECT host, rdn, password, baseDn, filter
FROM account.ldapConfig');
// Connects an authenticates against server
$ds = ldap_connect ($conf->host);
if (!$ds)
throw new Exception ("Can't connect to LDAP server: ". ldapError ($ds));
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$bind = ldap_bind ($ds, $conf->rdn, base64_decode ($conf->password));
if (!$bind)
throw new Exception ("Authentication failed on LDAP server: ". ldapError ($ds));
// Prepares the data
$domain = $db->getValue ('SELECT domain FROM account.mailConfig');
$user = $db->getObject (
'SELECT id, nickname, lang
FROM account.user
WHERE name = #',
[$userName]
);
$nameArgs = explode (' ', $user->nickname);
$givenName = $nameArgs[0];
if (count ($nameArgs) > 1)
$sn = $nameArgs[1];
if (empty ($sn))
$sn = 'Empty';
$info = [
'cn' => $user->nickname,
'displayName' => $user->nickname,
'givenName' => $givenName,
'sn' => $sn,
'mail' => "$userName@{$domain}",
'userPassword' => sshaEncode ($password),
'preferredLanguage' => $user->lang
];
// Search the user entry
$filter = "uid=$userName";
if (!empty($conf->filter))
$filter = "(&($filter)($conf->filter))";
$res = ldap_search ($ds, $conf->baseDn, $filter);
if (!$res)
throw new Exception ("Can't get the LDAP entry: ". ldapError ($ds));
$dn = "uid=$userName,{$conf->baseDn}";
$entry = ldap_first_entry ($ds, $res);
$classes = ldap_get_values ($ds, $entry, 'objectClass');
if (!in_array ('inetOrgPerson', $classes))
{
ldap_delete ($ds, $dn);
$entry = NULL;
}
if ($entry)
{
$updated = ldap_modify ($ds, $dn, $info);
}
else
{
$info = array_merge ($info, [
'objectClass' => ['inetOrgPerson'],
'uid' => $userName
]);
$updated = ldap_add ($ds, $dn, $info);
}
if (!$updated)
throw new Exception ("Can't update the LDAP entry: ". ldapError ($ds));
ldap_unbind ($ds);
}
/**
* Synchronizes the user credentials in the Samba server.
*/
static function sambaSync ($db, $userName, $password)
{
$conf = $db->getObject (
'SELECT host, sshUser, sshPass, uidBase
FROM account.sambaConfig'
);
$domain = $db->getValue ('SELECT domain FROM account.mailConfig');
$samba = new SshConnection ($conf->host
,$conf->sshUser
,base64_decode ($conf->sshPass)
);
$scriptDir = '/mnt/cluster/scripts';
// Creates the Samba user and initializes it's home directory
$userId = $db->getValue (
'SELECT id FROM account.user WHERE name = #', [$userName]);
$samba->exec ("$scriptDir/create-user.sh %s %s %s"
,$userName
,$conf->uidBase + $userId
,"$userName@{$domain}"
);
// Syncronizes the Samba password
if (empty ($password))
return;
$samba->exec ("$scriptDir/set-password.sh %s %s"
,$userName
,$password
);
}
}
function ldapError ($ds)
{
return ldap_errno ($ds) .': '. ldap_error ($ds);
}
function sshaEncode ($value)
{
mt_srand ((double) microtime () * 1000000);
$salt = pack ('CCCC', mt_rand (), mt_rand (), mt_rand (), mt_rand ());
$hash = '{SSHA}' . base64_encode (pack ('H*', sha1 ($value . $salt)) . $salt);
return $hash;
}
function sshaVerify ($hash, $value)
{
$ohash = base64_decode (substr ($hash, 6));
$osalt = substr ($ohash, 20);
$ohash = substr ($ohash, 0, 20);
$nhash = pack ('H*', sha1 ($value . $osalt));
return $ohash == $nhash;
}
class SshConnection
{
var $connection;
/**
* Abrebiated method to make SSH connections.
*/
function __construct ($host, $user, $password)
{
$this->connection = $connection = ssh2_connect ($host);
if (!$connection)
throw new Exception ("Can't connect to SSH server $host");
$authOk = ssh2_auth_password ($connection, $user, $password);
if (!$authOk)
throw new Exception ("SSH authentication failed on server $host");
return $connection;
}
/**
* Executes a command on the host.
*/
function exec ()
{
$nargs = func_num_args ();
$args = func_get_args ();
for ($i = 1; $i < $nargs; $i++)
$args[$i] = self::escape ($args[$i]);
$command = call_user_func_array ('sprintf', $args);
error_log ($command);
return ssh2_exec ($this->connection, $command);
}
/**
* Escapes the double quotes from an string.
*/
static function escape ($str)
{
return '"'. str_replace ('"', '\\"', $str) .'"';
}
}