model.authent-ldap.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. // Copyright (C) 2010 Combodo SARL
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; version 3 of the License.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. /**
  17. * Authent LDAP
  18. * User authentication Module, no password at all!
  19. *
  20. * @author Erwan Taloc <erwan.taloc@combodo.com>
  21. * @author Romain Quetiez <romain.quetiez@combodo.com>
  22. * @author Denis Flaven <denis.flaven@combodo.com>
  23. * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
  24. */
  25. class UserLDAP extends UserInternal
  26. {
  27. public static function Init()
  28. {
  29. $aParams = array
  30. (
  31. "category" => "addon/authentication",
  32. "key_type" => "autoincrement",
  33. "name_attcode" => "login",
  34. "state_attcode" => "",
  35. "reconc_keys" => array('login'),
  36. "db_table" => "",
  37. "db_key_field" => "id",
  38. "db_finalclass_field" => "",
  39. "display_template" => "",
  40. );
  41. MetaModel::Init_Params($aParams);
  42. MetaModel::Init_InheritAttributes();
  43. // Display lists
  44. MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
  45. MetaModel::Init_SetZListItems('list', array('first_name', 'last_name', 'login')); // Attributes to be displayed for a list
  46. // Search criteria
  47. MetaModel::Init_SetZListItems('standard_search', array('login', 'contactid')); // Criteria of the std search form
  48. MetaModel::Init_SetZListItems('advanced_search', array('login', 'contactid')); // Criteria of the advanced search form
  49. }
  50. /**
  51. * Check the user's password against the LDAP server
  52. * Algorithm:
  53. * 1) Connect to the LDAP server, using a predefined account (or anonymously)
  54. * 2) Search for the specified user, based on a specific search query/pattern
  55. * 3) If exactly one user is found, continue, otherwise return false (wrong user or wrong query configured)
  56. * 3) Bind again to LDAP using the DN of the found user and the password
  57. * 4) If the bind is successful return true, otherwise return false (wrong password)
  58. * @param string $sPassword The user's password to validate against the LDAP server
  59. * @return boolean True if the password is Ok, false otherwise
  60. */
  61. public function CheckCredentials($sPassword)
  62. {
  63. $sLDAPHost = MetaModel::GetModuleSetting('authent-ldap', 'host', 'localhost');
  64. $iLDAPPort = MetaModel::GetModuleSetting('authent-ldap', 'port', 389);
  65. $sDefaultLDAPUser = MetaModel::GetModuleSetting('authent-ldap', 'default_user', '');
  66. $sDefaultLDAPPwd = MetaModel::GetModuleSetting('authent-ldap', 'default_pwd', '');
  67. $hDS = @ldap_connect($sLDAPHost, $iLDAPPort);
  68. if ($hDS === false)
  69. {
  70. $this->LogMessage("ldap_authentication: can not connect to the LDAP server '$sLDAPHost' (port: $iLDAPPort). Check the configuration file config-itop.php.");
  71. return false;
  72. }
  73. $aOptions = MetaModel::GetModuleSetting('authent-ldap', 'options', array());
  74. foreach($aOptions as $name => $value)
  75. {
  76. ldap_set_option($hDS, $name, $value);
  77. }
  78. if ($bind = @ldap_bind($hDS, $sDefaultLDAPUser, $sDefaultLDAPPwd))
  79. {
  80. // Search for the person, using the specified query expression
  81. $sLDAPUserQuery = MetaModel::GetModuleSetting('authent-ldap', 'user_query', '');
  82. $sBaseDN = MetaModel::GetModuleSetting('authent-ldap', 'base_dn', '');
  83. $sLogin = $this->Get('login');
  84. $iContactId = $this->Get('contactid');
  85. $sFirstName = '';
  86. $sLastName = '';
  87. $sEMail = '';
  88. if ($iContactId > 0)
  89. {
  90. $oPerson = MetaModel::GetObject('Person', $iContactId);
  91. if (is_object($oPerson))
  92. {
  93. $sFirstName = $oPerson->Get('first_name');
  94. $sLastName = $oPerson->Get('name');
  95. $sEMail = $oPerson->Get('email');
  96. }
  97. }
  98. // %1$s => login
  99. // %2$s => first name
  100. // %3$s => last name
  101. // %4$s => email
  102. $sQuery = sprintf($sLDAPUserQuery, $sLogin, $sFirstName, $sLastName, $sEMail);
  103. $hSearchResult = @ldap_search($hDS, $sBaseDN, $sQuery);
  104. $iCountEntries = ($hSearchResult !== false) ? @ldap_count_entries($hDS, $hSearchResult) : 0;
  105. switch($iCountEntries)
  106. {
  107. case 1:
  108. // Exactly one entry found, let's check the password by trying to bind with this user
  109. $aEntry = ldap_get_entries($hDS, $hSearchResult);
  110. $sUserDN = $aEntry[0]['dn'];
  111. $bUserBind = @ldap_bind($hDS, $sUserDN, $sPassword);
  112. if ($bUserBind !== false)
  113. {
  114. ldap_unbind($hDS);
  115. return true; // Password Ok
  116. }
  117. $this->LogMessage("ldap_authentication: wrong password for user: '$sUserDN'.");
  118. return false; // Wrong password
  119. break;
  120. case 0:
  121. // User not found...
  122. $this->LogMessage("ldap_authentication: no entry found with the query '$sQuery', base_dn = '$sBaseDN'. User not found in LDAP.");
  123. break;
  124. default:
  125. // More than one entry... maybe the query is not specific enough...
  126. $this->LogMessage("ldap_authentication: several (".ldap_count_entries($hDS, $hSearchResult).") entries match the query '$sQuery', base_dn = '$sBaseDN', check that the query defined in config-itop.php is specific enough.");
  127. }
  128. return false;
  129. }
  130. else
  131. {
  132. // Trace: invalid default user for LDAP initial binding
  133. $this->LogMessage("ldap_authentication: can not bind to the LDAP server '$sLDAPHost' (port: $iLDAPPort), user='$sDefaultLDAPUser', pwd='$sDefaultLDAPPwd'. Error: '".ldap_error($hDS)."'. Check the configuration file config-itop.php.");
  134. return false;
  135. }
  136. }
  137. public function TrustWebServerContext()
  138. {
  139. return false;
  140. }
  141. public function CanChangePassword()
  142. {
  143. return false;
  144. }
  145. public function CanLogOff()
  146. {
  147. // Internal authentication allows everybody to log off
  148. return true;
  149. }
  150. public function ChangePassword($sOldPassword, $sNewPassword)
  151. {
  152. return false;
  153. }
  154. protected function LogMessage($sMessage, $aData = array())
  155. {
  156. if (MetaModel::IsLogEnabledIssue())
  157. {
  158. if (MetaModel::IsValidClass('EventIssue'))
  159. {
  160. $oLog = new EventIssue();
  161. $oLog->Set('message', $sMessage);
  162. $oLog->Set('userinfo', '');
  163. $oLog->Set('issue', 'LDAP Authentication');
  164. $oLog->Set('impact', 'User login rejected');
  165. $oLog->Set('data', $aData);
  166. $oLog->DBInsertNoReload();
  167. }
  168. IssueLog::Error($sMessage);
  169. }
  170. }
  171. }
  172. ?>