Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
authentication_ldap.inc
1 <?php
18 require_once SQ_CORE_PACKAGE_PATH.'/system/authentication/authentication/authentication.inc';
19 require_once SQ_FUDGE_PATH.'/ldap/ldap.inc';
20 
21 
34 {
35 
36 
43  function Authentication_LDAP($assetid=0)
44  {
45  $this->Authentication($assetid);
46 
47  }//end constructor
48 
49 
62  function &authenticateUser($username, $password)
63  {
64  $user = NULL;
65  $bridge_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_SC_LINK_BACKEND_NAV, 'ldap_bridge', TRUE);
66 
67  $bridges = Array();
68  if (!empty($bridge_links)) {
69  foreach($bridge_links as $bridge_info) {
70  $bridges[$bridge_info['sort_order']] = $bridge_info['minorid'];
71  }
72  }
73 
74  foreach ($bridges as $sort_order => $bridgeid) {
75  $bridge = $GLOBALS['SQ_SYSTEM']->am->getAsset($bridgeid);
76  if (is_null($bridge)) continue;
77 
78  // if status is not live then skip this bridge
79  if ($bridge->status != SQ_STATUS_LIVE) continue;
80 
81  $ldap = $bridge->connectToLdap();
82 
83  if (is_null($ldap)) continue;
84 
85  $entry = $this->_getLdapEntries($username, $bridge, $ldap);
86  if (!$entry || ($entry['count'] == 0)) {
87  continue;
88  }
89  if (isset($entry[0])) {
90  $entry = $entry[0];
91 
92  // create our user
93  $user_type = $bridge->attr('user_type');
94  $GLOBALS['SQ_SYSTEM']->am->includeAsset($user_type);
95  $user = new $user_type($bridge->id, $entry);
96 
97  // verify password
98  $success = @$ldap->connectAsUser($user->attr('dn'), $password);
99 
100  if ($success) {
101  // ldap user found with username and password supplied
102  if ($this->attr('log_in_as') == 'local') {
103  // If we are logging in as a local user, we will ask
104  // Default Auth to merely locate a user for us
105  $auth_assetids = $GLOBALS['SQ_SYSTEM']->am->getTypeAssetids('authentication_default');
106  if (count($auth_assetids) > 0) {
107  $auth_default = $GLOBALS['SQ_SYSTEM']->am->getAsset($auth_assetids[0]);
108  }
109 
110  $user = $auth_default->locateUser($username);
111  }
112 
113  if (!is_null($user)) {
114  unset($_SESSION['user_login_attempts']);
115  }
116  return $user;
117  }
118  }
119  }//end foreach
120 
121  if (!is_null($user)) {
122  // a user was found, but the wrong password was supplied
123  $this->_registerInvalidLogin($user);
124  }
125 
126  $return_value = NULL;
127  return $return_value;
128 
129  }//end authenticateUser()
130 
131 
143  function &authenticateHttpUser($username)
144  {
145  $user = NULL;
146  $bridge_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_SC_LINK_BACKEND_NAV, 'ldap_bridge', TRUE);
147 
148  $bridges = Array();
149  if (!empty($bridge_links)) {
150  foreach($bridge_links as $bridge_info) {
151  $bridges[$bridge_info['sort_order']] = $bridge_info['minorid'];
152  }
153  }
154 
155  foreach ($bridges as $sort_order => $bridgeid) {
156  $bridge = $GLOBALS['SQ_SYSTEM']->am->getAsset($bridgeid);
157  if (is_null($bridge)) continue;
158 
159  // if status is not live then skip this bridge
160  if ($bridge->status != SQ_STATUS_LIVE) continue;
161 
162  $entry = $this->_getLdapEntries($username, $bridge);
163  if (!$entry || ($entry['count'] == 0)) {
164  continue;
165  }
166  if (isset($entry[0])) {
167  $entry = $entry[0];
168  $user_type = $bridge->attr('user_type');
169  $GLOBALS['SQ_SYSTEM']->am->includeAsset($user_type);
170  $user = new $user_type($bridge->id, $entry);
171  break;
172  }
173  }
174 
175  return $user;
176 
177  }//end authenticateHttpUser()
178 
179 
188  function &locateUser($username)
189  {
190  $user = NULL;
191  $bridge_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_SC_LINK_BACKEND_NAV, 'ldap_bridge', TRUE);
192 
193  $bridges = Array();
194  if (!empty($bridge_links)) {
195  foreach($bridge_links as $bridge_info) {
196  $bridges[$bridge_info['sort_order']] = $bridge_info['minorid'];
197  }
198  }
199 
200  foreach ($bridges as $sort_order => $bridgeid) {
201  $bridge = $GLOBALS['SQ_SYSTEM']->am->getAsset($bridgeid);
202  if (is_null($bridge)) continue;
203 
204  // if status is not live then skip this bridge
205  if ($bridge->status != SQ_STATUS_LIVE) continue;
206 
207  $entry = $this->_getLdapEntries($username, $bridge);
208  if (!$entry || ($entry['count'] == 0)) {
209  continue;
210  }
211  if (isset($entry[0])) {
212  $entry = $entry[0];
213  $user_type = $bridge->attr('user_type');
214  $GLOBALS['SQ_SYSTEM']->am->includeAsset($user_type);
215  $user = new $user_type($bridge->id, $entry);
216  break;
217  }
218  }
219 
220  return $user;
221 
222  }//end locateUser()
223 
232  function _registerInvalidLogin(&$user)
233  {
234  $username = $user->attr('dn');
235  if (!isset($_SESSION['user_login_attempts'])) {
236  $_SESSION['user_login_attempts'] = Array();
237  }
238  if (empty($_SESSION['user_login_attempts'][$username])) {
239  $_SESSION['user_login_attempts'][$username] = 1;
240  } else {
241  $_SESSION['user_login_attempts'][$username]++;
242  }
243 
244  if ($_SESSION['user_login_attempts'][$username] >= SQ_CONF_MAX_LOGIN_ATTEMPTS) {
245  if (!is_null($user) && $user->canLogin()) {
246  // log a message so we know someone has tried to log in too many times
247  $ms =& $GLOBALS['SQ_SYSTEM']->getMessagingService();
248  $msg_reps = Array(
249  'asset_name' => $user->name,
250  'user_name' => $username,
251  'num_attempts' => (int)SQ_CONF_MAX_LOGIN_ATTEMPTS,
252  );
253  $log = $ms->newMessage(Array(), 'system.security.login.ldap', $msg_reps);
254  $log->parameters['remote_addr'] = $_SERVER['REMOTE_ADDR'];
255  $log->parameters['sessionid'] = session_id();
256  $log->send();
257  }
258  }
259 
260  }//end _registerInvalidLogin()
261 
262 
270  function _getAllowedLinks()
271  {
272  return Array(
273  SQ_LINK_TYPE_1 => Array(
274  'ldap_bridge' => Array(
275  'card' => 'M',
276  'exclusive' => FALSE,
277  ),
278  ),
279  );
280 
281  }//end _getAllowedLinks()
282 
283 
295  function &_getLdapEntries($username, &$bridge, &$ldap_conn=NULL)
296  {
297  $null = NULL;
298  $ldap = $ldap_conn ? $ldap_conn : $bridge->connectToLdap();
299  // the attribute mappings to the LDAP schemas
300  $attrs = $bridge->attr('attributes');
301 
302  if (is_null($ldap)) return $null;
303 
304  // we do the search instead of binding directly as the user because ldap->connect_as_user requires
305  // the full dn as the first arg and doing it this way doesn't limit you to having all the users in the
306  // same organisational unit in the ldap directory
307  if (trim($bridge->attr('auth_dn')) !== '') {
308  $auth_base_dn = $bridge->attr('auth_dn');
309  } else {
310  $auth_base_dn = $bridge->attr('root_dn');
311  }
312 
313  // See #4860 Can't authenticate LDAP username with brackets
314  $username = $ldap->escape_filter_value($username);
315  // Check for extra LDAP filtering
316  $auth_filter = trim($bridge->attr('auth_filter'));
317  if (!empty($auth_filter)) {
318  // Add surrounding parentheses only if the filter does not have them.
319  // If the filter already have surrounding parentheses, adding them will
320  // cause invalid filter, e.g. ((o=Squiz)) is an invalid filter
321  if ($auth_filter[0] != '(') {
322  $auth_filter = '('.$auth_filter.')';
323  }
324  $filter = '(&'.$auth_filter.'('.$attrs['uid'].'='.$username.'))';
325  } else {
326  $filter = '('.$attrs['uid'].'='.$username.')';
327  }//end if
328 
329  $required_attrs = array_merge(
330  array_keys(array_get_index($bridge->attr('user_attributes'), 'show', Array())),
331  array_values($attrs),
332  Array('objectclass')
333  );
334  $result = $ldap->search($auth_base_dn, $filter, NULL, TRUE, TRUE, $required_attrs);
335 
336  if (!$result) return $null;
337  $entry = $ldap->getEntries($result);
338 
339  return $entry;
340 
341  }//end _getLdapEntries()
342 
343 
344 }//end class
345 
346 ?>