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