X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/9ff5d2bf8c72ad82b68761b920475ac8175791c6..fad2dd8911abd78eaf95005e68c32796650a091a:/projects/rlm_stg/stg_client.cpp diff --git a/projects/rlm_stg/stg_client.cpp b/projects/rlm_stg/stg_client.cpp index 834f19c4..239770de 100644 --- a/projects/rlm_stg/stg_client.cpp +++ b/projects/rlm_stg/stg_client.cpp @@ -18,277 +18,135 @@ * 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 "conn.h" +#include "radlog.h" -#include -#include +#include "stg/locker.h" +#include "stg/common.h" -#include +#include +#include -#include "stg_client.h" +using STG::RLM::Client; +using STG::RLM::Conn; +using STG::RLM::RESULT; + +namespace { -using namespace std; +Client* stgClient = NULL; -void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password); -void Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8); -void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8); +} -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -STG_CLIENT::STG_CLIENT(const std::string & host, uint16_t port, uint16_t lp, const std::string & pass) - : localPort(lp), - password(pass), - framedIP(0) +class Client::Impl { -sock = socket(AF_INET, SOCK_DGRAM, 0); -if (sock == -1) - { - std::string message = strerror(errno); - message = "Socket create error: '" + message + "'"; - throw std::runtime_error(message); - } + public: + explicit Impl(const std::string& address); + ~Impl(); -struct hostent * he = NULL; -he = gethostbyname(host.c_str()); -if (he == NULL) - { - throw std::runtime_error("gethostbyname error"); - } + bool stop() { return m_conn ? m_conn->stop() : true; } -outerAddr.sin_family = AF_INET; -outerAddr.sin_port = htons(port); -outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr; + RESULT request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); -InitEncrypt(&ctx, password); + private: + std::string m_address; + boost::scoped_ptr m_conn; -PrepareNet(); -} -//----------------------------------------------------------------------------- -STG_CLIENT::~STG_CLIENT() -{ -close(sock); -} -//----------------------------------------------------------------------------- -uint32_t STG_CLIENT::GetFramedIP() const -{ -return framedIP; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::PrepareNet() -{ -if (localPort != 0) - { - 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");; + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + bool m_done; + RESULT m_result; + bool m_status; - if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr))) + static bool callback(void* data, const RESULT& result, bool status) { - errorStr = "Bind failed"; - return -1; + Impl& impl = *static_cast(data); + STG_LOCKER lock(impl.m_mutex); + impl.m_result = result; + impl.m_status = status; + impl.m_done = true; + pthread_cond_signal(&impl.m_cond); + return true; } - } -return 0; -} -//----------------------------------------------------------------------------- -string STG_CLIENT::GetUserPassword() const -{ -return userPassword; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::Send(const RAD_PACKET & packet) -{ -char buf[RAD_MAX_PACKET_LEN]; - -Encrypt(&ctx, buf, (char *)&packet, sizeof(RAD_PACKET) / 8); +}; -int res = sendto(sock, buf, sizeof(RAD_PACKET), 0, (struct sockaddr *)&outerAddr, sizeof(outerAddr)); - -if (res == -1) - errorStr = "Error sending data"; - -return res; -} -//----------------------------------------------------------------------------- -int STG_CLIENT::RecvData(RAD_PACKET * packet) +Client::Impl::Impl(const std::string& address) + : m_address(address) { -char buf[RAD_MAX_PACKET_LEN]; -int res; - -struct sockaddr_in addr; -socklen_t len = sizeof(struct sockaddr_in); - -res = recvfrom(sock, buf, RAD_MAX_PACKET_LEN, 0, reinterpret_cast(&addr), &len); -if (res == -1) + try { - errorStr = "Error receiving data"; - return -1; + m_conn.reset(new Conn(m_address, &Impl::callback, this)); } - -Decrypt(&ctx, (char *)packet, buf, res / 8); - -return 0; -} -//----------------------------------------------------------------------------- -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; - -if (strncmp((char *)packet->magic, RAD_ID, RAD_MAGIC_LEN)) + catch (const std::runtime_error& ex) { - errorStr = "Magic invalid. Wanted: '"; - errorStr += RAD_ID; - errorStr += "', got: '"; - errorStr += (char *)packet->magic; - errorStr += "'"; - return -1; + RadLog("Connection error: %s.", ex.what()); } - -return 0; + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_cond, NULL); + m_done = 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) +Client::Impl::~Impl() { -RAD_PACKET packet; - -userPassword = ""; - -if (Request(&packet, login, svc, RAD_AUTH_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; - -return 0; + pthread_cond_destroy(&m_cond); + pthread_mutex_destroy(&m_mutex); } -//----------------------------------------------------------------------------- -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) +RESULT Client::Impl::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, 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; - } + STG_LOCKER lock(m_mutex); + if (!m_conn || !m_conn->connected()) + m_conn.reset(new Conn(m_address, &Impl::callback, this)); + if (!m_conn->connected()) + throw Conn::Error("Failed to create connection to '" + m_address + "'."); + + m_done = false; + m_conn->request(type, userName, password, pairs); + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 5; + int res = 0; + while (!m_done && res == 0) + res = pthread_cond_timedwait(&m_cond, &m_mutex, &ts); + if (res != 0 || !m_status) + throw Conn::Error("Request failed."); + return m_result; +} -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1; +Client::Client(const std::string& address) + : m_impl(new Impl(address)) +{ +} -return 0; +Client::~Client() +{ } -//----------------------------------------------------------------------------- -inline -void Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8) + +bool Client::stop() { -// 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)); + return m_impl->stop(); } -//----------------------------------------------------------------------------- -inline -void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8) + +RESULT Client::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) { -// len8 - длина в 8-ми байтовых блоках -if (dst != src) - memcpy(dst, src, len8 * 8); + return m_impl->request(type, userName, password, pairs); +} -for (int i = 0; i < len8; i++) - Blowfish_Decrypt(ctx, (uint32_t *)(dst + i*8), (uint32_t *)(dst + i*8 + 4)); +Client* Client::get() +{ + return stgClient; } -//----------------------------------------------------------------------------- -inline -void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) + +bool Client::configure(const std::string& address) { -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); + if ( stgClient != NULL ) + return stgClient->configure(address); + try { + stgClient = new Client(address); + return true; + } catch (const std::exception& ex) { + RadLog("Client configuration error: %s.", ex.what()); + } + return false; } -//-----------------------------------------------------------------------------