summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordu.net>2010-10-01 00:14:05 +0200
committerLinus Nordberg <linus@nordu.net>2010-10-01 00:14:05 +0200
commitb1437bde86daa8826a8eeb1437cca11dda88283e (patch)
tree2dd210d9b424a8511a102e25d1abb9f78a9153fb /lib
parent727af5678906c03eedff8d8262d39fad788973a6 (diff)
WIP -- example client sending and receiving Access-Request/Accept.
Diffstat (limited to 'lib')
-rw-r--r--lib/HACKING8
-rw-r--r--lib/README11
-rw-r--r--lib/examples/client.c17
-rw-r--r--lib/libradsec-impl.h32
-rw-r--r--lib/libradsec.h31
-rw-r--r--lib/packet.c114
6 files changed, 158 insertions, 55 deletions
diff --git a/lib/HACKING b/lib/HACKING
new file mode 100644
index 0000000..cf42339
--- /dev/null
+++ b/lib/HACKING
@@ -0,0 +1,8 @@
+HACKING file for libradsec (in Emacs -*- org -*- mode).
+* Design of the libraray
+* Features
+** Not implemented
+** Not tested
+- short read
+- short write
+** Tested and verified
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000..c4d0609
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,11 @@
+This is a non-working RADIUS library doing UDP, TCP, TLS and DTLS.
+
+It depends on libradius from FreeRADIUS freeradius-server and
+libevent2.
+
+The parts of it thathas been tested has been so on Linux (Ubuntu
+10.04) with libfreeradius2 (2.1.8+dfsg-1ubuntu1) and
+libevent-2.0.7-rc-dev.
+
+The file HACKING contains more detailed info on the state of the
+various parts of the library.
diff --git a/lib/examples/client.c b/lib/examples/client.c
index d7e7270..1e9f209 100644
--- a/lib/examples/client.c
+++ b/lib/examples/client.c
@@ -6,7 +6,6 @@
#include <stdlib.h>
#include <event2/event.h>
#include "../libradsec.h"
-#include "../debug.h"
#define SECRET "sikrit"
#define USER_NAME "bob"
@@ -18,7 +17,7 @@ rsx_client (const char *srvname, int srvport)
struct rs_handle *h;
struct rs_connection *conn;
struct rs_peer *server;
- struct rs_packet *req;
+ struct rs_packet *req, *resp;
if (rs_context_create (&h, "/usr/share/freeradius/dictionary"))
return NULL;
@@ -39,13 +38,19 @@ rsx_client (const char *srvname, int srvport)
req = NULL;
#if 0
- if (rs_packet_recv (conn, &resp))
+ if (rs_packet_create_acc_request (conn, &req, USER_NAME, USER_PW))
return rs_conn_err_pop (conn);
-#if defined (DEBUG)
- rs_dump_packet (resp);
-#endif
+
+ if (rs_packet_send (conn, req, NULL))
+ return rs_conn_err_pop (conn);
+ req = NULL;
#endif
+ if (rs_packet_receive (conn, &resp))
+ return rs_conn_err_pop (conn);
+ /* TODO: do something interesting with the response */
+ rs_packet_destroy (resp);
+
rs_conn_destroy (conn);
rs_context_destroy (h);
return NULL;
diff --git a/lib/libradsec-impl.h b/lib/libradsec-impl.h
index a4ce7c2..3abb71e 100644
--- a/lib/libradsec-impl.h
+++ b/lib/libradsec-impl.h
@@ -30,40 +30,10 @@ struct rs_error {
char buf[1024];
};
-typedef void * (*rs_calloc_fp)(size_t nmemb, size_t size);
-typedef void * (*rs_malloc_fp)(size_t size);
-typedef void (*rs_free_fp)(void *ptr);
-typedef void * (*rs_realloc_fp)(void *ptr, size_t size);
-struct rs_alloc_scheme {
- rs_calloc_fp calloc;
- rs_malloc_fp malloc;
- rs_free_fp free;
- rs_realloc_fp realloc;
-};
-
-typedef void (*rs_conn_connected_cb)(void *user_data /* FIXME: peer? */);
-typedef void (*rs_conn_disconnected_cb)(void *user_data /* FIXME: reason? */);
-typedef void (*rs_conn_packet_received_cb)(const struct rs_packet *packet,
- void *user_data);
-typedef void (*rs_conn_packet_sent_cb)(void *user_data);
-
-/** Connection callbacks. */
-struct rs_conn_callbacks {
- /** Callback invoked when the connection has been established. */
- rs_conn_connected_cb connected_cb;
- /** Callback invoked when the connection has been torn down. */
- rs_conn_disconnected_cb disconnected_cb;
- /** Callback invoked when a packet was received. */
- rs_conn_packet_received_cb received_cb;
- /** Callback invoked when a packet was successfully sent. */
- rs_conn_packet_sent_cb sent_cb;
-};
-
struct rs_handle {
struct rs_alloc_scheme alloc_scheme;
struct rs_error *err;
fr_randctx fr_randctx;
-
/* TODO: dictionary? */
};
@@ -93,6 +63,8 @@ struct rs_connection {
struct rs_packet {
struct rs_connection *conn;
+ char hdr_read_flag;
+ uint8_t hdr[4];
RADIUS_PACKET *rpkt;
};
diff --git a/lib/libradsec.h b/lib/libradsec.h
index 2ccafe2..29fb1f6 100644
--- a/lib/libradsec.h
+++ b/lib/libradsec.h
@@ -31,9 +31,7 @@ typedef unsigned int rs_conn_type_t;
/* Data types. */
struct rs_handle; /* radsec-impl.h */
-struct rs_alloc_scheme; /* radsec-impl.h */
struct rs_connection; /* radsec-impl.h */
-struct rs_conn_callbacks; /* radsec-impl.h */
struct rs_packet; /* radsec-impl.h */
struct rs_conn; /* radsec-impl.h */
struct rs_attr; /* radsec-impl.h */
@@ -41,6 +39,33 @@ struct rs_error; /* radsec-impl.h */
struct rs_peer; /* radsec-impl.h */
struct event_base; /* <event.h> */
+typedef void * (*rs_calloc_fp)(size_t nmemb, size_t size);
+typedef void * (*rs_malloc_fp)(size_t size);
+typedef void (*rs_free_fp)(void *ptr);
+typedef void * (*rs_realloc_fp)(void *ptr, size_t size);
+struct rs_alloc_scheme {
+ rs_calloc_fp calloc;
+ rs_malloc_fp malloc;
+ rs_free_fp free;
+ rs_realloc_fp realloc;
+};
+
+typedef void (*rs_conn_connected_cb)(void *user_data /* FIXME: peer? */);
+typedef void (*rs_conn_disconnected_cb)(void *user_data /* FIXME: reason? */);
+typedef void (*rs_conn_packet_received_cb)(const struct rs_packet *packet,
+ void *user_data);
+typedef void (*rs_conn_packet_sent_cb)(void *user_data);
+struct rs_conn_callbacks {
+ /** Callback invoked when the connection has been established. */
+ rs_conn_connected_cb connected_cb;
+ /** Callback invoked when the connection has been torn down. */
+ rs_conn_disconnected_cb disconnected_cb;
+ /** Callback invoked when a packet was received. */
+ rs_conn_packet_received_cb received_cb;
+ /** Callback invoked when a packet was successfully sent. */
+ rs_conn_packet_sent_cb sent_cb;
+};
+
/* Function prototypes. */
int rs_context_create(struct rs_handle **ctx, const char *dict);
void rs_context_destroy(struct rs_handle *ctx);
@@ -72,7 +97,7 @@ int rs_attr_create(struct rs_connection *conn, struct rs_attr **attr, const char
void rs_attr_destroy(struct rs_attr *attr);
int rs_packet_send(struct rs_connection *conn, struct rs_packet *pkt, void *data);
-int rs_packet_recv(struct rs_connection *conn, struct rs_packet **pkt);
+int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt_out);
int rs_ctx_err_push(struct rs_handle *ctx, int code, const char *fmt, ...);
int rs_ctx_err_push_fl(struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, ...);
diff --git a/lib/packet.c b/lib/packet.c
index 90c8c31..c90511b 100644
--- a/lib/packet.c
+++ b/lib/packet.c
@@ -9,9 +9,8 @@
#include "debug.h"
#endif
-int
-_packet_create (struct rs_connection *conn, struct rs_packet **pkt_out,
- int code)
+static int
+_packet_create (struct rs_connection *conn, struct rs_packet **pkt_out)
{
struct rs_packet *p;
RADIUS_PACKET *rpkt;
@@ -22,7 +21,6 @@ _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out,
if (!rpkt)
return rs_conn_err_push (conn, RSE_NOMEM, __func__);
rpkt->id = -1;
- rpkt->code = code;
p = (struct rs_packet *) malloc (sizeof (struct rs_packet));
if (!p)
@@ -46,9 +44,10 @@ rs_packet_create_acc_request (struct rs_connection *conn,
struct rs_packet *pkt;
struct rs_attr *attr;
- if (_packet_create (conn, pkt_out, PW_AUTHENTICATION_REQUEST))
+ if (_packet_create (conn, pkt_out))
return -1;
pkt = *pkt_out;
+ pkt->rpkt->code = PW_AUTHENTICATION_REQUEST;
if (rs_attr_create (conn, &attr, "User-Name", user_name))
return -1;
@@ -83,6 +82,7 @@ _event_cb (struct bufferevent *bev, short events, void *ctx)
fprintf (stderr, "%s: connected\n", __func__);
#endif
rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret);
+ assert (pkt->rpkt);
#if defined (DEBUG)
fprintf (stderr, "%s: about to send this to %s:\n", __func__, "<fixme>");
rs_dump_packet (pkt);
@@ -118,6 +118,62 @@ _write_cb (struct bufferevent *bev, void *ctx)
rs_packet_destroy (pkt);
}
+static void
+_read_cb (struct bufferevent *bev, void *ctx)
+{
+ struct rs_packet *pkt = (struct rs_packet *) ctx;
+ size_t n;
+
+ assert (pkt);
+ assert (pkt->conn);
+ if (!pkt->hdr_read_flag)
+ {
+ n = bufferevent_read (pkt->conn->bev, pkt->hdr, 4);
+ if (n == 4)
+ {
+ uint16_t len = (pkt->hdr[2] << 8) + pkt->hdr[3];
+ uint8_t *buf = rs_malloc (pkt->conn->ctx, len);
+
+ pkt->hdr_read_flag = 1;
+ if (!buf)
+ {
+ rs_conn_err_push_fl (pkt->conn, RSE_NOMEM, __FILE__,
+ __LINE__, NULL);
+ abort (); /* FIXME: recovering takes reading of packet */
+ }
+ pkt->rpkt->data = buf;
+ pkt->rpkt->data_len = len;
+ bufferevent_setwatermark (pkt->conn->bev, EV_READ, len - 4, 0);
+#if defined (DEBUG)
+ fprintf (stderr, "%s: packet header read, pkt len=%d\n", __func__,
+ len);
+#endif
+ }
+ else if (n < 0)
+ return; /* Buffer frozen, i suppose. Let's hope it thaws. */
+ else
+ {
+ assert (n < 4);
+ return; /* Need more to complete header. */
+ }
+ }
+
+ printf ("%s: trying to read %d octets of packet data\n", __func__, pkt->rpkt->data_len - 4);
+ n = bufferevent_read (pkt->conn->bev, pkt->rpkt->data, pkt->rpkt->data_len - 4);
+ printf ("%s: read %d octets of packet data\n", __func__, n);
+ if (n == pkt->rpkt->data_len - 4)
+ {
+ bufferevent_disable (pkt->conn->bev, EV_READ);
+ pkt->hdr_read_flag = 0;
+ memset (pkt->hdr, 0, sizeof(*pkt->hdr));
+#if defined (DEBUG)
+ fprintf (stderr, "%s: complete packet read\n", __func__);
+#endif
+ if (event_base_loopbreak (pkt->conn->evb) < 0)
+ abort (); /* FIXME */
+ }
+}
+
static int
_init_evb (struct rs_connection *conn)
{
@@ -158,8 +214,7 @@ _pick_peer (struct rs_connection *conn)
}
static int
-_init_bev (struct rs_connection *conn, struct rs_peer *peer,
- struct rs_packet *pkt)
+_init_bev (struct rs_connection *conn, struct rs_peer *peer)
{
if (!conn->bev)
{
@@ -167,7 +222,6 @@ _init_bev (struct rs_connection *conn, struct rs_peer *peer,
if (!conn->bev)
return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_socket_new");
- bufferevent_setcb (conn->bev, NULL, _write_cb, _event_cb, pkt);
}
return RSE_OK;
}
@@ -198,8 +252,9 @@ _conn_open(struct rs_connection *conn, struct rs_packet *pkt)
if (_init_socket (conn, p))
return -1;
- if (_init_bev (conn, p, pkt))
+ if (_init_bev (conn, p))
return -1;
+ bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
if (!p->is_connected)
if (!p->is_connecting)
@@ -213,13 +268,16 @@ rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
{
assert (conn);
assert (pkt->rpkt);
+
if (_conn_open (conn, pkt))
return -1;
assert (conn->evb);
assert (conn->bev);
assert (conn->active_peer);
assert (conn->active_peer->s >= 0);
+
event_base_dispatch (conn->evb);
+
#if defined (DEBUG)
fprintf (stderr, "%s: event loop done\n", __func__);
assert (event_base_got_break(conn->evb));
@@ -228,15 +286,40 @@ rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
return RSE_OK;
}
-int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt)
+int
+rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt_out)
{
- //struct bufferevent *bev;
+ struct rs_packet *pkt;
- //skalleper;
- //bufferevent_enable(bev, EV_READ);
- return 0; /* FIXME */
-}
+ assert (conn);
+
+ if (_packet_create (conn, pkt_out))
+ return -1;
+ pkt = *pkt_out;
+ pkt->conn = conn;
+
+ if (_conn_open (conn, pkt))
+ return -1;
+ assert (conn->evb);
+ assert (conn->bev);
+ assert (conn->active_peer);
+ assert (conn->active_peer->s >= 0);
+ bufferevent_setwatermark (conn->bev, EV_READ, 4, 0);
+ bufferevent_enable (conn->bev, EV_READ);
+ event_base_dispatch (conn->evb);
+#if defined (DEBUG)
+ fprintf (stderr, "%s: event loop done\n", __func__);
+ assert (event_base_got_break(conn->evb));
+#endif
+
+#if defined (DEBUG)
+ fprintf (stderr, "%s: got this:\n", __func__);
+ rs_dump_packet (pkt);
+#endif
+
+ return RSE_OK;
+}
void
rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
@@ -244,4 +327,3 @@ rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
pairadd (&pkt->rpkt->vps, attr->vp);
attr->pkt = pkt;
}
-