summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/attr.c2
-rw-r--r--lib/err.c2
-rw-r--r--lib/examples/client-blocking.c18
-rw-r--r--lib/include/radsec/radsec-impl.h4
-rw-r--r--lib/include/radsec/radsec.h3
-rw-r--r--lib/include/radsec/request.h6
-rw-r--r--lib/packet.c129
-rw-r--r--lib/request.c61
8 files changed, 172 insertions, 53 deletions
diff --git a/lib/attr.c b/lib/attr.c
index 49735d9..4e66235 100644
--- a/lib/attr.c
+++ b/lib/attr.c
@@ -21,7 +21,7 @@ rs_attr_create(struct rs_connection *conn, struct rs_attr **attr, const char *ty
{
rs_attr_destroy (a);
return rs_err_conn_push_fl (conn, RSE_FR, __FILE__, __LINE__,
- "pairmake: %s", fr_strerror());
+ "pairmake: %s", fr_strerror ());
}
a->vp = vp;
diff --git a/lib/err.c b/lib/err.c
index 116c995..51e4421 100644
--- a/lib/err.c
+++ b/lib/err.c
@@ -19,7 +19,7 @@ const char *_errtxt[] = {
"libevent error" /* 9 RSE_EVENT */
"connection error" /* 10 RSE_CONNERR */
"invalid configuration file" /* 11 RSE_CONFIG */
- "ERR 12" /* RSE_ */
+ "authentication failed" /* RSE_BADAUTH */
"ERR 13" /* RSE_ */
"ERR 14" /* RSE_ */
"ERR 15" /* RSE_ */
diff --git a/lib/examples/client-blocking.c b/lib/examples/client-blocking.c
index bb9e653..365b3b0 100644
--- a/lib/examples/client-blocking.c
+++ b/lib/examples/client-blocking.c
@@ -55,17 +55,23 @@ blocking_client (const char *av1, const char *av2)
#if !defined(USE_REQUEST_OBJECT)
if (rs_packet_send (req, NULL))
- return rs_err_conn_pop (conn);
- req = NULL;
- if (rs_conn_receive_packet (conn, &resp))
- return rs_err_conn_pop (conn);
+ {
+ rs_packet_destroy (req);
+ return rs_err_conn_pop (conn);
+ }
+ if (rs_conn_receive_packet (conn, req, &resp))
+ {
+ rs_packet_destroy (req);
+ return rs_err_conn_pop (conn);
+ }
+ rs_packet_destroy (req);
#else
{
struct rs_request *request;
- if (rs_request_new (conn, &request))
+ if (rs_request_create (conn, &request))
return rs_err_conn_pop (conn);
- if (rs_req_send (request, req, &resp))
+ if (rs_request_send (request, req, &resp))
return rs_err_conn_pop (conn);
rs_request_destroy (request);
}
diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h
index b46bc47..6e5ee83 100644
--- a/lib/include/radsec/radsec-impl.h
+++ b/lib/include/radsec/radsec-impl.h
@@ -63,9 +63,12 @@ struct rs_connection {
enum rs_conn_type type;
struct rs_credentials transport_credentials;
struct rs_conn_callbacks callbacks;
+ void *user_data;
struct rs_peer *peers;
struct rs_peer *active_peer;
struct rs_error *err;
+ int nextid;
+ int user_dispatch_flag : 1; /* User does the dispatching. */
};
struct rs_packet {
@@ -73,6 +76,7 @@ struct rs_packet {
char hdr_read_flag;
uint8_t hdr[4];
RADIUS_PACKET *rpkt;
+ struct rs_packet *original;
};
struct rs_attr {
diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h
index 1d12787..8e97072 100644
--- a/lib/include/radsec/radsec.h
+++ b/lib/include/radsec/radsec.h
@@ -17,6 +17,7 @@ enum rs_err_code {
RSE_EVENT = 9,
RSE_CONNERR = 10,
RSE_CONFIG = 11,
+ RSE_BADAUTH = 12,
RSE_SOME_ERROR = 21,
};
@@ -96,6 +97,7 @@ int rs_conn_select_server(struct rs_connection *conn, const char *name);
int rs_conn_get_current_server(struct rs_connection *conn,
const char *name, size_t buflen);
int rs_conn_receive_packet(struct rs_connection *conn,
+ struct rs_packet *request,
struct rs_packet **pkt_out);
int rs_conn_fd(struct rs_connection *conn);
@@ -118,6 +120,7 @@ int rs_packet_send(struct rs_packet *pkt, void *data);
struct radius_packet *rs_packet_frpkt(struct rs_packet *pkt);
/* Attribute. */
+/* FIXME: Replace (or complement) with a wrapper for paircreate(). */
int rs_attr_create(struct rs_connection *conn, struct rs_attr **attr,
const char *type, const char *val);
void rs_attr_destroy(struct rs_attr *attr);
diff --git a/lib/include/radsec/request.h b/lib/include/radsec/request.h
index 3827da5..939345e 100644
--- a/lib/include/radsec/request.h
+++ b/lib/include/radsec/request.h
@@ -2,6 +2,6 @@
struct rs_request;
-int rs_req_create(struct rs_connection *conn, struct rs_request **req_out);
-void rs_req_destroy(struct rs_request *request);
-int rs_req_send(struct rs_request *request, struct rs_packet *req, struct rs_packet **resp);
+int rs_request_create(struct rs_connection *conn, struct rs_request **req_out);
+void rs_request_destroy(struct rs_request *request);
+int rs_request_send(struct rs_request *request, struct rs_packet *req, struct rs_packet **resp);
diff --git a/lib/packet.c b/lib/packet.c
index 9ac392d..cdd094a 100644
--- a/lib/packet.c
+++ b/lib/packet.c
@@ -24,7 +24,7 @@ _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out)
rpkt = rad_alloc (1);
if (!rpkt)
return rs_err_conn_push (conn, RSE_NOMEM, __func__);
- rpkt->id = -1;
+ rpkt->id = conn->nextid++;
p = (struct rs_packet *) malloc (sizeof (struct rs_packet));
if (!p)
@@ -40,13 +40,27 @@ _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out)
return RSE_OK;
}
-static void
+static int
_do_send (struct rs_packet *pkt)
{
int err;
+ VALUE_PAIR *vp;
- rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret);
assert (pkt->rpkt);
+ assert (!pkt->original);
+
+ vp = paircreate (PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
+ if (!vp)
+ return rs_err_conn_push_fl (pkt->conn, RSE_NOMEM, __FILE__, __LINE__,
+ "rad_encode: %s", fr_strerror ());
+ pairadd (&pkt->rpkt->vps, vp);
+
+ if (rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret))
+ return rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
+ "rad_encode: %s", fr_strerror ());
+ if (rad_sign (pkt->rpkt, NULL, pkt->conn->active_peer->secret))
+ return rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
+ "rad_sign: %s", fr_strerror ());
#if defined (DEBUG)
{
char host[80], serv[80];
@@ -63,16 +77,19 @@ _do_send (struct rs_packet *pkt)
err = bufferevent_write (pkt->conn->bev, pkt->rpkt->data,
pkt->rpkt->data_len);
if (err < 0)
- rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
- "bufferevent_write: %s", evutil_gai_strerror(err));
+ return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_write: %s",
+ evutil_gai_strerror(err));
+ return RSE_OK;
}
static void
_event_cb (struct bufferevent *bev, short events, void *ctx)
{
- struct rs_packet *pkt = (struct rs_packet *) ctx;
+ struct rs_packet *pkt = (struct rs_packet *)ctx;
struct rs_connection *conn;
struct rs_peer *p;
+ int err;
assert (pkt);
assert (pkt->conn);
@@ -84,10 +101,16 @@ _event_cb (struct bufferevent *bev, short events, void *ctx)
if (events & BEV_EVENT_CONNECTED)
{
p->is_connected = 1;
+ if (conn->callbacks.connected_cb)
+ conn->callbacks.connected_cb (conn->user_data);
+
#if defined (DEBUG)
fprintf (stderr, "%s: connected\n", __func__);
#endif
- _do_send (pkt);
+ if (_do_send (pkt))
+ return;
+ if (conn->callbacks.sent_cb)
+ conn->callbacks.sent_cb (conn->user_data);
/* Packet will be freed in write callback. */
}
else if (events & BEV_EVENT_ERROR)
@@ -106,17 +129,22 @@ _write_cb (struct bufferevent *bev, void *ctx)
#endif
if (event_base_loopbreak (pkt->conn->evb) < 0)
abort (); /* FIXME */
- rs_packet_destroy (pkt);
+ if (!pkt->conn->callbacks.sent_cb) /* Callback owns the packet now. */
+ rs_packet_destroy (pkt);
}
static void
_read_cb (struct bufferevent *bev, void *ctx)
{
- struct rs_packet *pkt = (struct rs_packet *) ctx;
+ struct rs_packet *pkt = (struct rs_packet *)ctx;
size_t n;
assert (pkt);
assert (pkt->conn);
+
+ pkt->rpkt->sockfd = pkt->conn->active_peer->fd; /* FIXME: Why? */
+ pkt->rpkt->vps = NULL; /* FIXME: Why? */
+
if (!pkt->hdr_read_flag)
{
n = bufferevent_read (pkt->conn->bev, pkt->hdr, RS_HEADER_LEN);
@@ -162,7 +190,31 @@ _read_cb (struct bufferevent *bev, void *ctx)
#if defined (DEBUG)
fprintf (stderr, "%s: complete packet read\n", __func__);
#endif
- rad_decode (pkt->rpkt, NULL, pkt->conn->active_peer->secret);
+ if (!rad_packet_ok (pkt->rpkt, 0) != 0)
+ return;
+ assert (pkt->original);
+
+ /* Verify header and message authenticator. */
+ if (rad_verify (pkt->rpkt, pkt->original->rpkt,
+ pkt->conn->active_peer->secret))
+ {
+ rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
+ "rad_verify: %s", fr_strerror ());
+ return;
+ }
+
+ /* Decode and decrypt. */
+ if (rad_decode (pkt->rpkt, pkt->original->rpkt,
+ pkt->conn->active_peer->secret))
+ {
+ rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
+ "rad_decode: %s", fr_strerror ());
+ return;
+ }
+
+ if (pkt->conn->callbacks.received_cb)
+ pkt->conn->callbacks.received_cb (pkt, pkt->conn->user_data);
+
if (event_base_loopbreak (pkt->conn->evb) < 0)
abort (); /* FIXME */
}
@@ -324,14 +376,14 @@ rs_packet_create_acc_request (struct rs_connection *conn,
if (rs_attr_create (conn, &attr, "User-Name", user_name))
return -1;
rs_packet_add_attr (pkt, attr);
- }
- if (user_pw)
- {
- if (rs_attr_create (conn, &attr, "User-Password", user_pw))
- return -1;
- /* FIXME: need this too? rad_pwencode(user_pw, &pwlen, SECRET, reqauth) */
- rs_packet_add_attr (pkt, attr);
+ if (user_pw)
+ {
+ if (rs_attr_create (conn, &attr, "User-Password", user_pw))
+ return -1;
+ /* FIXME: need this too? rad_pwencode(user_pw, &pwlen, SECRET, reqauth) */
+ rs_packet_add_attr (pkt, attr);
+ }
}
return RSE_OK;
@@ -341,6 +393,7 @@ int
rs_packet_send (struct rs_packet *pkt, void *user_data)
{
struct rs_connection *conn;
+
assert (pkt);
conn = pkt->conn;
@@ -355,14 +408,10 @@ rs_packet_send (struct rs_packet *pkt, void *user_data)
assert (conn->active_peer);
assert (conn->active_peer->fd >= 0);
- if (conn->callbacks.connected_cb || conn->callbacks.disconnected_cb
- || conn->callbacks.received_cb || conn->callbacks.sent_cb)
- ; /* FIXME: install event callbacks, other than below */
- else
- {
- bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
- event_base_dispatch (conn->evb);
- }
+ conn->user_data = user_data;
+ bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
+ if (!conn->user_dispatch_flag)
+ event_base_dispatch (conn->evb);
#if defined (DEBUG)
fprintf (stderr, "%s: event loop done\n", __func__);
@@ -373,7 +422,9 @@ rs_packet_send (struct rs_packet *pkt, void *user_data)
}
int
-rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet **pkt_out)
+rs_conn_receive_packet (struct rs_connection *conn,
+ struct rs_packet *request,
+ struct rs_packet **pkt_out)
{
struct rs_packet *pkt;
@@ -383,6 +434,7 @@ rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet **pkt_out)
return -1;
pkt = *pkt_out;
pkt->conn = conn;
+ pkt->original = request;
if (_conn_open (conn, pkt))
return -1;
@@ -393,17 +445,24 @@ rs_conn_receive_packet (struct rs_connection *conn, struct rs_packet **pkt_out)
bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0);
bufferevent_enable (conn->bev, EV_READ);
- event_base_dispatch (conn->evb);
-#if defined (DEBUG)
- fprintf (stderr, "%s: event loop done", __func__);
- if (event_base_got_break(conn->evb))
+ bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
+
+ if (!conn->user_dispatch_flag)
{
- fprintf (stderr, ", got this:\n");
- rs_dump_packet (pkt);
- }
- else
- fprintf (stderr, ", no reply\n");
+ event_base_dispatch (conn->evb);
+#if defined (DEBUG)
+ fprintf (stderr, "%s: event loop done", __func__);
+ if (event_base_got_break(conn->evb))
+ {
+ fprintf (stderr, ", got this:\n");
+ rs_dump_packet (pkt);
+ }
+ else
+ fprintf (stderr, ", no reply\n");
#endif
+ }
+
+ pkt->original = NULL;
return RSE_OK;
}
diff --git a/lib/request.c b/lib/request.c
index 3d4b096..5cb87bb 100644
--- a/lib/request.c
+++ b/lib/request.c
@@ -1,6 +1,7 @@
/* See the file COPYING for licensing information. */
#include <time.h>
+#include <assert.h>
#include <event2/event.h>
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
@@ -8,7 +9,7 @@
#include <radsec/request-impl.h>
int
-rs_req_create (struct rs_connection *conn, struct rs_request **req_out)
+rs_request_create (struct rs_connection *conn, struct rs_request **req_out)
{
struct rs_request *req = rs_malloc (conn->ctx, sizeof(*req));
if (!req)
@@ -20,7 +21,7 @@ rs_req_create (struct rs_connection *conn, struct rs_request **req_out)
}
void
-rs_req_destroy(struct rs_request *request)
+rs_request_destroy (struct rs_request *request)
{
rs_packet_destroy (request->req);
rs_packet_destroy (request->resp);
@@ -35,12 +36,58 @@ _timer_cb(evutil_socket_t fd, short what, void *arg)
}
#endif
+static void
+_rs_req_connected(void *user_data)
+{
+ struct rs_request *request = (struct rs_request *)user_data;
+}
+
+static void
+_rs_req_disconnected(void *user_data)
+{
+ struct rs_request *request = (struct rs_request *)user_data;
+}
+
+static void
+_rs_req_packet_received(const struct rs_packet *pkt, void *user_data)
+{
+ struct rs_request *request = (struct rs_request *)user_data;
+}
+
+static void
+_rs_req_packet_sent(void *user_data)
+{
+ struct rs_request *request = (struct rs_request *)user_data;
+}
+
int
-rs_req_send(struct rs_request *request, struct rs_packet *req,
- struct rs_packet **resp)
+rs_request_send(struct rs_request *request, struct rs_packet *req,
+ struct rs_packet **resp)
{
- /* install our own callback, backing up any user provided one in
- req->saved_cb*/
+ int err;
+ struct rs_connection *conn;
+
+ assert (request);
+ assert (request->conn);
+ conn = request->conn;
+
+ request->req = req; /* take ownership */
+ request->saved_cb = conn->callbacks;
+
+ conn->callbacks.connected_cb = _rs_req_connected;
+ conn->callbacks.disconnected_cb = _rs_req_disconnected;
+ conn->callbacks.received_cb = _rs_req_packet_received;
+ conn->callbacks.sent_cb = _rs_req_packet_sent;
+
+ err = rs_packet_send(request->req, request);
+ if (err)
+ goto cleanup;
+
+ err = rs_conn_receive_packet(request->conn, request->req, resp);
+ if (err)
+ goto cleanup;
- return -1;
+cleanup:
+ conn->callbacks = request->saved_cb;
+ return err;
}