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