WIP -- example client sending and receiving Access-Request/Accept.
authorLinus Nordberg <linus@nordu.net>
Thu, 30 Sep 2010 22:14:05 +0000 (00:14 +0200)
committerLinus Nordberg <linus@nordu.net>
Thu, 30 Sep 2010 22:14:05 +0000 (00:14 +0200)
lib/HACKING [new file with mode: 0644]
lib/README [new file with mode: 0644]
lib/examples/client.c
lib/libradsec-impl.h
lib/libradsec.h
lib/packet.c

diff --git a/lib/HACKING b/lib/HACKING
new file mode 100644 (file)
index 0000000..cf42339
--- /dev/null
@@ -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 (file)
index 0000000..c4d0609
--- /dev/null
@@ -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.
index d7e7270..1e9f209 100644 (file)
@@ -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;
index a4ce7c2..3abb71e 100644 (file)
@@ -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;
 };
 
index 2ccafe2..29fb1f6 100644 (file)
@@ -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, ...);
index 90c8c31..c90511b 100644 (file)
@@ -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;
 }
-