From b1437bde86daa8826a8eeb1437cca11dda88283e Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Fri, 1 Oct 2010 00:14:05 +0200 Subject: WIP -- example client sending and receiving Access-Request/Accept. --- lib/HACKING | 8 ++++ lib/README | 11 +++++ lib/examples/client.c | 17 +++++--- lib/libradsec-impl.h | 32 +------------- lib/libradsec.h | 31 ++++++++++++-- lib/packet.c | 114 +++++++++++++++++++++++++++++++++++++++++++------- 6 files changed, 158 insertions(+), 55 deletions(-) create mode 100644 lib/HACKING create mode 100644 lib/README (limited to 'lib') 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 #include #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; /* */ +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__, ""); 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; } - -- cgit v1.1