From: Maxim Mamontov Date: Tue, 14 Apr 2015 19:18:01 +0000 (+0300) Subject: Final icing on rlm_stg. X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/65a51d11c64daa4df3d4388df60bb4efc3e67e14?ds=sidebyside Final icing on rlm_stg. --- diff --git a/projects/rlm_stg/Makefile b/projects/rlm_stg/Makefile index efc1bcaa..1280bd91 100644 --- a/projects/rlm_stg/Makefile +++ b/projects/rlm_stg/Makefile @@ -13,7 +13,8 @@ SRCS = ./rlm_stg.c \ ./stg_client.cpp STGLIBS = crypto \ - common + common \ + sgcp STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS))) STGLIBS_LIBS = $(addprefix -L ../../stglibs/,$(addsuffix .lib,$(STGLIBS))) @@ -32,6 +33,7 @@ SEARCH_DIRS = -I ../../include OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))) +CFLAGS += -fPIC $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) CXXFLAGS += -fPIC $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) CFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) LDFLAGS += -shared -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-E $(STGLIBS_LIBS) diff --git a/projects/rlm_stg/build b/projects/rlm_stg/build index 433cd04f..e9be4ed0 100755 --- a/projects/rlm_stg/build +++ b/projects/rlm_stg/build @@ -61,7 +61,7 @@ printf "######################################################################## printf " Building rlm_stg for $sys $release\n" printf "#############################################################################\n" -STG_LIBS="crypto.lib common.lib" +STG_LIBS="crypto.lib common.lib sgcp.lib" if [ "$OS" = "linux" ] then diff --git a/projects/rlm_stg/iface.cpp b/projects/rlm_stg/iface.cpp index 40a96f72..485e9ef7 100644 --- a/projects/rlm_stg/iface.cpp +++ b/projects/rlm_stg/iface.cpp @@ -2,10 +2,14 @@ #include "stg_client.h" +#include + +#include + namespace { -STG_PAIR* toPairs(const PAIRS& source) +STG_PAIR* toSTGPairs(const PAIRS& source) { STG_PAIR * pairs = new STG_PAIR[source.size() + 1]; for (size_t pos = 0; pos < source.size(); ++pos) { @@ -15,101 +19,93 @@ STG_PAIR* toPairs(const PAIRS& source) strncpy(pairs[pos].value, source[pos].second.c_str(), sizeof(STG_PAIR::value)); ++pos; } - bzero(pairs[sources.size()].key, sizeof(STG_PAIR::key)); - bzero(pairs[sources.size()].value, sizeof(STG_PAIR::value)); + bzero(pairs[source.size()].key, sizeof(STG_PAIR::key)); + bzero(pairs[source.size()].value, sizeof(STG_PAIR::value)); return pairs; } +PAIRS fromSTGPairs(const STG_PAIR* pairs) +{ + const STG_PAIR* pair = pairs; + PAIRS res; + + while (!emptyPair(pair)) { + res.push_back(std::pair(pair->key, pair->value)); + ++pair; + } + + return res; } -int stgInstantiateImpl(const char* server, uint16_t port, const char* password) +STG_RESULT toResult(const RESULT& source) { - if (STG_CLIENT::configure(server, port, password)) - return 1; + STG_RESULT result; + result.modify = toSTGPairs(source.modify); + result.reply = toSTGPairs(source.reply); + return result; +} - return 0; +STG_RESULT emptyResult() +{ + STG_RESULT result = {NULL, NULL}; + return result; } -const STG_PAIR* stgAuthorizeImpl(const char* userName, const char* serviceType) +std::string toString(const char* value) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->authorize(userName, serviceType)); + if (value == NULL) + return ""; + else + return value; } -const STG_PAIR* stgAuthenticateImpl(const char* userName, const char* serviceType) +STG_RESULT stgRequest(STG_CLIENT::TYPE type, const char* userName, const char* password, const STG_PAIR* pairs) { STG_CLIENT* client = STG_CLIENT::get(); if (client == NULL) { // TODO: log "Not configured" - return NULL; + return emptyResult(); } - return toPairs(client->authenticate(userName, serviceType)); + try { + return toResult(client->request(type, toString(userName), toString(password), fromSTGPairs(pairs))); + } catch (const STG_CLIENT::Error& ex) { + // TODO: log error + return emptyResult(); + } +} + } -const STG_PAIR* stgPostAuthImpl(const char* userName, const char* serviceType) +int stgInstantiateImpl(const char* address) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->postAuth(userName, serviceType)); + if (STG_CLIENT::configure(toString(address))) + return 1; + + return 0; } -const STG_PAIR* stgPreAcctImpl(const char* userName, const char* serviceType) +STG_RESULT stgAuthorizeImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->preAcct(userName, serviceType)); + return stgRequest(STG_CLIENT::AUTHORIZE, userName, password, pairs); } -const STG_PAIR* stgAccountingImpl(const char* userName, const char* serviceType, const char* statusType, const char* sessionId) +STG_RESULT stgAuthenticateImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - STG_CLIENT* client = STG_CLIENT::get(); - if (client == NULL) { - // TODO: log "Not configured" - return NULL; - } - return toPairs(client->account(userName, serviceType, statusType, sessionId)); + return stgRequest(STG_CLIENT::AUTHENTICATE, userName, password, pairs); } -int countValuePairs(const VALUE_PAIR* pairs) +STG_RESULT stgPostAuthImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - unsigned count = 0; - while (pairs != NULL) { - ++count; - pairs = pairs->next; - } - return count; + return stgRequest(STG_CLIENT::POST_AUTH, userName, password, pairs); } -STG_PAIR* fromValuePairs(const VALUE_PAIR* pairs) +STG_RESULT stgPreAcctImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - unsigned size = countValuePairs(pairs); - STG_PAIR* res = new STG_PAIR[size + 1]; - size_t pos = 0; - while (pairs != NULL) { - bzero(res[pos].key, sizeof(STG_PAIR::key)); - bzero(res[pos].value, sizeof(STG_PAIR::value)); - strncpy(res[pos].key, pairs->name, sizeof(STG_PAIR::key)); - strncpy(res[pos].value, pairs->data.strvalue, sizeof(STG_PAIR::value)); - ++pos; - pairs = pairs->next; - } - bzero(res[pos].key, sizeof(STG_PAIR::key)); - bzero(res[pos].value, sizeof(STG_PAIR::value)); - return res; + return stgRequest(STG_CLIENT::PRE_ACCT, userName, password, pairs); } -void deletePairs(const STG_PAIR* pairs) +STG_RESULT stgAccountingImpl(const char* userName, const char* password, const STG_PAIR* pairs) { - delete[] pairs; + return stgRequest(STG_CLIENT::ACCOUNT, userName, password, pairs); } diff --git a/projects/rlm_stg/iface.h b/projects/rlm_stg/iface.h index e4504b6c..e863e939 100644 --- a/projects/rlm_stg/iface.h +++ b/projects/rlm_stg/iface.h @@ -9,16 +9,12 @@ extern "C" { #endif -int stgInstantiateImpl(const char* server, uint16_t port, const char* password); -const STG_PAIR* stgAuthorizeImpl(const char* userName, const char* serviceType); -const STG_PAIR* stgAuthenticateImpl(const char* userName, const char* serviceType); -const STG_PAIR* stgPostAuthImpl(const char* userName, const char* serviceType); -const STG_PAIR* stgPreAcctImpl(const char* userName, const char* serviceType); -const STG_PAIR* stgAccountingImpl(const char* userName, const char* serviceType, const char* statusType, const char* sessionId); - -void deletePairs(const STG_PAIR* pairs); -STG_PAIR* fromValuePairs(const VALUE_PAIR* pairs); -int countValuePairs(const VALUE_PAIR* pairs); +int stgInstantiateImpl(const char* address); +STG_RESULT stgAuthorizeImpl(const char* userName, const char* password, const STG_PAIR* vps); +STG_RESULT stgAuthenticateImpl(const char* userName, const char* password, const STG_PAIR* vps); +STG_RESULT stgPostAuthImpl(const char* userName, const char* password, const STG_PAIR* vps); +STG_RESULT stgPreAcctImpl(const char* userName, const char* password, const STG_PAIR* vps); +STG_RESULT stgAccountingImpl(const char* userName, const char* password, const STG_PAIR* vps); #ifdef __cplusplus } diff --git a/projects/rlm_stg/rlm_stg.c b/projects/rlm_stg/rlm_stg.c index 3c6e9c9b..0333fadc 100644 --- a/projects/rlm_stg/rlm_stg.c +++ b/projects/rlm_stg/rlm_stg.c @@ -26,6 +26,9 @@ * */ +#include "iface.h" +#include "stgpair.h" + #ifndef NDEBUG #define NDEBUG #include @@ -34,23 +37,80 @@ #undef NDEBUG #endif -#include "iface.h" -#include "stgpair.h" +#include // size_t typedef struct rlm_stg_t { - char* server; - uint16_t port; - char* password; + char* address; } rlm_stg_t; static const CONF_PARSER module_config[] = { - { "server", PW_TYPE_STRING_PTR, offsetof(rlm_stg_t,server), NULL, "localhost"}, - { "port", PW_TYPE_INTEGER, offsetof(rlm_stg_t,port), NULL, "9091" }, - { "password", PW_TYPE_STRING_PTR, offsetof(rlm_stg_t,password), NULL, "123456"}, + { "address", PW_TYPE_STRING_PTR, offsetof(rlm_stg_t, address), NULL, "unix:/var/run/stg.sock"}, { NULL, -1, 0, NULL, NULL } /* end the list */ }; +static void deletePairs(STG_PAIR* pairs) +{ + free(pairs); +} + +static size_t toVPS(const STG_PAIR* pairs, VALUE_PAIR* vps) +{ + const STG_PAIR* pair = pairs; + size_t count = 0; + + while (!emptyPair(pair)) { + VALUE_PAIR* vp = pairmake(pair->key, pair->value, T_OP_SET); + pairadd(&vps, vp); + DEBUG("Adding pair '%s': '%s'", pair->key, pair->value); + ++pair; + ++count; + } + + return count; +} + +static size_t toReply(STG_RESULT result, REQUEST* request) +{ + size_t count = 0; + + count += toVPS(result.modify, request->config_items); + count += toVPS(result.reply, request->reply->vps); + + deletePairs(result.modify); + deletePairs(result.reply); + + return count; +} + +static int countVPS(const VALUE_PAIR* pairs) +{ + unsigned count = 0; + while (pairs != NULL) { + ++count; + pairs = pairs->next; + } + return count; +} + +static STG_PAIR* fromVPS(const VALUE_PAIR* pairs) +{ + unsigned size = countVPS(pairs); + STG_PAIR* res = (STG_PAIR*)malloc(sizeof(STG_PAIR) * (size + 1)); + size_t pos = 0; + while (pairs != NULL) { + bzero(res[pos].key, sizeof(res[0].key)); + bzero(res[pos].value, sizeof(res[0].value)); + strncpy(res[pos].key, pairs->name, sizeof(res[0].key)); + strncpy(res[pos].value, pairs->data.strvalue, sizeof(res[0].value)); + ++pos; + pairs = pairs->next; + } + bzero(res[pos].key, sizeof(res[0].key)); + bzero(res[pos].value, sizeof(res[0].value)); + return res; +} + /* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections @@ -83,7 +143,7 @@ static int stg_instantiate(CONF_SECTION* conf, void** instance) return -1; } - if (!stgInstantiateImpl(data->server, data->port)) { + if (!stgInstantiateImpl(data->address)) { free(data); return -1; } @@ -99,10 +159,10 @@ static int stg_instantiate(CONF_SECTION* conf, void** instance) * from the database. The authentication code only needs to check * the password, the rest is done here. */ -static int stg_authorize(void*, REQUEST* request) +static int stg_authorize(void* instance, REQUEST* request) { - const STG_PAIR* pairs; - const STG_PAIR* pair; + STG_RESULT result; + STG_PAIR* pairs = fromVPS(request->packet->vps); size_t count = 0; const char* username = NULL; const char* password = NULL; @@ -121,22 +181,15 @@ static int stg_authorize(void*, REQUEST* request) DEBUG("rlm_stg: stg_authorize() request password field: '%s'", password); } - pairs = stgAuthorizeImpl(username, password, request->packet->vps); + result = stgAuthorizeImpl(username, password, pairs); + deletePairs(pairs); - if (!pairs) { + if (!result.modify && !result.reply) { DEBUG("rlm_stg: stg_authorize() failed."); return RLM_MODULE_REJECT; } - pair = pairs; - while (!emptyPair(pair)) { - VALUE_PAIR* vp = pairmake(pair->key, pair->value, T_OP_SET); - pairadd(&request->config_items, vp); - DEBUG("Adding pair '%s': '%s'", pair->key, pair->value); - ++pair; - ++count; - } - deletePairs(pairs); + count = toReply(result, request); if (count) return RLM_MODULE_UPDATED; @@ -147,10 +200,10 @@ static int stg_authorize(void*, REQUEST* request) /* * Authenticate the user with the given password. */ -static int stg_authenticate(void*, REQUEST* request) +static int stg_authenticate(void* instance, REQUEST* request) { - const STG_PAIR* pairs; - const STG_PAIR* pair; + STG_RESULT result; + STG_PAIR* pairs = fromVPS(request->packet->vps); size_t count = 0; const char* username = NULL; const char* password = NULL; @@ -169,21 +222,15 @@ static int stg_authenticate(void*, REQUEST* request) DEBUG("rlm_stg: stg_authenticate() request password field: '%s'", password); } - pairs = stgAuthenticateImpl(username, password, request->packet->vps); + result = stgAuthenticateImpl(username, password, pairs); + deletePairs(pairs); - if (!pairs) { + if (!result.modify && !result.reply) { DEBUG("rlm_stg: stg_authenticate() failed."); return RLM_MODULE_REJECT; } - pair = pairs; - while (!emptyPair(pair)) { - VALUE_PAIR* vp = pairmake(pair->key, pair->value, T_OP_SET); - pairadd(&request->reply->vps, vp); - ++pair; - ++count; - } - deletePairs(pairs); + count = toReply(result, request); if (count) return RLM_MODULE_UPDATED; @@ -194,10 +241,10 @@ static int stg_authenticate(void*, REQUEST* request) /* * Massage the request before recording it or proxying it */ -static int stg_preacct(void*, REQUEST*) +static int stg_preacct(void* instance, REQUEST* request) { - const STG_PAIR* pairs; - const STG_PAIR* pair; + STG_RESULT result; + STG_PAIR* pairs = fromVPS(request->packet->vps); size_t count = 0; const char* username = NULL; const char* password = NULL; @@ -216,21 +263,15 @@ static int stg_preacct(void*, REQUEST*) DEBUG("rlm_stg: stg_preacct() request password field: '%s'", password); } - pairs = stgPreAcctImpl(username, password, request->packet->vps); + result = stgPreAcctImpl(username, password, pairs); + deletePairs(pairs); - if (!pairs) { + if (!result.modify && !result.reply) { DEBUG("rlm_stg: stg_preacct() failed."); return RLM_MODULE_REJECT; } - pair = pairs; - while (!emptyPair(pair)) { - VALUE_PAIR* vp = pairmake(pair->key, pair->value, T_OP_SET); - pairadd(&request->reply->vps, vp); - ++pair; - ++count; - } - deletePairs(pairs); + count = toReply(result, request); if (count) return RLM_MODULE_UPDATED; @@ -241,51 +282,37 @@ static int stg_preacct(void*, REQUEST*) /* * Write accounting information to this modules database. */ -static int stg_accounting(void*, REQUEST* request) +static int stg_accounting(void* instance, REQUEST* request) { - const STG_PAIR* pairs; - const STG_PAIR* pair; + STG_RESULT result; + STG_PAIR* pairs = fromVPS(request->packet->vps); size_t count = 0; - - instance = instance; + const char* username = NULL; + const char* password = NULL; DEBUG("rlm_stg: stg_accounting()"); - VALUE_PAIR* svc = pairfind(request->packet->vps, PW_SERVICE_TYPE); - VALUE_PAIR* sessid = pairfind(request->packet->vps, PW_ACCT_SESSION_ID); - VALUE_PAIR* sttype = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE); + instance = instance; - if (!sessid) { - DEBUG("rlm_stg: stg_accounting() Acct-Session-ID undefined"); - return RLM_MODULE_FAIL; + if (request->username) { + username = request->username->data.strvalue; + DEBUG("rlm_stg: stg_accounting() request username field: '%s'", username); } - if (sttype) { - DEBUG("Acct-Status-Type := %s", sttype->data.strvalue); - if (svc) { - DEBUG("rlm_stg: stg_accounting() Service-Type defined as '%s'", svc->data.strvalue); - pairs = stgAccountingImpl((const char*)request->username->data.strvalue, (const char*)svc->data.strvalue, (const char*)sttype->data.strvalue, (const char*)sessid->data.strvalue); - } else { - DEBUG("rlm_stg: stg_accounting() Service-Type undefined"); - pairs = stgAccountingImpl((const char*)request->username->data.strvalue, "", (const char*)sttype->data.strvalue, (const char*)sessid->data.strvalue); - } - } else { - DEBUG("rlm_stg: stg_accounting() Acct-Status-Type := NULL"); - return RLM_MODULE_OK; + if (request->password) { + password = request->password->data.strvalue; + DEBUG("rlm_stg: stg_accounting() request password field: '%s'", password); } - if (!pairs) { + + result = stgAccountingImpl(username, password, pairs); + deletePairs(pairs); + + if (!result.modify && !result.reply) { DEBUG("rlm_stg: stg_accounting() failed."); return RLM_MODULE_REJECT; } - pair = pairs; - while (!emptyPair(pair)) { - VALUE_PAIR* pwd = pairmake(pair->key, pair->value, T_OP_SET); - pairadd(&request->reply->vps, pwd); - ++pair; - ++count; - } - deletePairs(pairs); + count = toReply(result, request); if (count) return RLM_MODULE_UPDATED; @@ -303,7 +330,7 @@ static int stg_accounting(void*, REQUEST* request) * max. number of logins, do a second pass and validate all * logins by querying the terminal server (using eg. SNMP). */ -static int stg_checksimul(void*, REQUEST* request) +static int stg_checksimul(void* instance, REQUEST* request) { DEBUG("rlm_stg: stg_checksimul()"); @@ -314,38 +341,37 @@ static int stg_checksimul(void*, REQUEST* request) return RLM_MODULE_OK; } -static int stg_postauth(void*, REQUEST* request) +static int stg_postauth(void* instance, REQUEST* request) { - const STG_PAIR* pairs; - const STG_PAIR* pair; + STG_RESULT result; + STG_PAIR* pairs = fromVPS(request->packet->vps); size_t count = 0; - - instance = instance; + const char* username = NULL; + const char* password = NULL; DEBUG("rlm_stg: stg_postauth()"); - VALUE_PAIR* svc = pairfind(request->packet->vps, PW_SERVICE_TYPE); + instance = instance; - if (svc) { - DEBUG("rlm_stg: stg_postauth() Service-Type defined as '%s'", svc->data.strvalue); - pairs = stgPostAuthImpl((const char*)request->username->data.strvalue, (const char*)svc->data.strvalue); - } else { - DEBUG("rlm_stg: stg_postauth() Service-Type undefined"); - pairs = stgPostAuthImpl((const char*)request->username->data.strvalue, ""); + if (request->username) { + username = request->username->data.strvalue; + DEBUG("rlm_stg: stg_postauth() request username field: '%s'", username); } - if (!pairs) { + + if (request->password) { + password = request->password->data.strvalue; + DEBUG("rlm_stg: stg_postauth() request password field: '%s'", password); + } + + result = stgPostAuthImpl(username, password, pairs); + deletePairs(pairs); + + if (!result.modify && !result.reply) { DEBUG("rlm_stg: stg_postauth() failed."); return RLM_MODULE_REJECT; } - pair = pairs; - while (!emptyPair(pair)) { - VALUE_PAIR* pwd = pairmake(pair->key, pair->value, T_OP_SET); - pairadd(&request->reply->vps, pwd); - ++pair; - ++count; - } - deletePairs(pairs); + count = toReply(result, request); if (count) return RLM_MODULE_UPDATED; @@ -355,7 +381,7 @@ static int stg_postauth(void*, REQUEST* request) static int stg_detach(void* instance) { - free(((struct rlm_stg_t*)instance)->server); + free(((struct rlm_stg_t*)instance)->address); free(instance); return 0; } @@ -381,8 +407,8 @@ module_t rlm_stg = { stg_preacct, /* preaccounting */ stg_accounting, /* accounting */ stg_checksimul, /* checksimul */ - stg_pre_proxy, /* pre-proxy */ - stg_post_proxy, /* post-proxy */ + NULL, /* pre-proxy */ + NULL, /* post-proxy */ stg_postauth /* post-auth */ }, }; diff --git a/projects/rlm_stg/stg_client.cpp b/projects/rlm_stg/stg_client.cpp index c04f177d..199aca90 100644 --- a/projects/rlm_stg/stg_client.cpp +++ b/projects/rlm_stg/stg_client.cpp @@ -18,279 +18,146 @@ * Author : Maxim Mamontov */ -/* - * Realization of data access via Stargazer for RADIUS - * - * $Revision: 1.8 $ - * $Date: 2010/04/16 12:30:02 $ - * - */ - -#include -#include -#include // close +#include "stg_client.h" -#include -#include -#include -#include +#include "stg/common.h" #include -#include "stg_client.h" - namespace { STG_CLIENT* stgClient = NULL; -} - -//----------------------------------------------------------------------------- - -STG_CLIENT::STG_CLIENT(const std::string & host, uint16_t port, uint16_t lp, const std::string & pass) - : password(pass), - framedIP(0) -{ -/*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); - } - -struct hostent * he = NULL; -he = gethostbyname(host.c_str()); -if (he == NULL) - { - throw std::runtime_error("gethostbyname error"); - } - -outerAddr.sin_family = AF_INET; -outerAddr.sin_port = htons(port); -outerAddr.sin_addr.s_addr = *(uint32_t *)he->h_addr; - -InitEncrypt(&ctx, password); - -PrepareNet();*/ -} - -STG_CLIENT::~STG_CLIENT() +unsigned fromType(STG_CLIENT::TYPE type) { -/*close(sock);*/ + return static_cast(type); } -int STG_CLIENT::PrepareNet() +STG::SGCP::TransportType toTransport(const std::string& value) { -return 0; + 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'."); } -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) +ChannelConfig::ChannelConfig(std::string addr) + : transport(STG::SGCP::TCP) { -/*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) - { - errorStr = "Error receiving data"; - return -1; + // unix:pass@/var/run/stg.sock + // tcp:secret@192.168.0.1:12345 + // udp:key@isp.com.ua:54321 + + 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."); } - -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)) + if (transport == STG::SGCP::UNIX) { - errorStr = "Magic invalid. Wanted: '"; - errorStr += RAD_ID; - errorStr += "', got: '"; - errorStr += (char *)packet->magic; - errorStr += "'"; - return -1; + address = addr; + return; } - -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."); } -//----------------------------------------------------------------------------- - -const STG_PAIRS * STG_CLIENT::Authorize(const PAIRS& pairs) +STG_CLIENT::STG_CLIENT(const std::string& address) + : m_config(address), + m_proto(m_config.transport, m_config.key) { -/*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;*/ - -PAIRS pairs; -pairs.push_back(std::make_pair("Cleartext-Password", userPassword)); - -return ToSTGPairs(pairs); + try { + m_proto.connect(m_config.address, m_config.port); + } catch (const STG::SGCP::Proto::Error& ex) { + throw Error(ex.what()); + } } -const STG_PAIRS * STG_CLIENT::Authenticate(const PAIRS& pairs) +STG_CLIENT::~STG_CLIENT() { -/*RAD_PACKET packet; - -userPassword = ""; - -if (Request(&packet, login, svc, RAD_AUTH_PACKET)) - return -1; - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1;*/ - -PAIRS pairs; - -return ToSTGPairs(pairs); } -const STG_PAIRS * STG_CLIENT::PostAuth(const PAIRS& pairs) +RESULT STG_CLIENT::request(TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) { -/*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;*/ - -PAIRS pairs; -pairs.push_back(std::make_pair("Framed-IP-Address", inet_ntostring(framedIP))); - -return ToSTGPairs(pairs); + m_writeHeader(type, userName, password); + m_writePairBlock(pairs); + RESULT result; + result.modify = m_readPairBlock(); + result.reply = m_readPairBlock(); + return result; } -const STG_PAIRS * STG_CLIENT::PreAcct(const PAIRS& pairs) +STG_CLIENT* STG_CLIENT::get() { -PAIRS pairs; - -return ToSTGPairs(pairs); + return stgClient; } -const STG_PAIRS * STG_CLIENT::Account(const PAIRS& pairs) +bool STG_CLIENT::configure(const std::string& address) { -/*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; + if ( stgClient != NULL ) + delete stgClient; + try { + stgClient = new STG_CLIENT(address); + return true; + } catch (const ChannelConfig::Error& ex) { + // TODO: Log it } - -if (packet.packetType != RAD_ACCEPT_PACKET) - return -1;*/ - -PAIRS pairs; - -return ToSTGPairs(pairs); + return false; } -//----------------------------------------------------------------------------- - -std::string STG_CLIENT_ST::m_host; -uint16_t STG_CLIENT_ST::m_port(6666); -std::string STG_CLIENT_ST::m_password; - -//----------------------------------------------------------------------------- - -STG_CLIENT* STG_CLIENT::get() +void STG_CLIENT::m_writeHeader(TYPE type, const std::string& userName, const std::string& password) { - return stgClient; + 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()); + } } -void STG_CLIENT::configure(const std::string& server, uint16_t port, const std::string& password) +void STG_CLIENT::m_writePairBlock(const PAIRS& pairs) { - if ( stgClient != NULL ) - delete stgClient; - stgClient = new STG_CLIENT(server, port, password); + 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()); + } } -//----------------------------------------------------------------------------- - -const STG_PAIR * ToSTGPairs(const PAIRS & source) +PAIRS STG_CLIENT::m_readPairBlock() { - STG_PAIR * pairs = new STG_PAIR[source.size() + 1]; - for (size_t pos = 0; pos < source.size(); ++pos) { - bzero(pairs[pos].key, sizeof(STG_PAIR::key)); - bzero(pairs[pos].value, sizeof(STG_PAIR::value)); - strncpy(pairs[pos].key, source[pos].first.c_str(), sizeof(STG_PAIR::key)); - strncpy(pairs[pos].value, source[pos].second.c_str(), sizeof(STG_PAIR::value)); - ++pos; + 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()); } - bzero(pairs[sources.size()].key, sizeof(STG_PAIR::key)); - bzero(pairs[sources.size()].value, sizeof(STG_PAIR::value)); - - return pairs; } diff --git a/projects/rlm_stg/stg_client.h b/projects/rlm_stg/stg_client.h index 680d0883..6315a0a5 100644 --- a/projects/rlm_stg/stg_client.h +++ b/projects/rlm_stg/stg_client.h @@ -18,44 +18,67 @@ * Author : Maxim Mamontov */ -/* - * Header file for client part of data access via Stargazer for RADIUS - * - * $Revision: 1.4 $ - * $Date: 2010/04/16 12:30:02 $ - * - */ - #ifndef STG_CLIENT_H #define STG_CLIENT_H +#include "stg/sgcp_proto.h" // Proto +#include "stg/sgcp_types.h" // TransportType +#include "stg/os_int.h" + #include +#include +#include -#include -#include -#include // socklen_t +typedef std::vector > PAIRS; -#include "stg/blowfish.h" -#include "stg/rad_packets.h" +struct RESULT +{ + PAIRS modify; + PAIRS reply; +}; -typedef std::vector > PAIRS; +struct ChannelConfig { + struct Error : std::runtime_error { + Error(const std::string& message) : runtime_error(message) {} + }; + + ChannelConfig(std::string address); + + STG::SGCP::TransportType transport; + std::string key; + std::string address; + uint16_t port; +}; class STG_CLIENT { public: - STG_CLIENT(const std::string & host, uint16_t port, const std::string & password); + enum TYPE { + AUTHORIZE, + AUTHENTICATE, + POST_AUTH, + PRE_ACCT, + ACCOUNT + }; + struct Error : std::runtime_error { + Error(const std::string& message) : runtime_error(message) {} + }; + + STG_CLIENT(const std::string& address); ~STG_CLIENT(); static STG_CLIENT* get(); - static void configure(const std::string& server, uint16_t port, const std::string& password); + static bool configure(const std::string& address); - PAIRS authorize(const PAIRS& pairs); - PAIRS authenticate(const PAIRS& pairs); - PAIRS postAuth(const PAIRS& pairs); - PAIRS preAcct(const PAIRS& pairs); - PAIRS account(const PAIRS& pairs); + RESULT request(TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); private: + ChannelConfig m_config; + STG::SGCP::Proto m_proto; + + void m_writeHeader(TYPE type, const std::string& userName, const std::string& password); + void m_writePairBlock(const PAIRS& source); + PAIRS m_readPairBlock(); }; #endif diff --git a/projects/rlm_stg/stgpair.c b/projects/rlm_stg/stgpair.c deleted file mode 100644 index 2dfb59d6..00000000 --- a/projects/rlm_stg/stgpair.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "stgpair.h" - -int emptyPair(const STG_PAIR* pair) -{ - return pair != NULL && pair->key[0] != '\0' && pair->value[0] != '\0'; -} diff --git a/projects/rlm_stg/stgpair.h b/projects/rlm_stg/stgpair.h index 046d06bf..dba9e3eb 100644 --- a/projects/rlm_stg/stgpair.h +++ b/projects/rlm_stg/stgpair.h @@ -1,16 +1,33 @@ #ifndef __STG_STGPAIR_H__ #define __STG_STGPAIR_H__ -#include // VALUE_PAIR +#include #define STGPAIR_KEYLENGTH 64 #define STGPAIR_VALUELENGTH 256 +#ifdef __cplusplus +extern "C" { +#endif + typedef struct STG_PAIR { char key[STGPAIR_KEYLENGTH]; char value[STGPAIR_VALUELENGTH]; } STG_PAIR; -int emptyPair(const STG_PAIR* pair); +typedef struct STG_RESULT { + STG_PAIR* modify; + STG_PAIR* reply; +} STG_RESULT; + +inline +int emptyPair(const STG_PAIR* pair) +{ + return pair != NULL && pair->key[0] != '\0' && pair->value[0] != '\0'; +} + +#ifdef __cplusplus +} +#endif #endif diff --git a/stglibs/common.lib/Makefile b/stglibs/common.lib/Makefile index 0ef14dea..33f29440 100644 --- a/stglibs/common.lib/Makefile +++ b/stglibs/common.lib/Makefile @@ -7,9 +7,11 @@ include ../../Makefile.conf LIB_NAME = stgcommon SRCS = common.cpp \ - strptime.cpp + strptime.cpp \ + blockio.cpp -INCS = common.h +INCS = common.h \ + blockio.h ifneq ($(OS),linux) LIBS += -liconv