X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/641204dfbdb9fc870cdd2e7f9e3169a44693e7bf..10c0d7324d1a25feebaaf6f5bf9b6054e03dd0b3:/projects/rlm_stg/stg_client.cpp?ds=inline diff --git a/projects/rlm_stg/stg_client.cpp b/projects/rlm_stg/stg_client.cpp index 7be0a55e..6987976b 100644 --- a/projects/rlm_stg/stg_client.cpp +++ b/projects/rlm_stg/stg_client.cpp @@ -18,303 +18,156 @@ * Author : Maxim Mamontov */ -/* - * Realization of data access via Stargazer for RADIUS - * - * $Revision: 1.8 $ - * $Date: 2010/04/16 12:30:02 $ - * - */ +#include "stg_client.h" -#include -#include -#include // close -#include +#include "stg/common.h" -#include "stg_client.h" +#include -using namespace std; +#include -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -STG_CLIENT::STG_CLIENT() - : port(0), - localPort(0), - sock(0) -{ -} -//----------------------------------------------------------------------------- -STG_CLIENT::~STG_CLIENT() -{ -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetServer(const string & host) -{ -STG_CLIENT::host = host; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetPort(uint16_t port) -{ -STG_CLIENT::port = port; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetLocalPort(uint16_t port) -{ -STG_CLIENT::localPort = port; -} -//----------------------------------------------------------------------------- -void STG_CLIENT::SetPassword(const string & password) +namespace { + +STG_CLIENT* stgClient = NULL; + +unsigned fromType(STG_CLIENT::TYPE type) { -STG_CLIENT::password = password; + return static_cast(type); } -//----------------------------------------------------------------------------- -uint32_t STG_CLIENT::GetFramedIP() const + +STG::SGCP::TransportType toTransport(const std::string& value) { -return framedIP; + std::string type = ToLower(value); + if (type == "unix") return STG::SGCP::UNIX; + else if (type == "udp") return STG::SGCP::UDP; + else if (type == "tcp") return STG::SGCP::TCP; + throw ChannelConfig::Error("Invalid transport type. Should be 'unix', 'udp' or 'tcp'."); } -//----------------------------------------------------------------------------- -void STG_CLIENT::InitEncrypt() -{ -unsigned char keyL[RAD_PASSWORD_LEN]; -memset(keyL, 0, RAD_PASSWORD_LEN); -strncpy((char *)keyL, password.c_str(), RAD_PASSWORD_LEN); -Blowfish_Init(&ctx, keyL, RAD_PASSWORD_LEN); + } -//----------------------------------------------------------------------------- -int STG_CLIENT::PrepareNet() + +ChannelConfig::ChannelConfig(std::string addr) + : transport(STG::SGCP::TCP) { -sock = socket(AF_INET, SOCK_DGRAM, 0); -if (sock == -1) - { - errorStr = "Socket create error"; - return -1; - } + // unix:pass@/var/run/stg.sock + // tcp:secret@192.168.0.1:12345 + // udp:key@isp.com.ua:54321 -struct hostent * he = NULL; -he = gethostbyname(host.c_str()); -if (he == NULL) - { - errorStr = "gethostbyname error"; - return -1; + size_t pos = addr.find_first_of(':'); + if (pos == std::string::npos) + throw Error("Missing transport name."); + transport = toTransport(addr.substr(0, pos)); + addr = addr.substr(pos + 1); + if (addr.empty()) + throw Error("Missing address to connect to."); + pos = addr.find_first_of('@'); + if (pos != std::string::npos) { + key = addr.substr(0, pos); + addr = addr.substr(pos + 1); + if (addr.empty()) + throw Error("Missing address to connect to."); } - -if (localPort != 0) + if (transport == STG::SGCP::UNIX) { - struct sockaddr_in localAddr; - localAddr.sin_family = AF_INET; - localAddr.sin_port = htons(localPort); - localAddr.sin_addr.s_addr = inet_addr("0.0.0.0");; - - if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr))) - { - errorStr = "Bind failed"; - return -1; - } + address = addr; + return; } - -outerAddr.sin_family = AF_INET; -outerAddr.sin_port = htons(port); -outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr; - -outerAddrLen = sizeof(struct sockaddr_in); - -return 0; + pos = addr.find_first_of(':'); + if (pos == std::string::npos) + throw Error("Missing port."); + address = addr.substr(0, pos); + if (str2x(addr.substr(pos + 1), port)) + throw Error("Invalid port value."); } -//----------------------------------------------------------------------------- -void STG_CLIENT::FinalizeNet() + +STG_CLIENT::STG_CLIENT(const std::string& address) + : m_config(address), + m_proto(m_config.transport, m_config.key), + m_thread(boost::bind(&STG_CLIENT::m_run, this)) { -close(sock); } -//----------------------------------------------------------------------------- -int STG_CLIENT::Start() -{ -InitEncrypt(); -return PrepareNet(); -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Stop() +STG_CLIENT::~STG_CLIENT() { -FinalizeNet(); - -return 0; + stop(); } -//----------------------------------------------------------------------------- -string STG_CLIENT::GetUserPassword() const + +bool STG_CLIENT::stop() { -return userPassword; + return m_proto.stop(); } -//----------------------------------------------------------------------------- -int STG_CLIENT::Send(const RAD_PACKET & packet) -{ -char buf[RAD_MAX_PACKET_LEN]; - -Encrypt(buf, (char *)&packet, sizeof(RAD_PACKET) / 8); - -int res = sendto(sock, buf, sizeof(RAD_PACKET), 0, (struct sockaddr *)&outerAddr, outerAddrLen); -if (res == -1) - errorStr = "Error sending data"; - -return res; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::RecvData(RAD_PACKET * packet) +RESULT STG_CLIENT::request(TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) { -char buf[RAD_MAX_PACKET_LEN]; -int res; - -outerAddrLen = sizeof(struct sockaddr_in); - -res = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, (struct sockaddr *)&outerAddr, &outerAddrLen); -if (res == -1) - { - errorStr = "Error receiving data"; - return -1; - } - -Decrypt((char *)packet, buf, res / 8); - -return 0; + m_writeHeader(type, userName, password); + m_writePairBlock(pairs); + RESULT result; + result.modify = m_readPairBlock(); + result.reply = m_readPairBlock(); + return result; } -//----------------------------------------------------------------------------- -int STG_CLIENT::Request(RAD_PACKET * packet, const std::string & login, const std::string & svc, uint8_t packetType) -{ -int res; - -memcpy((void *)&packet->magic, (void *)RAD_ID, RAD_MAGIC_LEN); -packet->protoVer[0] = '0'; -packet->protoVer[1] = '1'; -packet->packetType = packetType; -packet->ip = 0; -strncpy((char *)packet->login, login.c_str(), RAD_LOGIN_LEN); -strncpy((char *)packet->service, svc.c_str(), RAD_SERVICE_LEN); - -res = Send(*packet); -if (res == -1) - return -1; -res = RecvData(packet); -if (res == -1) - return -1; +STG_CLIENT* STG_CLIENT::get() +{ + return stgClient; +} -if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN)) - { - errorStr = "Magic invalid. Wanted: '"; - errorStr += RAD_ID; - errorStr += "', got: '"; - errorStr += (char *)packet->magic; - errorStr += "'"; - return -1; +bool STG_CLIENT::configure(const std::string& address) +{ + if ( stgClient != NULL && stgClient->stop() ) + delete stgClient; + try { + stgClient = new STG_CLIENT(address); + return true; + } catch (const ChannelConfig::Error& ex) { + // TODO: Log it } - -return 0; + return false; } -//----------------------------------------------------------------------------- -int STG_CLIENT::Authorize(const string & login, const string & svc) -{ -RAD_PACKET packet; -userPassword = ""; - -if (Request(&packet, login, svc, RAD_AUTZ_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -userPassword = (char *)packet.password; - -return 0; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Authenticate(const string & login, const string & svc) +void STG_CLIENT::m_writeHeader(TYPE type, const std::string& userName, const std::string& password) { -RAD_PACKET packet; - -userPassword = ""; - -if (Request(&packet, login, svc, RAD_AUTH_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -return 0; + try { + m_proto.writeAll(fromType(type)); + m_proto.writeAll(userName); + m_proto.writeAll(password); + } catch (const STG::SGCP::Proto::Error& ex) { + throw Error(ex.what()); + } } -//----------------------------------------------------------------------------- -int STG_CLIENT::PostAuthenticate(const string & login, const string & svc) -{ -RAD_PACKET packet; -userPassword = ""; - -if (Request(&packet, login, svc, RAD_POST_AUTH_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -if (svc == "Framed-User") - framedIP = packet.ip; -else - framedIP = 0; - -return 0; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Account(const std::string & type, const string & login, const string & svc, const string & sessid) +void STG_CLIENT::m_writePairBlock(const PAIRS& pairs) { -RAD_PACKET packet; - -userPassword = ""; -strncpy((char *)packet.sessid, sessid.c_str(), RAD_SESSID_LEN); - -if (type == "Start") - { - if (Request(&packet, login, svc, RAD_ACCT_START_PACKET)) - return -1; - } -else if (type == "Stop") - { - if (Request(&packet, login, svc, RAD_ACCT_STOP_PACKET)) - return -1; - } -else if (type == "Interim-Update") - { - if (Request(&packet, login, svc, RAD_ACCT_UPDATE_PACKET)) - return -1; - } -else - { - if (Request(&packet, login, svc, RAD_ACCT_OTHER_PACKET)) - return -1; + try { + m_proto.writeAll(pairs.size()); + for (size_t i = 0; i < pairs.size(); ++i) { + m_proto.writeAll(pairs[i].first); + m_proto.writeAll(pairs[i].second); + } + } catch (const STG::SGCP::Proto::Error& ex) { + throw Error(ex.what()); } - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -return 0; } -//----------------------------------------------------------------------------- -void STG_CLIENT::Encrypt(char * dst, const char * src, int len8) + +PAIRS STG_CLIENT::m_readPairBlock() { -// len8 - длина в 8-ми байтовых блоках -if (dst != src) - memcpy(dst, src, len8 * 8); - -for (int i = 0; i < len8; i++) - Blowfish_Encrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4)); + try { + size_t count = m_proto.readAll(); + if (count == 0) + return PAIRS(); + PAIRS res(count); + for (size_t i = 0; i < count; ++i) { + res[i].first = m_proto.readAll(); + res[i].second = m_proto.readAll(); + } + return res; + } catch (const STG::SGCP::Proto::Error& ex) { + throw Error(ex.what()); + } } -//----------------------------------------------------------------------------- -void STG_CLIENT::Decrypt(char * dst, const char * src, int len8) -{ -// len8 - длина в 8-ми байтовых блоках -if (dst != src) - memcpy(dst, src, len8 * 8); -for (int i = 0; i < len8; i++) - Blowfish_Decrypt(&ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4)); +void STG_CLIENT::m_run() +{ + m_proto.connect(m_config.address, m_config.port); + m_proto.run(); } -//-----------------------------------------------------------------------------