Add account lockout on failed attempts

This commit is contained in:
MrDave
2021-06-06 23:04:57 -06:00
committed by Mr-Dave
parent 418ac0d673
commit ad6e32a29c
2 changed files with 110 additions and 11 deletions

View File

@@ -48,6 +48,7 @@
#include <pthread.h>
#include <microhttpd.h>
#include <string>
#include <list>
#if defined(HAVE_PTHREAD_NP_H)
#include <pthread_np.h>
@@ -165,6 +166,12 @@ enum MOTION_SIGNAL {
MOTION_SIGNAL_SIGTERM
};
struct ctx_failauth {
std::string clientip;
int attempt_nbr;
struct timespec attempt_time;
};
struct ctx_params_item {
char *param_name; /* The name or description of the ID as requested by user*/
char *param_value; /* The value that the user wants the control set to*/
@@ -402,10 +409,12 @@ struct ctx_motapp {
bool pause;
bool native_language;
volatile int webcontrol_running;
volatile int webcontrol_finish;
struct MHD_Daemon *webcontrol_daemon;
char webcontrol_digest_rand[12];
volatile int webcontrol_running;
volatile int webcontrol_finish;
struct MHD_Daemon *webcontrol_daemon;
char webcontrol_digest_rand[12];
std::list<ctx_failauth> webcontrol_failauth; /* C++ list of ips that failed authentication */
bool parms_changed; /*bool indicating if the parms have changed */
pthread_mutex_t mutex_parms; /* mutex used to lock when changing parms */

View File

@@ -307,7 +307,6 @@ static void webu_clientip(struct ctx_webui *webui)
webui->clientip.assign(client);
}
}
MOTION_LOG(INF,TYPE_ALL, NO_ERRNO, _("Connection from: %s"),webui->clientip.c_str());
}
@@ -342,6 +341,91 @@ static void webu_hostname(struct ctx_webui *webui)
return;
}
/* Log the failed authentication check */
static void webu_failauth_log(struct ctx_webui *webui)
{
timespec tm_cnct;
struct ctx_failauth failauth;
std::list<ctx_failauth>::iterator it;
MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO
,_("Failed authentication from %s"), webui->clientip.c_str());
clock_gettime(CLOCK_REALTIME, &tm_cnct);
it = webui->motapp->webcontrol_failauth.begin();
while (it != webui->motapp->webcontrol_failauth.end()) {
if (it->clientip == webui->clientip) {
it->attempt_nbr++;
it->attempt_time.tv_sec =tm_cnct.tv_sec;
return;
}
it++;
}
failauth.clientip = webui->clientip;
failauth.attempt_nbr = 1;
failauth.attempt_time = tm_cnct;
webui->motapp->webcontrol_failauth.push_back(failauth);
return;
}
/* Log the failed authentication check */
static void webu_failauth_reset(struct ctx_webui *webui)
{
timespec tm_cnct;
std::list<ctx_failauth>::iterator it;
clock_gettime(CLOCK_REALTIME, &tm_cnct);
it = webui->motapp->webcontrol_failauth.begin();
while (it != webui->motapp->webcontrol_failauth.end()) {
if ((it->clientip == webui->clientip) ||
((tm_cnct.tv_sec - it->attempt_time.tv_sec) >= 600)) {
it = webui->motapp->webcontrol_failauth.erase(it);
} else {
it++;
}
}
return;
}
/* Check for ips with excessive failed authentication attempts */
static mhdrslt webu_failauth_check(struct ctx_webui *webui)
{
timespec tm_cnct;
std::list<ctx_failauth>::iterator it;
if (webui->motapp->webcontrol_failauth.size() == 0) {
return MHD_YES;
}
clock_gettime(CLOCK_REALTIME, &tm_cnct);
it = webui->motapp->webcontrol_failauth.begin();
while (it != webui->motapp->webcontrol_failauth.end()) {
if ((it->clientip == webui->clientip) &&
((tm_cnct.tv_sec - it->attempt_time.tv_sec) < 600) &&
(it->attempt_nbr > 5)) {
MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO
,_("ignoring attempt from %s"), webui->clientip.c_str());
it->attempt_time = tm_cnct;
return MHD_NO;
} else if ((tm_cnct.tv_sec - it->attempt_time.tv_sec) >= 600) {
it = webui->motapp->webcontrol_failauth.erase(it);
} else {
it++;
}
}
return MHD_YES;
}
/* Create a authorization denied response to user*/
static mhdrslt webu_mhd_digest_fail(struct ctx_webui *webui,int signal_stale)
{
@@ -386,8 +470,7 @@ static mhdrslt webu_mhd_digest(struct ctx_webui *webui)
/* Check for valid user name */
if (mystrne(user, webui->auth_user)) {
MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO
,_("Failed authentication from %s"), webui->clientip.c_str());
webu_failauth_log(webui);
if (user != NULL) {
free(user);
}
@@ -404,8 +487,7 @@ static mhdrslt webu_mhd_digest(struct ctx_webui *webui)
, webui->auth_user, webui->auth_pass, 300);
if (retcd == MHD_NO) {
MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO
,_("Failed authentication from %s"), webui->clientip.c_str());
webu_failauth_log(webui);
}
if ( (retcd == MHD_INVALID_NONCE) || (retcd == MHD_NO) ) {
@@ -469,8 +551,7 @@ static mhdrslt webu_mhd_basic(struct ctx_webui *webui)
}
if ((mystrne(user, webui->auth_user)) || (mystrne(pass, webui->auth_pass))) {
MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO
,_("Failed authentication from %s"),webui->clientip.c_str());
webu_failauth_log(webui);
if (user != NULL) {
free(user);
}
@@ -754,6 +835,7 @@ static mhdrslt webu_answer_get(struct ctx_webui *webui)
}
/* Answer the connection request for the webcontrol*/
static mhdrslt webu_answer(void *cls, struct MHD_Connection *connection, const char *url
, const char *method, const char *version, const char *upload_data, size_t *upload_data_size
@@ -787,6 +869,10 @@ static mhdrslt webu_answer(void *cls, struct MHD_Connection *connection, const c
webu_clientip(webui);
}
if (webu_failauth_check(webui) == MHD_NO) {
return MHD_NO;
}
webu_hostname(webui);
if (!webui->authenticated) {
@@ -796,6 +882,10 @@ static mhdrslt webu_answer(void *cls, struct MHD_Connection *connection, const c
}
}
webu_failauth_reset(webui);
MOTION_LOG(INF,TYPE_ALL, NO_ERRNO, _("Connection from: %s"),webui->clientip.c_str());
if (webui->mhd_first) {
webui->mhd_first = false;
if (mystreq(method,"POST")) {