%PDF- %PDF-
| Direktori : /home/bitrix/www/bitrix/modules/ldap/classes/general/ |
| Current File : //home/bitrix/www/bitrix/modules/ldap/classes/general/ldap_util.php |
<?php
IncludeModuleLangFile(__FILE__);
class CLdapUtil
{
public static function GetSynFields()
{
static $arSyncFields = false;
if(!is_array($arSyncFields))
{
// "Field in CUser"=>Array("NAME" => "Name in Bitrix CMS", "AD"=>"Default attribute in AD", "LDAP"=>"Default Attribute in LDAP")
$arSyncFields = Array(
"ACTIVE" =>Array("NAME" => GetMessage("LDAP_FIELD_ACTIVE"), "AD"=>"UserAccountControl&2"),
"EMAIL" =>Array("NAME" => GetMessage("LDAP_FIELD_EMAIIL"), "AD"=>"mail", "LDAP"=>"email"),
"NAME" =>Array("NAME" => GetMessage("LDAP_FIELD_NAME"), "AD"=>"givenName", "LDAP"=>"cn"),
"LAST_NAME" =>Array("NAME" => GetMessage("LDAP_FIELD_LAST_NAME"), "AD"=>"sn", "LDAP"=>"sn"),
"SECOND_NAME" =>Array("NAME" => GetMessage("LDAP_FIELD_SECOND_NAME")),
"PERSONAL_GENDER" =>Array("NAME" => GetMessage("LDAP_FIELD_GENDER")),
"PERSONAL_BIRTHDAY" =>Array("NAME" => GetMessage("LDAP_FIELD_BIRTHDAY")),
"PERSONAL_PROFESSION" =>Array("NAME" => GetMessage("LDAP_FIELD_PROF")),
"PERSONAL_PHOTO" =>Array("NAME" => GetMessage("LDAP_FIELD_PHOTO"), "AD"=>"thumbnailPhoto", "LDAP"=>"jpegPhoto"),
"PERSONAL_WWW" =>Array("NAME" => GetMessage("LDAP_FIELD_WWW"), "AD"=>"wWWHomePage"),
"PERSONAL_ICQ" =>Array("NAME" => "ICQ"),
"PERSONAL_PHONE" =>Array("NAME" => GetMessage("LDAP_FIELD_PHONE"), "AD"=>"homePhone"),
"PERSONAL_FAX" =>Array("NAME" => GetMessage("LDAP_FIELD_FAX")),
"PERSONAL_MOBILE" =>Array("NAME" => GetMessage("LDAP_FIELD_MOB"), "AD"=>"mobile"),
"PERSONAL_PAGER" =>Array("NAME" => GetMessage("LDAP_FIELD_PAGER")),
"PERSONAL_STREET" =>Array("NAME" => GetMessage("LDAP_FIELD_STREET"), "AD"=>"streetAddress"),
"PERSONAL_MAILBOX" =>Array("NAME" => GetMessage("LDAP_FIELD_MAILBOX"), "AD"=>"postOfficeBox"),
"PERSONAL_CITY" =>Array("NAME" => GetMessage("LDAP_FIELD_CITY"), "AD"=>"l"),
"PERSONAL_STATE" =>Array("NAME" => GetMessage("LDAP_FIELD_STATE"), "AD"=>"st"),
"PERSONAL_ZIP" =>Array("NAME" => GetMessage("LDAP_FIELD_ZIP"), "AD"=>"postalCode"),
"PERSONAL_COUNTRY" =>Array("NAME" => GetMessage("LDAP_FIELD_COUNTRY"), "AD"=>"c"),
//"PERSONAL_NOTES" =>Array("NAME" => "Personal notes"),
"WORK_COMPANY" =>Array("NAME" => GetMessage("LDAP_FIELD_COMPANY"), "AD"=>"company"),
"WORK_DEPARTMENT" =>Array("NAME" => GetMessage("LDAP_FIELD_DEP"), "AD"=>"department"),
"WORK_POSITION" =>Array("NAME" => GetMessage("LDAP_FIELD_POS"), "AD"=>"title"),
//"WORK_WWW" =>Array("NAME" => "Company web page"),
"WORK_PHONE" =>Array("NAME" => GetMessage("LDAP_FIELD_WORK_PHONE"), "AD"=>"telephoneNumber"),
"WORK_FAX" =>Array("NAME" => GetMessage("LDAP_FIELD_WORK_FAX"), "AD"=>"facsimileTelephoneNumber"),
"WORK_PAGER" =>Array("NAME" => GetMessage("LDAP_FIELD_WORK_PAGER")),
//"WORK_STREET" =>Array("NAME" => "Work address"),
//"WORK_MAILBOX" =>Array("NAME" => ""),
//"WORK_CITY" =>Array("NAME" => ""),
//"WORK_STATE" =>Array("NAME" => ""),
//"WORK_ZIP" =>Array("NAME" => ""),
//"WORK_COUNTRY" =>Array("NAME" => ""),
//"WORK_PROFILE" =>Array("NAME" => ""),
//"WORK_NOTES" =>Array("NAME" => "Additional notes"),
"ADMIN_NOTES" =>Array("NAME" => GetMessage("LDAP_FIELD_ADMIN_NOTES"), "AD"=>"description"),
);
$arRes = $GLOBALS["USER_FIELD_MANAGER"]->GetUserFields("USER", 0, LANGUAGE_ID);
foreach($arRes as $pr_id=>$pr_v)
if($pr_v["EDIT_FORM_LABEL"]!='')
$arSyncFields[$pr_id] = Array("NAME"=>$pr_v["EDIT_FORM_LABEL"]);
}
return $arSyncFields;
}
public static function ConvertADDate($d)
{
if(preg_match('#(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d)Z#', $d, $dt))
return gmmktime($dt[4], $dt[5], $dt[6], $dt[2], $dt[3], $dt[1]);
return false;
}
public static function ByteXOR($a,$b,$l)
{
$c="";
for($i=0; $i<$l; $i++)
$c .= $a[$i]^$b[$i];
return($c);
}
public static function BinMD5($val)
{
return(pack("H*",md5($val)));
}
public static function Decrypt($str, $key=false)
{
if($key===false)
$key = COption::GetOptionString("main", "pwdhashadd", "ldap");
$key1 = CLdapUtil::BinMD5($key);
$str = base64_decode($str);
$res = '';
while($str)
{
if (function_exists('mb_substr'))
{
$m = mb_substr($str, 0, 16, "ASCII");
$str = mb_substr($str, 16, mb_strlen($str,"ASCII")-16, "ASCII");
}
else
{
$m = substr($str, 0, 16);
$str = substr($str, 16);
}
$m = CLdapUtil::ByteXOR($m, $key1, 16);
$res .= $m;
$key1 = CLdapUtil::BinMD5($key.$key1.$m);
}
return $res;
}
public static function Crypt($str, $key=false)
{
if($key===false)
$key = COption::GetOptionString("main", "pwdhashadd", "ldap");
$key1 = CLdapUtil::BinMD5($key);
$res = '';
while($str)
{
if (function_exists('mb_substr'))
{
$m = mb_substr($str, 0, 16, "ASCII");
$str = mb_substr($str, 16, mb_strlen($str,"ASCII")-16, "ASCII");
}
else
{
$m = substr($str, 0, 16);
$str = substr($str, 16);
}
$res .= CLdapUtil::ByteXOR($m, $key1, 16);
$key1 = CLdapUtil::BinMD5($key.$key1.$m);
}
return(base64_encode($res));
}
public static function MkOperationFilter($key)
{
if(substr($key, 0, 1)=="!")
{
$key = substr($key, 1);
$cOperationType = "N";
}
elseif(substr($key, 0, 1)=="?")
{
$key = substr($key, 1);
$cOperationType = "?";
}
elseif(substr($key, 0, 2)==">=")
{
$key = substr($key, 2);
$cOperationType = "GE";
}
elseif(substr($key, 0, 1)==">")
{
$key = substr($key, 1);
$cOperationType = "G";
}
elseif(substr($key, 0, 2)=="<=")
{
$key = substr($key, 2);
$cOperationType = "LE";
}
elseif(substr($key, 0, 1)=="<")
{
$key = substr($key, 1);
$cOperationType = "L";
}
else
$cOperationType = "E";
return Array("FIELD"=>$key, "OPERATION"=>$cOperationType);
}
public static function FilterCreate($fname, $vals, $type, $cOperationType=false, $bSkipEmpty = true)
{
return CLdapUtil::FilterCreateEx($fname, $vals, $type, $bFullJoin, $cOperationType, $bSkipEmpty);
}
public static function FilterCreateEx($fname, $vals, $type, &$bFullJoin, $cOperationType=false, $bSkipEmpty = true)
{
global $DB;
if(!is_array($vals))
$vals=Array($vals);
if(count($vals)<1)
return "";
if(is_bool($cOperationType))
{
if($cOperationType===true)
$cOperationType = "N";
else
$cOperationType = "E";
}
if($cOperationType=="G")
$strOperation = ">";
elseif($cOperationType=="GE")
$strOperation = ">=";
elseif($cOperationType=="LE")
$strOperation = "<=";
elseif($cOperationType=="L")
$strOperation = "<";
else
$strOperation = "=";
$bFullJoin = false;
$bWasLeftJoin = false;
$res = Array();
for($i=0, $c=count($vals); $i < $c; $i++)
{
$val = $vals[$i];
if(!$bSkipEmpty || strlen($val)>0 || (is_bool($val) && $val===false))
{
switch ($type)
{
case "string_equal":
if($cOperationType=="?")
{
if(strlen($val)>0)
$res[] = GetFilterQuery($fname, $val, "N");
}
else
{
if(strlen($val)<=0)
$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL OR ".$DB->Length($fname)."<=0)";
else
$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".CLdapUtil::_Upper($fname).$strOperation.CLdapUtil::_Upper("'".$DB->ForSql($val)."'").")";
}
break;
case "string":
if($cOperationType=="?")
{
if(strlen($val)>0)
{
$sr = GetFilterQuery($fname, $val, "Y", array(), "N");
if($sr != "0")
$res[] = $sr;
}
}
else
{
if(strlen($val)<=0)
$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL OR ".$DB->Length($fname)."<=0)";
else
if($strOperation=="=")
$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".($DB->type=="ORACLE"?CLdapUtil::_Upper($fname)." LIKE ".CLdapUtil::_Upper("'".$DB->ForSqlLike($val)."'")." ESCAPE '\\'" : $fname." ".($strOperation=="="?"LIKE":$strOperation)." '".$DB->ForSqlLike($val)."'").")";
else
$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".($DB->type=="ORACLE"?CLdapUtil::_Upper($fname)." ".$strOperation." ".CLdapUtil::_Upper("'".$DB->ForSql($val)."'")." " : $fname." ".$strOperation." '".$DB->ForSql($val)."'").")";
}
break;
case "date":
if(strlen($val)<=0)
$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)";
else
$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." ".$DB->CharToDateFunction($DB->ForSql($val), "FULL").")";
break;
case "number":
if($cOperationType=="?")
{
$res[] = GetFilterQuery($fname, $val);
}
else
{
if(strlen($val)<=0)
$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)";
else
$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." '".DoubleVal($val)."')";
}
break;
case "number_above":
if(strlen($val)<=0)
$res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)";
else
$res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." '".$DB->ForSql($val)."')";
break;
}
// we need this conditions to do INNER JOIN
if(strlen($val)>0 && $cOperationType!="N")
$bFullJoin = true;
else
$bWasLeftJoin = true;
}
}
$strResult = "";
for($i=0, $c=count($res); $i < $c; $i++)
{
if($i>0)
$strResult .= ($cOperationType=="N"?" AND ":" OR ");
$strResult .= "(".$res[$i].")";
}
if($strResult!="")
$strResult = "(".$strResult.")";
if($bFullJoin && $bWasLeftJoin && $cOperationType!="N")
$bFullJoin = false;
return $strResult;
}
public static function _Upper($str)
{
global $DB;
return ($DB->type=="ORACLE"?"UPPER(".$str.")":$str);
}
// gets department list from system (iblock) for displaying in select box
public static function getDepartmentListFromSystem($arFilter = Array())
{
if (!IsModuleInstalled('intranet'))
{
return false;
}
$l=false;
if (CModule::IncludeModule('iblock'))
{
$iblockId=COption::GetOptionInt("intranet","iblock_structure",false,false);
if ($iblockId)
{
$arFilter["IBLOCK_ID"] = $iblockId;
$arFilter["CHECK_PERMISSIONS"]="N";
$l = CIBlockSection::GetTreeList($arFilter);
}
}
return $l;
}
public static function SetDepartmentHead($userId, $sectionId)
{
//echo "Setting ".$userId." as head of ".$sectionId;
$iblockId=COption::GetOptionInt("intranet","iblock_structure",false,false);
if ($iblockId && $sectionId && $userId && CModule::IncludeModule('iblock'))
{
/*$perm = CIBlock::GetPermission($iblockId);
if ($perm >= 'W')
{*/
$obS = new CIBlockSection();
if ($obS->Update($sectionId, array('UF_HEAD' => $userId), false, false))
{
return true;
}
else //if ($obS->LAST_ERROR)
{
// update error
return false;
}
/*}
else
{
// access denied
return false;
}*/
}
else
{
// bad data
return false;
}
}
public static function OnAfterUserAuthorizeHandler()
{
if(defined("LDAP_NO_PORT_REDIRECTION"))
return false;
global $USER;
if($USER->IsAuthorized())
{
$authNet = COption::GetOptionString("ldap", 'bitrixvm_auth_net', '');
if (trim($authNet))
if(self::IsIpFromNet($_SERVER['REMOTE_ADDR'],$authNet)===false)
return false;
$backUrl = isset($_GET['back_url']) ? $_GET['back_url'] : "/";
if ($_SERVER['SERVER_PORT'] == '8890')
LocalRedirect('http://'.$_SERVER["SERVER_NAME"].$backUrl);
if ($_SERVER['SERVER_PORT'] == '8891')
LocalRedirect('https://'.$_SERVER["SERVER_NAME"].$backUrl);
}
return true;
}
public static function OnEpilogHandler()
{
return self::bitrixVMAuthorize();
}
public static function bitrixVMAuthorize()
{
if(defined("LDAP_NO_PORT_REDIRECTION"))
return false;
global $USER, $APPLICATION;
if(!$USER->IsAuthorized())
{
$authNet = COption::GetOptionString("ldap", 'bitrixvm_auth_net', '');
if (trim($authNet))
if(self::IsIpFromNet($_SERVER['REMOTE_ADDR'],$authNet)===false)
return false;
$backUrl=strlen($APPLICATION->GetCurPage())>1 ? "?back_url=".rawurlencode($APPLICATION->GetCurUri()) : "";
if ($_SERVER['SERVER_PORT'] == '80')
LocalRedirect('http://'.$_SERVER["SERVER_NAME"].':8890/'.$backUrl, true);
elseif (($_SERVER['SERVER_PORT'] == '443'))
LocalRedirect('https://'.$_SERVER["SERVER_NAME"].':8891/'.$backUrl, true);
}
return true;
}
public static function isBitrixVMAuthSupported()
{
$eventManager = \Bitrix\Main\EventManager::getInstance();
$hndl = $eventManager->findEventHandlers("main", "OnEpilog", array("ldap"));
return !empty($hndl);
}
public static function SetBitrixVMAuthSupport($setOption=false, $netAndMask=false)
{
RegisterModuleDependences("main", "OnAfterUserAuthorize", 'ldap', 'CLdapUtil', 'OnAfterUserAuthorizeHandler');
RegisterModuleDependences("main", "OnEpilog", 'ldap', 'CLdapUtil', 'OnEpilogHandler');
if($setOption)
COption::SetOptionString("ldap", "bitrixvm_auth_support", "Y");
if($netAndMask)
COption::SetOptionString("ldap", "bitrixvm_auth_net", $netAndMask);
}
public static function UnSetBitrixVMAuthSupport($unSetOption=false)
{
UnRegisterModuleDependences("main", "OnAfterUserAuthorize", 'ldap', 'CLdapUtil', 'OnAfterUserAuthorizeHandler');
UnRegisterModuleDependences("main", "OnEpilog", 'ldap', 'CLdapUtil', 'OnEpilogHandler');
if($unSetOption)
COption::SetOptionString("ldap", "bitrixvm_auth_support", "N");
}
/**
* decides if ip address is from given network/mask;network1/mask1;network2/mask2;...
* @param str $ip - valid ip address - xxx.xxx.xxx.xxx
* @param str @netAndMask - valid mask/network - xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx;xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx;... or xxx.xxx.xxx.xxx/xx;xxx.xxx.xxx.xxx/xx;...
* @return bool true - if in, bool false - not in, or bad params
*/
public static function IsIpFromNet($ip,$netsAndMasks)
{
$arNetsMasks = explode(";",$netsAndMasks);
if(!is_array($arNetsMasks) || empty($arNetsMasks))
return false;
foreach ($arNetsMasks as $netAndMask)
{
$netAndMask = trim($netAndMask);
if(!$netAndMask)
continue;
if((!preg_match("#^(\d{1,3}\.){3,3}(\d{1,3})/(\d{1,3}\.){3,3}(\d{1,3})$#",$netAndMask) && !preg_match("#^(\d{1,3}\.){3,3}(\d{1,3})/(\d{1,3})$#",$netAndMask)) || !preg_match("#^(\d{1,3}\.){3,3}(\d{1,3})$#",$ip))
continue;
$arNetAndMask = explode("/", $netAndMask);
$net = $arNetAndMask[0];
if(strpos($arNetAndMask[1],".") !== false) //xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx
$mask = $arNetAndMask[1];
else //xxx.xxx.xxx.xxx/xx -> xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx
$mask=long2ip('11111111111111111111111111111111'<<(32-$arNetAndMask[1]));
$newNet = long2ip(ip2long($ip) & ip2long($mask));
if($newNet == $net)
return true;
else
continue;
}
return false;
}
/**
* Returns image file extension/type/format
* @param str $signature - first 12 bytes of the file.
* @return mix (str type if success or bool false in opposite case)
*/
public static function GetImgTypeBySignature($signature)
{
if($signature == "")
return false;
$signature = substr($signature,0,12);
$arSigs = array(
"GIF" => "gif",
"\xff\xd8\xff" => "jpg",
"\x89\x50\x4e" => "png",
"FWS" => "swf",
"CWS" => "swc",
"8BPS" => "psd",
"BM" => "bmp",
"\xff\x4f\xff" => "jpc",
"II\x2a\x00" => "tif",
"MM\x00\x2a" => "tif",
"FORM" => "iff",
"\x00\x00\x01\x00" => "ico",
"\x0d\x0a\x87\x0a" => "jp2"
);
foreach ($arSigs as $sig => $type)
if(preg_match("/^".$sig."/x", $signature))
return $type;
return false;
}
public static function isLdapPaginationAviable()
{
return function_exists("ldap_control_paged_result");
}
/**
* Returns true id defined net range for redirection
* on ntlm authorization ports 8890, 8891
* @return bool
*/
public static function isNtlmRedirectNetRangeDefined()
{
$authNet = COption::GetOptionString("ldap", 'bitrixvm_auth_net', '');
return strlen(trim($authNet)) > 0;
}
/**
* @param string $serverPort Server port.
* @return bool|string Port for outlook connection.
*/
public static function getTargetPort($serverPort = false)
{
if($serverPort === false)
$serverPort = $_SERVER["SERVER_PORT"];
$result = false;
$vmAuth = COption::GetOptionString("ldap", "bitrixvm_auth_support","N") == "Y";
$useNtlm = COption::GetOptionString("ldap", "use_ntlm","N") == "Y";
$isNtlmOn = $vmAuth && $useNtlm;
if($serverPort == "80")
$result = $isNtlmOn ? "8890" : "80";
elseif($serverPort == "443")
$result = $isNtlmOn ? "8891" : "443";
return $result;
}
}