WIP commit moving towards working server support.
[libradsec.git] / lib / listener.c
1 /* Copyright 2013 NORDUnet A/S. All rights reserved.
2    See LICENSE for licensing information. */
3
4 #if defined HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7
8 #include <stdlib.h>
9 #include <assert.h>
10 #include <event2/listener.h>
11 #include <radsec/radsec.h>
12 #include <radsec/radsec-impl.h>
13 #include "listener.h"
14 #include "conn.h"
15 #include "peer.h"
16 #include "event.h"
17 #include "debug.h"
18
19 struct rs_listener *
20 listener_create (struct rs_context *ctx, struct rs_listener **rootp)
21 {
22   struct rs_listener *listener;
23
24   listener = rs_calloc (ctx, 1, sizeof (*listener));
25   if (listener)
26     {
27       if (*rootp == NULL)
28         *rootp = listener;
29       else
30         {
31           listener->next = (*rootp)->next;
32           (*rootp)->next = listener;
33         }
34     }
35   return listener;
36 }
37
38 void
39 listener_accept_cb_ (struct evconnlistener *evconnlistener,
40                      evutil_socket_t newfd,
41                      struct sockaddr *srcaddr_sa,
42                      int srcaddr_len,
43                      void *user_data)
44 {
45   int err = RSE_OK;
46   struct rs_listener *l = NULL;
47   struct rs_connection *newconn = NULL;
48   struct rs_context *ctx = NULL;
49   struct rs_peer *clients = NULL;
50
51   l = (struct rs_listener *) user_data;
52   assert (l);
53   assert (l->base_.magic == RS_CONN_MAGIC_LISTENER);
54   assert (l->evlistener == evconnlistener);
55   ctx = l->base_.ctx;
56   assert (ctx);
57
58 #if defined (DEBUG)
59   {
60     char host[80], port[80];
61     getnameinfo (srcaddr_sa, srcaddr_len, host, sizeof(host),
62                  port, sizeof(port), 0);
63     rs_debug (("%s: incoming connection from %s:%s\n", __func__, host, port));
64   }
65 #endif
66
67 /*
68 Application needs to specify acceptable clients -- we need to verify
69 src addr in the UDP case and x509 client cert in the TLS case. A list
70 of peers with proper pointers to realms should be a good way of doing
71 this.
72
73 Ask the application for a list of acceptable clients. Default to
74 accepting any potential configured client block in the realm of the
75 listener.  Note that this for this to be an opption, the application
76 must have read a config file. If there is no configuration, reject the
77 client.
78 */
79   if (l->callbacks.client_filter_cb)
80     clients = l->callbacks.client_filter_cb (l, TO_BASE_CONN(l)->user_data);
81   if (clients == NULL)
82     clients = connbase_get_peers (TO_BASE_CONN(l));
83   if (clients == NULL)
84     {
85       rs_debug (("%s: didn't get a client list for listener %p\n",
86                  __func__, l));
87       return;
88     }
89   rs_debug (("%s: using client list %p\n", __func__, clients));
90
91   err = rs_conn_create (ctx, &newconn, NULL);
92   if (err)
93     {
94       rs_debug (("%s: failed creating a new struct rs_connection: %d\n",
95                 __func__, err));
96       return;                /* FIXME: Verify that this is handled. */
97     }
98
99   assert(clients);
100   /* TODO: Picking the very first peer is not really what we want to
101      do. For UDP, we can look at src ip and try to find a matching
102      peer. For TLS, it's worse because we don't have the certificate
103      until we've accepted the TCP connection. */
104   TO_BASE_CONN(newconn)->realm = clients->realm;
105   newconn->active_peer = clients;
106
107   TO_BASE_CONN(newconn)->fd = newfd;
108   TO_BASE_CONN(newconn)->transport = TO_BASE_CONN(l)->realm->type;
109   err = event_init_bufferevent (newconn);
110   if (err)
111     {
112       rs_debug (("%s: failed init bev: %d\n", __func__, err));
113       goto errout;
114     }
115
116   /* Create a message and set up a read event. This installs the
117      callback performing the TLS verification. */
118   {                             /* FIXME */
119     struct rs_message *msg = NULL;
120     err = rs_message_create (newconn, &msg);
121     if (err)
122       abort ();                 /* FIXME */
123     conn_add_read_event (newconn, msg);
124   }
125
126   if (l->callbacks.new_conn_cb)
127     l->callbacks.new_conn_cb (newconn, TO_BASE_CONN(l)->user_data);
128   return;                       /* Success. */
129
130  errout:
131   rs_conn_destroy (newconn);
132   if (l->callbacks.error_cb)
133     l->callbacks.error_cb (newconn, TO_BASE_CONN(l)->user_data);
134 }
135
136 void
137 listener_err_cb_ (struct evconnlistener *listener, void *user_data)
138 {
139   rs_debug (("%s: FIXME: handle error\n", __func__));
140 }
141
142 /* Public functions. */
143 int
144 rs_listener_create (struct rs_context *ctx,
145                     struct rs_listener **listener_out,
146                     const char *config)
147 {
148   int err = RSE_OK;
149   struct rs_listener *listener = NULL;
150
151   assert (ctx);
152
153   listener = rs_calloc (ctx, 1, sizeof (*listener));
154   if (listener == NULL)
155     return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
156   conn_init (ctx, TO_BASE_CONN (listener), RS_CONN_OBJTYPE_LISTENER);
157   err = conn_configure (ctx, TO_BASE_CONN (listener), config);
158   if (err)
159     goto errout;
160
161   if (listener_out)
162     *listener_out = listener;
163   return RSE_OK;
164
165  errout:
166   if (listener)
167     rs_free (ctx, listener);
168   return err;
169 }
170
171 void
172 rs_listener_set_callbacks (struct rs_listener *listener,
173                            const struct rs_listener_callbacks *cb,
174                            void *user_data)
175 {
176   assert (listener);
177   TO_BASE_CONN(listener)->user_data = user_data;
178   memcpy (&listener->callbacks, cb, sizeof (listener->callbacks));
179 }
180
181 int
182 rs_listener_listen (struct rs_listener *listener)
183 {
184   int err = RSE_OK;
185   struct rs_conn_base *connbase = NULL;
186   assert (listener);
187   connbase = TO_BASE_CONN (listener);
188
189   err = event_init_eventbase (connbase);
190   if (err)
191     return err;
192   err = event_init_socket (connbase, connbase->realm->local_addr);
193   if (err)
194     return err;
195 #if 0
196   {
197     struct linger l;
198     l.l_onoff = 1;
199     l.l_linger = 0;
200     rs_debug (("%s: setting SO_LINGER 0s on fd %d\n", __func__, connbase->fd));
201     assert (0 == setsockopt (connbase->fd, SOL_SOCKET, SO_LINGER,
202                              (void*)&l, sizeof(l)));
203   }
204 #endif
205   return err;
206 }
207
208 int
209 rs_listener_dispatch (const struct rs_listener *listener)
210 {
211   assert (listener);
212   assert (TO_BASE_CONN(listener)->ctx);
213   return event_base_dispatch (TO_BASE_CONN(listener)->ctx->evb);
214 }
215
216 int
217 rs_listener_close (struct rs_listener *l)
218 {
219   int err = baseconn_close (TO_BASE_CONN (l));
220   return err;
221 }
222
223 struct event_base *
224 rs_listener_get_eventbase (const struct rs_listener *l)
225 {
226   assert (TO_BASE_CONN (l));
227   assert (TO_BASE_CONN (l)->ctx);
228   return TO_BASE_CONN (l)->ctx->evb;
229 }
230
231 int
232 rs_listener_get_fd (const struct rs_listener *l)
233 {
234   assert (TO_BASE_CONN (l));
235   return TO_BASE_CONN (l)->fd;
236 }