summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/conf.c104
-rw-r--r--lib/err.c45
-rw-r--r--lib/examples/Makefile4
-rw-r--r--lib/examples/client-blocking.c29
-rw-r--r--lib/examples/client.conf10
-rw-r--r--lib/include/radsec/radsec-impl.h8
-rw-r--r--lib/include/radsec/radsec.h3
-rw-r--r--lib/radsec.c70
8 files changed, 211 insertions, 62 deletions
diff --git a/lib/conf.c b/lib/conf.c
new file mode 100644
index 0000000..9acf4d4
--- /dev/null
+++ b/lib/conf.c
@@ -0,0 +1,104 @@
+#include <confuse.h>
+#include <string.h>
+#include <radsec/radsec.h>
+#include <radsec/radsec-impl.h>
+
+#if 0
+ realm NAME {
+ type = STRING
+ server {
+ hostname = STRING
+ service = STRING
+ secret = STRING
+ timeout = INT /* optional */
+ tries = INT /* optional */
+ }
+ }
+#endif
+
+int
+rs_context_read_config(struct rs_handle *ctx, const char *config_file)
+{
+#warning "Missing some error handling in rs_context_config_read()"
+ cfg_opt_t server_opts[] =
+ {
+ CFG_STR ("hostname", NULL, CFGF_NONE),
+ CFG_STR ("service", "radius", CFGF_NONE),
+ CFG_STR ("secret", NULL, CFGF_NONE),
+ CFG_INT ("timeout", 3, CFGF_NONE),
+ CFG_INT ("tries", 1, CFGF_NONE),
+ CFG_END ()
+ };
+ cfg_opt_t realm_opts[] =
+ {
+ CFG_STR ("type", "UDP", CFGF_NONE),
+ CFG_SEC ("server", server_opts, CFGF_MULTI),
+ CFG_END ()
+ };
+ cfg_opt_t opts[] =
+ {
+ CFG_SEC ("realm", realm_opts, CFGF_TITLE | CFGF_MULTI),
+ CFG_END ()
+ };
+ cfg_t *cfg, *cfg_realm, *cfg_server;
+ int i, j;
+
+ cfg = cfg_init (opts, CFGF_NONE);
+ if (cfg_parse (cfg, config_file) == CFG_PARSE_ERROR)
+ return rs_err_ctx_push (ctx, RSE_CONFIG, "%s: invalid configuration file",
+ config_file);
+ for (i = 0; i < cfg_size (cfg, "realm"); i++)
+ {
+ struct rs_realm *r = rs_malloc (ctx, sizeof(*r));
+ const char *typestr;
+ enum rs_conn_type type;
+
+ if (!r)
+ return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
+ memset (r, 0, sizeof(*r));
+ if (ctx->realms)
+ ctx->realms->next = r;
+ else
+ ctx->realms = r;
+ cfg_realm = cfg_getnsec (cfg, "realm", i);
+ r->name = strdup (cfg_title (cfg_realm));
+ typestr = cfg_getstr (cfg_realm, "type");
+ if (!strcmp (typestr, "UDP"))
+ type = RS_CONN_TYPE_UDP;
+ else if (!strcmp (typestr, "TCP"))
+ type = RS_CONN_TYPE_TCP;
+ else if (!strcmp (typestr, "TLS"))
+ type = RS_CONN_TYPE_TLS;
+ else if (!strcmp (typestr, "DTLS"))
+ type = RS_CONN_TYPE_DTLS;
+ else
+ return rs_err_ctx_push_fl (ctx, RSE_CONFIG, __FILE__, __LINE__,
+ "%s: invalid connection type", typestr);
+ for (j = 0; j < cfg_size (cfg_realm, "server"); j++)
+ {
+ struct rs_peer *p = _rs_peer_create (ctx, &r->peers);
+ if (!p)
+ return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
+ NULL);
+
+ cfg_server = cfg_getnsec (cfg_realm, "server", j);
+ _rs_resolv (&p->addr, type, cfg_getstr (cfg_server, "hostname"),
+ cfg_getstr (cfg_server, "service"));
+ p->secret = strdup (cfg_getstr (cfg_server, "secret"));
+ p->timeout = cfg_getint (cfg_server, "timeout");
+ p->tries = cfg_getint (cfg_server, "tries");
+ }
+ }
+ return RSE_OK;
+}
+
+struct rs_realm
+*rs_conf_find_realm(struct rs_handle *ctx, const char *name)
+{
+ struct rs_realm *r;
+
+ for (r = ctx->realms; r; r = r->next)
+ if (!strcmp (r->name, name))
+ return r;
+ return NULL;
+}
diff --git a/lib/err.c b/lib/err.c
index 00de47f..71a8380 100644
--- a/lib/err.c
+++ b/lib/err.c
@@ -18,22 +18,23 @@ const char *_errtxt[] = {
"no peer configured" /* 8 RSE_NOPEER */
"libevent error" /* 9 RSE_EVENT */
"connection error" /* 10 RSE_CONNERR */
- "ERR 11" /* RSE_ */
+ "invalid configuration file" /* 11 RSE_CONFIG */
"ERR 12" /* RSE_ */
"ERR 13" /* RSE_ */
- "ERR " /* RSE_ */
- "ERR " /* RSE_ */
- "ERR " /* RSE_ */
- "ERR " /* RSE_ */
- "ERR " /* RSE_ */
- "ERR " /* RSE_ */
- "ERR " /* RSE_ */
+ "ERR 14" /* RSE_ */
+ "ERR 15" /* RSE_ */
+ "ERR 16" /* RSE_ */
+ "ERR 17" /* RSE_ */
+ "ERR 18" /* RSE_ */
+ "ERR 19" /* RSE_ */
+ "ERR 20" /* RSE_ */
"some error" /* 21 RSE_SOME_ERROR */
};
#define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
static struct rs_error *
-_err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args)
+_err_vcreate (unsigned int code, const char *file, int line, const char *fmt,
+ va_list args)
{
struct rs_error *err;
@@ -64,10 +65,23 @@ _err_new (unsigned int code, const char *file, int line, const char *fmt, va_lis
return err;
}
+struct rs_error *
+_rs_err_create (unsigned int code, const char *file, int line, const char *fmt,
+ ...)
+{
+ struct rs_error *err;
+
+ va_list args;
+ va_start (args, fmt);
+ err = _err_vcreate (code, file, line, fmt, args);
+ va_end (args);
+ return err;
+}
+
static int
_ctx_err_vpush_fl (struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, va_list args)
{
- struct rs_error *err = _err_new (code, file, line, fmt, args);
+ struct rs_error *err = _err_vcreate (code, file, line, fmt, args);
if (err)
ctx->err = err;
@@ -94,13 +108,20 @@ rs_err_ctx_push_fl (struct rs_handle *ctx, int code, const char *file, int line,
return code;
}
+int
+_rs_err_conn_push_err (struct rs_connection *conn, struct rs_error *err)
+{
+ conn->err = err; /* FIXME: use a stack */
+ return err->code;
+}
+
static int
_conn_err_vpush_fl (struct rs_connection *conn, int code, const char *file, int line, const char *fmt, va_list args)
{
- struct rs_error *err = _err_new (code, file, line, fmt, args);
+ struct rs_error *err = _err_vcreate (code, file, line, fmt, args);
if (err)
- conn->err = err;
+ _rs_err_conn_push_err (conn, err);
return code;
}
diff --git a/lib/examples/Makefile b/lib/examples/Makefile
index 4802c4b..cf3441b 100644
--- a/lib/examples/Makefile
+++ b/lib/examples/Makefile
@@ -1,6 +1,6 @@
SPECIAL =
#SPECIAL += -DUSE_REQUEST_OBJECT
-#SPECIAL += -DUSE_CONFIG_FILE
+SPECIAL += -DUSE_CONFIG_FILE
CFLAGS = -Wall -g -I ../include $(SPECIAL)
@@ -9,7 +9,7 @@ HFILES = ../include/radsec/radsec.h ../include/radsec/radsec-impl.h
all: client-blocking
client-blocking: client-blocking.c ../libradsec.a $(HFILES)
- $(CC) $(CFLAGS) -o $@ $< -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent_core
+ $(CC) $(CFLAGS) -o $@ $< -lconfuse -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent_core
clean:
-rm *.o *.gch client-blocking
diff --git a/lib/examples/client-blocking.c b/lib/examples/client-blocking.c
index 0e6ad39..8cd9968 100644
--- a/lib/examples/client-blocking.c
+++ b/lib/examples/client-blocking.c
@@ -20,7 +20,6 @@ blocking_client (const char *av1, const char *av2)
{
struct rs_handle *h;
struct rs_connection *conn;
- struct rs_peer *server;
struct rs_packet *req, *resp;
RADIUS_PACKET *fr_pkt;
VALUE_PAIR *fr_vp;
@@ -29,19 +28,23 @@ blocking_client (const char *av1, const char *av2)
return NULL;
#if !defined (USE_CONFIG_FILE)
- if (rs_conn_create (h, &conn, NULL))
- return rs_err_conn_pop (conn);
- rs_conn_set_type (conn, RS_CONN_TYPE_UDP);
- if (rs_server_create (conn, &server))
- return rs_err_conn_pop (conn);
- if (rs_server_set_address (server, av1, atoi (av2)))
- return rs_err_conn_pop (conn);
- rs_server_set_timeout (server, 1);
- rs_server_set_tries (server, 3);
- if (rs_server_set_secret (server, SECRET))
- return rs_err_conn_pop (conn);
+ {
+ struct rs_peer *server;
+
+ if (rs_conn_create (h, &conn, NULL))
+ return rs_err_conn_pop (conn);
+ rs_conn_set_type (conn, RS_CONN_TYPE_UDP);
+ if (rs_server_create (conn, &server))
+ return rs_err_conn_pop (conn);
+ if (rs_server_set_address (server, av1, av2))
+ return rs_err_conn_pop (conn);
+ rs_server_set_timeout (server, 1);
+ rs_server_set_tries (server, 3);
+ if (rs_server_set_secret (server, SECRET))
+ return rs_err_conn_pop (conn);
+ }
#else
- if (rs_context_config_read (h, av1))
+ if (rs_context_read_config (h, av1))
return rs_err_ctx_pop (h);
if (rs_conn_create (h, &conn, av2))
return rs_err_conn_pop (conn);
diff --git a/lib/examples/client.conf b/lib/examples/client.conf
new file mode 100644
index 0000000..5f9536f
--- /dev/null
+++ b/lib/examples/client.conf
@@ -0,0 +1,10 @@
+realm blocking {
+ type = "UDP"
+ server {
+ hostname = "localhost"
+ service = "1820"
+ secret = "sikrit"
+ timeout = 1 /* optional */
+ tries = 10 /* optional */
+ }
+}
diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h
index 503b2e5..9421fd6 100644
--- a/lib/include/radsec/radsec-impl.h
+++ b/lib/include/radsec/radsec-impl.h
@@ -46,6 +46,7 @@ struct rs_realm {
char *name;
enum rs_conn_type type;
struct rs_peer *peers;
+ struct rs_realm *next;
};
struct rs_handle {
@@ -79,6 +80,13 @@ struct rs_attr {
VALUE_PAIR *vp;
};
+/* Nonpublic functions. */
+struct rs_error *_rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type, const char *hostname, const char *service);
+struct rs_peer *_rs_peer_create (struct rs_handle *ctx, struct rs_peer **rootp);
+struct rs_error *_rs_err_create (unsigned int code, const char *file, int line, const char *fmt, ...);
+int _rs_err_conn_push_err (struct rs_connection *conn, struct rs_error *err);
+
+
/* Convenience macros. */
#define rs_calloc(h, nmemb, size) \
(h->alloc_scheme.calloc ? h->alloc_scheme.calloc : calloc)(nmemb, size)
diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h
index c108d8a..982c430 100644
--- a/lib/include/radsec/radsec.h
+++ b/lib/include/radsec/radsec.h
@@ -16,6 +16,7 @@ enum rs_err_code {
RSE_NOPEER = 8,
RSE_EVENT = 9,
RSE_CONNERR = 10,
+ RSE_CONFIG = 11,
RSE_SOME_ERROR = 21,
};
@@ -89,7 +90,7 @@ int rs_conn_receive_packet(struct rs_connection *conn, struct rs_packet **pkt_ou
/* Server and client. */
int rs_server_create(struct rs_connection *conn, struct rs_peer **server);
-int rs_server_set_address(struct rs_peer *server, const char *hostname, int port);
+int rs_server_set_address(struct rs_peer *server, const char *hostname, const char *service);
int rs_server_set_secret(struct rs_peer *server, const char *secret);
void rs_server_set_timeout(struct rs_peer *server, int timeout);
void rs_server_set_tries(struct rs_peer *server, int tries);
diff --git a/lib/radsec.c b/lib/radsec.c
index adf5576..96182a6 100644
--- a/lib/radsec.c
+++ b/lib/radsec.c
@@ -73,12 +73,6 @@ int rs_context_set_alloc_scheme(struct rs_handle *ctx, struct rs_alloc_scheme *s
"%s: NYI", __func__);
}
-int rs_context_config_read(struct rs_handle *ctx, const char *config_file)
-{
- return rs_err_ctx_push_fl (ctx, RSE_NOSYS, __FILE__, __LINE__,
- "%s: NYI", __func__);
-}
-
int
rs_conn_create(struct rs_handle *ctx, struct rs_connection **conn,
const char *config)
@@ -95,8 +89,12 @@ rs_conn_create(struct rs_handle *ctx, struct rs_connection **conn,
struct rs_realm *r = rs_conf_find_realm (ctx, config);
if (r)
{
+ struct rs_peer *p;
+
c->type = r->type;
- c->peers = r->peers; /* FIXME: Copy? */
+ c->peers = r->peers; /* FIXME: Copy instead? */
+ for (p = c->peers; p; p = p->next)
+ p->conn = c;
}
}
}
@@ -111,22 +109,21 @@ rs_conn_set_type(struct rs_connection *conn, rs_conn_type_t type)
conn->type = type;
}
-struct addrinfo *
-_resolv (struct rs_connection *conn, const char *hostname, int port)
+
+struct rs_error *
+_rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type,
+ const char *hostname, const char *service)
{
int err;
- char portstr[6];
struct evutil_addrinfo hints, *res = NULL;
- snprintf (portstr, sizeof(portstr), "%d", port);
memset (&hints, 0, sizeof(struct evutil_addrinfo));
hints.ai_family = AF_UNSPEC; /* v4 or v6. */
hints.ai_flags = AI_ADDRCONFIG;
- switch (conn->type)
+ switch (type)
{
case RS_CONN_TYPE_NONE:
- rs_err_conn_push_fl (conn, RSE_INVALID_CONN, __FILE__, __LINE__, NULL);
- return NULL;
+ return _rs_err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL);
case RS_CONN_TYPE_TCP:
/* Fall through. */
case RS_CONN_TYPE_TLS:
@@ -140,33 +137,30 @@ _resolv (struct rs_connection *conn, const char *hostname, int port)
hints.ai_protocol = IPPROTO_UDP;
break;
}
- err = evutil_getaddrinfo (hostname, portstr, &hints, &res);
+ err = evutil_getaddrinfo (hostname, service, &hints, &res);
if (err)
- rs_err_conn_push_fl (conn, RSE_BADADDR, __FILE__, __LINE__,
- "%s:%d: bad host name or port (%s)",
- hostname, port, evutil_gai_strerror(err));
- return res; /* Simply use first result. */
+ return _rs_err_create (RSE_BADADDR, __FILE__, __LINE__,
+ "%s:%s: bad host name or service name (%s)",
+ hostname, service, evutil_gai_strerror(err));
+ *addr = res; /* Simply use first result. */
+ return NULL;
}
-static struct rs_peer *
-_peer_new (struct rs_connection *conn)
+struct rs_peer *
+_rs_peer_create (struct rs_handle *ctx, struct rs_peer **rootp)
{
struct rs_peer *p;
- p = (struct rs_peer *) malloc (sizeof(*p));
+ p = (struct rs_peer *) rs_malloc (ctx, sizeof(*p));
if (p)
{
memset (p, 0, sizeof(struct rs_peer));
- p->conn = conn;
p->fd = -1;
- p->next = conn->peers;
- if (conn->peers)
- conn->peers->next = p;
+ if (*rootp)
+ (*rootp)->next = p;
else
- conn->peers = p;
+ *rootp = p;
}
- else
- rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
return p;
}
@@ -175,22 +169,30 @@ rs_server_create (struct rs_connection *conn, struct rs_peer **server)
{
struct rs_peer *srv;
- srv = _peer_new (conn);
+ srv = _rs_peer_create (conn->ctx, &conn->peers);
if (srv)
{
+ srv->conn = conn;
srv->timeout = 1;
srv->tries = 3;
}
+ else
+ return rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
if (*server)
*server = srv;
- return srv ? RSE_OK : -1;
+ return RSE_OK;
}
int
-rs_server_set_address (struct rs_peer *server, const char *hostname, int port)
+rs_server_set_address (struct rs_peer *server, const char *hostname,
+ const char *service)
{
- server->addr = _resolv (server->conn, hostname, port);
- return server->addr ? RSE_OK : -1;
+ struct rs_error *err;
+
+ err = _rs_resolv (&server->addr, server->conn->type, hostname, service);
+ if (err)
+ return _rs_err_conn_push_err (server->conn, err);
+ return RSE_OK;
}
void