blob: 364f30dfb4f5ced47efacf6004277c2b3a834715 [file] [log] [blame]
<?php
/*******************************************************************************
* Copyright (c) 2014, 2015 Eclipse Foundation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christopher Guindon (Eclipse Foundation) - initial API and implementation
*******************************************************************************/
require_once(realpath(dirname(__FILE__) . "/../../system/app.class.php"));
require_once(realpath(dirname(__FILE__) . "/../friends/friend.class.php"));
require_once(realpath(dirname(__FILE__) . "/../../system/session.class.php"));
require_once("accountCreator.class.php");
require_once('/home/data/httpd/eclipse-php-classes/system/ldapconnection.class.php');
require_once(realpath(dirname(__FILE__) . "/../../system/evt_log.class.php"));
require_once(realpath(dirname(__FILE__) . "/../captcha/captcha.class.php"));
require_once(realpath(dirname(__FILE__) . "/../forms/formToken.class.php"));
define('SITELOGIN_EMAIL_REGEXP', '/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/');
define('SITELOGIN_NAME_REGEXP', '/[^\p{L}\p{N}\-\.\' ]/u');
class Sitelogin {
private $App = NULL;
private $agree = "";
private $bio = "";
private $Captcha = NULL;
private $country = "";
private $country_list = NULL;
private $githubid = "";
private $formToken = NULL;
private $Friend = NULL;
private $fname = "";
private $exipred_pass_token = FALSE;
private $interests = "";
private $jobtitle = "";
private $Ldapconn = NULL;
private $lname = "";
private $messages = array();
private $newsletter_status = "";
private $organization = "";
private $p = "";
private $page = "";
private $password = "";
private $password1 = "";
private $password2 = "";
private $password_update = 0;
private $password_expired = "";
private $path_public_key = "";
private $profile_default = array();
private $referer = "";
private $remember = "";
private $Session = NULL;
private $stage = "";
private $submit = "";
private $takemeback = "";
private $t = "";
private $twitter_handle = "";
private $username = "";
private $user_uid = "";
private $user_mail = "";
private $website = "";
private $xss_patterns = array();
private $is_committer = "";
private $changed_employer = "";
function Sitelogin($stage = NULL) {
$this->xss_patterns = array(
'/<script[^>]*?>.*?<\/script>/si',
'/<[\/\!]*?[^<>]*?>/si',
'/<style[^>]*?>.*?<\/style>/siU',
'/<![\s\S]*?–[ \t\n\r]*>/'
);
$this->path_public_key = "/home/data/httpd/dev.eclipse.org/html/public_key.pem";
global $App;
$this->App = $App;
$this->Captcha = New Captcha();
$this->Session = $this->App->useSession();
$this->Friend = $this->Session->getFriend();
$this->Ldapconn = new LDAPConnection();
$this->FormToken = new FormToken();
$this->_sanitizeVariables();
$this->user_uid = $this->Ldapconn->getUIDFromMail($this->Friend->getEmail());
$this->user_mail = $this->Friend->getEmail();
$this->is_committer = $this->Friend->getIsCommitter();
$this->password_expired = $this->_verifyIfPasswordExpired();
$this->_setStage($stage);
switch ($this->stage) {
case 'login':
$this->_userAuthentification();
break;
case 'create':
$this->_createAccount();
break;
case 'reset':
$this->_resetPassword();
break;
case 'reset2':
$this->_resetPassword2();
break;
case 'reset3':
$this->_resetPassword3();
break;
case 'confirm':
$this->_confirmAccount();
break;
case 'save':
$this->_processSave();
break;
case 'save-account':
$this->_processSave(FALSE);
break;
case 'save-profile':
$this->_processSaveProfile();
break;
}
}
public function getDomain() {
$domain = $this->App->getEclipseDomain();
return 'https://' . $domain['dev_domain'];
}
public function getStage(){
return $this->stage;
}
public function getIsCommitter(){
return $this->is_committer;
}
public function getCountryList() {
if (is_null($this->country_list)) {
$this->_fetchCountries();
}
return $this->country_list;
}
public function getSystemMessage() {
$return = "";
$allowed_type = array(
'success',
'info',
'warning',
'danger'
);
foreach ($this->messages as $type) {
foreach ($type as $key => $value) {
if (!in_array($key, $allowed_type)) {
continue;
}
$list = '<ul>';
if (count($value) == 1) {
if ($key == 'danger'){
$org_value = $value[0];
$value[0] = '<p><strong>' . $org_value . '</strong></p>';
}
$return .= $this->_getMessageContainer($value[0], $key);
continue;
}
foreach ($value as $msg) {
$list .= '<li><strong>' . $msg . '</strong></li>';
}
$list .= '</ul>';
$return .= $this->_getMessageContainer($list, $key);
}
}
return $return;
}
public function getVariables($type = NULL){
$return = array(
'agree' => "",
'username' => "",
'password' => "",
'remember' => "",
'submit' => "",
'takemeback' => "",
'githubid' => "",
'referer' => "",
'password1' => "",
'password2' => "",
'password_update' => "",
'fname' => "",
'lname' => "",
'githubid' => "",
'organization' => "",
'jobtitle' => "",
'website' => "",
'bio' => "",
'interests' => "",
'twitter_handle' => "",
'country' => "",
'newsletter_status' => "",
);
$this->_get_default_profile_fields();
# Bug 428032 - Multiple XSS on site_login
$username = filter_var($this->username, FILTER_SANITIZE_EMAIL);
$fname = filter_var($this->fname, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$lname = filter_var($this->lname, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$takemeback = filter_var($this->takemeback, FILTER_SANITIZE_ENCODED);
$remember = filter_var($this->remember, FILTER_SANITIZE_NUMBER_INT);
$agree = filter_var($this->agree, FILTER_SANITIZE_NUMBER_INT);
$password_update = filter_var($this->password_update, FILTER_SANITIZE_NUMBER_INT);
$githubid = filter_var($this->Ldapconn->getGithubIDFromMail($this->Friend->getEmail()), FILTER_SANITIZE_STRING);
$organization = filter_var($this->organization, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$country = filter_var($this->country, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$jobtitle = filter_var($this->jobtitle, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$website = filter_var($this->website, FILTER_SANITIZE_URL);
$bio = filter_var($this->bio, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$interests = filter_var($this->interests, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$token = filter_var($this->t, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$twitter_handle = filter_var($this->twitter_handle, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
$newsletter_status = filter_var($this->newsletter_status, FILTER_SANITIZE_STRING,FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
switch ($type) {
case 'login':
$return['username'] = $username;
$return['remember'] = ($remember) ? 'checked="checked"' : "";
$return['takemeback'] = $takemeback;
break;
case 'welcomeback':
$return['username'] = $this->_get_default_field_value('username', $username);
$return['fname'] = $this->_get_default_field_value('fname', $fname);
$return['lname'] = $this->_get_default_field_value('lname', $lname);
$return['githubid'] = $this->_get_default_field_value('githubid', $githubid);
$return['takemeback'] = $takemeback;
$return['organization'] = $organization;
$return['jobtitle'] = $jobtitle;
$return['website'] = $website;
$return['bio'] = $bio;
$return['country'] = $country;
$return['interests'] = $interests;
$return['twitter_handle'] = $twitter_handle;
$return['friend'] = array(
'uid' => $this->Friend->getUID(),
'is_committer' => $this->Friend->getIsCommitter(),
'is_benefit' => $this->Friend->getIsBenefit(),
'date_joined' => substr($this->Friend->getDateJoined(), 0, 10),
'date_expired' => substr($this->Friend->getBenefitExpires(), 0, 10),
);
break;
case 'create':
if ($this->stage == 'create') {
$return['username'] = $username;
$return['fname'] = $fname;
$return['lname'] = $lname;
$return['organization'] = $organization;
$return['country'] = $country;
$return['agree'] = $agree;
$return['takemeback'] = $takemeback;
$return['newsletter_status'] = $newsletter_status;
}
break;
case 'reset':
$return['token'] = $token;
break;
case 'logout':
$return['password_update'] = $password_update;
break;
}
return $return;
}
public function logout() {
$referer = "";
if (isset($_SERVER['HTTP_REFERER'])) {
$referer = $_SERVER['HTTP_REFERER'];
}
$eclipse_domains = array(
'projects.eclipse.org' => 'https://projects.eclipse.org/',
'eclipse.org/forums/' => 'https://www.eclipse.org/forums/',
'wiki.eclipse.org' => 'https://wiki.eclipse.org/index.php?title=Special:UserLogout',
'git.eclipse.org/r/' => 'https://git.eclipse.org/r/',
'bugs.eclipse.org/bugs/' => 'https://bugs.eclipse.org/bugs/',
'lts.eclipse.org' => 'https://lts.eclipse.org/',
'marketplace.eclipse.org' => 'https://marketplace.eclipse.org',
);
$redirect = 'https://www.eclipse.org/';
foreach ($eclipse_domains as $key => $value) {
if (strpos($referer, $key)){
$redirect = $value;
break;
}
}
// Destroy the session for the user.
// Bug 443883 - [site_login] Password change should invalidate all active sessions
if ($this->Session->isLoggedIn()) {
$this->Session->destroy(TRUE);
$this->messages['logout']['info'][] = 'You have been logged out.';
}
else{
$this->messages['logout']['danger'][] = 'You are currently not logged in.';
$redirect = 'https://dev.eclipse.org/site_login/';
}
return $redirect;
}
public function password_update() {
$this->messages['logout']['success'][] = "Your account details have been updated successfully.";
$this->messages['logout']['warning'][] = 'Please login to confirm your new password.';
}
public function showCountries() {
$options = "";
$continents = $this->_fetchcontinents();
$countries = $this->_fetchCountries();
foreach ($continents as $continent) {
$options .= '<optgroup label="'. $continent .'">';
foreach ($countries as $country) {
if ($country['continent'] == $continent) {
$selected = "";
if (!empty($this->country) && $this->country == $country['ccode']) {
$selected = "selected";
}
$options .= '<option value="'. $country['ccode'] .'" ' . $selected.'>'. $country['description'] .'</option>';
}
}
$options .= '</optgroup>';
}
return $options;
}
function verifyUserStatus() {
# bug 432822 - if someone is already logged in, send them to their account info page
if (empty($this->takemeback)) {
$this->takemeback = 'myaccount.php';
}
if ($this->Session->getGID() != "") {
header("Location: " . $this->takemeback, 302);
exit;
}
}
/**
* Validate takemeback Url
*
* Bug 421097
* @return boolean
*/
public function validateTakemebackUrl($takemeback = "") {
if ($takemeback == "") {
$takemeback = $this->takemeback;
}
$domains = array(
'eclipse.org',
'planeteclipse.org',
'locationtech.org',
'polarsys.org',
'eclipse.local'
);
foreach ($domains as $d) {
if (preg_match('#^(http(s)?:\/\/)(www\.)?([\w+0-9-]{0,}\.)?' . $d . '(:\d{1,5})?(\/)?#', $takemeback) &&
strpos($takemeback, $d . ".") === FALSE){
return TRUE;
break;
}
}
return FALSE;
}
private function _confirmAccount() {
$sql = "SELECT /* USE MASTER */ COUNT(1) AS RecordCount
FROM account_requests
WHERE token IN ('TOKEN_FAILED', 'CONFIRM_SUCCESS')
AND ip = " . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']);
$rs = $this->App->eclipse_sql($sql);
$myrow = mysql_fetch_assoc($rs);
if ($myrow['RecordCount'] > 0) {
$this->messages['confirm']['danger'][] = "<b>You have already submitted a request. Please check your email inbox and spam folders to respond to the previous request.</b> (8728s)";
}
else {
if ($this->t != "") {
$sql = "SELECT /* USE MASTER */ email, fname, password, lname, COUNT(1) AS RecordCount FROM account_requests WHERE token = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->t));
$rs = $this->App->eclipse_sql($sql);
$myrow = mysql_fetch_assoc($rs);
if ($myrow['RecordCount'] <= 0) {
$this->messages['confirm']['danger'][] = "We were unable to validate your request. The supplied token is invalid; perhaps it has expired? Please try creating your account again, and contact webmaster@eclipse.org if the problem persists. (8729s)";
# If we can't find a record, insert a record preventing this dude from bombing us
$this->t = $this->App->getAlphaCode(64);
$this->App->eclipse_sql("INSERT INTO account_requests VALUES (" . $this->App->returnQuotedString($this->App->sqlSanitize($this->t)) . ",
'',
'token_failed',
'token_failed',
'token_failed',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
'TOKEN_FAILED')"
);
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->App->sqlSanitize($this->t));
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("ACCT_CREATE_TOKEN_FAILED");
$EventLog->insertModLog("apache");
}
else {
// New accounts will always have a value in $myrow['password'].
$token_confirm = 'CONFIRM_SUCCESS';
# Update this row, change IP address to reflect that of the person who successfully confirmed this email to avoid bombing
$sql = "UPDATE account_requests SET token = ". $this->App->returnQuotedString($this->App->sqlSanitize($token_confirm)) .", ip = " . $this->App->returnQuotedString($this->App->sqlSanitize($_SERVER['REMOTE_ADDR']))
. " WHERE token = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->t));
$rs = $this->App->eclipse_sql($sql);
$this->messages['confirm']['success'][] = "Thank you for confirming your email address.
Your Eclipse.org account is now active and you may now </strong>log in</strong></a>.
Please note that some Eclipse.org pages may require you to provide your login
credentials.";
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->App->sqlSanitize($this->t));
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("ACCT_CREATE_CONFIRM");
$EventLog->insertModLog($myrow['email']);
}
}
else {
$this->messages['confirm']['danger'][] = "We were unable to validate your request. The supplied token is invalid. Please contact webmaster@eclipse.org.";
}
}
}
private function _createAccount() {
if ($this->username != "" && $this->fname != "" && $this->lname != "" && $this->password1 != "") {
if (!$this->FormToken->verifyToken($_POST['token-create-account']) || !empty($_POST['create-account-email-req'])) {
# Send mail to webmaster
$mail = "Dear webmaster,\n\n";
$mail .= "A new eclipse.org account was denied:\n\n";
$mail .= "Email: " . $this->username . "\n\n";
$mail .= "First name: " . $this->fname . "\n\n";
$mail .= "Last name: " . $this->lname . "\n\n";
$mail .= "Organization: " . $this->organization. "\n\n";
$mail .= "Country: " . $this->country. "\n\n";
$mail .= "Remote addr: " . $_SERVER['REMOTE_ADDR'] . "\n\n";
$mail .= "Browser: " . $_SERVER['HTTP_USER_AGENT'] . "\n\n";
$mail .= "Referer: " . $_SERVER['HTTP_REFERER'] . "\n\n";
$mail .= " -- Eclipse webdev\n";
$headers = 'From: Eclipse Webmaster (automated) <webmaster@eclipse.org>' . "\n" . 'Content-Type: text/plain; charset=UTF-8';
mail('webmaster@eclipse.org', "Denied Account: Possible spammer", $mail, $headers);
return FALSE;
}
// Select entries that are only created on an account creation
$sql = "SELECT /* USE MASTER */ email
FROM account_requests
WHERE ip = " . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . "
AND fname NOT IN ('MAILCHANGE','RESET')
AND lname NOT IN ('MAILCHANGE','RESET')
AND password = ''
AND new_email = ''
AND token NOT IN ('CLA_SIGNED','CLA_INVALIDATED','TOKEN_FAILED')";
$rs = $this->App->eclipse_sql($sql);
$list_of_emails = array();
while ($row = mysql_fetch_array($rs)) {
$list_of_emails[] = $row['email'];
}
// Check if there are more than 25 request coming from the same ip address
if (count($list_of_emails) >= 25) {
$this->messages['create']['danger'][] = "You have already submitted a request. Please check your email inbox and spam folders to respond to the previous request. (8723s)";
}
// Check if there are more than one request from the same email address
if (!empty($list_of_emails) && in_array($this->username, $list_of_emails)) {
$this->messages['create']['danger'][] = "You have already submitted a request. Please check your email inbox and spam folders to respond to the previous request. (8724s)";
}
// If there are no errors, we can insert in the account_request table
if (empty($this->messages['create']['danger'])) {
# Check LDAP
if(!$this->Ldapconn->checkEmailAvailable($this->username)) {
$this->messages['create']['danger'][] = "That account already exists. If you cannot remember your password, please use the password reset option below. (8725s)";
# Jot this down to avoid repetitively polling ldap
$this->App->eclipse_sql("INSERT INTO account_requests VALUES (" . $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) . ",
'',
" . $this->App->returnQuotedString($this->App->sqlSanitize($this->fname)) . ",
" . $this->App->returnQuotedString($this->App->sqlSanitize($this->lname)) . ",
'',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
" . $this->App->returnQuotedString("CREATE_FAILED") . ")");
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->username);
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("ACCT_CREATE_ALREADY_EXISTS");
$EventLog->insertModLog("apache");
}
else {
if ($this->agree != 1) {
$this->messages['create']['danger'][] = "- You must agree to the terms and contitions of use<br />";
}
if (!preg_match(SITELOGIN_EMAIL_REGEXP, $this->username)) {
$this->messages['create']['danger'][] = "- Your email address is not formatted correctly<br />";
}
if (!$this->Captcha->validate()) {
$this->messages['create']['danger'][] = "- You haven't answered the captcha question correctly<br />";
}
if (!preg_match("/(?=^.{6,}$)(?=.*[\d|\W])(?=.*[A-Za-z]).*$/", $this->password1)) {
$this->messages['create']['danger'][] = "- Your password does not meet the complexity requirements. It must be at least 6 characters long, and contain one number or one symbol.<br />";
}
if (!$cryptopass = $this->_generateCryptotext($this->App->sqlSanitize($this->password1))) {
$this->messages['create']['danger'][] = "- An error occurred while processing your request. (8730s)";
}
if (empty($this->country)) {
$this->messages['create']['danger'][] = "- You must select your country of residence.";
}
if (empty($this->messages['create']['danger'])) {
# Add request to database
$this->t = $this->App->getAlphaCode(64);
$this->App->eclipse_sql("INSERT INTO account_requests VALUES (" . $this->App->returnQuotedString($this->App->sqlSanitize(trim($this->username))) . ",
'',
" . $this->App->returnQuotedString($this->App->sqlSanitize(trim($this->fname))) . ",
" . $this->App->returnQuotedString($this->App->sqlSanitize(trim($this->lname))) . ",
'" . $cryptopass . "',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
" . $this->App->returnQuotedString($this->t) . ")");
$this->App->eclipse_sql("INSERT INTO users_profiles
(user_uid,user_mail,user_country,user_org,user_status)
VALUES (
". $this->App->returnQuotedString($this->App->sqlSanitize($this->t)) .",
". $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) .",
". $this->App->returnQuotedString($this->App->sqlSanitize($this->country)) .",
". $this->App->returnQuotedString($this->App->sqlSanitize($this->organization)) .",
0
)"
);
if ($this->newsletter_status === 'subscribe') {
$Subscriptions = $this->App->getSubscriptions();
$Subscriptions->setFirstName($this->fname);
$Subscriptions->setLastName($this->lname);
$Subscriptions->setEmail($this->username);
$Subscriptions->addUserToList();
}
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->t);
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("ACCT_CREATE_REQ_SUCCESS");
$EventLog->insertModLog($this->username);
# Send mail to dest
$mail = "Dear $this->fname,\n\n";
$mail .= "Thank you for registering for an account at Eclipse.org. Before we can activate your account one last step must be taken to complete your registration.\n\n";
$mail .= "To complete your registration, please visit this URL:\nhttps://dev.eclipse.org/site_login/token.php?stage=confirm&t=$this->t\n\n";
$mail .= "Your Username is: $this->username\n\n";
$mail .= "If you have any problems signing up please contact webmaster@eclipse.org\n\n";
$mail .= " -- Eclipse webmaster\n";
$headers = 'From: Eclipse Webmaster (automated) <webmaster@eclipse.org>' . "\n" . 'Content-Type: text/plain; charset=UTF-8';
mail($this->username, "Eclipse Account Registration", $mail, $headers);
# Debug
//print $mail;
$this->messages['create']['success'][] = "<p>Welcome to the Eclipse.org community! We've sent a confirmation to the email address
you have provided. In that email there are instructions you must follow in order to activate your account.</p>
<p>If you have not received the email within a few hours, and you've made sure it's not in your Junk, Spam or trash folders, please contact webmaster@eclipse.org</p>";
}
else {
$this->messages['create']['danger'][] = "An error occurred while processing your request. Please ensure that all the required fields are entered correctly and try again. (5496s)";
}
}
}
}
else {
$this->messages['create']['danger'][] = "An error occurred while processing your request. Please ensure that all the required fields are entered correctly and try again. (8726s)";
}
}
private function _generateBugzillaSHA256Password($_password) {
$cp = 0;
if ($_password != "") {
# Generate random salt
$hash = "{SHA-256}";
$salt = $this->App->getAlphaCode(8);
$cp = str_replace("=", "", $salt . base64_encode(hash("sha256", $_password . $salt, true))) . $hash;
}
return $cp;
}
private function _generateCryptotext($plaintext) {
if (empty($plaintext) || !is_readable($this->path_public_key)) {
return FALSE;
}
#load public key
$fp = fopen($this->path_public_key, "r");
$pub_key = fread($fp, 8192);
fclose($fp);
$key = openssl_pkey_get_public($pub_key);
openssl_public_encrypt($plaintext, $cryptotext, $key, OPENSSL_PKCS1_OAEP_PADDING);
#encode the output
return base64_encode($cryptotext);
}
private function _generatePassword($_num_chars) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1023456789,.;:/@#$%^&*()-_=+";
srand((double)microtime()*1000000);
$loopcount = 0;
$rValue = "";
while (!preg_match("/(?=^.{6,}$)(?=.*\d)(?=.*[A-Za-z]).*$/", $rValue)) {
$rValue = "";
$i = 0;
$loopcount++;
srand((double)microtime()*1000000);
while ($i <= $_num_chars) {
$num = rand() % strlen($chars);
$rValue .= substr($chars, $num, 1);
$i++;
}
# antilooper
if($loopcount > 1000) {
$rValue = "aA1$" . $this->App->getAlphaCode(4);
}
}
return $rValue;
}
private function _getMessageContainer($message = '', $type = 'alert') {
$class = "alert alert-" . $type;
return '<div class="' . $class . '" role="alert">' . $message . '</div>';
}
private function _get_default_field_value($id, $value, $default_values = TRUE) {
// If the value is not empty and the user is not requesting the default values,
// return the updated values.
if (!empty($value) && $default_values === FALSE) {
return $value;
}
switch ($id) {
case 'fname':
return $this->Friend->getFirstName();
break;
case 'lname':
return $this->Friend->getLastName();
break;
case 'username':
return $this->Friend->getEmail();
break;
case 'githubid':
return $this->Ldapconn->getGithubIDFromMail($this->Friend->getEmail());
break;
}
}
private function _get_profile_from_token($token = NULL){
if (empty($token)) {
return FALSE;
}
$sql = "SELECT /* USE MASTER */
user_org as organization, user_jobtitle as jobtitle, user_bio as bio, user_interests as interests, user_website as website, user_twitter_handle as twitter_handle, user_country as country
FROM users_profiles
WHERE user_uid = " . $this->App->returnQuotedString($token) . "
ORDER BY user_update DESC LIMIT 1";
$rs = $this->App->eclipse_sql($sql);
$profile = mysql_fetch_assoc($rs);
if (!empty($profile)) {
foreach ($profile as $key => $value) {
if (is_null($value)) {
$value = "";
}
$this->{$key} = $value;
}
return TRUE;
}
return FALSE;
}
private function _get_default_profile_fields($get_default_values = FALSE){
// Making sure we don't have an empty user_uid to avoid pre-populating
// the account creation fields with an empty user_uid
if (empty($this->user_uid)) {
return FALSE;
}
if (empty($this->messages['profile']['danger'])) {
$sql = "SELECT /* USE MASTER */
user_org as organization, user_jobtitle as jobtitle, user_bio as bio, user_interests as interests, user_website as website, user_twitter_handle as twitter_handle, user_country as country
FROM users_profiles
WHERE user_uid = " . $this->App->returnQuotedString($this->user_uid) . "
ORDER BY user_update DESC LIMIT 1";
$rs = $this->App->eclipse_sql($sql);
$profile = mysql_fetch_assoc($rs);
$this->profile_default = $profile;
if ($get_default_values) {
return TRUE;
}
if (!empty($profile)) {
foreach ($profile as $key => $value) {
if (is_null($value)) {
$value = "";
}
$this->{$key} = $value;
}
}
}
}
private function _getProfileDefaultValues(){
if (empty($this->profile_default)) {
$this->_get_default_profile_fields(TRUE);
}
return $this->profile_default;
}
private function _processSaveProfile() {
if (!$this->FormToken->verifyToken($_POST['token-update-profile']) || !empty($_POST['profile-name-req'])) {
//token verification failed or expected empty field wasn't empty
return FALSE;
}
if ($this->password_expired === TRUE) {
$this->messages['password_expired']['danger'][] = "You need to set a new password before you can update your profile.";
return FALSE;
}
$fname = $this->_get_default_field_value('fname', $this->fname, FALSE);
$lname = $this->_get_default_field_value('lname', $this->lname, FALSE);
$default_values = $this->_getProfileDefaultValues();
$default_org = $default_values['organization'];
$fields = array(
'user_uid' => $this->user_uid,
'user_mail' => $this->user_mail,
'user_org' => $this->organization,
'user_jobtitle' => $this->jobtitle,
'user_website' => $this->website,
'user_bio' => $this->bio,
'user_interests' => $this->interests,
'user_twitter_handle' => $this->twitter_handle,
'user_country' => $this->country,
);
$possible_null_field = array(
'user_org',
'user_jobtitle',
'user_website',
'user_bio',
'user_interests',
'user_twitter_handle',
);
# Validate values
if (empty($fields['user_uid']) || !is_string($fields['user_uid'])) {
$this->messages['profile']['danger'][] = 'Invalid user id<br>';
}
if (!empty($fields['user_website']) && !filter_var($fields['user_website'], FILTER_VALIDATE_URL)) {
$this->messages['profile']['danger'][] = 'Invalid website URL<br>';
}
if (empty($fields['user_country']) && !in_array($fields['user_country'], $this->getCountryList())) {
$this->messages['profile']['danger'][] = 'You must enter a valid country<br>';
}
if (!empty($this->messages['profile']['danger'])) {
return FALSE;
}
//if they are a committer and have changed employers toss all changes and throw a warning + send a message
if ($this->is_committer) {
if ($default_org !== $fields["user_org"]) {
if ($this->changed_employer === 'Yes') {
// Send mail to dest
$this->_sendNotice();
$this->messages['myaccount']['danger'][] = "You have indicated a change in employer. As such any changes you made have not been saved. A notice has been sent to you and EMO legal (emo-records@eclipse.org) so that they can advise what paperwork(if any) needs to be updated.";
//exit
return FALSE;
}
else if ($this->changed_employer !== "No") {
$this->messages['myaccount']['danger'][] = "You must indicate if you have changed employers in order to save changes to your organization.";
return FALSE;
}
} else {
if ($this->changed_employer === 'Yes') {
// Send mail to dest
$this->_sendNotice();
$this->messages['myaccount']['danger'][] = "A notice has been sent to you and EMO legal (emo-records@eclipse.org) so that they can advise what paperwork (if any) needs to be updated due to your change in employers.";
}
}
}
foreach ($possible_null_field as $value) {
if (empty($fields[$value])) {
$fields[$value] = NULL;
}
}
$sql = "INSERT INTO users_profiles (";
$columns = array();
$values = array();
foreach ($fields as $key => $value) {
if (!empty($value)) {
$columns[] = $key;
$values[] = '"' . $this->App->sqlSanitize($value) . '"';
}
else if(in_array($key, $possible_null_field)) {
$columns[] = $key;
$values[] = 'NULL';
}
}
$sql .= implode(',', $columns);
$sql .= ') VALUES (';
$sql .= implode(',', $values);
$sql .= ") ON DUPLICATE KEY UPDATE";
foreach ($columns as $key => $value){
$sql .= ' ' .$value . '=' . $values[$key] . ',';
}
$sql = rtrim($sql, ',');
$this->App->eclipse_sql($sql);
$this->messages['profile']['success'][] = 'Your profile have been updated successfully.';
}
private function _processSave() {
if (!$this->FormToken->verifyToken($_POST['token-edit-account']) || !empty($_POST['edit-account-email-req'])) {
//token verification failed or expected empty field wasn't empty
return FALSE;
}
// Check IF the password is expired
// AND if the user is NOT trying to change the password
if ($this->password_expired === TRUE && (empty($this->password1) && empty($this->password2))) {
$this->messages['password_expired']['danger'][] = "You need to set a new password before you can update your Account Settings.";
$this->getVariables("welcomeback");
return FALSE;
}
$user_is_changing_password = FALSE;
if ($this->username != "" && $this->fname != "" && $this->lname != "" && $this->password != "") {
# update account.
# we must first bind to ldap to be able to change attributes
$dn = $this->Ldapconn->authenticate($this->Friend->getEmail(), $this->password);
if ($dn) {
#work out what's changed
$fname_changed = ($this->Ldapconn->getLDAPAttribute($dn, "givenName") !== $this->fname) ? TRUE : FALSE ;
$lname_changed = ($this->Ldapconn->getLDAPAttribute($dn, "sn") !== $this->lname) ? TRUE : FALSE ;
$email_changed = ($this->Ldapconn->getLDAPAttribute($dn, "mail") !== $this->username) ? TRUE : FALSE ;
//if they are a committer and have changed employers toss all changes and throw a warning + send a message
if ($this->is_committer && $this->changed_employer === 'Yes') {
// Send mail to dest
$this->_sendNotice();
//notify the user
if ( !$lname_changed && !$email_changed) {
//I guess they just want us to know they've changed employers
$this->messages['myaccount']['danger'][] = "A notice has been sent to you and EMO legal (emo-records@eclipse.org) so that they can advise what paperwork(if any) needs to be updated due to your change in employers.";
}
else {
//they've changed something
$this->messages['myaccount']['danger'][] = "You have indicated a change in employer. As such any changes you made have not been saved. A notice has been sent to you and EMO legal (emo-records@eclipse.org) so that they can advise what paperwork(if any) needs to be updated.";
}
//reset form data
$this->getVariables("welcomeback");
//return
return;
}
$update_bz_name = FALSE;
if ($fname_changed) {
$this->Ldapconn->changeAttributeValue($dn, $this->password, "givenName", $this->fname);
$this->Friend->setFirstName($this->fname);
$update_bz_name = TRUE;
}
if ($lname_changed) {
if ($this->changed_employer === 'No' || !$this->is_committer) {
$this->Ldapconn->changeAttributeValue($dn, $this->password, "sn", $this->lname);
$this->Friend->setLastName($this->lname);
$update_bz_name = TRUE;
$this->_sendNotice("surname", "to: " . $this->lname);
} else if($this->is_committer && empty($this->changed_employer)) {
$this->messages['myaccount']['danger'][] = "You must indicate if you have changed employers in order to save changes to your last name.";
return;
}
}
//if either the first or last name has changed the cn should be updated.
if ($fname_changed || $lname_changed) {
$this->Ldapconn->changeAttributeValue($dn, $this->password, "cn", $this->fname . " " . $this->lname);
$update_bz_name = TRUE;
}
if ($update_bz_name) {
$this->App->bugzilla_sql("SET NAMES 'utf8'");
$sql = "UPDATE profiles SET realname='" . $this->App->sqlSanitize($this->fname . " " . $this->lname) . "' WHERE login_name = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) . " LIMIT 1";
$this->App->bugzilla_sql($sql);
$this->Session->updateSessionData($this->Friend);
}
# Update GitHub ID?
if ($this->githubid != "") {
$oldgithubid = $this->Ldapconn->getGithubIDFromMail($this->Friend->getEmail());
# we can't change GH ID's automagically
if ($oldgithubid != "") {
$this->messages['myaccount']['danger'][] = "- Your GitHub ID cannot be changed from this form. Please contact webmaster@eclipse.org to update your GitHub ID.<br />";
}
else {
$this->Ldapconn->setGithubID($dn, $this->password, $this->githubid);
$this->messages['myaccount']['success'][] = "Your github id was saved successfully.";
}
}
# User is trying to update change is password
if (!empty($this->password1) && !empty($this->password2)) {
if (!preg_match("/(?=^.{6,}$)(?=.*[\d|\W])(?=.*[A-Za-z]).*$/", $this->password1)) {
$this->messages['myaccount']['danger'][] = "- Your password does not meet the complexity requirements. It must be at least 6 characters long, and contain one number or one symbol.<br />";
}
else {
if ($this->password != $this->password1) {
$user_is_changing_password = TRUE;
$this->Ldapconn->changePassword($dn, $this->password, $this->password1);
$bzpass = &$this->_generateBugzillaSHA256Password($this->password1);
$sql = "UPDATE profiles SET cryptpassword='" . $this->App->sqlSanitize($bzpass) . "' WHERE login_name = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) . " LIMIT 1";
$this->App->bugzilla_sql($sql);
$this->App->ipzilla_sql($sql);
$this->messages['myaccount']['success'][] = "Your password was updated successfully.";
}
// If the user is trying to update password with the current password
else{
$this->messages['myaccount']['danger'][] = "- Your new password must be different than your current password.";
}
}
}
# if email address has changed, we must update Bugzilla DB record too.
$oldmail = $this->Ldapconn->getLDAPAttribute($dn, "mail");
$mailmsg = "";
if($email_changed) {
#Not a committer or didn't change employers?
if (!$this->is_committer || $this->changed_employer === 'No') {
if (!$this->Ldapconn->checkEmailAvailable($this->username)) {
$this->messages['myaccount']['danger'][] = "- Unable to change your email address<br />";
}
elseif (!preg_match(SITELOGIN_EMAIL_REGEXP, $this->username)) {
$this->messages['myaccount']['danger'][] = "- Your email address is not formatted correctly<br />";
}
else {
$sql = "SELECT /* USE MASTER */ email
FROM account_requests
WHERE ip = " . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . "
AND fname = 'MAILCHANGE'
AND lname = 'MAILCHANGE'";
$rs = $this->App->eclipse_sql($sql);
$list_of_emails = array();
while ($row = mysql_fetch_array($rs)) {
$list_of_emails[] = $row['email'];
}
// Check if there are more than 3 request coming from the same ip address
if (count($list_of_emails) > 3) {
$this->messages['myaccount']['danger'][] = "<b>You have already submitted a request. Please check your email inbox and spam folders to respond to the previous request.</b>";
}
// Check if there are more than one request from the same email address
if (!empty($list_of_emails) && in_array($this->username, $list_of_emails)) {
$this->messages['myaccount']['danger'][] = "<b>You have already submitted a request. Please check your email inbox and spam folders to respond to the previous request.</b>";
}
if (empty($this->messages['myaccount']['danger'])) {
# Toss in a request to change the email address
$this->messages['myaccount']['success'][] = " Please check your Inbox for a confirmation email with instructions to complete the email address change. Your email address will not be updated until the process is complete.";
$this->t = $this->t = $this->App->getAlphaCode(64);
$sql = "INSERT INTO account_requests (email,new_email,fname,lname,password,ip,req_when,token)VALUES (" . $this->App->returnQuotedString($oldmail) . ",
" . $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) . ",
" . $this->App->returnQuotedString("MAILCHANGE") . ",
" . $this->App->returnQuotedString("MAILCHANGE") . ",
'',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
" . $this->App->returnQuotedString($this->t) . ")";
$this->App->eclipse_sql($sql);
# Send mail to dest
$mail = "You (or someone pretending to be you) has changed their Eclipse.org account email address to this one (" . $this->App->sqlSanitize($this->username) . ") from this IP address:\n";
$mail .= " " . $_SERVER['REMOTE_ADDR'] . "\n\n";
$mail .= "To confirm this email change, please click the link below:\n";
$mail .= " https://dev.eclipse.org/site_login/token.php?stage=confirm&t=$this->t\n\n";
$mail .= "If you have not issued this request, you can safely ignore it.\n\n";
$mail .= " -- Eclipse webmaster\n";
$headers = 'From: Eclipse Webmaster (automated) <webmaster@eclipse.org>';
mail($this->username, "Eclipse Account Change", $mail, $headers);
//notify EMO
$this->_sendNotice("Email address","from: " . $oldmail . " to: " . $this->username );
}
}
}
else if ($this->is_committer && $this->changed_employer === "") {
$this->messages['myaccount']['danger'][] = "You must indicate if you have changed employers in order to save changes to your email address.";
return;
}
}
if (empty($this->messages['myaccount']['danger'])) {
$this->messages['myaccount']['success'][] = "Your account details have been updated successfully." . $mailmsg . "";
if ($user_is_changing_password) {
header("Location: https://dev.eclipse.org/site_login/logout.php?password_update=1", 302);
}
}
}
else {
$this->messages['myaccount']['danger'][] = "Your current password is incorrect.";
}
}
else {
$this->messages['myaccount']['danger'][] = "Please ensure that all the required fields are entered correctly and try again.";
}
}
private function _resetPassword() {
if (!$this->FormToken->verifyToken($_POST['token-password-recovery']) || !empty($_POST['recover-account-email-req'])) {
//token verification failed or expected empty field wasn't empty
return FALSE;
}
# reset stage 1. We got an email address, create token and email to user
# make sure someone isn't blasting us. We disregard "token failed" since a common use-case
# is to click the reset link after it has expired.
$sql = "SELECT /* USE MASTER */ email
FROM account_requests
WHERE token <> 'TOKEN_FAILED'
AND fname = 'RESET'
AND lname = 'RESET'
AND ip = " . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']);
$rs = $this->App->eclipse_sql($sql);
$list_of_emails = array();
while ($row = mysql_fetch_array($rs)) {
$list_of_emails[] = $row['email'];
}
// Check if a valid email has been provided
if (!preg_match(SITELOGIN_EMAIL_REGEXP, $this->username)) {
$this->messages['reset']['danger'][] = "<b>Your email address is not formatted correctly.</b><br />";
}
// Check if the provided email is in LDAP
if ($this->Ldapconn->checkEmailAvailable($this->username)) {
$this->messages['reset']['danger'][] = "<b>We were unable to determine your identity with the information you've supplied.</b> Perhaps you don't have an Eclipse.org account, or your account is under a different email address.(8x27s)";
}
// Check if there are more than 13 request coming from the same ip address
if (count($list_of_emails) >= 13) {
$this->messages['reset']['danger'][] = "<b>We were unable to determine your identity after several attempts. Subsequent inquiries will be ignored for our protection. Please try later, or contact webmaster@eclipse.org for support.</b> (8727s)";
}
// Check if there are more than one request from the same email address
if (!empty($list_of_emails) && in_array($this->username, $list_of_emails)) {
$this->messages['reset']['danger'][] = "<b>There's already a reset password request associated to this email address. Please try later, or contact webmaster@eclipse.org for support.</b> (8728s)";
}
// If there are no errors we can proceed
if (empty($this->messages['reset']['danger'])) {
# Check to see if we're trying to reset the password of a valid account.
$this->t = $this->App->getAlphaCode(64);
$this->App->eclipse_sql("INSERT IGNORE INTO account_requests VALUES (" . $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) . ",
'',
" . $this->App->returnQuotedString("RESET") . ",
" . $this->App->returnQuotedString("RESET") . ",
'',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
" . $this->App->returnQuotedString($this->t) . ")");
# Send mail to dest
$mail = "You (or someone pretending to be you) has requested a password reset from:\n";
$mail .= " " . $_SERVER['REMOTE_ADDR'] . "\n\n";
$mail .= "To change your password, please visit this URL:\nhttps://dev.eclipse.org/site_login/token.php?p=p&t=$this->t\n\n";
$mail .= "If you have not requested this change, you can safely let it expire. If you have any problems signing in please contact webmaster@eclipse.org\n\n";
$mail .= " -- Eclipse webmaster\n";
$headers = 'From: Eclipse Webmaster (automated) <webmaster@eclipse.org>';
mail($this->username, "Eclipse Account Password Reset", $mail, $headers);
$this->messages['reset']['success'][] = '<strong>Password Recovery:</strong> A token has been emailed to you to allow
you to reset your Eclipse.org password. Please check your Trash and Junk/Spam
folders if you do not see this email in your inbox.';
# Debug
//print $mail;
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->t);
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("PASSWD_RESET_REQ");
$EventLog->insertModLog($this->username);
}
}
private function _resetPassword2() {
# reset stage 2. We got an token back. If we find a record, allow user to reset password, then proceed to stage3
if($this->t != "") {
$sql = "SELECT /* USE MASTER */ email, COUNT(1) AS RecordCount FROM account_requests WHERE token = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->t));
$rs = $this->App->eclipse_sql($sql);
$myrow = mysql_fetch_assoc($rs);
if($myrow['RecordCount'] <= 0) {
$this->exipred_pass_token = TRUE;
$this->_setStage('reset');
$this->messages['reset2']['danger'][] = "<b>The supplied reset token is invalid; perhaps it has expired? Please wait 5 minutes and try to <a href='password_recovery.php'>reset your password again</a>. If the problem persits, please contact webmaster@eclipse.org.</b> (8129rs)";
# If we can't find a record, insert a record preventing this dude from bombing us
$this->t = $this->App->getAlphaCode(64);
$this->App->eclipse_sql("INSERT INTO account_requests VALUES (" . $this->App->returnQuotedString($this->App->sqlSanitize($this->t)) . ",
'',
'token_failed',
'token_failed',
'token_failed',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
'TOKEN_FAILED')"
);
}
else {
# display password reset page.
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->t);
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("PASSWD_RESET_CONF");
$EventLog->insertModLog($myrow['email']);
}
}
}
private function _resetPassword3() {
if (!$this->FormToken->verifyToken($_POST['token-password-reset']) || !empty($_POST['reset-account-email-req'])) {
//token verification failed or expected empty field wasn't empty
return FALSE;
}
# reset stage 3. We got a token back, and user is submitting a password.
if ($this->t != "" && $this->password1 != "" ) {
if ($this->password1 != $this->password2) {
$this->messages['reset3']['danger'][] = "Submitted passwords don't match.";
$this->_setStage('reset2');
return FALSE;
}
if (!$this->Captcha->validate()) {
$this->messages['reset3']['danger'][] = "- You haven't answered the captcha question correctly<br />";
$this->_setStage('reset2');
return FALSE;
}
$sql = "SELECT /* USE MASTER */ email, COUNT(1) AS RecordCount FROM account_requests WHERE token = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->t));
$rs = $this->App->eclipse_sql($sql);
$myrow = mysql_fetch_assoc($rs);
if ($myrow['RecordCount'] <= 0) {
$this->messages['reset3']['danger'][] = "We were unable to validate your request. The supplied token is invalid; perhaps it has expired? Please try to <a href='createaccount.php'>reset your password again</a>. If the problem persits, please contact webmaster@eclipse.org. (8329rs)";
$this->_setStage('reset2');
# If we can't find a record, insert a record preventing this dude from bombing us
$this->t = $this->App->getAlphaCode(64);
$this->App->eclipse_sql("INSERT INTO account_requests VALUES (" . $this->App->returnQuotedString($this->App->sqlSanitize($this->t)) . ",
'',
'token_failed',
'token_failed',
'token_failed',
" . $this->App->returnQuotedString($_SERVER['REMOTE_ADDR']) . ",
NOW(),
'TOKEN_FAILED')"
);
}
else {
if (!preg_match("/(?=^.{6,}$)(?=.*\d)(?=.*[A-Za-z]).*$/", $this->password1)) {
$this->messages['reset3']['danger'][] = "- Your password does not meet the complexity requirements<br />";
$this->_setStage('reset2');
}
elseif ($cryptopass = $this->_generateCryptotext($this->App->sqlSanitize($this->password1))) {
# Update this row, change IP address to reflect that of the person who successfully confirmed this password to avoid bombing
$sql = "UPDATE account_requests SET token = 'PASSWORD_SUCCESS', password='" . $cryptopass . "', ip = " . $this->App->returnQuotedString($this->App->sqlSanitize($_SERVER['REMOTE_ADDR']))
. " WHERE token = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->t));
$rs = $this->App->eclipse_sql($sql);
$bzpass = &$this->_generateBugzillaSHA256Password($this->password1);
$sql = "UPDATE profiles SET cryptpassword='" . $this->App->sqlSanitize($bzpass) . "' WHERE login_name = " . $this->App->returnQuotedString($this->App->sqlSanitize($myrow['email'])) . " LIMIT 1";
$this->App->bugzilla_sql($sql);
$this->App->ipzilla_sql($sql);
$this->messages['reset']['success'][] = '<strong>Password Recovery:</strong> Your password was reset. You may now <a href="/site_login/index.php">log in</a>. Please note that some Eclipse.org sites, such as Bugzilla, Wiki or Forums, may ask you to login again with your new password.';
$EventLog = new EvtLog();
$EventLog->setLogTable("__ldap");
$EventLog->setPK1($this->t);
$EventLog->setPK2($_SERVER['REMOTE_ADDR']);
$EventLog->setLogAction("PASSWD_RESET_SUCCESS");
$EventLog->insertModLog($myrow['email']);
}
else {
$this->messages['create']['danger'][] = "An error occurred while processing your request. Please ensure that all the required fields are entered correctly and try again. (3543s)";
}
}
}
else {
$this->_setStage('reset2');
$this->messages['reset3']['danger'][] = "Please enter a new password.";
return FALSE;
}
}
private function _sanitizeVariables() {
$inputs = array(
'agree',
'githubid',
'fname',
'lname',
'password',
'p',
'page',
'password',
'password1',
'password2',
'password_update',
'remember',
'stage',
'submit',
'takemeback',
't',
'username',
'organization',
'jobtitle',
'website',
'bio',
'interests',
'twitter_handle',
'changed_employer',
'country',
'newsletter_status',
);
foreach ($inputs as $field) {
$this->$field = $this->App->getHTTPParameter($field, "POST");
if ($field == 'takemeback' || $field == 'website') {
$this->$field = urldecode($this->$field);
}
if ($field == 'fname' || $field == 'lname') {
$this->$field = preg_replace(SITELOGIN_NAME_REGEXP, '', $this->$field);
}
else if ($field == 't') {
$this->$field = preg_replace("/[^a-zA-Z0-9]/", "", $this->t);
}
else {
$this->$field = preg_replace($this->xss_patterns, '', $this->$field);
}
// Remove whitespace characters on the githubid field
if ($field == 'githubid') {
$this->$field = preg_replace("/\s+/", "", $this->$field);
}
# Magic quotes feature is removed from PHP 5.4 but just incase.
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
$this->$field = stripslashes($this->$field);
}
}
$this->username = trim($this->username);
if (!is_numeric($this->remember)) {
$this->remember = 0;
}
# Takemeback processing
$this->referer = "";
if (isset($_SERVER['HTTP_REFERER'])) {
$this->referer = $_SERVER['HTTP_REFERER'];
}
# Coming from the Wiki? Redirect to Special:Userlogin to finish processign
if(preg_match('/^(http|https):\/\/(wiki|wikitest)\.eclipse\.org\//', $this->referer, $matches)) {
$location = substr($this->referer, strlen($matches[0]));
#strip 'extra' index data bug 308257
$location = preg_replace("/index\.php\?title\=/","",$location);
$this->takemeback = $matches[0] . "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . $location ;
}
# Forum login process broken with bad redirect
# Bug 430302
if (preg_match('#^https?://.*eclipse.org/forums/index.php\?t=login#', $this->referer, $matches)) {
$this->takemeback = "https://www.eclipse.org/forums/index.php/l/";
}
# Since we use a secure cookie, anything http should be sent back https.
if (preg_match("#^http://(.*)#", $this->takemeback, $matches)) {
$this->takemeback = "https://" . $matches[1];
}
if (preg_match('#^https?://dev.eclipse.org/#', $this->takemeback) && !preg_match('#^https?://dev.eclipse.org/site_login/myaccount.php#', $this->takemeback)){
$this->takemeback = "";
}
if (!$this->validateTakemebackUrl()) {
$this->takemeback = "";
}
}
private function _setStage($stage){
$possible_values = array(
'login',
'create',
'save',
'save-profile',
'reset',
'reset2',
'reset3',
'confirm',
);
if ($this->t != "" && $stage == "confirm") {
$this->stage = 'confirm';
}
elseif ($this->exipred_pass_token) {
$this->stage = "reset";
}
elseif ($this->t == "" && $this->p == "" && $stage == 'password-recovery' && !empty($this->username)) {
$this->stage = "reset";
}
elseif ($this->t != "" && $this->p == "p" && $stage == 'password-recovery') {
$this->stage = "reset2";
}
elseif ($this->t != "" && $stage == 'password-recovery') {
$this->stage = "reset3";
}
elseif (in_array($stage, $possible_values)){
$this->stage = $stage;
}
}
private function _sendNotice($changed="", $details=""){
if ($this->is_committer) {
//do nothing if the changed state isn't yes or no.
if ($this->changed_employer === 'Yes') {
$mail = "Because you have changed employers, you must promptly provide the EMO(emo-records@eclipse.org) with your new employer information.\r\n";
$mail .= "The EMO will determine what, if any, new legal agreements and/or employer consent forms are required for your committer account to remain active.\r\n\r\n";
$mail .= " -- Eclipse webmaster\r\n";
$headers = "From: Eclipse Webmaster (automated) <webmaster@eclipse.org>\r\n";
$headers .= "CC: EMO-Records <emo-records@eclipse.org>";
mail($this->user_mail, "Eclipse Account Change", $mail, $headers);
} else if ($this->changed_employer === 'No') {
if ($changed === "" || $details === "" ){
$mail = "Committer: " . $this->user_uid . "\r\n";
$mail .= "Has changed something, but details are incomplete. \r\n";
$mail .= "What changed: " . $changed . " \r\n";
$mail .= "Details: " . $details . "\r\n\r\n";
$mail .= "Committer confirms they have NOT changed employers \r\n\r\n";
} else {
$mail = "Committer: " . $this->user_uid . "\r\n";
$mail .= "Has changed their " . $changed . " " . $details . "\r\n\r\n";
$mail .= "Committer confirms they have NOT changed employers \r\n\r\n";
}
$headers = "From: Eclipse Webmaster (automated) <webmaster@eclipse.org>";
mail("emo-records@eclipse.org", "Eclipse Account Change", $mail, $headers);
}
}
}
public function _showChangedEmployer() {
//show the changed employer buttons
if ($this->is_committer) {
echo <<<END
<div class="form-group clearfix has-feedback">
<label class="col-sm-6 control-label">Have you changed employers<sup>[<a href="https://www.eclipse.org/legal/#CommitterAgreements" title="Why are we asking this?">?</a>]</sup><span class="required">*</span></label>
<div class="col-sm-16">
<input type="radio" name="changed_employer" value="Yes"> Yes
<input type="radio" name="changed_employer" value="No"> No
</div>
</div>
END;
}
}
private function _userAuthentification() {
$process = FALSE;
if ($this->FormToken->verifyToken($_POST['token-login']) && empty($_POST['login-username'])) {
$process = TRUE;
}
if (!preg_match(SITELOGIN_EMAIL_REGEXP, $this->username) && $this->stage == "login") {
$this->messages['login']['danger'][] = "Your email address does not appear to be valid.";
$process = FALSE;
}
if ($process) {
$dn = $this->Ldapconn->authenticate($this->username, $this->password);
if ($dn) {
# If you've logged in with your uid, we need to get the email.
if (!preg_match("/@/", $this->username)) {
$this->username = $this->Ldapconn->getLDAPAttribute($dn, "mail");
}
$this->Friend->getIsCommitter();
# Look up BZ ID
$sql = "SELECT /* USE MASTER */ userid FROM profiles where login_name = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->username));
$rs = $this->App->bugzilla_sql($sql);
if ($myrow = mysql_fetch_assoc($rs)) {
$uid = $this->Ldapconn->getUIDFromMail($this->username);
$this->Friend->selectFriend($this->Friend->selectFriendID("uid", $uid));
$this->Friend->setBugzillaID($myrow['userid']);
}
else {
# Try to log into Bugzilla using these credentials
# This will create one
# creating one is important, since not all our sites use LDAP auth, and some rely on BZ auth
$AccountCreator = New AccountCreator();
$AccountCreator->setUsername($this->username);
$AccountCreator->setPassword($this->password);
$AccountCreator->execute();
# create/update Gerrit account
# Bug 421319
# sleep(1); # not needed if we take the time to log into Gerrit
$AccountCreator = New AccountCreator();
$AccountCreator->setUrl('https://git.eclipse.org/r/login/q/status:open,n,z');
$AccountCreator->setAccountType('gerrit');
$AccountCreator->setUsername($this->username);
$AccountCreator->setPassword($this->password);
$http_code = $AccountCreator->execute();
# TODO: verify that account was created (see bugzilla SQL below)
# Get BZ ID now that an acct should be created
$sql = "SELECT /* USE MASTER */ userid FROM profiles where login_name = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->username));
$rs = $this->App->bugzilla_sql($sql);
if ($myrow = mysql_fetch_assoc($rs)) {
$uid = $this->Ldapconn->getUIDFromMail($this->username);
$this->Friend->selectFriend($this->Friend->selectFriendID("uid", $uid));
$this->Friend->setBugzillaID($myrow['userid']);
}
else {
$EventLog = new EvtLog();
$EventLog->setLogTable("bugs");
$EventLog->setPK1($this->password);
$EventLog->setPK2($sql);
$EventLog->setLogAction("AUTH_BZID_NOT_FOUND");
$EventLog->insertModLog($dn);
$this->Friend->setBugzillaID(41806); # Nobody.
}
}
# Override loaded friends info with LDAP info
$this->Friend->setFirstName($this->Ldapconn->getLDAPAttribute($dn, "givenName"));
$this->Friend->setLastName($this->Ldapconn->getLDAPAttribute($dn, "sn"));
$realname = $this->Friend->getFirstName() . " " . $this->Friend->getLastName();
$this->Friend->setDn($dn);
$this->Friend->setEMail($this->username);
$this->Session->setIsPersistent($this->remember);
$this->Session->setFriend($this->Friend);
$this->Session->create();
# Only temporarily, re-hash the password in Bugzilla so that other services can use it
$bzpass = $this->_generateBugzillaSHA256Password($this->password);
$this->App->bugzilla_sql("SET NAMES 'utf8'");
$sql = "UPDATE profiles SET cryptpassword='" . $this->App->sqlSanitize($bzpass) . "', realname='" . $this->App->sqlSanitize($realname) . "' WHERE login_name = " . $this->App->returnQuotedString($this->App->sqlSanitize($this->username)) . " LIMIT 1";
$this->App->bugzilla_sql($sql);
# Begin: Bug 432830 - Remove the continue button in site_login
if ($this->takemeback != "") {
header("Location: " . $this->takemeback, 302);
}
else {
header("Location: myaccount.php", 302);
}
exit();
# END: Bug 432830 - Remove the continue button in site_login
}
else {
$this->messages["login"]['danger'][] = "Authentication Failed. Please verify that your email address and password are correct.";
}
}
}
private function _verifyIfPasswordExpired() {
// Check if the user is logged in
if($this->Session->isLoggedIn()){
// Get the Distinguished Name from UID
$dn = $this->Ldapconn->getDNFromUID($this->user_uid);
// Get shadowLastChange in seconds
$lastChange = ($this->Ldapconn->getLDAPAttribute($dn, "shadowLastChange")) * 86400;
// Get the number of days
$shadowMax = $this->Ldapconn->getLDAPAttribute($dn, "shadowMax");
// Set the expiry date
$expiryDate = strtotime('+'.$shadowMax.' days', $lastChange);
$expireSoon = strtotime('-30 days', $expiryDate);
if ($this->Friend->getIsCommitter()) {
$numberOfDays = round(($expiryDate - time()) / (3600*24));
if ($expiryDate >= time() && time() > $expireSoon) {
$days = $numberOfDays == 1 ? 'day' : 'days';
$this->messages['password_expire_soon']['info'][] = 'Your password expires in <strong>' . $numberOfDays . ' '. $days .'.</strong>';
return FALSE;
}
if ($expiryDate < time()) {
$this->messages['password_expired']['danger'][] = "Your password is expired. <br>Please update it immediately.";
return TRUE;
}
}
}
return FALSE;
}
/**
* This function fetches all the countries and continents
* @return array
* */
private function _fetchCountries() {
$sql = "SELECT
countries.ccode,
countries.en_description as description,
countries.continent_code,
continents.en_description as continent
FROM SYS_countries as countries
LEFT JOIN SYS_continents as continents
ON countries.continent_code = continents.continent_code";
$result = $this->App->eclipse_sql($sql);
$countries = array();
while ($row = mysql_fetch_array($result)) {
$countries[] = $row;
}
$this->country_list = $countries;
return $countries;
}
/**
* This function fetches all the continents from the SYS_continents table
* @return array
* */
private function _fetchcontinents() {
$sql = "SELECT en_description FROM SYS_continents ORDER BY sort_order DESC";
$result = $this->App->eclipse_sql($sql);
$continents = array();
while ($row = mysql_fetch_array($result)) {
$continents[] = $row['en_description'];
}
return $continents;
}
}