mirror of
https://github.com/Motion-Project/motion.git
synced 2026-05-11 00:02:44 -04:00
Add account lockout on failed attempts
This commit is contained in:
@@ -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 */
|
||||
|
||||
104
src/webu.cpp
104
src/webu.cpp
@@ -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")) {
|
||||
|
||||
Reference in New Issue
Block a user