Improve server logging with IPs and error messages

This commit is contained in:
BenDr0id 2018-08-24 10:09:07 +02:00
parent 0281597e2f
commit 4bf6a07f9c
4 changed files with 73 additions and 48 deletions

View file

@ -93,28 +93,29 @@ std::string Httpd::readFile(const std::string &fileName)
return data.str(); return data.str();
} }
unsigned Httpd::tokenAuth(struct MHD_Connection* connection) unsigned Httpd::tokenAuth(struct MHD_Connection* connection, const std::string& clientIp)
{ {
if (!m_options->ccToken()) { if (!m_options->ccToken()) {
LOG_WARN("AccessToken not set. Access Granted!"); LOG_WARN("[%s] AccessToken not set. Access Granted!", clientIp.c_str());
return MHD_HTTP_OK; return MHD_HTTP_OK;
} }
const char* header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_AUTHORIZATION); const char* header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_AUTHORIZATION);
if (m_options->ccToken() && !header) { if (m_options->ccToken() && !header) {
LOG_WARN("[%s] No auth header. Access Forbidden!", clientIp.c_str());
return MHD_HTTP_UNAUTHORIZED; return MHD_HTTP_UNAUTHORIZED;
} }
const size_t size = strlen(header); const size_t size = strlen(header);
if (size < 8 || strlen(m_options->ccToken()) != size - 7 || memcmp("Bearer ", header, 7) != 0) { if (size < 8 || strlen(m_options->ccToken()) != size - 7 || memcmp("Bearer ", header, 7) != 0) {
LOG_WARN("AccessToken wrong. Access Forbidden!"); LOG_ERR("[%s] AccessToken wrong. Access Forbidden!", clientIp.c_str());
return MHD_HTTP_FORBIDDEN; return MHD_HTTP_FORBIDDEN;
} }
return strncmp(m_options->ccToken(), header + 7, strlen(m_options->ccToken())) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; return strncmp(m_options->ccToken(), header + 7, strlen(m_options->ccToken())) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
} }
unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp) unsigned Httpd::basicAuth(struct MHD_Connection* connection, const std::string& clientIp, std::string& resp)
{ {
unsigned result = MHD_HTTP_OK; unsigned result = MHD_HTTP_OK;
@ -123,7 +124,7 @@ unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp)
"Please configure admin user and pass to view this Page." "Please configure admin user and pass to view this Page."
"</body><html\\>"); "</body><html\\>");
LOG_WARN("Admin user/password not set. Access Forbidden!"); LOG_WARN("[%s] Admin user/password not set. Access Forbidden!", clientIp.c_str());
result = MHD_HTTP_FORBIDDEN; result = MHD_HTTP_FORBIDDEN;
} }
else { else {
@ -136,7 +137,7 @@ unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp)
if (user == nullptr || strcmp(user, m_options->ccAdminUser()) != 0 || if (user == nullptr || strcmp(user, m_options->ccAdminUser()) != 0 ||
pass == nullptr || strcmp(pass, m_options->ccAdminPass()) != 0) { pass == nullptr || strcmp(pass, m_options->ccAdminPass()) != 0) {
LOG_WARN("Admin user/password wrong. Access Unauthorized!"); LOG_ERR("[%s] Admin user/password wrong. Access Forbidden!", clientIp.c_str());
result = MHD_HTTP_UNAUTHORIZED; result = MHD_HTTP_UNAUTHORIZED;
} }
@ -148,6 +149,7 @@ unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp)
free(pass); free(pass);
} }
} else { } else {
LOG_WARN("[%s] No auth header. Access Forbidden!", clientIp.c_str());
result = MHD_HTTP_UNAUTHORIZED; result = MHD_HTTP_UNAUTHORIZED;
} }
} }
@ -179,24 +181,36 @@ int Httpd::sendResponse(MHD_Connection* connection, unsigned status, MHD_Respons
int Httpd::handler(void* httpd, MHD_Connection* connection, const char* url, const char* method, int Httpd::handler(void* httpd, MHD_Connection* connection, const char* url, const char* method,
const char* version, const char* upload_data, size_t* upload_data_size, void** con_cls) const char* version, const char* upload_data, size_t* upload_data_size, void** con_cls)
{ {
std::string clientIp;
const MHD_ConnectionInfo *info = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
if (info) {
char clientHost[NI_MAXHOST];
int ec = getnameinfo(info->client_addr, sizeof(*info->client_addr), clientHost, sizeof(clientHost),
0, 0, NI_NUMERICHOST|NI_NUMERICSERV);
if (ec == 0) {
clientIp = std::string(clientHost);
}
}
if (strcmp(method, MHD_HTTP_METHOD_OPTIONS) == 0) { if (strcmp(method, MHD_HTTP_METHOD_OPTIONS) == 0) {
LOG_INFO("OPTIONS Requested"); LOG_INFO("[%s] OPTIONS Requested", clientIp.c_str());
return sendResponse(connection, MHD_HTTP_OK, nullptr, CONTENT_TYPE_HTML); return sendResponse(connection, MHD_HTTP_OK, nullptr, CONTENT_TYPE_HTML);
} }
if (strcmp(method, MHD_HTTP_METHOD_GET) != 0 && strcmp(method, MHD_HTTP_METHOD_POST) != 0) { if (strcmp(method, MHD_HTTP_METHOD_GET) != 0 && strcmp(method, MHD_HTTP_METHOD_POST) != 0) {
LOG_ERR("HTTP_METHOD_NOT_ALLOWED"); LOG_ERR("[%s] HTTP_METHOD_NOT_ALLOWED (%s)", clientIp.c_str(), method);
return sendResponse(connection, MHD_HTTP_METHOD_NOT_ALLOWED, nullptr, CONTENT_TYPE_HTML); return sendResponse(connection, MHD_HTTP_METHOD_NOT_ALLOWED, nullptr, CONTENT_TYPE_HTML);
} }
if (strstr(url, "/client/")) { if (strstr(url, "/client/")) {
unsigned status = static_cast<Httpd*>(httpd)->tokenAuth(connection); unsigned status = static_cast<Httpd*>(httpd)->tokenAuth(connection, clientIp);
if (status != MHD_HTTP_OK) { if (status != MHD_HTTP_OK) {
return sendResponse(connection, status, nullptr, CONTENT_TYPE_JSON); return sendResponse(connection, status, nullptr, CONTENT_TYPE_JSON);
} }
} else { } else {
std::string resp; std::string resp;
unsigned status = static_cast<Httpd*>(httpd)->basicAuth(connection, resp); unsigned status = static_cast<Httpd*>(httpd)->basicAuth(connection, clientIp, resp);
if (status != MHD_HTTP_OK) { if (status != MHD_HTTP_OK) {
MHD_Response* rsp = nullptr; MHD_Response* rsp = nullptr;
if (!resp.empty()) { if (!resp.empty()) {
@ -207,15 +221,15 @@ int Httpd::handler(void* httpd, MHD_Connection* connection, const char* url, con
} }
if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) { if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) {
return handleGET(static_cast<Httpd*>(httpd), connection, url); return handleGET(static_cast<Httpd*>(httpd), connection, clientIp, url);
} else { } else {
return handlePOST(static_cast<Httpd*>(httpd), connection, url, upload_data, upload_data_size, con_cls); return handlePOST(static_cast<Httpd*>(httpd), connection, clientIp, url, upload_data, upload_data_size, con_cls);
} }
return MHD_NO; return MHD_NO;
} }
int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, const char* urlPtr) int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, const std::string& clientIp, const char* urlPtr)
{ {
std::string resp; std::string resp;
std::string url(urlPtr); std::string url(urlPtr);
@ -227,7 +241,7 @@ int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, cons
clientId = std::string(clientIdPtr); clientId = std::string(clientIdPtr);
} }
unsigned status = Service::handleGET(httpd->m_options, url, clientId, resp); unsigned status = Service::handleGET(httpd->m_options, url, clientIp, clientId, resp);
MHD_Response* rsp = nullptr; MHD_Response* rsp = nullptr;
if (!resp.empty()) { if (!resp.empty()) {
@ -244,7 +258,7 @@ int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, cons
return sendResponse(connection, status, rsp, contentType); return sendResponse(connection, status, rsp, contentType);
} }
int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, const char* urlPtr, const char* upload_data, int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, const std::string& clientIp, const char* urlPtr, const char* upload_data,
size_t* upload_data_size, void** con_cls) size_t* upload_data_size, void** con_cls)
{ {
auto* cc = (ConnectionContext*)* con_cls; auto* cc = (ConnectionContext*)* con_cls;
@ -259,20 +273,8 @@ int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, con
} else { } else {
std::string resp; std::string resp;
std::string url(urlPtr); std::string url(urlPtr);
std::string clientIp;
std::string clientId; std::string clientId;
const MHD_ConnectionInfo *info = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS);
if (info) {
char clientHost[NI_MAXHOST];
int ec = getnameinfo(info->client_addr, sizeof(*info->client_addr), clientHost, sizeof(clientHost),
0, 0, NI_NUMERICHOST|NI_NUMERICSERV);
if (ec == 0) {
clientIp = std::string(clientHost);
}
}
const char* clientIdPtr = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "clientId"); const char* clientIdPtr = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "clientId");
if (clientIdPtr) { if (clientIdPtr) {
clientId = std::string(clientIdPtr); clientId = std::string(clientIdPtr);

View file

@ -51,12 +51,12 @@ private:
static int sendResponse(MHD_Connection* connection, unsigned status, MHD_Response* rsp, const char* contentType); static int sendResponse(MHD_Connection* connection, unsigned status, MHD_Response* rsp, const char* contentType);
unsigned basicAuth(MHD_Connection* connection, std::string &resp); unsigned basicAuth(MHD_Connection* connection, const std::string& clientIp, std::string &resp);
unsigned tokenAuth(MHD_Connection* connection); unsigned tokenAuth(MHD_Connection* connection, const std::string& clientIp);
static int handler(void* httpd, MHD_Connection* connection, const char* url, const char* method, const char* version, const char* upload_data, size_t* upload_data_size, void**con_cls); static int handler(void* httpd, MHD_Connection* connection, const char* url, const char* method, const char* version, const char* upload_data, size_t* upload_data_size, void**con_cls);
static int handleGET(const Httpd* httpd, MHD_Connection* connection, const char* url); static int handleGET(const Httpd* httpd, MHD_Connection* connection, const std::string& clientIp, const char* url);
static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls); static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const std::string& clientIp, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls);
static std::string readFile(const std::string &fileName); static std::string readFile(const std::string &fileName);

View file

@ -62,13 +62,20 @@ void Service::release()
uv_mutex_unlock(&m_mutex); uv_mutex_unlock(&m_mutex);
} }
unsigned Service::handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp) unsigned Service::handleGET(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, std::string& resp)
{ {
uv_mutex_lock(&m_mutex); uv_mutex_lock(&m_mutex);
unsigned resultCode = MHD_HTTP_NOT_FOUND; unsigned resultCode = MHD_HTTP_NOT_FOUND;
LOG_INFO("GET(url='%s', clientId='%s')", url.c_str(), clientId.c_str()); std::string params;
if (!clientId.empty())
{
params += "?clientId=";
params += clientId;
}
LOG_INFO("[%s] GET '%s%s'", clientIp.c_str(), url.c_str(), params.c_str());
if (url == "/") { if (url == "/") {
resultCode = getAdminPage(options, resp); resultCode = getAdminPage(options, resp);
@ -82,10 +89,12 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons
resultCode = getClientCommand(clientId, resp); resultCode = getClientCommand(clientId, resp);
} else if (url.rfind("/admin/getClientLog", 0) == 0) { } else if (url.rfind("/admin/getClientLog", 0) == 0) {
resultCode = getClientLog(clientId, resp); resultCode = getClientLog(clientId, resp);
} else {
LOG_WARN("[%s] METHOD_NOT_FOUND (%s)", clientIp.c_str(), url.c_str());
} }
} }
else { else {
LOG_ERR("Request does not contain clientId: %s", url.c_str()); LOG_ERR("[%s] Request does not contain clientId: %s", clientIp.c_str(), url.c_str());
} }
} }
@ -101,17 +110,32 @@ unsigned Service::handlePOST(const Options* options, const std::string& url, con
unsigned resultCode = MHD_HTTP_NOT_FOUND; unsigned resultCode = MHD_HTTP_NOT_FOUND;
LOG_INFO("POST(url='%s', clientIp='%s', clientId='%s', dataLen='%d')", std::string params;
url.c_str(), clientIp.c_str(), clientId.c_str(), data.length()); if (!clientId.empty())
{
params += "?clientId=";
params += clientId;
}
LOG_INFO("[%s] POST '%s%s', dataLen='%d'",
clientIp.c_str(), url.c_str(), params.c_str(), data.length());
if (!clientId.empty()) {
if (url.rfind("/client/setClientStatus", 0) == 0) { if (url.rfind("/client/setClientStatus", 0) == 0) {
resultCode = setClientStatus(options, clientIp, clientId, data, resp); resultCode = setClientStatus(options, clientIp, clientId, data, resp);
} else if (url.rfind("/admin/setClientConfig", 0) == 0 || url.rfind("/client/setClientConfig", 0) == 0) { } else if (url.rfind("/admin/setClientConfig", 0) == 0 || url.rfind("/client/setClientConfig", 0) == 0) {
resultCode = setClientConfig(options, clientId, data, resp); resultCode = setClientConfig(options, clientId, data, resp);
} else if (url.rfind("/admin/setClientCommand", 0) == 0) { } else if (url.rfind("/admin/setClientCommand", 0) == 0) {
resultCode = setClientCommand(clientId, data, resp); resultCode = setClientCommand(clientId, data, resp);
} else if (url.rfind("/admin/resetClientStatusList", 0) == 0) { } else {
LOG_WARN("[%s] METHOD_NOT_FOUND (%s)", clientIp.c_str(), url.c_str());
}
} else {
if (url.rfind("/admin/resetClientStatusList", 0) == 0) {
resultCode = resetClientStatusList(data, resp); resultCode = resetClientStatusList(data, resp);
} else {
LOG_WARN("[%s] METHOD_NOT_FOUND (%s)", clientIp.c_str(), url.c_str());
}
} }
uv_mutex_unlock(&m_mutex); uv_mutex_unlock(&m_mutex);
@ -227,8 +251,6 @@ unsigned Service::setClientStatus(const Options* options, const std::string& cli
rapidjson::Document document; rapidjson::Document document;
if (!document.Parse(data.c_str()).HasParseError()) { if (!document.Parse(data.c_str()).HasParseError()) {
LOG_INFO("Status from client: %s", clientId.c_str());
ClientStatus clientStatus; ClientStatus clientStatus;
clientStatus.parseFromJson(document); clientStatus.parseFromJson(document);
clientStatus.setExternalIp(clientIp); clientStatus.setExternalIp(clientIp);
@ -245,7 +267,8 @@ unsigned Service::setClientStatus(const Options* options, const std::string& cli
m_clientCommand.erase(clientId); m_clientCommand.erase(clientId);
} }
} else { } else {
LOG_ERR("Parse Error Occured: %d", document.GetParseError()); LOG_ERR("[%s] ClientStatus for client '%s' - Parse Error Occured: %d",
clientIp.c_str(), clientId.c_str(), document.GetParseError());
} }
return resultCode; return resultCode;

View file

@ -42,7 +42,7 @@ public:
static bool start(); static bool start();
static void release(); static void release();
static unsigned handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp); static unsigned handleGET(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, std::string& resp);
static unsigned handlePOST(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp); static unsigned handlePOST(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp);
private: private: