%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/modules/ldap/classes/general/ |
Current File : /home/bitrix/www/bitrix/modules/ldap/classes/general/ldap_server.php |
<?php IncludeModuleLangFile(__FILE__); class CLdapServer { public $arFields = array(); public static $syncErrors = array(); /** * * @param $arOrder * @param $arFilter * @return __CLDAPServerDBResult */ public static function GetList($arOrder=Array(), $arFilter=Array()) { global $USER, $DB, $APPLICATION; $strSql = "SELECT ls.*, ". " ".$DB->DateToCharFunction("ls.TIMESTAMP_X")." as TIMESTAMP_X, ". " ".$DB->DateToCharFunction("ls.SYNC_LAST")." as SYNC_LAST ". "FROM b_ldap_server ls "; if(!is_array($arFilter)) $arFilter = Array(); $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); $fkCount = count($filter_keys); for($i=0; $i<$fkCount; $i++) { $val = $arFilter[$filter_keys[$i]]; $key=$filter_keys[$i]; $res = CLdapUtil::MkOperationFilter($key); $key = strtoupper($res["FIELD"]); $cOperationType = $res["OPERATION"]; switch($key) { case "ACTIVE": case "SYNC": case "CONVERT_UTF8": case "USER_GROUP_ACCESSORY": $arSqlSearch[] = CLdapUtil::FilterCreate("ls.".$key, $val, "string_equal", $cOperationType); break; case "ID": case "PORT": case "MAX_PAX_SIZE": case "CONNECTION_TYPE": $arSqlSearch[] = CLdapUtil::FilterCreate("ls.".$key, $val, "number", $cOperationType); break; case "TIMESTAMP_X": $arSqlSearch[] = CLdapUtil::FilterCreate("ls.".$key, $val, "date", $cOperationType); break; case "SYNC_LAST": $arSqlSearch[] = CLdapUtil::FilterCreate("ls.".$key, $val, "date", $cOperationType); break; case "CODE": case "NAME": case "DESCRIPTION": case "SERVER": case "ADMIN_LOGIN": case "ADMIN_PASSWORD": case "BASE_DN": case "GROUP_FILTER": case "GROUP_ID_ATTR": case "GROUP_NAME_ATTR": case "GROUP_MEMBERS_ATTR": case "USER_FILTER": case "USER_ID_ATTR": case "USER_NAME_ATTR": case "USER_LAST_NAME_ATTR": case "USER_EMAIL_ATTR": case "USER_GROUP_ATTR": $arSqlSearch[] = CldapUtil::FilterCreate("ls.".$key, $val, "string", $cOperationType); break; } } $is_filtered = false; $strSqlSearch = ""; for($i=0, $ssCount=count($arSqlSearch); $i<$ssCount; $i++) { if(strlen($arSqlSearch[$i])>0) { $is_filtered = true; $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; } } $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $order = strtolower($order); if ($order!="asc") $order = "desc".($DB->type=="ORACLE"?" NULLS LAST":""); else $order = "asc".($DB->type=="ORACLE"?" NULLS FIRST":""); switch(strtoupper($by)) { case "ID": case "NAME": case "CODE": case "ACTIVE": case "CONVERT_UTF8": case "SERVER": case "PORT": case "ADMIN_LOGIN": case "ADMIN_PASSWORD": case "BASE_DN": case "GROUP_FILTER": case "SYNC": case "SYNC_LAST": case "GROUP_ID_ATTR": case "GROUP_NAME_ATTR": case "GROUP_MEMBERS_ATTR": case "USER_FILTER": case "USER_ID_ATTR": case "USER_NAME_ATTR": case "USER_LAST_NAME_ATTR": case "USER_EMAIL_ATTR": case "USER_GROUP_ATTR": case "USER_GROUP_ACCESSORY": case "MAX_PAX_SIZE": case "CONNECTION_TYPE": $arSqlOrder[] = " ls.".$by." ".$order." "; break; default: $arSqlOrder[] = " ls.TIMESTAMP_X ".$order." "; } } $strSqlOrder = ""; DelDuplicateSort($arSqlOrder); for ($i=0, $c=count($arSqlOrder); $i < $c; $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= strtolower($arSqlOrder[$i]); } $strSql .= " WHERE 1=1 ".$strSqlSearch.$strSqlOrder; $res = $DB->Query($strSql); $res = new __CLDAPServerDBResult($res); return $res; } /** * * @param $ID * @return __CLDAPServerDBResult */ public static function GetByID($ID) { return CLdapServer::GetList(Array(), $arFilter=Array("ID"=>IntVal($ID))); } public static function CheckFields($arFields, $ID=false) { global $DB, $APPLICATION; $strErrors = ""; $arMsg = Array(); if(($ID===false || is_set($arFields, "NAME")) && strlen($arFields["NAME"])<1) $arMsg[] = array("id"=>"NAME", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_NAME")); //$strErrors .= GetMessage("LDAP_ERR_NAME").", "; if(($ID===false || is_set($arFields, "SERVER")) && strlen($arFields["SERVER"])<1) $arMsg[] = array("id"=>"SERVER", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_SERVER")); //$strErrors .= GetMessage("LDAP_ERR_SERVER").", "; if(($ID===false || is_set($arFields, "PORT")) && strlen($arFields["PORT"])<1) $arMsg[] = array("id"=>"PORT", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_PORT")); //$strErrors .= GetMessage("LDAP_ERR_PORT").", "; if(($ID===false || is_set($arFields, "BASE_DN")) && strlen($arFields["BASE_DN"])<1) //$strErrors .= GetMessage("LDAP_ERR_BASE_DN").", "; $arMsg[] = array("id"=>"BASE_DN", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_BASE_DN")); if(($ID===false || is_set($arFields, "GROUP_FILTER")) && strlen($arFields["GROUP_FILTER"])<1) //$strErrors .= GetMessage("LDAP_ERR_GROUP_FILT").", "; $arMsg[] = array("id"=>"GROUP_FILTER", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_GROUP_FILT")); if(($ID===false || is_set($arFields, "GROUP_ID_ATTR")) && strlen($arFields["GROUP_ID_ATTR"])<1) $arMsg[] = array("id"=>"GROUP_ID_ATTR", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_GROUP_ATTR")); //$strErrors .= GetMessage("LDAP_ERR_GROUP_ATTR").", "; if(($ID===false || is_set($arFields, "USER_FILTER")) && strlen($arFields["USER_FILTER"])<1) $arMsg[] = array("id"=>"USER_FILTER", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_USER_FILT")); //$strErrors .= GetMessage("LDAP_ERR_USER_FILT").", "; if(($ID===false || is_set($arFields, "USER_ID_ATTR")) && strlen($arFields["USER_ID_ATTR"])<1) $arMsg[] = array("id"=>"USER_ID_ATTR", "text"=> GetMessage("LDAP_ERR_EMPTY")." ".GetMessage("LDAP_ERR_USER_ATTR")); //$strErrors .= GetMessage("LDAP_ERR_USER_ATTR").", "; //if(strlen($strErrors)>0) //{ // $APPLICATION->throwException(GetMessage("LDAP_ERR_EMPTY").substr($strErrors, 0, -2)); // return false; //} if(!empty($arMsg)) { $e = new CAdminException($arMsg); $GLOBALS["APPLICATION"]->ThrowException($e); return false; } return true; } public static function Add($arFields) { global $DB, $APPLICATION; $APPLICATION->ResetException(); if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y") $arFields["ACTIVE"]="N"; if(is_set($arFields, "SYNC") && $arFields["SYNC"]!="Y") $arFields["SYNC"]="N"; if(is_set($arFields, "CONVERT_UTF8") && $arFields["CONVERT_UTF8"]!="Y") $arFields["CONVERT_UTF8"]="N"; if(is_set($arFields, "USER_GROUP_ACCESSORY") && $arFields["USER_GROUP_ACCESSORY"]!="Y") $arFields["USER_GROUP_ACCESSORY"]="N"; if(!CLdapServer::CheckFields($arFields)) return false; if(is_set($arFields, "ADMIN_PASSWORD")) $arFields["ADMIN_PASSWORD"]=CLdapUtil::Crypt($arFields["ADMIN_PASSWORD"]); if(is_set($arFields, "FIELD_MAP") && is_array($arFields["FIELD_MAP"])) { $arFields["USER_NAME_ATTR"] = "".$arFields["FIELD_MAP"]["NAME"]; $arFields["USER_LAST_NAME_ATTR"] = "".$arFields["FIELD_MAP"]["LAST_NAME"]; $arFields["USER_EMAIL_ATTR"] = "".$arFields["FIELD_MAP"]["EMAIL"]; $arFields["FIELD_MAP"] = serialize($arFields["FIELD_MAP"]); } $ID = CDatabase::Add("b_ldap_server", $arFields); if(is_set($arFields, 'GROUPS')) CLdapServer::SetGroupMap($ID, $arFields['GROUPS']); if($arFields["SYNC"]=="Y") CLdapServer::__UpdateAgentPeriod($ID, $arFields["SYNC_PERIOD"]); return $ID; } public static function __UpdateAgentPeriod($server_id, $time) { $server_id = IntVal($server_id); $time = IntVal($time); CAgent::RemoveAgent("CLdapServer::SyncAgent(".$server_id.");", "ldap"); if($time>0) CAgent::AddAgent("CLdapServer::SyncAgent(".$server_id.");", "ldap", "N", $time*60*60); } public static function SyncAgent($id) { CLdapServer::Sync($id); return "CLdapServer::SyncAgent(".$id.");"; } /********************************************************************* *********************************************************************/ public static function Update($ID, $arFields) { global $DB, $APPLICATION; $APPLICATION->ResetException(); $ID = IntVal($ID); if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y") $arFields["ACTIVE"]="N"; if(is_set($arFields, "SYNC") && $arFields["SYNC"]!="Y") $arFields["SYNC"]="N"; if(is_set($arFields, "SYNC_USER_ADD") && $arFields["SYNC_USER_ADD"] != "Y") $arFields["SYNC_USER_ADD"] = "N"; if(is_set($arFields, "CONVERT_UTF8") && $arFields["CONVERT_UTF8"]!="Y") $arFields["CONVERT_UTF8"]="N"; if(is_set($arFields, "USER_GROUP_ACCESSORY") && $arFields["USER_GROUP_ACCESSORY"]!="Y") $arFields["USER_GROUP_ACCESSORY"]="N"; if(is_set($arFields, "IMPORT_STRUCT") && $arFields["IMPORT_STRUCT"]!="Y") $arFields["IMPORT_STRUCT"]="N"; if(is_set($arFields, "STRUCT_HAVE_DEFAULT") && $arFields["STRUCT_HAVE_DEFAULT"]!="Y") $arFields["STRUCT_HAVE_DEFAULT"]="N"; if(!CLdapServer::CheckFields($arFields, $ID)) return false; if(is_set($arFields, "ADMIN_PASSWORD")) $arFields["ADMIN_PASSWORD"]=CLdapUtil::Crypt($arFields["ADMIN_PASSWORD"]); if(is_set($arFields, "FIELD_MAP") && is_array($arFields["FIELD_MAP"])) { $arFields["USER_NAME_ATTR"] = "".$arFields["FIELD_MAP"]["NAME"]; $arFields["USER_LAST_NAME_ATTR"] = "".$arFields["FIELD_MAP"]["LAST_NAME"]; $arFields["USER_EMAIL_ATTR"] = "".$arFields["FIELD_MAP"]["EMAIL"]; $arFields["FIELD_MAP"] = serialize($arFields["FIELD_MAP"]); } if(isset($arFields["SYNC"]) || isset($arFields["SYNC_PERIOD"])) { $dbld = CLdapServer::GetById($ID); $arLdap = $dbld->Fetch(); } $strUpdate = $DB->PrepareUpdate("b_ldap_server", $arFields); $strSql = "UPDATE b_ldap_server SET ". $strUpdate." ". "WHERE ID=".$ID; $DB->Query($strSql); if(is_set($arFields, 'GROUPS')) CLdapServer::SetGroupMap($ID, $arFields['GROUPS']); if(isset($arFields["SYNC"]) || isset($arFields["SYNC_PERIOD"])) { if($arLdap) { if(isset($arFields["SYNC"])) { if($arFields["SYNC"]!="Y" && $arLdap["SYNC"]=="Y") CLdapServer::__UpdateAgentPeriod($ID, 0); elseif($arFields["SYNC"]=="Y" && $arLdap["SYNC"]!="Y") CLdapServer::__UpdateAgentPeriod($ID, (isset($arFields["SYNC_PERIOD"])? $arFields["SYNC_PERIOD"] : $arLdap["SYNC_PERIOD"])); elseif(isset($arFields["SYNC_PERIOD"]) && $arLdap["SYNC_PERIOD"]!=$arFields["SYNC_PERIOD"]) CLdapServer::__UpdateAgentPeriod($ID, $arFields["SYNC_PERIOD"]); } elseif($arLdap["SYNC_PERIOD"]!=$arFields["SYNC_PERIOD"]) CLdapServer::__UpdateAgentPeriod($ID, $arFields["SYNC_PERIOD"]); } } return true; } public static function Delete($ID) { global $DB; $ID = IntVal($ID); $strSql = "DELETE FROM b_ldap_group WHERE LDAP_SERVER_ID=".$ID; if(!$DB->Query($strSql, true)) return false; $strSql = "DELETE FROM b_ldap_server WHERE ID=".$ID; return $DB->Query($strSql, true); } public static function GetGroupMap($ID) { global $DB, $APPLICATION; $ID = IntVal($ID); return $DB->Query("SELECT GROUP_ID, LDAP_GROUP_ID FROM b_ldap_group WHERE LDAP_SERVER_ID=".$ID." AND NOT (GROUP_ID=-1)"); } public static function GetGroupBan($ID) { global $DB, $APPLICATION; $ID = IntVal($ID); return $DB->Query("SELECT LDAP_GROUP_ID FROM b_ldap_group WHERE LDAP_SERVER_ID=".$ID." AND GROUP_ID=-1"); } public static function SetGroupMap($ID, $arFields) { global $DB, $APPLICATION; $ID = IntVal($ID); $DB->Query("DELETE FROM b_ldap_group WHERE LDAP_SERVER_ID=".$ID); foreach($arFields as $arGroup) { // check whether entry is valid, and if it is - add it if(array_key_exists('GROUP_ID',$arGroup) && ($arGroup['GROUP_ID']>0 || $arGroup['GROUP_ID']==-1) && strlen($arGroup['LDAP_GROUP_ID'])>0) { $strSql = "SELECT 'x' ". "FROM b_ldap_group ". "WHERE LDAP_SERVER_ID=".$ID." ". " AND GROUP_ID = ".IntVal($arGroup['GROUP_ID'])." ". " AND LDAP_GROUP_ID = '".$DB->ForSQL($arGroup['LDAP_GROUP_ID'], 255)."' "; $r = $DB->Query($strSql); if(!$r->Fetch()) { $strSql = "INSERT INTO b_ldap_group(GROUP_ID, LDAP_GROUP_ID, LDAP_SERVER_ID)". "VALUES(".IntVal($arGroup['GROUP_ID']).", '".$DB->ForSQL($arGroup['LDAP_GROUP_ID'], 255)."', ".$ID.")"; $DB->Query($strSql); } } } } public static function Sync($ldap_server_id) { global $DB, $USER, $APPLICATION; $bUSERGen = false; self::$syncErrors = array(); if(!is_object($USER)) { $USER = new CUser(); $bUSERGen = true; } $dbLdapServers = CLdapServer::GetByID($ldap_server_id); if(!($oLdapServer = $dbLdapServers->GetNextServer())) return false; if(!$oLdapServer->Connect()) return false; if(!$oLdapServer->BindAdmin()) { $oLdapServer->Disconnect(); return false; } $APPLICATION->ResetException(); $db_events = GetModuleEvents("ldap", "OnLdapBeforeSync"); while($arEvent = $db_events->Fetch()) { $arParams['oLdapServer'] = $oLdapServer; if(ExecuteModuleEventEx($arEvent, array(&$arParams))===false) { if(!($err = $APPLICATION->GetException())) $APPLICATION->ThrowException("Unknown error"); return false; } } // select all users from LDAP $arLdapUsers = array(); $ldapLoginAttr = strtolower($oLdapServer->arFields["~USER_ID_ATTR"]); $APPLICATION->ResetException(); $dbLdapUsers = $oLdapServer->GetUserList(); $ldpEx = $APPLICATION->GetException(); while($arLdapUser = $dbLdapUsers->Fetch()) $arLdapUsers[strtolower($arLdapUser[$ldapLoginAttr])] = $arLdapUser; unset($dbLdapUsers); // select all Bitrix CMS users for this LDAP $arUsers = Array(); CTimeZone::Disable(); $dbUsers = CUser::GetList(($o=""), ($b=""), Array("EXTERNAL_AUTH_ID"=>"LDAP#".$ldap_server_id)); CTimeZone::Enable(); while($arUser = $dbUsers->Fetch()) $arUsers[strtolower($arUser["LOGIN"])] = $arUser; unset($dbUsers); $arDelLdapUsers = array(); if(!$ldpEx || $ldpEx->msg != 'LDAP_SEARCH_ERROR') $arDelLdapUsers = array_diff(array_keys($arUsers), array_keys($arLdapUsers)); if(strlen($oLdapServer->arFields["SYNC_LAST"]) > 0) $syncTime = MakeTimeStamp($oLdapServer->arFields["SYNC_LAST"]); else $syncTime = 0; $cnt = 0; $departmentCache = array(); // have to update $oLdapServer->arFields["FIELD_MAP"] for user fields // for each one of them looking for similar in user list foreach($arLdapUsers as $userLogin => $arLdapUserFields) { if(!is_array($arUsers[$userLogin])) { //For manual users import - always add if($oLdapServer->arFields["SYNC_USER_ADD"] != "Y") continue; // if user is not found among already existing ones, then import him // $arLdapUserFields - user fields from ldap $userActive = $oLdapServer->getLdapValueByBitrixFieldName("ACTIVE", $arLdapUserFields); if($userActive != "Y") continue; $arUserFields = $oLdapServer->GetUserFields($arLdapUserFields, $departmentCache); if(self::isUserInBannedGroups($ldap_server_id, $arUserFields)) continue; if($oLdapServer->SetUser($arUserFields)) $cnt++; } else { // if date of update is set, then compare it $ldapTime = time(); if($syncTime > 0 && strlen($oLdapServer->arFields["SYNC_ATTR"])>0 && preg_match("'([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})\.0Z'", $arLdapUserFields[strtolower($oLdapServer->arFields["SYNC_ATTR"])], $arTimeMatch) ) { $ldapTime = gmmktime($arTimeMatch[4], $arTimeMatch[5], $arTimeMatch[6], $arTimeMatch[2], $arTimeMatch[3], $arTimeMatch[1]); $userTime = MakeTimeStamp($arUsers[$userLogin]["TIMESTAMP_X"]); } if($syncTime < $ldapTime || $syncTime < $userTime) { $arUserFields = $oLdapServer->GetUserFields($arLdapUserFields, $departmentCache); if(self::isUserInBannedGroups($ldap_server_id, $arUserFields)) continue; $arUserFields["ID"] = $arUsers[$userLogin]["ID"]; if($oLdapServer->SetUser($arUserFields)) $cnt++; } } if($USER->LAST_ERROR != '') { self::$syncErrors[] = $userLogin.': '.$USER->LAST_ERROR; $USER->LAST_ERROR = ''; } } foreach ($arDelLdapUsers as $userLogin) { $USER = new CUser(); if (isset($arUsers[$userLogin]) && $arUsers[$userLogin]['ACTIVE'] == 'Y') { $ID = intval($arUsers[$userLogin]["ID"]); $USER->Update($ID, array('ACTIVE' => 'N')); } } $oLdapServer->Disconnect(); CLdapServer::Update($ldap_server_id, Array("~SYNC_LAST"=>$DB->CurrentTimeFunction())); if(CModule::IncludeModule('intranet')) { \Bitrix\Intranet\Internals\UserSubordinationTable::performReInitialization(); \Bitrix\Intranet\Internals\UserToDepartmentTable::performReInitialization(); } if($bUSERGen) unset($USER); return $cnt; } protected static function isUserInBannedGroups($ldap_server_id, $arUserFields) { static $noImportGroups = null; if($noImportGroups === null) { $noImportGroups = array(); $dbGroups = CLdapServer::GetGroupBan($ldap_server_id); while($arGroup = $dbGroups->Fetch()) $noImportGroups[md5($arGroup['LDAP_GROUP_ID'])] = $arGroup['LDAP_GROUP_ID']; } if(empty($noImportGroups)) return false; $allUserGroups = $arUserFields['LDAP_GROUPS']; $result = false; foreach($allUserGroups as $groupId) { $groupId = trim($groupId); if(!empty($groupId) && array_key_exists(md5($groupId), $noImportGroups)) { $result = true; break; } } return $result; } } class __CLDAPServerDBResult extends CDBResult { function Fetch() { if($res = parent::Fetch()) { $res["ADMIN_PASSWORD"] = CLdapUtil::Decrypt($res["ADMIN_PASSWORD"]); $res["FIELD_MAP"] = unserialize($res["FIELD_MAP"]); if(!is_array($res["FIELD_MAP"])) $res["FIELD_MAP"] = Array(); } return $res; } function GetNextServer() { if(!($r = $this->GetNext())) return $r; $ldap = new CLDAP(); $ldap->arFields = $r; return $ldap; } }