1 /* See the file COPYING for licensing information. */
3 #if defined HAVE_CONFIG_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>
17 #include <radsec/radsec.h>
18 #include <radsec/radsec-impl.h>
23 #include <sys/socket.h>
27 _do_send (struct rs_packet *pkt)
33 assert (!pkt->original);
35 vp = paircreate (PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
37 return rs_err_conn_push_fl (pkt->conn, RSE_NOMEM, __FILE__, __LINE__,
38 "paircreate: %s", fr_strerror ());
39 pairadd (&pkt->rpkt->vps, vp);
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 ());
49 char host[80], serv[80];
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);
60 err = bufferevent_write (pkt->conn->bev, pkt->rpkt->data,
63 return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
64 "bufferevent_write: %s",
65 evutil_gai_strerror(err));
70 _event_cb (struct bufferevent *bev, short events, void *ctx)
72 struct rs_packet *pkt = (struct rs_packet *)ctx;
73 struct rs_connection *conn;
75 #if defined RS_ENABLE_TLS
81 assert (pkt->conn->active_peer);
83 p = conn->active_peer;
86 if (events & BEV_EVENT_CONNECTED)
89 if (conn->callbacks.connected_cb)
90 conn->callbacks.connected_cb (conn->user_data);
91 rs_debug ("%s: connected\n", __func__);
94 if (conn->callbacks.sent_cb)
95 conn->callbacks.sent_cb (conn->user_data);
96 /* Packet will be freed in write callback. */
98 else if (events & BEV_EVENT_ERROR)
100 #if defined RS_ENABLE_TLS
101 if (conn->tls_ssl) /* FIXME: correct check? */
103 for (err = bufferevent_get_openssl_error (conn->bev);
105 err = bufferevent_get_openssl_error (conn->bev))
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__,
113 #endif /* RS_ENABLE_TLS */
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 */
121 _write_cb (struct bufferevent *bev, void *ctx)
123 struct rs_packet *pkt = (struct rs_packet *) ctx;
129 rs_debug ("%s: packet written, breaking event loop\n", __func__);
130 err = event_base_loopbreak (pkt->conn->evb);
132 rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
133 "event_base_loopbreak: %s",
134 evutil_gai_strerror(err));
138 _read_cb (struct bufferevent *bev, void *ctx)
140 struct rs_packet *pkt = (struct rs_packet *)ctx;
148 pkt->rpkt->sockfd = pkt->conn->active_peer->fd; /* FIXME: Why? */
149 pkt->rpkt->vps = NULL; /* FIXME: Why? */
151 if (!pkt->hdr_read_flag)
153 n = bufferevent_read (pkt->conn->bev, pkt->hdr, RS_HEADER_LEN);
154 if (n == RS_HEADER_LEN)
156 pkt->hdr_read_flag = 1;
157 pkt->rpkt->data_len = (pkt->hdr[2] << 8) + pkt->hdr[3];
158 if (pkt->rpkt->data_len < 20 /* || len > 4096 */)
159 abort (); /* FIXME: Read and discard invalid packet. */
160 pkt->rpkt->data = rs_malloc (pkt->conn->ctx, pkt->rpkt->data_len);
161 if (!pkt->rpkt->data)
163 rs_err_conn_push_fl (pkt->conn, RSE_NOMEM, __FILE__, __LINE__,
165 abort (); /* FIXME: handle ENOMEM. */
167 memcpy (pkt->rpkt->data, pkt->hdr, RS_HEADER_LEN);
168 bufferevent_setwatermark (pkt->conn->bev, EV_READ,
169 pkt->rpkt->data_len - RS_HEADER_LEN, 0);
170 rs_debug ("%s: packet header read, total pkt len=%d\n",
171 __func__, pkt->rpkt->data_len);
174 return; /* Buffer frozen. FIXME: Properly handled above? */
177 assert (!"short header");
178 abort (); /* FIXME: handle short header */
182 rs_debug ("%s: trying to read %d octets of packet data\n", __func__,
183 pkt->rpkt->data_len - RS_HEADER_LEN);
184 n = bufferevent_read (pkt->conn->bev,
185 pkt->rpkt->data + RS_HEADER_LEN,
186 pkt->rpkt->data_len - RS_HEADER_LEN);
187 rs_debug ("%s: read %ld octets of packet data\n", __func__, n);
189 if (n == pkt->rpkt->data_len - RS_HEADER_LEN)
191 bufferevent_disable (pkt->conn->bev, EV_READ);
192 rs_debug ("%s: complete packet read\n", __func__);
193 pkt->hdr_read_flag = 0;
194 memset (pkt->hdr, 0, sizeof(*pkt->hdr));
195 if (!rad_packet_ok (pkt->rpkt, 0) != 0)
197 rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
198 "rad_packet_ok: %s", fr_strerror ());
201 assert (pkt->original); /* FIXME: where's the bug if this fires? */
203 /* Verify header and message authenticator. */
204 if (rad_verify (pkt->rpkt, pkt->original->rpkt,
205 pkt->conn->active_peer->secret))
207 rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
208 "rad_verify: %s", fr_strerror ());
212 /* Decode and decrypt. */
213 if (rad_decode (pkt->rpkt, pkt->original->rpkt,
214 pkt->conn->active_peer->secret))
216 rs_err_conn_push_fl (pkt->conn, RSE_FR, __FILE__, __LINE__,
217 "rad_decode: %s", fr_strerror ());
221 if (pkt->conn->callbacks.received_cb)
222 pkt->conn->callbacks.received_cb (pkt, pkt->conn->user_data);
224 err = event_base_loopbreak (pkt->conn->evb);
227 rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
228 "event_base_loopbreak: %s",
229 evutil_gai_strerror(err));
234 return; /* Buffer frozen. FIXME: Properly handled? */
237 assert (!"short packet");
238 abort (); /* FIXME: handle short packet */
243 _evlog_cb (int severity, const char *msg)
248 case _EVENT_LOG_DEBUG:
249 #if !defined (DEBUG_LEVENT)
257 case _EVENT_LOG_WARN:
267 fprintf (stderr, "libevent: [%s] %s\n", sevstr, msg); /* FIXME: stderr? */
271 _init_evb (struct rs_connection *conn)
276 event_enable_debug_mode ();
278 event_set_log_callback (_evlog_cb);
279 conn->evb = event_base_new ();
281 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
288 _init_socket (struct rs_connection *conn, struct rs_peer *p)
294 p->fd = socket (p->addr->ai_family, p->addr->ai_socktype,
295 p->addr->ai_protocol);
297 return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
299 if (evutil_make_socket_nonblocking (p->fd) < 0)
301 evutil_closesocket (p->fd);
302 return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
308 static struct rs_peer *
309 _pick_peer (struct rs_connection *conn)
311 if (!conn->active_peer)
312 conn->active_peer = conn->peers;
313 return conn->active_peer;
317 _init_bev (struct rs_connection *conn, struct rs_peer *peer)
324 case RS_CONN_TYPE_UDP:
325 case RS_CONN_TYPE_TCP:
326 conn->bev = bufferevent_socket_new (conn->evb, peer->fd, 0);
328 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
329 "bufferevent_socket_new");
331 #if defined RS_ENABLE_TLS
332 case RS_CONN_TYPE_TLS:
333 if (rs_tls_init (conn))
335 /* Would be convenient to pass BEV_OPT_CLOSE_ON_FREE but things
336 seem to break when be_openssl_ctrl() (in libevent) calls
337 SSL_set_bio() after BIO_new_socket() with flag=1. */
339 bufferevent_openssl_socket_new (conn->evb, peer->fd, conn->tls_ssl,
340 BUFFEREVENT_SSL_CONNECTING, 0);
342 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
343 "bufferevent_openssl_socket_new");
346 case RS_CONN_TYPE_DTLS:
347 return rs_err_conn_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
348 "%s: NYI", __func__);
349 #endif /* RS_ENABLE_TLS */
351 return rs_err_conn_push_fl (conn, RSE_INTERNAL, __FILE__, __LINE__,
352 "%s: unknown connection type: %d", __func__,
360 _do_connect (struct rs_peer *p)
364 err = bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
365 p->addr->ai_addrlen);
367 rs_err_conn_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
368 "bufferevent_socket_connect: %s",
369 evutil_gai_strerror(err));
371 p->is_connecting = 1;
375 _conn_open(struct rs_connection *conn, struct rs_packet *pkt)
379 if (_init_evb (conn))
382 p = _pick_peer (conn);
384 return rs_err_conn_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
386 if (_init_socket (conn, p))
389 if (_init_bev (conn, p))
392 if (!p->is_connected)
393 if (!p->is_connecting)
400 _conn_is_open_p (struct rs_connection *conn)
402 return conn->active_peer && conn->active_peer->is_connected;
405 /* Public functions. */
407 rs_packet_create (struct rs_connection *conn, struct rs_packet **pkt_out)
414 rpkt = rad_alloc (1);
416 return rs_err_conn_push (conn, RSE_NOMEM, __func__);
417 rpkt->id = conn->nextid++;
419 p = (struct rs_packet *) malloc (sizeof (struct rs_packet));
423 return rs_err_conn_push (conn, RSE_NOMEM, __func__);
425 memset (p, 0, sizeof (struct rs_packet));
434 rs_packet_create_auth_request (struct rs_connection *conn,
435 struct rs_packet **pkt_out,
436 const char *user_name, const char *user_pw)
438 struct rs_packet *pkt;
439 struct rs_attr *attr;
441 if (rs_packet_create (conn, pkt_out))
444 pkt->rpkt->code = PW_AUTHENTICATION_REQUEST;
448 if (rs_attr_create (conn, &attr, "User-Name", user_name))
450 rs_packet_add_attr (pkt, attr);
454 if (rs_attr_create (conn, &attr, "User-Password", user_pw))
456 rs_packet_add_attr (pkt, attr);
464 rs_packet_send (struct rs_packet *pkt, void *user_data)
466 struct rs_connection *conn;
472 if (_conn_is_open_p (conn))
475 if (_conn_open (conn, pkt))
476 return RSE_SOME_ERROR; /* FIXME */
480 assert (conn->active_peer);
481 assert (conn->active_peer->fd >= 0);
483 conn->user_data = user_data;
484 bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
485 if (!conn->user_dispatch_flag)
487 err = event_base_dispatch (conn->evb);
489 return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
490 "event_base_dispatch: %s",
491 evutil_gai_strerror(err));
493 rs_debug ("%s: event loop done\n", __func__);
494 if (!event_base_got_break(conn->evb))
496 /* Something went wrong -- we never reached loopbreak in
497 _write_cb(). FIXME: Pull error/errors? */
498 return RSE_SOME_ERROR; /* FIXME */
506 rs_conn_receive_packet (struct rs_connection *conn,
507 struct rs_packet *request,
508 struct rs_packet **pkt_out)
510 struct rs_packet *pkt;
514 if (rs_packet_create (conn, pkt_out))
518 pkt->original = request;
520 if (_conn_open (conn, pkt))
524 assert (conn->active_peer);
525 assert (conn->active_peer->fd >= 0);
527 bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0);
528 bufferevent_enable (conn->bev, EV_READ);
529 bufferevent_setcb (conn->bev, _read_cb, _write_cb, _event_cb, pkt);
531 /* Do dispatch, unless the user wants to do it herself. */
532 if (!conn->user_dispatch_flag)
534 event_base_dispatch (conn->evb);
535 rs_debug ("%s: event loop done", __func__);
536 if (event_base_got_break (conn->evb))
538 rs_debug (", got this:\n");
540 rs_dump_packet (pkt);
545 rs_debug (", no reply\n");
546 /* Something went wrong -- we never reached loopbreak in
547 _read_cb(). FIXME: Pull error/errors? */
548 return RSE_SOME_ERROR; /* FIXME */
552 pkt->original = NULL;
558 rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
560 pairadd (&pkt->rpkt->vps, attr->vp);
564 struct radius_packet *
565 rs_packet_frpkt(struct rs_packet *pkt)
572 rs_packet_destroy(struct rs_packet *pkt)
576 // FIXME: memory leak! TODO: free all attributes
577 rad_free (&pkt->rpkt);
578 rs_free (pkt->conn->ctx, pkt);