X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/641204dfbdb9fc870cdd2e7f9e3169a44693e7bf..9d39c12e0f22efa4648989e1f01368ad34e0f929:/projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp diff --git a/projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp b/projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp index 8ceb7e70..f7e6169e 100644 --- a/projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp +++ b/projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp @@ -14,37 +14,34 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/******************************************************************* -* -* DESCRIPTION: æÁÊÌ Ó ÏÓÎÏ×ÎÙÍÉ ÆÕÎËÃÉÑÍÉ ÄÌÑ ÓÅÔÅ×ÏÇÏ ÏÂÍÅÎÁ ÄÁÎÎÙÍÉ -* Ó ÍÅÎÅÄÖÅÒÏÍ ËÌÉÅÎÔÏ×. ðÒÉÅÍ, ÐÅÒÅÄÁÞÁ É ÛÉÆÒÏ×ÁÎÉÅ ÓÏÏÂÝÅÎÉÊ. -* -* AUTHOR: Boris Mikhailenko -* -* $Revision: 1.24 $ -* $Date: 2010/10/04 20:24:54 $ -* -*******************************************************************/ - -/*#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include */ +/* + * Author : Boris Mikhailenko + */ + +#include "configproto.h" + +#include "parser.h" + +#include "stg/admins.h" +#include "stg/logger.h" +#include "stg/common.h" +#include "stg/blowfish.h" #include #include +#include // snprintf +#include // strerror -#include "configproto.h" -#include "blowfish.h" +#include // close +#include +#include +#include +#include + +#ifndef ENODATA +// FreeBSD 4.* - suxx +#define ENODATA -1 +#endif enum CONF_STATE { @@ -63,7 +60,6 @@ enum //----------------------------------------------------------------------------- int CONFIGPROTO::Prepare() { -list ansList; //óÀÄÁ ÂÕÄÅÔ ÐÏÍÅÝÅÎ ÏÔ×ÅÔ ÄÌÑ ÍÅÎÅÄÖÅÒÁ ËÌÉÅÎÔÏ× int res; struct sockaddr_in listenAddr; @@ -80,6 +76,7 @@ listenSocket = socket(PF_INET, SOCK_STREAM, 0); if (listenSocket < 0) { errorStr = "Create NET_CONFIGURATOR socket failed."; + logger("Cannot create a socket: %s", strerror(errno)); return -1; } @@ -91,7 +88,8 @@ int lng = 1; if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4)) { - errorStr = "Setsockopt failed. " + string(strerror(errno)); + errorStr = "Setsockopt failed. " + std::string(strerror(errno)); + logger("setsockopt error: %s", strerror(errno)); return -1; } @@ -100,6 +98,7 @@ res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)); if (res == -1) { errorStr = "Bind admin socket failed"; + logger("Cannot bind the socket: %s", strerror(errno)); return -1; } @@ -107,15 +106,9 @@ res = listen(listenSocket, 0); if (res == -1) { errorStr = "Listen admin socket failed"; + logger("Cannot listen the socket: %s", strerror(errno)); return -1; } -outerAddrLen = sizeof(outerAddr); - -/*if (0 != fcntl(listenSocket, F_SETFL, O_NONBLOCK)) - { - errorStr = "fcntl error!"; - return -1; - }*/ errorStr = ""; nonstop = true; @@ -134,7 +127,7 @@ addr.sin_family = PF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); -addrLen = sizeof(outerAddr); +addrLen = sizeof(addr); sock = socket(PF_INET, SOCK_STREAM, 0); connect(sock, (sockaddr*)&addr, addrLen); close(sock); @@ -142,148 +135,133 @@ close(sock); return 0; } //----------------------------------------------------------------------------- -// æÕÎËÃÉÑ ÏÂÝÅÎÉÑ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ -void * CONFIGPROTO::Run(void * a) +void CONFIGPROTO::Run() { -/* - * Function Name:ReciveSendConf - * Parameters: void * a ÕËÁÚÁÔÅÌØ ÎÁ ÜËÚÅÍÐÌÑÒ ËÌÁÓÓÁ CONFIGPROTO - * Description: üÔÁ ÆÕÎËÃÉÑ ÏÂÅÓÐÅÞÉ×ÁÅÔ ÓÅÔÅ×ÏÅ ×ÚÁÉÍÏÄÅÊÓÔ×ÉÅ - * Ó íÅÎÅÄÖÅÒÏÍ ëÌÉÅÎÔÏ×. ÷ ÅÅ ÚÁÄÁÞÉ ×ÈÏÄÉÔ: ÐÒÉÅÍ ÚÁÐÒÏÓÏ× ÐÏ TCP/IP - * ÉÈ ÒÁÓÛÉÆÒÏ×ËÁ, ÐÅÒÅÄÁÞÁ ÐÒÉÎÑÔÙÈ ÄÁÎÎÙÈ ÁÎÁÌÉÚÁÔÏÒÕ É ÏÔÐÒÁ×ËÁ ÏÔ×ÅÔÁ ÎÁÚÁÄ. - * Returns: ×ÏÚ×ÒÁÝÁÅÔ NULL - */ - -CONFIGPROTO * cp = (CONFIGPROTO*)a; -cp->state = confHdr; +state = confHdr; -while (cp->nonstop) +while (nonstop) { - cp->state = confHdr; - cp->outerSocket = accept(cp->listenSocket, - (struct sockaddr*)(&cp->outerAddr), - &cp->outerAddrLen); + state = confHdr; + struct sockaddr_in outerAddr; + socklen_t outerAddrLen(sizeof(outerAddr)); + int outerSocket = accept(listenSocket, + (struct sockaddr*)(&outerAddr), + &outerAddrLen); - if (!cp->nonstop) - { - continue; - } + if (!nonstop) + break; - if (cp->outerSocket == -1) + if (outerSocket < 0) { + logger("accept error: %s", strerror(errno)); printfd(__FILE__, "accept failed\n"); - usleep(100000); continue; } - cp->adminIP = *(unsigned int*)&(cp->outerAddr.sin_addr); - - /* TODO - if (!cp->hostAllow->HostAllowed(cp->adminIP)) - { - close(outerSocket); - continue; - }*/ - - printfd(__FILE__, "Connection accepted from %s\n", inet_ntostring(cp->outerAddr.sin_addr.s_addr).c_str()); + adminIP = *(unsigned int*)&(outerAddr.sin_addr); - if (cp->state == confHdr) + if (state == confHdr) { - if (cp->RecvHdr(cp->outerSocket) < 0) + if (RecvHdr(outerSocket) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - if (cp->state == confLogin) + if (state == confLogin) { - if (cp->SendHdrAnswer(cp->outerSocket, ans_ok) < 0) + if (SendHdrAnswer(outerSocket, ans_ok) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - - if (cp->RecvLogin(cp->outerSocket) < 0) + if (RecvLogin(outerSocket) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - - if (cp->state == confLoginCipher) + if (state == confLoginCipher) { - if (cp->SendLoginAnswer(cp->outerSocket, ans_ok) < 0) + if (SendLoginAnswer(outerSocket) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - if (cp->RecvLoginS(cp->outerSocket) < 0) + if (RecvLoginS(outerSocket) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - - if (cp->state == confData) + if (state == confData) { - if (cp->SendLoginSAnswer(cp->outerSocket, ans_ok) < 0) + if (SendLoginSAnswer(outerSocket, ans_ok) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - if (cp->RecvData(cp->outerSocket) < 0) + if (RecvData(outerSocket) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - cp->state = confHdr; + state = confHdr; } else { - if (cp->SendLoginSAnswer(cp->outerSocket, ans_err) < 0) + if (SendLoginSAnswer(outerSocket, ans_err) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } - cp->WriteLogAccessFailed(cp->adminIP); + WriteLogAccessFailed(adminIP); } } else { - cp->WriteLogAccessFailed(cp->adminIP); + WriteLogAccessFailed(adminIP); } } else { - cp->WriteLogAccessFailed(cp->adminIP); - if (cp->SendHdrAnswer(cp->outerSocket, ans_err) < 0) + WriteLogAccessFailed(adminIP); + if (SendHdrAnswer(outerSocket, ans_err) < 0) { - close(cp->outerSocket); + close(outerSocket); continue; } } } else { - cp->WriteLogAccessFailed(cp->adminIP); + WriteLogAccessFailed(adminIP); } - close(cp->outerSocket); + printfd(__FILE__, "Successfull connection from %s\n", inet_ntostring(outerAddr.sin_addr.s_addr).c_str()); + close(outerSocket); } - -return NULL; } //----------------------------------------------------------------------------- int CONFIGPROTO::RecvHdr(int sock) { char buf[sizeof(STG_HEADER)]; memset(buf, 0, sizeof(STG_HEADER)); -int ret; -int stgHdrLen = strlen(STG_HEADER); -for (int i = 0; i < stgHdrLen; i++) +size_t stgHdrLen = sizeof(STG_HEADER) - 1; // Without 0-char +size_t pos = 0; +while (pos < stgHdrLen) { - ret = recv(sock, &buf[i], 1, 0); + if (!WaitPackets(sock)) + { + state = confHdr; + SendError(sock, "Bad request"); + return -1; + } + ssize_t ret = recv(sock, &buf[pos], static_cast(stgHdrLen) - static_cast(pos), 0); if (ret <= 0) { + if (ret < 0) + logger("recv error: %s", strerror(errno)); state = confHdr; return -1; } + pos += ret; } if (0 == strncmp(buf, STG_HEADER, strlen(STG_HEADER))) @@ -293,7 +271,7 @@ if (0 == strncmp(buf, STG_HEADER, strlen(STG_HEADER))) } else { - SendError("Bad request"); + SendError(sock, "Bad request"); } state = confHdr; @@ -302,23 +280,19 @@ return -1; //----------------------------------------------------------------------------- int CONFIGPROTO::SendHdrAnswer(int sock, int err) { -int ret; - if (err) { - ret = send(sock, ERR_HEADER, sizeof(ERR_HEADER)-1, 0); - if (ret < 0) + if (send(sock, ERR_HEADER, sizeof(ERR_HEADER) - 1, 0) < 0) { - WriteServLog("send ERR_HEADER error in SendHdrAnswer."); + logger("send error: %s", strerror(errno)); return -1; } } else { - ret = send(sock, OK_HEADER, sizeof(OK_HEADER)-1, 0); - if (ret < 0) + if (send(sock, OK_HEADER, sizeof(OK_HEADER) - 1, 0) < 0) { - WriteServLog("send OK_HEADER error in SendHdrAnswer."); + logger("send error: %s", strerror(errno)); return -1; } } @@ -328,64 +302,49 @@ return 0; //----------------------------------------------------------------------------- int CONFIGPROTO::RecvLogin(int sock) { -char login[ADM_LOGIN_LEN+1]; -int ret; +char login[ADM_LOGIN_LEN + 1]; memset(login, 0, ADM_LOGIN_LEN + 1); -//printfd(__FILE__, "RecvLogin\n"); +size_t pos = 0; +while (pos < ADM_LOGIN_LEN) { + if (!WaitPackets(sock)) + { + state = confHdr; + return ENODATA; + } -/*for (int i = 0; i < ADM_LOGIN_LEN; i++) - { - ret = recv(sock, &login[i], 1, 0); + ssize_t ret = recv(sock, &login[pos], ADM_LOGIN_LEN - static_cast(pos), 0); if (ret <= 0) { - close(sock); + // Error in network + logger("recv error: %s", strerror(errno)); state = confHdr; return ENODATA; } - }*/ - -ret = recv(sock, login, ADM_LOGIN_LEN, 0); -if (ret < 0) - { - // Error in network - close(sock); - state = confHdr; - return ENODATA; - } - -if (ret < ADM_LOGIN_LEN) - { - // Error in protocol - close(sock); - state = confHdr; - return ENODATA; - } + pos += ret; +} -if (admins->FindAdmin(login, &currAdmin)) +if (admins->Find(login, &currAdmin)) { // Admin not found - close(sock); state = confHdr; return ENODATA; } -currAdmin.SetAdminIP(adminIP); + +currAdmin->SetIP(adminIP); adminLogin = login; state = confLoginCipher; return 0; } //----------------------------------------------------------------------------- -int CONFIGPROTO::SendLoginAnswer(int sock, int) +int CONFIGPROTO::SendLoginAnswer(int sock) { -int ret; - -ret = send(sock, OK_LOGIN, sizeof(OK_LOGIN)-1, 0); -if (ret < 0) +if (send(sock, OK_LOGIN, sizeof(OK_LOGIN) - 1, 0) < 0) { - WriteServLog("Send OK_LOGIN error in SendLoginAnswer."); + logger("Send OK_LOGIN error in SendLoginAnswer."); return -1; } return 0; @@ -394,66 +353,43 @@ return 0; int CONFIGPROTO::RecvLoginS(int sock) { char loginS[ADM_LOGIN_LEN + 1]; -char login[ADM_LOGIN_LEN + 1]; -int ret; -BLOWFISH_CTX ctx; memset(loginS, 0, ADM_LOGIN_LEN + 1); -//printfd(__FILE__, "RecvLoginS\n"); - -/*for (int i = 0; i < ADM_LOGIN_LEN; i++) +size_t pos = 0; +while (pos < ADM_LOGIN_LEN) { - ret = recv(sock, &loginS[i], 1, 0); - - if (ret <= 0) + if (!WaitPackets(sock)) { - //printfd(__FILE__, "RecvLoginS close\n"); - close(sock); state = confHdr; return ENODATA; } - }*/ -int total = 0; - -while (total < ADM_LOGIN_LEN) - { - ret = recv(sock, &loginS[total], ADM_LOGIN_LEN - total, 0); + ssize_t ret = recv(sock, &loginS[pos], ADM_LOGIN_LEN - static_cast(pos), 0); - if (ret < 0) + if (ret <= 0) { // Network error printfd(__FILE__, "recv error: '%s'\n", strerror(errno)); - close(sock); + logger("recv error: %s", strerror(errno)); state = confHdr; return ENODATA; } - total += ret; + pos += ret; } -// TODO: implement select on socket -/*if (total < ADM_LOGIN_LEN) - { - // Protocol error - printfd(__FILE__, "Protocol error. Need %d bytes of cryptologin. Got %d bytes.\n", ADM_LOGIN_LEN, ret); - close(sock); - state = confHdr; - return ENODATA; - }*/ - -if (currAdmin.GetLogin() == "") +if (currAdmin->GetLogin().empty()) { state = confHdr; return ENODATA; } -EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx); +BLOWFISH_CTX ctx; +InitContext(currAdmin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx); -for (int i = 0; i < ADM_LOGIN_LEN/8; i++) - { - DecodeString(login + i*8, loginS + i*8, &ctx); - } +char login[ADM_LOGIN_LEN + 1]; +for (size_t i = 0; i < ADM_LOGIN_LEN / 8; i++) + DecryptBlock(login + i * 8, loginS + i * 8, &ctx); if (currAdmin == admins->GetNoAdmin()) { @@ -462,35 +398,32 @@ if (currAdmin == admins->GetNoAdmin()) return 0; } -if (strncmp(currAdmin.GetLogin().c_str(), login, ADM_LOGIN_LEN) != 0) +if (strncmp(currAdmin->GetLogin().c_str(), login, ADM_LOGIN_LEN) != 0) { state = confHdr; return ENODATA; } state = confData; +adminPassword = currAdmin->GetPassword(); return 0; } //----------------------------------------------------------------------------- int CONFIGPROTO::SendLoginSAnswer(int sock, int err) { -int ret; - if (err) { - ret = send(sock, ERR_LOGINS, sizeof(ERR_LOGINS)-1, 0); - if (ret < 0) + if (send(sock, ERR_LOGINS, sizeof(ERR_LOGINS) - 1, 0) < 0) { - WriteServLog("send ERR_LOGIN error in SendLoginAnswer."); + logger("send error: %s", strerror(errno)); return -1; } } else { - ret = send(sock, OK_LOGINS, sizeof(OK_LOGINS)-1, 0); - if (ret < 0) + if (send(sock, OK_LOGINS, sizeof(OK_LOGINS) - 1, 0) < 0) { - WriteServLog("send OK_LOGINS error in SendLoginSAnswer."); + logger("send error: %s", strerror(errno)); return -1; } } @@ -499,149 +432,90 @@ return 0; //----------------------------------------------------------------------------- int CONFIGPROTO::RecvData(int sock) { -//printfd(__FILE__, "RecvData\n"); -//int n = 0; -int ret; -char bufferS[8]; -char buffer[9]; - -buffer[8] = 0; - requestList.clear(); BLOWFISH_CTX ctx; -EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx); +InitContext(currAdmin->GetPassword().c_str(), ADM_PASSWD_LEN, &ctx); while (1) { - /*ret = recv(sock, &bufferS[n++], 1, 0); - if (ret <= 0) - { - //printfd(__FILE__, "RecvData close\n"); - close(sock); - return 0; - }*/ - int total = 0; bool done = false; - while (total < 8) + char bufferS[8]; + size_t pos = 0; + while (pos < sizeof(bufferS)) { - ret = recv(sock, &bufferS[total], 8 - total, 0); + if (!WaitPackets(sock)) + { + done = true; + break; + } + + ssize_t ret = recv(sock, &bufferS[pos], sizeof(bufferS) - static_cast(pos), 0); if (ret < 0) { // Network error - close(sock); - return 0; + logger("recv error: %s", strerror(errno)); + printfd(__FILE__, "recv error: '%s'\n", strerror(errno)); + return -1; } - if (ret < 8) + if (ret == 0) { - if (memchr(buffer, 0, ret) != NULL) - { - done = true; - break; - } + done = true; + break; } - total += ret; + pos += ret; } - DecodeString(buffer, bufferS, &ctx); - requestList.push_back(std::string(buffer, total)); + char buffer[8]; + buffer[7] = 0; - if (done || memchr(buffer, 0, total) != NULL) + DecryptBlock(buffer, bufferS, &ctx); + requestList.push_back(std::string(buffer, pos)); + + if (done || memchr(buffer, 0, pos) != NULL) { - // ëÏÎÅà ÐÏÓÙÌËÉ + // End of data if (ParseCommand()) - { - SendError("Bad command"); - } - return SendDataAnswer(sock); + return SendError(sock, "Bad command"); + else + return SendDataAnswer(sock, GetDataAnswer()); } - - /*if (n == 8) - { - n = 0; - DecodeString(buffer, bufferS, &ctx); - requestList.push_back(std::string(buffer, 8)); - for (int j = 0; j < 8; j++) - { - if (buffer[j] == 0) - { - // ëÏÎÅà ÐÏÓÙÌËÉ - if (ParseCommand()) - { - SendError("Bad command"); - } - return SendDataAnswer(sock); - } - } - }*/ } -return 0; +//return 0; } //----------------------------------------------------------------------------- -int CONFIGPROTO::SendDataAnswer(int sock) +int CONFIGPROTO::SendDataAnswer(int sock, const std::string & answer) { -list::iterator li; -li = answerList.begin(); +if (answer.empty()) + return 0; BLOWFISH_CTX ctx; +InitContext(adminPassword.c_str(), ADM_PASSWD_LEN, &ctx); -char buff[8]; -char buffS[8]; -int n = 0; -int k = 0; -int ret = 0; - -EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx); - -while (li != answerList.end()) +std::string::size_type pos = 0; +std::string::size_type length = answer.length() + 1; +while (pos < length) { - while ((*li).c_str()[k]) - { - buff[n%8] = (*li).c_str()[k]; - n++; - k++; - - if (n%8 == 0) - { - EncodeString(buffS, buff, &ctx); - ret = send(sock, buffS, 8, 0); - if (ret < 0) - { - return -1; - } - } - } - k = 0;// new node - li++; + char buffer[1024]; + std::string::size_type chunkLength = std::min(length - pos, sizeof(buffer)); + EncryptString(buffer, answer.c_str() + pos, chunkLength, &ctx); + if (send(sock, buffer, (chunkLength & ~7) < chunkLength ? chunkLength + 8 : chunkLength, 0) < 0) // Need to send data adjusted to the 8-byte boundary. + return -1; + pos += chunkLength; } -if (answerList.empty()) { - return 0; -} - -buff[n%8] = 0; -EncodeString(buffS, buff, &ctx); - -answerList.clear(); - -return send(sock, buffS, 8, 0); +return 1; } //----------------------------------------------------------------------------- -void CONFIGPROTO::SendError(const char * text) +int CONFIGPROTO::SendError(int sock, const std::string & text) { -char s[255]; -answerList.clear(); -sprintf(s, "", text); -answerList.push_back(s); +return SendDataAnswer(sock, ""); } //----------------------------------------------------------------------------- void CONFIGPROTO::WriteLogAccessFailed(uint32_t ip) { -WriteServLog("Admin's connect failed. IP %s", inet_ntostring(ip).c_str()); +logger("Admin's connection failed. IP %s", inet_ntostring(ip).c_str()); } //----------------------------------------------------------------------------- - - -