moved winix directories to winixd subdirectory
git-svn-id: svn://ttmath.org/publicrep/winix/trunk@1027 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
317
winixd/functions/login.cpp
Normal file
317
winixd/functions/login.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* This file is a part of Winix
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008-2014, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/sessionmanager.h"
|
||||
#include "login.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
|
||||
namespace Winix
|
||||
{
|
||||
|
||||
|
||||
namespace Fun
|
||||
{
|
||||
|
||||
Login::Login()
|
||||
{
|
||||
fun.url = L"login";
|
||||
need_ssl = true;
|
||||
}
|
||||
|
||||
|
||||
void Login::ClearTmpStruct()
|
||||
{
|
||||
system->crypt.ClearString(pass_decrypted);
|
||||
system->crypt.ClearString(pass_hashed);
|
||||
system->crypt.ClearString(up.pass);
|
||||
system->crypt.ClearString(up.pass_encrypted);
|
||||
system->crypt.ClearString(up2.pass);
|
||||
system->crypt.ClearString(up2.pass_encrypted);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Login::CheckPasswords(const std::wstring & password)
|
||||
{
|
||||
if( !up.pass_encrypted.empty() )
|
||||
{
|
||||
if( system->crypt.RSA(false, config->pass_rsa_private_key, up.pass_encrypted, pass_decrypted) )
|
||||
{
|
||||
PT::UTF8ToWide(pass_decrypted, up.pass);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log1 << "Login: I cannot decrypt a stored password, login failure" << logend;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pass_hashed = password;
|
||||
up2.pass_type = up.pass_type;
|
||||
up2.pass = password;
|
||||
|
||||
if( up.pass_hash_salted )
|
||||
salt = config->pass_hash_salt;
|
||||
else
|
||||
salt.clear();
|
||||
|
||||
if( !system->crypt.PassHash(salt, up2) )
|
||||
{
|
||||
log << log1 << "Login: I cannot hash a password, login failure" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = (up.pass == up2.pass);
|
||||
|
||||
if( !result )
|
||||
log << log2 << "Login: incorrect login/password" << logend;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
this method is checking whether there is a person with that login and password
|
||||
in the database
|
||||
|
||||
return true if it has found one and sets it user_id
|
||||
*/
|
||||
bool Login::CheckUserPass(const std::wstring & login, const std::wstring & password, long & user_id)
|
||||
{
|
||||
bool result;
|
||||
|
||||
if( db->GetUserPass(login, user_id, up) )
|
||||
{
|
||||
if( up.has_pass )
|
||||
{
|
||||
result = CheckPasswords(password);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "Login: this account has not a password set yet" << logend;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "Login: there is no a user name: " << login << logend;
|
||||
result = false;
|
||||
}
|
||||
|
||||
ClearTmpStruct();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Login::CheckBan()
|
||||
{
|
||||
IPBan * ip_ban = cur->session->ip_ban;
|
||||
|
||||
if( !ip_ban )
|
||||
{
|
||||
ip_ban = &session_manager->AddIPToBanList(cur->request->ip, cur->request->start_time);
|
||||
cur->session->ip_ban = ip_ban;
|
||||
}
|
||||
|
||||
if( ip_ban->incorrect_login_events < config->incorrect_login_cannot_login_treshold )
|
||||
{
|
||||
ip_ban->incorrect_login_events += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "Login: too many incorrect login attempts from this IP" << logend;
|
||||
|
||||
if( config->incorrect_login_cannot_login_mode == 0 )
|
||||
{
|
||||
time_t expires = cur->request->start_time + (time_t)config->incorrect_login_cannot_login_delay;
|
||||
|
||||
if( ip_ban->expires < expires )
|
||||
ip_ban->expires = expires;
|
||||
|
||||
PT::Date date(ip_ban->expires);
|
||||
log << log2 << "Login: logging from this IP address has been blocked until to: " << date << " UTC" << logend;
|
||||
}
|
||||
else
|
||||
{
|
||||
session_manager->IncrementBanLevel(ip_ban);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Login::ShouldUseCaptchaForCurrentIP()
|
||||
{
|
||||
if( cur->session->ip_ban )
|
||||
return ShouldUseCaptchaFor(*cur->session->ip_ban);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Login::ShouldUseCaptchaFor(const IPBan & ipban)
|
||||
{
|
||||
if( ipban.expires != 0 && cur->request->start_time >= ipban.expires )
|
||||
return false; // the 'ip block' has expired (but incorrect_login_events has the old value)
|
||||
|
||||
return ipban.incorrect_login_events >= config->incorrect_login_captcha_treshold;
|
||||
}
|
||||
|
||||
|
||||
bool Login::CannotLoginFromCurrentIP()
|
||||
{
|
||||
if( cur->session->ip_ban )
|
||||
return CannotLoginFrom(*cur->session->ip_ban);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Login::CannotLoginFrom(const IPBan & ipban)
|
||||
{
|
||||
if( ipban.IsIPBanned() )
|
||||
return true;
|
||||
|
||||
/*
|
||||
* if incorrect_login_cannot_login_mode is equal to one then we only
|
||||
* block logging (there is no a ban actually -- neither the active flag is enabled
|
||||
* nor any ban_level is set)
|
||||
*/
|
||||
if( ipban.expires != 0 &&
|
||||
cur->request->start_time < ipban.expires &&
|
||||
ipban.incorrect_login_events >= config->incorrect_login_cannot_login_treshold )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Login::CheckAbuse()
|
||||
{
|
||||
time_t diff = (time_t)config->incorrect_login_min_time_between_get_post;
|
||||
|
||||
if( cur->session->last_time_get + diff > cur->request->start_time )
|
||||
{
|
||||
log << log2 << "Login: the minimum time between GET and POST have not passed" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ShouldUseCaptchaForCurrentIP() )
|
||||
{
|
||||
if( !system->rebus.CheckRebus() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// if you are logging not from a webbrowser but from an application
|
||||
// then probably you need check_abuse to be false
|
||||
bool Login::LoginUser(const std::wstring & login, const std::wstring & password, bool remember_me,
|
||||
bool use_ses_log, bool check_abuse)
|
||||
{
|
||||
long user_id;
|
||||
|
||||
if( cur->session->id == 0 )
|
||||
{
|
||||
log << log2 << "Login: can't login in a temporary session (skipped)" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( CannotLoginFromCurrentIP() )
|
||||
{
|
||||
log << log2 << "Login: you cannot login from this IP address" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( login.empty() )
|
||||
{
|
||||
log << log3 << "Login: login is empty (skipping)" << logend;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( check_abuse && !CheckAbuse() )
|
||||
{
|
||||
CheckBan();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( CheckUserPass(login, password, user_id) )
|
||||
{
|
||||
if( system->users.LoginUser(user_id, remember_me, use_ses_log) )
|
||||
{
|
||||
if( cur->session->ip_ban )
|
||||
cur->session->ip_ban->incorrect_login_events = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckBan();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Login::MakePost()
|
||||
{
|
||||
const std::wstring & login = cur->request->PostVar(L"login");
|
||||
const std::wstring & pass = cur->request->PostVar(L"password");
|
||||
const std::wstring & remem = cur->request->PostVar(L"rememberme");
|
||||
|
||||
if( LoginUser(login, pass, !remem.empty(), true, true) )
|
||||
system->RedirectToLastItem();
|
||||
}
|
||||
|
||||
|
||||
void Login::MakeGet()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace Winix
|
||||
|
Reference in New Issue
Block a user