/** * Reset user password * * @param TBGRequest $request */ public function runResetPassword(TBGRequest $request) { $this->user = TBGUser::getByUsername(str_replace('%2E', '.', $request->getParameter('user'))); $this->username = $request->getParameter('user'); $this->id = $request->getParameter('reset_hash'); $this->forward403unless($this->user instanceof TBGUser && $this->id == $this->user->getHashPassword(), 'Invalid password reset request'); }
/** * Forgotten password logic (AJAX call) * * @param TBGRequest $request */ public function runForgot(TBGRequest $request) { $i18n = TBGContext::getI18n(); try { $username = str_replace('%2E', '.', $request['forgot_password_username']); if (!empty($username)) { if (($user = TBGUser::getByUsername($username)) instanceof TBGUser) { if ($user->isActivated() && $user->isEnabled() && !$user->isDeleted()) { if ($user->getEmail()) { TBGMailing::getModule()->sendForgottenPasswordEmail($user); return $this->renderJSON(array('message' => $i18n->__('Please use the link in the email you received'))); } else { throw new Exception($i18n->__('Cannot find an email address for this user')); } } else { throw new Exception($i18n->__('Forbidden for this username, please contact your administrator')); } } else { throw new Exception($i18n->__('This username does not exist')); } } else { throw new Exception($i18n->__('Please enter an username')); } } catch (Exception $e) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => $e->getMessage())); } }
public function runUpdateUser(TBGRequest $request) { try { $user = TBGContext::factory()->TBGUser($request->getParameter('user_id')); if ($user instanceof TBGUser) { $testuser = TBGUser::getByUsername($request->getParameter('username')); if (!$testuser instanceof TBGUser || $testuser->getID() == $user->getID()) { $user->setUsername($request->getParameter('username')); } else { return $this->renderJSON(array('failed' => true, 'error' => TBGContext::getI18n()->__('This username is already taken'))); } $password_changed = false; if ($request->getParameter('password_action') == 'change' && $request->getParameter('new_password_1') && $request->getParameter('new_password_2')) { if ($request->getParameter('new_password_1') == $request->getParameter('new_password_2')) { $user->setPassword($request->getParameter('new_password_1')); $password_changed = true; } else { return $this->renderJSON(array('failed' => true, 'error' => TBGContext::getI18n()->__('Please enter the new password twice'))); } } elseif ($request->getParameter('password_action') == 'random') { $random_password = TBGUser::createPassword(); $user->setPassword($random_password); $password_changed = true; } $user->setRealname($request->getParameter('realname')); $return_options = array(); try { if ($group = TBGContext::factory()->TBGGroup($request->getParameter('group'))) { if ($user->getGroupID() != $group->getID()) { $groups = array($user->getGroupID(), $group->getID()); $return_options['update_groups'] = array('ids' => array(), 'membercounts' => array()); } $user->setGroup($group); } } catch (Exception $e) { throw new Exception(TBGContext::getI18n()->__('Invalid user group')); } $existing_teams = array_keys($user->getTeams()); $new_teams = array(); $user->clearTeams(); try { foreach ($request->getParameter('teams', array()) as $team_id => $team) { if ($team = TBGContext::factory()->TBGTeam($team_id)) { $new_teams[] = $team_id; $user->addToTeam($team); } } } catch (Exception $e) { throw new Exception(TBGContext::getI18n()->__('One or more teams were invalid')); } try { $user->clearClients(); foreach ($request->getParameter('clients', array()) as $client_id => $client) { if ($client = TBGContext::factory()->TBGClient($client_id)) { $new_clients[] = $client_id; $user->addToClient($client); } } } catch (Exception $e) { throw new Exception(TBGContext::getI18n()->__('One or more clients were invalid')); } $user->setBuddyname($request->getParameter('nickname')); $user->setActivated((bool) $request->getParameter('activated')); $user->setEmail($request->getParameter('email')); $user->setEnabled((bool) $request->getParameter('enabled')); $user->save(); if (isset($groups)) { foreach ($groups as $group_id) { if (!$group_id) { continue; } $return_options['update_groups']['ids'][] = $group_id; $return_options['update_groups']['membercounts'][$group_id] = TBGContext::factory()->TBGGroup($group_id)->getNumberOfMembers(); } } if ($new_teams != $existing_teams) { $new_team_ids = array_diff($new_teams, $existing_teams); $existing_team_ids = array_diff($existing_teams, $new_teams); $teams_to_update = array_merge($new_team_ids, $existing_team_ids); $return_options['update_teams'] = array('ids' => array(), 'membercounts' => array()); foreach ($teams_to_update as $team_id) { $return_options['update_teams']['ids'][] = $team_id; $return_options['update_teams']['membercounts'][$team_id] = TBGContext::factory()->TBGTeam($team_id)->getNumberOfMembers(); } } $return_options['failed'] = false; $template_options = array('user' => $user); if (isset($random_password)) { $template_options['random_password'] = $random_password; } $return_options['content'] = $this->getTemplateHTML('configuration/finduser_row', $template_options); $return_options['title'] = TBGContext::getI18n()->__('User updated!'); if ($password_changed) { $return_options['message'] = TBGContext::getI18n()->__('The password was changed'); } return $this->renderJSON($return_options); } } catch (Exception $e) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('failed' => true, 'error' => TBGContext::getI18n()->__('This user could not be updated: %message%', array('%message%' => $e->getMessage())))); } $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('failed' => true, 'error' => TBGContext::getI18n()->__('This user could not be updated'))); }
/** * Import all valid users * * @param TBGRequest $request */ public function runImportUsers(TBGRequest $request) { $validgroups = TBGContext::getModule('auth_ldap')->getSetting('groups'); $base_dn = TBGContext::getModule('auth_ldap')->getSetting('b_dn'); $dn_attr = TBGContext::getModule('auth_ldap')->getSetting('dn_attr'); $username_attr = TBGContext::getModule('auth_ldap')->getSetting('u_attr'); $fullname_attr = TBGContext::getModule('auth_ldap')->getSetting('f_attr'); $buddyname_attr = TBGContext::getModule('auth_ldap')->getSetting('b_attr'); $email_attr = TBGContext::getModule('auth_ldap')->getSetting('e_attr'); $groups_members_attr = TBGContext::getModule('auth_ldap')->getSetting('g_attr'); $user_class = TBGContext::getModule('auth_ldap')->getSetting('u_type'); $group_class = TBGContext::getModule('auth_ldap')->getSetting('g_type'); $users = array(); $importcount = 0; $updatecount = 0; try { /* * Connect and bind to the control user */ $connection = TBGContext::getModule('auth_ldap')->connect(); TBGContext::getModule('auth_ldap')->bind($connection, TBGContext::getModule('auth_ldap')->getSetting('control_user'), TBGContext::getModule('auth_ldap')->getSetting('control_pass')); /* * Get a list of all users of a certain objectClass */ $fields = array($fullname_attr, $buddyname_attr, $username_attr, $email_attr, 'cn', $dn_attr); $filter = '(objectClass=' . TBGLDAPAuthentication::getModule()->escape($user_class) . ')'; $results = ldap_search($connection, $base_dn, $filter, $fields); if (!$results) { TBGLogging::log('failed to search for users: ' . ldap_error($connection), 'ldap', TBGLogging::LEVEL_FATAL); throw new Exception(TBGContext::geti18n()->__('Search failed: ') . ldap_error($connection)); } $data = ldap_get_entries($connection, $results); /* * For every user that exists, process it. */ for ($i = 0; $i != $data['count']; $i++) { $user_dn = $data[$i][strtolower($dn_attr)][0]; /* * If groups are specified, perform group restriction tests */ if ($validgroups != '') { /* * We will repeat this for every group, but groups are supplied as a comma-separated list */ if (strstr($validgroups, ',')) { $groups = explode(',', $validgroups); } else { $groups = array(); $groups[] = $validgroups; } // Assumed we are initially banned $allowed = false; foreach ($groups as $group) { // No need to carry on looking if we have access if ($allowed == true) { continue; } /* * Find the group we are looking for, we search the entire directory * We want to find 1 group, if we don't get 1, silently ignore this group. */ $fields2 = array($groups_members_attr); $filter2 = '(&(cn=' . TBGLDAPAuthentication::getModule()->escape($group) . ')(objectClass=' . TBGLDAPAuthentication::getModule()->escape($group_class) . '))'; $results2 = ldap_search($connection, $base_dn, $filter2, $fields2); if (!$results2) { TBGLogging::log('failed to search for user: '******'ldap', TBGLogging::LEVEL_FATAL); throw new Exception(TBGContext::geti18n()->__('Search failed: ') . ldap_error($connection)); } $data2 = ldap_get_entries($connection, $results2); if ($data2['count'] != 1) { continue; } /* * Look through the group's member list. If we are found, grant access. */ foreach ($data2[0][strtolower($groups_members_attr)] as $member) { $member = preg_replace('/(?<=,) +(?=[a-zA-Z])/', '', $member); $user_dn = preg_replace('/(?<=,) +(?=[a-zA-Z])/', '', $user_dn); if (!is_numeric($member) && strtolower($member) == strtolower($user_dn)) { $allowed = true; } } } if ($allowed == false) { continue; } } $users[$i] = array(); /* * Set user's properties. * Realname is obtained from directory, if not found we set it to the username * Email is obtained from directory, if not found we set it to blank */ if (!array_key_exists(strtolower($fullname_attr), $data[$i])) { $users[$i]['realname'] = $data[$i]['cn'][0]; } else { $users[$i]['realname'] = $data[$i][strtolower($fullname_attr)][0]; } if (!array_key_exists(strtolower($buddyname_attr), $data[$i])) { $users[$i]['buddyname'] = $data[$i]['cn'][0]; } else { $users[$i]['buddyname'] = $data[$i][strtolower($buddyname_attr)][0]; } if (!array_key_exists(strtolower($email_attr), $data[$i])) { $users[$i]['email'] = ''; } else { $users[$i]['email'] = $data[$i][strtolower($email_attr)][0]; } $users[$i]['username'] = $data[$i][strtolower($username_attr)][0]; } } catch (Exception $e) { TBGContext::setMessage('module_error', TBGContext::getI18n()->__('Import failed')); TBGContext::setMessage('module_error_details', $e->getMessage()); $this->forward(TBGContext::getRouting()->generate('configure_module', array('config_module' => 'auth_ldap'))); } /* * For every user that was found, either create a new user object, or update * the existing one. This will update the created and updated counts as appropriate. */ foreach ($users as $ldapuser) { $username = $ldapuser['username']; $email = $ldapuser['email']; $realname = $ldapuser['realname']; $buddyname = $ldapuser['buddyname']; try { $user = TBGUser::getByUsername($username); if ($user instanceof TBGUser) { $user->setRealname($realname); $user->setEmail($email); // update email address $user->save(); $updatecount++; } else { // create user $user = new TBGUser(); $user->setUsername($username); $user->setRealname($realname); $user->setBuddyname($buddyname); $user->setEmail($email); $user->setEnabled(); $user->setActivated(); $user->setPassword($user->getJoinedDate() . $username); $user->setJoined(); $user->save(); $importcount++; } } catch (Exception $e) { ldap_unbind($connection); TBGContext::setMessage('module_error', TBGContext::getI18n()->__('Import failed')); TBGContext::setMessage('module_error_details', $e->getMessage()); $this->forward(TBGContext::getRouting()->generate('configure_module', array('config_module' => 'auth_ldap'))); } } ldap_unbind($connection); TBGContext::setMessage('module_message', TBGContext::getI18n()->__('Import successful! %imp users imported, %upd users updated from LDAP', array('%imp' => $importcount, '%upd' => $updatecount))); $this->forward(TBGContext::getRouting()->generate('configure_module', array('config_module' => 'auth_ldap'))); }
/** * Reset user password * * @param TBGRequest $request The request object * */ public function runReset(TBGRequest $request) { $i18n = TBGContext::getI18n(); try { if ($request->hasParameter('user') && $request->hasParameter('reset_hash')) { $user = TBGUser::getByUsername(str_replace('%2E', '.', $request['user'])); if ($user instanceof TBGUser) { if ($request['reset_hash'] == $user->getActivationKey()) { $this->error = false; if ($request->isPost()) { $p1 = trim($request['password_1']); $p2 = trim($request['password_2']); if ($p1 && $p2 && $p1 == $p2) { $user->setPassword($p1); $user->regenerateActivationKey(); $user->save(); TBGContext::setMessage('login_message', $i18n->__('Your password has been reset. Please log in.')); TBGContext::setMessage('login_referer', $this->getRouting()->generate('home')); return $this->forward(TBGContext::getRouting()->generate('login_page')); } else { $this->error = true; } } else { $user->regenerateActivationKey(); } $this->user = $user; } else { throw new Exception('Your password recovery token is either invalid or has expired'); } } else { throw new Exception('User is invalid or does not exist'); } } else { throw new Exception('An internal error has occured'); } } catch (Exception $e) { TBGContext::setMessage('login_message_err', $i18n->__($e->getMessage())); return $this->forward(TBGContext::getRouting()->generate('login_page')); } }
public function doLogin($username, $password, $mode = 1) { $validgroups = $this->getSetting('groups'); $base_dn = $this->getSetting('b_dn'); $dn_attr = $this->escape($this->getSetting('dn_attr')); $username_attr = $this->escape($this->getSetting('u_attr')); $fullname_attr = $this->escape($this->getSetting('f_attr')); $buddyname_attr = $this->escape($this->getSetting('b_attr')); $email_attr = $this->escape($this->getSetting('e_attr')); $groups_members_attr = $this->escape($this->getSetting('g_attr')); $user_class = TBGContext::getModule('auth_ldap')->getSetting('u_type'); $group_class = TBGContext::getModule('auth_ldap')->getSetting('g_type'); $email = null; $integrated_auth = $this->getSetting('integrated_auth'); /* * Do the LDAP check here. * * If a connection error or something, throw an exception and log * * If we can, set $mail and $realname to correct values from LDAP * otherwise don't touch those variables. * * To log do: * TBGLogging::log('error goes here', 'ldap', TBGLogging::LEVEL_FATAL); */ try { /* * First job is to connect to our control user (may be an anonymous bind) * so we can find the user we want to log in as/validate. */ $connection = $this->connect(); $control_user = $this->getSetting('control_user'); $control_password = $this->getSetting('control_pass'); $this->bind($connection, $control_user, $control_password); // Assume bind successful, otherwise we would have had an exception /* * Search for a user with the username specified. We search in the base_dn, so we can * find users in multiple parts of the directory, and only return users of a specific * class (default person). * * We want exactly 1 user to be returned. We get the user's full name, email, cn * and dn. */ $fields = array($fullname_attr, $buddyname_attr, $email_attr, 'cn', $dn_attr); $filter = '(&(objectClass=' . TBGLDAPAuthentication::getModule()->escape($user_class) . ')(' . $username_attr . '=' . $this->escape($username) . '))'; $results = ldap_search($connection, $base_dn, $filter, $fields); if (!$results) { TBGLogging::log('failed to search for user: '******'ldap', TBGLogging::LEVEL_FATAL); throw new Exception(TBGContext::geti18n()->__('Search failed: ') . ldap_error($connection)); } $data = ldap_get_entries($connection, $results); // User does not exist if ($data['count'] == 0) { TBGLogging::log('could not find user ' . $username . ', class ' . $user_class . ', attribute ' . $username_attr, 'ldap', TBGLogging::LEVEL_FATAL); throw new Exception(TBGContext::geti18n()->__('User does not exist in the directory')); } // If we have more than 1 user, something is seriously messed up... if ($data['count'] > 1) { TBGLogging::log('too many users for ' . $username . ', class ' . $user_class . ', attribute ' . $username_attr, 'ldap', TBGLogging::LEVEL_FATAL); throw new Exception(TBGContext::geti18n()->__('This user was found multiple times in the directory, please contact your admimistrator')); } /* * If groups are specified, perform group restriction tests */ if ($validgroups != '') { /* * We will repeat this for every group, but groups are supplied as a comma-separated list */ if (strstr($validgroups, ',')) { $groups = explode(',', $validgroups); } else { $groups = array(); $groups[] = $validgroups; } // Assumed we are initially banned $allowed = false; foreach ($groups as $group) { // No need to carry on looking if we have access if ($allowed == true) { continue; } /* * Find the group we are looking for, we search the entire directory as per users (See that stuff) * We want to find 1 group, if we don't get 1, silently ignore this group. */ $fields2 = array($groups_members_attr); $filter2 = '(&(objectClass=' . TBGLDAPAuthentication::getModule()->escape($group_class) . ')(cn=' . $this->escape($group) . '))'; $results2 = ldap_search($connection, $base_dn, $filter2, $fields2); if (!$results2) { TBGLogging::log('failed to search for user after binding: ' . ldap_error($connection), 'ldap', TBGLogging::LEVEL_FATAL); throw new Exception(TBGContext::geti18n()->__('Search failed ') . ldap_error($connection)); } $data2 = ldap_get_entries($connection, $results2); if ($data2['count'] != 1) { continue; } /* * Look through the group's member list. If we are found, grant access. */ foreach ($data2[0][strtolower($groups_members_attr)] as $member) { $member = preg_replace('/(?<=,) +(?=[a-zA-Z])/', '', $member); $user_dn = preg_replace('/(?<=,) +(?=[a-zA-Z])/', '', $data[0][strtolower($dn_attr)][0]); if (!is_numeric($member) && strtolower($member) == strtolower($user_dn)) { $allowed = true; } } } if ($allowed == false) { throw new Exception(TBGContext::getI18n()->__('You are not a member of a group allowed to log in')); } } /* * Set user's properties. * Realname is obtained from directory, if not found we set it to the username * Email is obtained from directory, if not found we set it to blank */ if (!array_key_exists(strtolower($fullname_attr), $data[0])) { $realname = $username; } else { $realname = $data[0][strtolower($fullname_attr)][0]; } if (!array_key_exists(strtolower($buddyname_attr), $data[0])) { $buddyname = $username; } else { $buddyname = $data[0][strtolower($buddyname_attr)][0]; } if (!array_key_exists(strtolower($email_attr), $data[0])) { $email = ''; } else { $email = $data[0][strtolower($email_attr)][0]; } /* * If we are performing a non integrated authentication login, * now bind to the user and see if the credentials * are valid. We bind using the full DN of the user, so no need for DOMAIN\ stuff * on Windows, and more importantly it fixes other servers. * * If the bind fails (exception), we throw a nicer exception and don't continue. */ if ($mode == 1 && !$integrated_auth) { try { if (!is_array($data[0][strtolower($dn_attr)])) { $dn = $data[0][strtolower($dn_attr)]; } else { $dn = $data[0][strtolower($dn_attr)][0]; } $bind = $this->bind($connection, $this->escape($dn), $password); } catch (Exception $e) { throw new Exception(TBGContext::geti18n()->__('Your password was not accepted by the server')); } } elseif ($mode == 1) { if (!isset($_SERVER[$this->getSetting('integrated_auth_header')]) || $_SERVER[$this->getSetting('integrated_auth_header')] != $username) { throw new Exception(TBGContext::geti18n()->__('HTTP authentication internal error.')); } } } catch (Exception $e) { ldap_unbind($connection); throw $e; } try { /* * Get the user object. If the user exists, update the user's * data from the directory. */ $user = TBGUser::getByUsername($username); if ($user instanceof TBGUser) { $user->setBuddyname($buddyname); $user->setRealname($realname); $user->setPassword($user->getJoinedDate() . $username); // update password $user->setEmail($email); // update email address $user->save(); } else { /* * If not, and we are performing an initial login, create the user object * if we are validating a log in, kick the user out as the session is invalid. */ if ($mode == 1) { // create user $user = new TBGUser(); $user->setUsername($username); $user->setRealname('temporary'); $user->setBuddyname($username); $user->setEmail('temporary'); $user->setEnabled(); $user->setActivated(); $user->setJoined(); $user->setPassword($user->getJoinedDate() . $username); $user->save(); } else { throw new Exception('User does not exist in TBG'); } } } catch (Exception $e) { ldap_unbind($connection); throw $e; } ldap_unbind($connection); /* * Set cookies and return user row for general operations. */ TBGContext::getResponse()->setCookie('tbg3_username', $username); TBGContext::getResponse()->setCookie('tbg3_password', TBGUser::hashPassword($user->getJoinedDate() . $username, $user->getSalt())); return TBGUsersTable::getTable()->getByUsername($username); }
/** * Reset user password * * @param TBGRequest $request The request object * */ public function runReset(TBGRequest $request) { $i18n = TBGContext::getI18n(); if ($request->hasParameter('user') && $request->hasParameter('id') && $request->hasParameter('forgot_password_mail')) { try { $user = TBGUser::getByUsername($request->getParameter('user')); if ($user instanceof TBGUser) { if ($request->getParameter('id') == $user->getHashPassword()) { if ($request->getParameter('forgot_password_mail') == $user->getEmail()) { $password = $user->createPassword(); $user->changePassword($password); $user->save(); $event = TBGEvent::createNew('core', 'password_reset', $user, array('password' => $password))->trigger(); return $this->renderJSON(array('message' => $i18n->__('An email has been sent to you with your new password.'))); } else { throw new Exception('Invalid email address'); } } else { throw new Exception('Your password recovery token is either invalid or has expired'); } } else { throw new Exception('User is invalid or does not exist'); } } catch (Exception $e) { return $this->renderJSON(array('failed' => true, 'error' => $i18n->__($e->getMessage()))); } } else { return $this->renderJSON(array('failed' => true, 'error' => 'An internal error has occured')); } }