diff --git a/src/motionplus.hpp b/src/motionplus.hpp index 8afce318..a139664e 100644 --- a/src/motionplus.hpp +++ b/src/motionplus.hpp @@ -48,6 +48,7 @@ #include #include #include +#include #if defined(HAVE_PTHREAD_NP_H) #include @@ -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 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 */ diff --git a/src/webu.cpp b/src/webu.cpp index d181ffc3..2350ac41 100644 --- a/src/webu.cpp +++ b/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::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::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::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")) {