Build even when not configured with `--enable-tls'.
[radsecproxy.git] / lib / packet.c
1 /* See the file COPYING for licensing information.  */
2
3 #if defined HAVE_CONFIG_H
4 #include <config.h>
5 #endif
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <freeradius/libradius.h>
11 #include <event2/event.h>
12 #include <event2/bufferevent.h>
13 #if defined RS_ENABLE_TLS
14 #include <event2/bufferevent_ssl.h>
15 #include <openssl/err.h>
16 #endif
17 #include <radsec/radsec.h>
18 #include <radsec/radsec-impl.h>
19 #include "tls.h"
20 #if defined DEBUG
21 #include <netdb.h>
22 #include <sys/socket.h>
23 #include "debug.h"
24 #endif
25
26 static int
27 _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out)
28 {
29   struct rs_packet *p;
30   RADIUS_PACKET *rpkt;
31
32   *pkt_out = NULL;
33
34   rpkt = rad_alloc (1);
35   if (!rpkt)
36     return rs_err_conn_push (conn, RSE_NOMEM, __func__);
37   rpkt->id = conn->nextid++;
38
39   p = (struct rs_packet *) malloc (sizeof (struct rs_packet));
40   if (!p)
41     {
42       rad_free (&rpkt);
43       return rs_err_conn_push (conn, RSE_NOMEM, __func__);
44     }
45   memset (p, 0, sizeof (struct rs_packet));
46   p->conn = conn;
47   p->rpkt = rpkt;
48
49   *pkt_out = p;
50   return RSE_OK;
51 }
52
53 static int
54 _do_send (struct rs_packet *pkt)
55 {
56   int err;
57   VALUE_PAIR *vp;
58
59   assert (pkt->rpkt);
60   assert (!pkt->original);
61
62   vp = paircreate (PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
63   if (!vp)
64     return rs_err_conn_push_fl (pkt->conn, RSE_NOMEM, __FILE__, __LINE__,
65                                 "rad_encode: %s", fr_strerror ());
66   pairadd (&pkt->rpkt->vps, vp);
67
68   if (rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret))
69     return rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
70                                 "rad_encode: %s", fr_strerror ());
71   if (rad_sign (pkt->rpkt, NULL, pkt->conn->active_peer->secret))
72     return rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
73                                 "rad_sign: %s", fr_strerror ());
74 #if defined (DEBUG)
75   {
76     char host[80], serv[80];
77
78     getnameinfo (pkt->conn->active_peer->addr->ai_addr,
79                  pkt->conn->active_peer->addr->ai_addrlen,
80                  host, sizeof(host), serv, sizeof(serv),
81                  0 /* NI_NUMERICHOST|NI_NUMERICSERV*/);
82     fprintf (stderr, "%s: about to send this to %s:%s:\n", __func__, host,
83              serv);
84     rs_dump_packet (pkt);
85   }
86 #endif
87   err = bufferevent_write (pkt->conn->bev, pkt->rpkt->data,
88                            pkt->rpkt->data_len);
89   if (err < 0)
90     return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
91                                 "bufferevent_write: %s",
92                                 evutil_gai_strerror(err));
93   return RSE_OK;
94 }
95
96 static void
97 _event_cb (struct bufferevent *bev, short events, void *ctx)
98 {
99   struct rs_packet *pkt = (struct rs_packet *)ctx;
100   struct rs_connection *conn;
101   struct rs_peer *p;
102 #if defined RS_ENABLE_TLS
103   unsigned long err;
104 #endif
105
106   assert (pkt);
107   assert (pkt->conn);
108   assert (pkt->conn->active_peer);
109   conn = pkt->conn;
110   p = conn->active_peer;
111
112   p->is_connecting = 0;
113   if (events & BEV_EVENT_CONNECTED)
114     {
115       p->is_connected = 1;
116       if (conn->callbacks.connected_cb)
117         conn->callbacks.connected_cb (conn->user_data);
118 #if defined (DEBUG)
119       fprintf (stderr, "%s: connected\n", __func__);
120 #endif
121       if (_do_send (pkt))
122         return;
123       if (conn->callbacks.sent_cb)
124         conn->callbacks.sent_cb (conn->user_data);
125       /* Packet will be freed in write callback.  */
126     }
127   else if (events & BEV_EVENT_ERROR)
128     {
129 #if defined RS_ENABLE_TLS
130       if (conn->tls_ssl)        /* FIXME: correct check?  */
131         {
132           for (err = bufferevent_get_openssl_error (conn->bev);
133                err;
134                err = bufferevent_get_openssl_error (conn->bev))
135             {
136               fprintf (stderr, "%s: openssl error: %s\n", __func__,
137                        ERR_error_string (err, NULL)); /* DEBUG, until verified that pushed errors will actually be handled  */
138               rs_err_conn_push_fl (pkt->conn, RSE_SSLERR, __FILE__, __LINE__,
139                                    "%d", err);
140             }
141         }
142 #endif  /* RS_ENABLE_TLS */
143       rs_err_conn_push_fl (pkt->conn, RSE_CONNERR, __FILE__, __LINE__, NULL);
144       fprintf (stderr, "%s: BEV_EVENT_ERROR\n", __func__); /* DEBUG, until verified that pushed errors will actually be handled  */
145     }
146 }
147
148 static void
149 _write_cb (struct bufferevent *bev, void *ctx)
150 {
151   struct rs_packet *pkt = (struct rs_packet *) ctx;
152
153   assert (pkt);
154   assert (pkt->conn);
155 #if defined (DEBUG)
156   fprintf (stderr, "%s: packet written, breaking event loop\n", __func__);
157 #endif
158   if (event_base_loopbreak (pkt->conn->evb) < 0)
159     abort ();                   /* FIXME */
160   if (!pkt->conn->callbacks.sent_cb) /* Callback owns the packet now.  */
161     rs_packet_destroy (pkt);
162 }
163
164 static void
165 _read_cb (struct bufferevent *bev, void *ctx)
166 {
167   struct rs_packet *pkt = (struct rs_packet *)ctx;
168   size_t n;
169
170   assert (pkt);
171   assert (pkt->conn);
172
173   pkt->rpkt->sockfd = pkt->conn->active_peer->fd; /* FIXME: Why?  */
174   pkt->rpkt->vps = NULL;                          /* FIXME: Why?  */
175
176   if (!pkt->hdr_read_flag)
177     {
178       n = bufferevent_read (pkt->conn->bev, pkt->hdr, RS_HEADER_LEN);
179       if (n == RS_HEADER_LEN)
180         {
181           pkt->hdr_read_flag = 1;
182           pkt->rpkt->data_len = (pkt->hdr[2] << 8) + pkt->hdr[3];
183           if (pkt->rpkt->data_len < 20 /* || len > 4096 */)
184             abort ();           /* FIXME: Read and discard packet.  */
185           pkt->rpkt->data = rs_malloc (pkt->conn->ctx, pkt->rpkt->data_len);
186           if (!pkt->rpkt->data)
187             {
188               rs_err_conn_push_fl (pkt->conn, RSE_NOMEM, __FILE__, __LINE__,
189                                    NULL);
190               abort ();         /* FIXME: Read and discard packet.  */
191             }
192           memcpy (pkt->rpkt->data, pkt->hdr, RS_HEADER_LEN);
193           bufferevent_setwatermark (pkt->conn->bev, EV_READ,
194                                     pkt->rpkt->data_len - RS_HEADER_LEN, 0);
195 #if defined (DEBUG)
196           fprintf (stderr, "%s: packet header read, total pkt len=%d\n",
197                    __func__, pkt->rpkt->data_len);
198 #endif
199         }
200       else if (n < 0)
201         return;                 /* Buffer frozen.  */
202       else
203         assert (!"short header");
204     }
205
206 #if defined (DEBUG)
207   printf ("%s: trying to read %d octets of packet data\n", __func__, pkt->rpkt->data_len - RS_HEADER_LEN);
208 #endif
209   n = bufferevent_read (pkt->conn->bev, pkt->rpkt->data + RS_HEADER_LEN, pkt->rpkt->data_len - RS_HEADER_LEN);
210 #if defined (DEBUG)
211   printf ("%s: read %d octets of packet data\n", __func__, n);
212 #endif
213   if (n == pkt->rpkt->data_len - RS_HEADER_LEN)
214     {
215       bufferevent_disable (pkt->conn->bev, EV_READ);
216       pkt->hdr_read_flag = 0;
217       memset (pkt->hdr, 0, sizeof(*pkt->hdr));
218 #if defined (DEBUG)
219       fprintf (stderr, "%s: complete packet read\n", __func__);
220 #endif
221       if (!rad_packet_ok (pkt->rpkt, 0) != 0)
222         return;
223       assert (pkt->original);
224
225       /* Verify header and message authenticator.  */
226       if (rad_verify (pkt->rpkt, pkt->original->rpkt,
227                       pkt->conn->active_peer->secret))
228         {
229           rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
230                                "rad_verify: %s", fr_strerror ());
231           return;
232         }
233
234       /* Decode and decrypt.  */
235       if (rad_decode (pkt->rpkt, pkt->original->rpkt,
236                       pkt->conn->active_peer->secret))
237         {
238           rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
239                                "rad_decode: %s", fr_strerror ());
240           return;
241         }
242
243       if (pkt->conn->callbacks.received_cb)
244         pkt->conn->callbacks.received_cb (pkt, pkt->conn->user_data);
245
246       if (event_base_loopbreak (pkt->conn->evb) < 0)
247         abort ();               /* FIXME */
248     }
249   else if (n < 0)
250     return;                     /* Buffer frozen.  */
251   else
252     assert (!"short packet");
253 }
254
255 static void
256 _evlog_cb (int severity, const char *msg)
257 {
258   const char *sevstr;
259   switch (severity)
260     {
261     case _EVENT_LOG_DEBUG:
262 #if !defined (DEBUG_LEVENT)
263       return;
264 #endif
265       sevstr = "debug";
266       break;
267     case _EVENT_LOG_MSG:
268       sevstr = "msg";
269       break;
270     case _EVENT_LOG_WARN:
271       sevstr = "warn";
272       break;
273     case _EVENT_LOG_ERR:
274       sevstr = "err";
275       break;
276     default:
277       sevstr = "???";
278       break;
279     }
280   fprintf (stderr, "libevent: [%s] %s\n", sevstr, msg);
281 }
282
283 static int
284 _init_evb (struct rs_connection *conn)
285 {
286   if (!conn->evb)
287     {
288 #if defined (DEBUG)
289       event_enable_debug_mode ();
290 #endif
291       event_set_log_callback (_evlog_cb);
292       conn->evb = event_base_new ();
293       if (!conn->evb)
294         return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
295                                     "event_base_new");
296     }
297   return RSE_OK;
298 }
299
300 static int
301 _init_socket (struct rs_connection *conn, struct rs_peer *p)
302 {
303   if (p->fd != -1)
304     return RSE_OK;
305
306   assert (p->addr);
307   p->fd = socket (p->addr->ai_family, p->addr->ai_socktype,
308                   p->addr->ai_protocol);
309   if (p->fd < 0)
310     return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
311                                 strerror (errno));
312   if (evutil_make_socket_nonblocking (p->fd) < 0)
313     {
314       evutil_closesocket (p->fd);
315       return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
316                                   strerror (errno));
317     }
318   return RSE_OK;
319 }
320
321 static struct rs_peer *
322 _pick_peer (struct rs_connection *conn)
323 {
324   if (!conn->active_peer)
325     conn->active_peer = conn->peers;
326   return conn->active_peer;
327 }
328
329 static int
330 _init_bev (struct rs_connection *conn, struct rs_peer *peer)
331 {
332   if (conn->bev)
333     return RSE_OK;
334
335   switch (conn->type)
336     {
337     case RS_CONN_TYPE_UDP:
338     case RS_CONN_TYPE_TCP:
339       conn->bev = bufferevent_socket_new (conn->evb, peer->fd, 0);
340       if (!conn->bev)
341         return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
342                                     "bufferevent_socket_new");
343       break;
344 #if defined RS_ENABLE_TLS
345     case RS_CONN_TYPE_TLS:
346       if (rs_tls_init (conn))
347         return -1;
348       /* Would be convenient to pass BEV_OPT_CLOSE_ON_FREE but things
349          seem to break when be_openssl_ctrl() (in libevent) calls
350          SSL_set_bio() after BIO_new_socket() with flag=1.  */
351       conn->bev =
352         bufferevent_openssl_socket_new (conn->evb, peer->fd, conn->tls_ssl,
353                                         BUFFEREVENT_SSL_CONNECTING, 0);
354       if (!conn->bev)
355         return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
356                                     "bufferevent_openssl_socket_new");
357
358       break;
359     case RS_CONN_TYPE_DTLS:
360       return rs_err_conn_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
361                                   "%s: NYI", __func__);
362 #endif  /* RS_ENABLE_TLS */
363     default:
364       return rs_err_conn_push_fl (conn, RSE_INTERNAL, __FILE__, __LINE__,
365                                   "%s: invalid connection type: %d", __func__,
366                                   conn->type);
367     }
368
369   return RSE_OK;
370 }
371
372 static void
373 _do_connect (struct rs_peer *p)
374 {
375   int err;
376
377   err = bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
378                                     p->addr->ai_addrlen);
379   if (err < 0)
380     rs_err_conn_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
381                          "bufferevent_socket_connect: %s",
382                          evutil_gai_strerror(err));
383   else
384     p->is_connecting = 1;
385 }
386
387 static int
388 _conn_open(struct rs_connection *conn, struct rs_packet *pkt)
389 {
390   struct rs_peer *p;
391
392   if (_init_evb (conn))
393     return -1;
394
395   p = _pick_peer (conn);
396   if (!p)
397     return rs_err_conn_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
398
399   if (_init_socket (conn, p))
400     return -1;
401
402   if (_init_bev (conn, p))
403     return -1;
404
405   if (!p->is_connected)
406     if (!p->is_connecting)
407       _do_connect (p);
408
409   return RSE_OK;
410 }
411
412 static int
413 _conn_is_open_p (struct rs_connection *conn)
414 {
415   return conn->active_peer && conn->active_peer->is_connected;
416 }
417
418 /* Public functions.  */
419 int
420 rs_packet_create_acc_request (struct rs_connection *conn,
421                               struct rs_packet **pkt_out,
422                               const char *user_name, const char *user_pw)
423 {
424   struct rs_packet *pkt;
425   struct rs_attr *attr;
426
427   if (_packet_create (conn, pkt_out))
428     return -1;
429   pkt = *pkt_out;
430   pkt->rpkt->code = PW_AUTHENTICATION_REQUEST;
431
432   if (user_name)
433     {
434       if (rs_attr_create (conn, &attr, "User-Name", user_name))
435         return -1;
436       rs_packet_add_attr (pkt, attr);
437
438       if (user_pw)
439         {
440           if (rs_attr_create (conn, &attr, "User-Password", user_pw))
441             return -1;
442           /* FIXME: need this too? rad_pwencode(user_pw, &pwlen, SECRET, reqauth) */
443           rs_packet_add_attr (pkt, attr);
444         }
445     }
446
447   return RSE_OK;
448 }
449
450 int
451 rs_packet_send (struct rs_packet *pkt, void *user_data)
452 {
453   struct rs_connection *conn;
454
455   assert (pkt);
456   conn = pkt->conn;
457
458   if (_conn_is_open_p (conn))
459     _do_send (pkt);
460   else
461     if (_conn_open (conn, pkt))
462       return -1;
463
464   assert (conn->evb);
465   assert (conn->bev);
466   assert (conn->active_peer);
467   assert (conn->active_peer->fd >= 0);
468
469   conn->user_data = user_data;
470   bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
471   if (!conn->user_dispatch_flag)
472     event_base_dispatch (conn->evb);
473
474 #if defined (DEBUG)
475   fprintf (stderr, "%s: event loop done\n", __func__);
476   assert (event_base_got_break(conn->evb));
477 #endif
478
479   return RSE_OK;
480 }
481
482 int
483 rs_conn_receive_packet (struct rs_connection *conn,
484                         struct rs_packet *request,
485                         struct rs_packet **pkt_out)
486 {
487   struct rs_packet *pkt;
488
489   assert (conn);
490
491   if (_packet_create (conn, pkt_out))
492     return -1;
493   pkt = *pkt_out;
494   pkt->conn = conn;
495   pkt->original = request;
496
497   if (_conn_open (conn, pkt))
498     return -1;
499   assert (conn->evb);
500   assert (conn->bev);
501   assert (conn->active_peer);
502   assert (conn->active_peer->fd >= 0);
503
504   bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0);
505   bufferevent_enable (conn->bev, EV_READ);
506   bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
507
508   if (!conn->user_dispatch_flag)
509     {
510       event_base_dispatch (conn->evb);
511 #if defined (DEBUG)
512       fprintf (stderr, "%s: event loop done", __func__);
513       if (event_base_got_break(conn->evb))
514         {
515           fprintf (stderr, ", got this:\n");
516           rs_dump_packet (pkt);
517         }
518       else
519         fprintf (stderr, ", no reply\n");
520 #endif
521     }
522
523   pkt->original = NULL;
524
525   return RSE_OK;
526 }
527
528 void
529 rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
530 {
531   pairadd (&pkt->rpkt->vps, attr->vp);
532   attr->pkt = pkt;
533 }
534
535 struct radius_packet *
536 rs_packet_frpkt(struct rs_packet *pkt)
537 {
538   assert (pkt);
539   return pkt->rpkt;
540 }
541
542 void
543 rs_packet_destroy(struct rs_packet *pkt)
544 {
545   if (pkt)
546     {
547       // TODO: free all attributes
548       rad_free (&pkt->rpkt);
549       rs_free (pkt->conn->ctx, pkt);
550     }
551 }