]> git.stg.codes - stg.git/commitdiff
Final icing on rlm_stg.
authorMaxim Mamontov <faust.madf@gmail.com>
Tue, 14 Apr 2015 19:18:01 +0000 (22:18 +0300)
committerMaxim Mamontov <faust.madf@gmail.com>
Tue, 14 Apr 2015 19:18:01 +0000 (22:18 +0300)
projects/rlm_stg/Makefile
projects/rlm_stg/build
projects/rlm_stg/iface.cpp
projects/rlm_stg/iface.h
projects/rlm_stg/rlm_stg.c
projects/rlm_stg/stg_client.cpp
projects/rlm_stg/stg_client.h
projects/rlm_stg/stgpair.c [deleted file]
projects/rlm_stg/stgpair.h
stglibs/common.lib/Makefile

index efc1bcaa9f38ad657030b4c7aa74103c9d45395c..1280bd9134e809d3c5f5e061811f3f8fae7e1f73 100644 (file)
@@ -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)
index 433cd04fc0ff97e4182beab41996782c0cead587..e9be4ed0f86562b891a840d4996618f966d8a434 100755 (executable)
@@ -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
index 40a96f729490f75b0bdaaa9c1ddf748e78ab57c6..485e9ef7439d9b3d1d5854e0a38429b8c6df472c 100644 (file)
@@ -2,10 +2,14 @@
 
 #include "stg_client.h"
 
+#include <cstring>
+
+#include <strings.h>
+
 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<std::string, std::string>(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);
 }
index e4504b6c1337ce3b0ee0e2376633e7f51cc0ca80..e863e939ce650d525c85bddf527138bd36f1b32f 100644 (file)
@@ -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
 }
index 3c6e9c9b3b16210c34c10d1661815b529c45ba01..0333fadc55304795cbf2b3475895d6e5979a88ae 100644 (file)
@@ -26,6 +26,9 @@
  *
  */
 
+#include "iface.h"
+#include "stgpair.h"
+
 #ifndef NDEBUG
 #define NDEBUG
 #include <freeradius/ident.h>
 #undef NDEBUG
 #endif
 
-#include "iface.h"
-#include "stgpair.h"
+#include <stddef.h> // 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 */
     },
 };
index c04f177dea4a043de30d6d59651c6386fc5b5ff1..199aca905df76b3c5ba703fa21b35d7f42b907e1 100644 (file)
  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
  */
 
-/*
- *  Realization of data access via Stargazer for RADIUS
- *
- *  $Revision: 1.8 $
- *  $Date: 2010/04/16 12:30:02 $
- *
- */
-
-#include <netdb.h>
-#include <sys/types.h>
-#include <unistd.h> // close
+#include "stg_client.h"
 
-#include <cerrno>
-#include <cstring>
-#include <vector>
-#include <utility>
+#include "stg/common.h"
 
 #include <stdexcept>
 
-#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<unsigned>(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<struct sockaddr *>(&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<uint64_t>(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<uint64_t>(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<uint64_t>();
+        if (count == 0)
+            return PAIRS();
+        PAIRS res(count);
+        for (size_t i = 0; i < count; ++i) {
+            res[i].first = m_proto.readAll<std::string>();
+            res[i].second = m_proto.readAll<std::string>();
+        }
+        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;
 }
index 680d088387907fede8851bde53e843642db9ef96..6315a0a5dc3d18ee2dda1a7256cf3b104c3ffe6d 100644 (file)
  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
  */
 
-/*
- *  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 <string>
+#include <vector>
+#include <utility>
 
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h> // socklen_t
+typedef std::vector<std::pair<std::string, std::string> > PAIRS;
 
-#include "stg/blowfish.h"
-#include "stg/rad_packets.h"
+struct RESULT
+{
+    PAIRS modify;
+    PAIRS reply;
+};
 
-typedef std::vector<std::pair<std::string, std::string> > 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 (file)
index 2dfb59d..0000000
+++ /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';
-}
index 046d06bfc2a71b7a62fea503c0eb815ad4b9c2c7..dba9e3eb4b5af5c1643337423f54c0392f8a3499 100644 (file)
@@ -1,16 +1,33 @@
 #ifndef __STG_STGPAIR_H__
 #define __STG_STGPAIR_H__
 
-#include <freeradius/libradius.h> // VALUE_PAIR
+#include <stddef.h>
 
 #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
index 0ef14dea0a8af4f700317e1a2d0dad97b69972a8..33f29440463ef847f362e1fa703980d43ea2e9ba 100644 (file)
@@ -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