diff options
| -rw-r--r-- | lib/attr.c | 2 | ||||
| -rw-r--r-- | lib/err.c | 2 | ||||
| -rw-r--r-- | lib/examples/client-blocking.c | 18 | ||||
| -rw-r--r-- | lib/include/radsec/radsec-impl.h | 4 | ||||
| -rw-r--r-- | lib/include/radsec/radsec.h | 3 | ||||
| -rw-r--r-- | lib/include/radsec/request.h | 6 | ||||
| -rw-r--r-- | lib/packet.c | 129 | ||||
| -rw-r--r-- | lib/request.c | 61 | 
8 files changed, 172 insertions, 53 deletions
| @@ -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; @@ -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;  } | 
