Move dump_hex() function to tls_listen.c
[freeradius.git] / src / main / tls_listen.c
1 /*
2  * tls.c
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
21  * Copyright 2003  Alan DeKok <aland@freeradius.org>
22  * Copyright 2006  The FreeRADIUS server project
23  */
24
25 #include <freeradius-devel/ident.h>
26 RCSID("$Id$")
27
28 #include <freeradius-devel/autoconf.h>
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/process.h>
31 #include <freeradius-devel/rad_assert.h>
32
33 #ifdef HAVE_SYS_STAT_H
34 #include <sys/stat.h>
35 #endif
36
37 #ifdef WITH_TLS
38 #ifdef HAVE_OPENSSL_RAND_H
39 #include <openssl/rand.h>
40 #endif
41
42 #ifdef HAVE_OPENSSL_OCSP_H
43 #include <openssl/ocsp.h>
44 #endif
45
46 #ifdef HAVE_PTHREAD_H
47 #define PTHREAD_MUTEX_LOCK pthread_mutex_lock
48 #define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
49 #else
50 #define PTHREAD_MUTEX_LOCK(_x)
51 #define PTHREAD_MUTEX_UNLOCK(_x)
52 #endif
53
54 static void dump_hex(const char *msg, const uint8_t *data, size_t data_len)
55 {
56         size_t i;
57
58         if (debug_flag < 3) return;
59
60         printf("%s %d\n", msg, (int) data_len);
61         if (data_len > 256) data_len = 256;
62
63         for (i = 0; i < data_len; i++) {
64                 if ((i & 0x0f) == 0x00) printf ("%02x: ", (unsigned int) i);
65                 printf("%02x ", data[i]);
66                 if ((i & 0x0f) == 0x0f) printf ("\n");
67         }
68         printf("\n");
69         fflush(stdout);
70 }
71
72 static void tls_socket_close(rad_listen_t *listener)
73 {
74         listen_socket_t *sock = listener->data;
75
76         listener->status = RAD_LISTEN_STATUS_REMOVE_FD;
77         listener->tls = NULL; /* parent owns this! */
78         
79         if (sock->parent) {
80                 /*
81                  *      Decrement the number of connections.
82                  */
83                 if (sock->parent->num_connections > 0) {
84                         sock->parent->num_connections--;
85                 }
86                 if (sock->client->num_connections > 0) {
87                         sock->client->num_connections--;
88                 }
89         }
90         
91         /*
92          *      Tell the event handler that an FD has disappeared.
93          */
94         DEBUG("Client has closed connection");
95         event_new_fd(listener);
96         
97         /*
98          *      Do NOT free the listener here.  It's in use by
99          *      a request, and will need to hang around until
100          *      all of the requests are done.
101          *
102          *      It is instead free'd in remove_from_request_hash()
103          */
104 }
105
106 static int tls_socket_write(rad_listen_t *listener, REQUEST *request)
107 {
108         uint8_t *p;
109         ssize_t rcode;
110         listen_socket_t *sock = listener->data;
111
112         p = sock->ssn->dirty_out.data;
113         
114         while (p < (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used)) {
115                 RDEBUG3("Writing to socket %d", request->packet->sockfd);
116                 rcode = write(request->packet->sockfd, p,
117                               (sock->ssn->dirty_out.data + sock->ssn->dirty_out.used) - p);
118                 if (rcode <= 0) {
119                         RDEBUG("Error writing to TLS socket: %s", strerror(errno));
120                         
121                         tls_socket_close(listener);
122                         return 0;
123                 }
124                 p += rcode;
125         }
126
127         sock->ssn->dirty_out.used = 0;
128         
129         return 1;
130 }
131
132
133 static int tls_socket_recv(rad_listen_t *listener)
134 {
135         int doing_init = FALSE;
136         ssize_t rcode;
137         RADIUS_PACKET *packet;
138         REQUEST *request;
139         listen_socket_t *sock = listener->data;
140         fr_tls_status_t status;
141         RADCLIENT *client = sock->client;
142
143         if (!sock->packet) {
144                 sock->packet = rad_alloc(0);
145                 if (!sock->packet) return 0;
146
147                 sock->packet->sockfd = listener->fd;
148                 sock->packet->src_ipaddr = sock->other_ipaddr;
149                 sock->packet->src_port = sock->other_port;
150                 sock->packet->dst_ipaddr = sock->my_ipaddr;
151                 sock->packet->dst_port = sock->my_port;
152
153                 if (sock->request) sock->request->packet = sock->packet;
154         }
155
156         /*
157          *      Allocate a REQUEST for debugging.
158          */
159         if (!sock->request) {
160                 sock->request = request = request_alloc();
161                 if (!sock->request) {
162                         radlog(L_ERR, "Out of memory");
163                         return 0;
164                 }
165
166                 rad_assert(request->packet == NULL);
167                 rad_assert(sock->packet != NULL);
168                 request->packet = sock->packet;
169
170                 request->component = "<core>";
171                 request->component = "<tls-connect>";
172
173                 /*
174                  *      Not sure if we should do this on every packet...
175                  */
176                 request->reply = rad_alloc(0);
177                 if (!request->reply) return 0;
178
179                 request->options = RAD_REQUEST_OPTION_DEBUG2;
180
181                 rad_assert(sock->ssn == NULL);
182
183                 sock->ssn = tls_new_session(listener->tls, sock->request,
184                                             listener->tls->require_client_cert);
185                 if (!sock->ssn) {
186                         request_free(&sock->request);
187                         sock->packet = NULL;
188                         return 0;
189                 }
190
191                 SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
192                 SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_CERTS, (void *)&request->packet->vps);
193
194                 doing_init = TRUE;
195         }
196
197         rad_assert(sock->request != NULL);
198         rad_assert(sock->request->packet != NULL);
199         rad_assert(sock->packet != NULL);
200         rad_assert(sock->ssn != NULL);
201
202         request = sock->request;
203
204         RDEBUG3("Reading from socket %d", request->packet->sockfd);
205         PTHREAD_MUTEX_LOCK(&sock->mutex);
206         rcode = read(request->packet->sockfd,
207                      sock->ssn->dirty_in.data,
208                      sizeof(sock->ssn->dirty_in.data));
209         if ((rcode < 0) && (errno == ECONNRESET)) {
210         do_close:
211                 PTHREAD_MUTEX_UNLOCK(&sock->mutex);
212                 tls_socket_close(listener);
213                 return 0;
214         }
215         
216         if (rcode < 0) {
217                 RDEBUG("Error reading TLS socket: %s", strerror(errno));
218                 goto do_close;
219         }
220
221         /*
222          *      Normal socket close.
223          */
224         if (rcode == 0) goto do_close;
225         
226         sock->ssn->dirty_in.used = rcode;
227         memset(sock->ssn->dirty_in.data + sock->ssn->dirty_in.used,
228                0, 16);
229
230         dump_hex("READ FROM SSL", sock->ssn->dirty_in.data, sock->ssn->dirty_in.used);
231
232         /*
233          *      Catch attempts to use non-SSL.
234          */
235         if (doing_init && (sock->ssn->dirty_in.data[0] != handshake)) {
236                 RDEBUG("Non-TLS data sent to TLS socket: closing");
237                 goto do_close;
238         }
239         
240         /*
241          *      Skip ahead to reading application data.
242          */
243         if (SSL_is_init_finished(sock->ssn->ssl)) goto app;
244
245         if (!tls_handshake_recv(request, sock->ssn)) {
246                 RDEBUG("FAILED in TLS handshake receive");
247                 goto do_close;
248         }
249         
250         if (sock->ssn->dirty_out.used > 0) {
251                 tls_socket_write(listener, request);
252                 PTHREAD_MUTEX_UNLOCK(&sock->mutex);
253                 return 0;
254         }
255
256 app:
257         /*
258          *      FIXME: Run the packet through a virtual server in
259          *      order to see if we like the certificate presented by
260          *      the client.
261          */
262
263         status = tls_application_data(sock->ssn, request);
264         RDEBUG("Application data status %d", status);
265
266         if (status == FR_TLS_MORE_FRAGMENTS) {
267                 PTHREAD_MUTEX_UNLOCK(&sock->mutex);
268                 return 0;
269         }
270
271         if (sock->ssn->clean_out.used == 0) {
272                 PTHREAD_MUTEX_UNLOCK(&sock->mutex);
273                 return 0;
274         }
275
276         dump_hex("TUNNELED DATA", sock->ssn->clean_out.data, sock->ssn->clean_out.used);
277
278         /*
279          *      If the packet is a complete RADIUS packet, return it to
280          *      the caller.  Otherwise...
281          */
282         if ((sock->ssn->clean_out.used < 20) ||
283             (((sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]) != (int) sock->ssn->clean_out.used)) {
284                 RDEBUG("Received bad packet: Length %d contents %d",
285                        sock->ssn->clean_out.used,
286                        (sock->ssn->clean_out.data[2] << 8) | sock->ssn->clean_out.data[3]);
287                 goto do_close;
288         }
289
290         packet = sock->packet;
291         packet->data = rad_malloc(sock->ssn->clean_out.used);
292         packet->data_len = sock->ssn->clean_out.used;
293         record_minus(&sock->ssn->clean_out, packet->data, packet->data_len);
294         packet->vps = NULL;
295         PTHREAD_MUTEX_UNLOCK(&sock->mutex);
296
297         if (!rad_packet_ok(packet, 0)) {
298                 RDEBUG("Received bad packet: %s", fr_strerror());
299                 tls_socket_close(listener);
300                 return 0;       /* do_close unlocks the mutex */
301         }
302
303         /*
304          *      Copied from src/lib/radius.c, rad_recv();
305          */
306         if (fr_debug_flag) {
307                 char host_ipaddr[128];
308
309                 if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
310                         RDEBUG("tls_recv: %s packet from host %s port %d, id=%d, length=%d",
311                                fr_packet_codes[packet->code],
312                                inet_ntop(packet->src_ipaddr.af,
313                                          &packet->src_ipaddr.ipaddr,
314                                          host_ipaddr, sizeof(host_ipaddr)),
315                                packet->src_port,
316                                packet->id, (int) packet->data_len);
317                 } else {
318                         RDEBUG("tls_recv: Packet from host %s port %d code=%d, id=%d, length=%d",
319                                inet_ntop(packet->src_ipaddr.af,
320                                          &packet->src_ipaddr.ipaddr,
321                                          host_ipaddr, sizeof(host_ipaddr)),
322                                packet->src_port,
323                                packet->code,
324                                packet->id, (int) packet->data_len);
325                 }
326         }
327
328         FR_STATS_INC(auth, total_requests);
329
330         return 1;
331 }
332
333
334 int dual_tls_recv(rad_listen_t *listener)
335 {
336         RADIUS_PACKET *packet;
337         REQUEST *request;
338         RAD_REQUEST_FUNP fun = NULL;
339         listen_socket_t *sock = listener->data;
340         RADCLIENT       *client = sock->client;
341
342         if (!tls_socket_recv(listener)) {
343                 return 0;
344         }
345
346         rad_assert(sock->request != NULL);
347         rad_assert(sock->request->packet != NULL);
348         rad_assert(sock->packet != NULL);
349         rad_assert(sock->ssn != NULL);
350
351         request = sock->request;
352         packet = sock->packet;
353
354         /*
355          *      Some sanity checks, based on the packet code.
356          */
357         switch(packet->code) {
358         case PW_AUTHENTICATION_REQUEST:
359                 if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
360                 FR_STATS_INC(auth, total_requests);
361                 fun = rad_authenticate;
362                 break;
363
364         case PW_ACCOUNTING_REQUEST:
365                 if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
366                 FR_STATS_INC(acct, total_requests);
367                 fun = rad_accounting;
368                 break;
369
370         case PW_STATUS_SERVER:
371                 if (!mainconfig.status_server) {
372                         FR_STATS_INC(auth, total_unknown_types);
373                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
374                         rad_free(&sock->packet);
375                         request->packet = NULL;
376                         return 0;
377                 }
378                 fun = rad_status_server;
379                 break;
380
381         default:
382         bad_packet:
383                 FR_STATS_INC(auth, total_unknown_types);
384
385                 DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
386                       packet->code, client->shortname, packet->src_port);
387                 rad_free(&sock->packet);
388                 request->packet = NULL;
389                 return 0;
390         } /* switch over packet types */
391
392         if (!request_receive(listener, packet, client, fun)) {
393                 FR_STATS_INC(auth, total_packets_dropped);
394                 rad_free(&sock->packet);
395                 request->packet = NULL;
396                 return 0;
397         }
398
399         sock->packet = NULL;    /* we have no need for more partial reads */
400         request->packet = NULL;
401
402         return 1;
403 }
404
405
406 /*
407  *      Send a response packet
408  */
409 int dual_tls_send(rad_listen_t *listener, REQUEST *request)
410 {
411         listen_socket_t *sock = listener->data;
412
413         rad_assert(request->listener == listener);
414         rad_assert(listener->send == dual_tls_send);
415
416         /*
417          *      Accounting reject's are silently dropped.
418          *
419          *      We do it here to avoid polluting the rest of the
420          *      code with this knowledge
421          */
422         if (request->reply->code == 0) return 0;
423
424         /*
425          *      Pack the VPs
426          */
427         if (rad_encode(request->reply, request->packet,
428                        request->client->secret) < 0) {
429                 RDEBUG("Failed encoding packet: %s", fr_strerror());
430                 return 0;
431         }
432
433         /*
434          *      Sign the packet.
435          */
436         if (rad_sign(request->reply, request->packet,
437                        request->client->secret) < 0) {
438                 RDEBUG("Failed signing packet: %s", fr_strerror());
439                 return 0;
440         }
441         
442         PTHREAD_MUTEX_LOCK(&sock->mutex);
443         /*
444          *      Write the packet to the SSL buffers.
445          */
446         record_plus(&sock->ssn->clean_in,
447                     request->reply->data, request->reply->data_len);
448
449         /*
450          *      Do SSL magic to get encrypted data.
451          */
452         tls_handshake_send(request, sock->ssn);
453
454         /*
455          *      And finally write the data to the socket.
456          */
457         if (sock->ssn->dirty_out.used > 0) {
458                 dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used);
459
460                 tls_socket_write(listener, request);
461         }
462         PTHREAD_MUTEX_UNLOCK(&sock->mutex);
463
464         return 0;
465 }
466
467
468 int proxy_tls_recv(rad_listen_t *listener)
469 {
470         int rcode;
471         size_t length;
472         listen_socket_t *sock = listener->data;
473         char buffer[256];
474         uint8_t data[1024];
475         RADIUS_PACKET *packet;
476         RAD_REQUEST_FUNP fun = NULL;
477
478         DEBUG3("Proxy SSL socket has data to read");
479         PTHREAD_MUTEX_LOCK(&sock->mutex);
480 redo:
481         rcode = SSL_read(sock->ssn->ssl, data, 4);
482         if (rcode <= 0) {
483                 int err = SSL_get_error(sock->ssn->ssl, rcode);
484                 switch (err) {
485                 case SSL_ERROR_WANT_READ:
486                 case SSL_ERROR_WANT_WRITE:
487                         rcode = 0;
488                         goto redo;
489                 case SSL_ERROR_ZERO_RETURN:
490                         /* remote end sent close_notify, send one back */
491                         SSL_shutdown(sock->ssn->ssl);
492
493                 case SSL_ERROR_SYSCALL:
494                 do_close:
495                         PTHREAD_MUTEX_UNLOCK(&sock->mutex);
496                         tls_socket_close(listener);
497                         return 0;
498
499                 default:
500                         while ((err = ERR_get_error())) {
501                                 DEBUG("proxy recv says %s",
502                                       ERR_error_string(err, NULL));
503                         }
504                         
505                         goto do_close;
506                 }
507         }
508
509         length = (data[2] << 8) | data[3];
510         DEBUG3("Proxy received header saying we have a packet of %u bytes",
511                (unsigned int) length);
512
513         if (length > sizeof(data)) {
514                 DEBUG("Received packet will be too large! (%u)",
515                       (data[2] << 8) | data[3]);
516                 goto do_close;
517         }
518         
519         rcode = SSL_read(sock->ssn->ssl, data + 4, length);
520         if (rcode <= 0) {
521                 switch (SSL_get_error(sock->ssn->ssl, rcode)) {
522                 case SSL_ERROR_WANT_READ:
523                 case SSL_ERROR_WANT_WRITE:
524                         rcode = 0;
525                         break;
526
527                 case SSL_ERROR_ZERO_RETURN:
528                         /* remote end sent close_notify, send one back */
529                         SSL_shutdown(sock->ssn->ssl);
530                         goto do_close;
531                 default:
532                         goto do_close;
533                 }
534         }
535         PTHREAD_MUTEX_UNLOCK(&sock->mutex);
536
537         packet = rad_alloc(0);
538         packet->sockfd = listener->fd;
539         packet->src_ipaddr = sock->other_ipaddr;
540         packet->src_port = sock->other_port;
541         packet->dst_ipaddr = sock->my_ipaddr;
542         packet->dst_port = sock->my_port;
543         packet->code = data[0];
544         packet->id = data[1];
545         packet->data_len = length;
546         packet->data = rad_malloc(packet->data_len);
547         memcpy(packet->data, data, packet->data_len);
548         memcpy(packet->vector, packet->data + 4, 16);
549
550         /*
551          *      FIXME: Client MIB updates?
552          */
553         switch(packet->code) {
554         case PW_AUTHENTICATION_ACK:
555         case PW_ACCESS_CHALLENGE:
556         case PW_AUTHENTICATION_REJECT:
557                 fun = rad_authenticate;
558                 break;
559
560 #ifdef WITH_ACCOUNTING
561         case PW_ACCOUNTING_RESPONSE:
562                 fun = rad_accounting;
563                 break;
564 #endif
565
566         default:
567                 /*
568                  *      FIXME: Update MIB for packet types?
569                  */
570                 radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
571                        "from home server %s port %d - ID %d : IGNORED",
572                        packet->code,
573                        ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
574                        packet->src_port, packet->id);
575                 rad_free(&packet);
576                 return 0;
577         }
578
579         if (!request_proxy_reply(packet)) {
580                 rad_free(&packet);
581                 return 0;
582         }
583
584         return 1;
585 }
586
587 int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
588 {
589         int rcode;
590         listen_socket_t *sock = listener->data;
591
592         /*
593          *      Normal proxying calls us with the data already
594          *      encoded.  The "ping home server" code does not.  So,
595          *      if there's no packet, encode it here.
596          */
597         if (!request->proxy->data) {
598                 request->proxy_listener->encode(request->proxy_listener,
599                                                 request);
600         }
601
602         DEBUG3("Proxy is writing %u bytes to SSL",
603                (unsigned int) request->proxy->data_len);
604         PTHREAD_MUTEX_LOCK(&sock->mutex);
605         while ((rcode = SSL_write(sock->ssn->ssl, request->proxy->data,
606                                   request->proxy->data_len)) < 0) {
607                 int err;
608                 while ((err = ERR_get_error())) {
609                         DEBUG("proxy SSL_write says %s",
610                               ERR_error_string(err, NULL));
611                 }
612                 PTHREAD_MUTEX_UNLOCK(&sock->mutex);
613                 tls_socket_close(listener);
614                 return 0;
615         }
616         PTHREAD_MUTEX_UNLOCK(&sock->mutex);
617
618         return 1;
619 }
620
621 #endif  /* WITH_TLS */