_gnutls_strdatum_to_buf() will account for NULL input.
[gnutls.git] / src / crywrap / crywrap.c
blob8338d073a9c96b44850f836d96d9ad7b8f152954
1 /* -*- mode: c; c-file-style: "gnu" -*-
2 * crywrap.c -- CryWrap
3 * Copyright (C) 2003, 2004 Gergely Nagy <algernon@bonehunter.rulez.org>
4 * Copyright (C) 2011 Nikos Mavrogiannopoulos
6 * This file is part of CryWrap.
8 * CryWrap is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * CryWrap is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /** @file crywrap.c
23 * CryWrap itself.
26 #include <config.h>
28 #ifdef HAVE_ARGP_H
29 #include <argp.h>
30 #endif
31 #include <arpa/inet.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <gnutls/gnutls.h>
35 #include <gnutls/x509.h>
36 #include <grp.h>
37 #include <idna.h>
38 #include <netdb.h>
39 #include <netinet/in.h>
40 #include <pwd.h>
41 #include <signal.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <stringprep.h>
46 #include <sys/select.h>
47 #include <sys/socket.h>
48 #include <sys/types.h>
49 #include <sys/wait.h>
50 #include <syslog.h>
51 #include <stdarg.h>
52 #include <unistd.h>
54 /* Gnulib portability files. */
55 #include "progname.h"
56 #include "argp.h"
57 #include <read-file.h>
59 #include "crywrap.h"
60 #include "primes.h"
62 static int system_log(const char* fmt, ...)
63 #ifdef __GNUC__
64 __attribute__ ((format (printf, 1, 2)))
65 #endif
68 static int system_log_error(const char* fmt, ...)
69 #ifdef __GNUC__
70 __attribute__ ((format (printf, 1, 2)))
71 #endif
74 static int debug_log(const char* fmt, ...)
75 #ifdef __GNUC__
76 __attribute__ ((format (printf, 1, 2)))
77 #endif
80 typedef int (*cry_log_func)(const char *format, ...)
81 #ifdef __GNUC__
82 __attribute__ ((format (printf, 1, 2)))
83 #endif
86 static cry_log_func cry_log = system_log;
87 static cry_log_func cry_error = system_log_error;
89 static void
90 tls_audit_log_func (gnutls_session_t session, const char *str)
92 char peer_name[NI_MAXHOST] = "Unknown";
93 gnutls_transport_ptr_t r, s;
94 struct sockaddr_storage faddr;
95 socklen_t socklen = sizeof (struct sockaddr_storage);
97 if (session != NULL)
99 gnutls_transport_get_ptr2(session, &r, &s);
101 /* Log the connection */
102 if (getpeername ((int)(long)r, (struct sockaddr *)&faddr, &socklen) != 0)
103 cry_error ("getpeername(): %s", strerror (errno));
105 cry_log ("Peer %s: %s", peer_name, str);
107 else
108 cry_log ("%s", str);
112 /** @defgroup globals Global variables.
113 * @{
116 /** An array of pids.
117 * This array holds the PIDs of all of our children, indexed by the
118 * socket the associated client connected to us.
120 static pid_t main_pid = -1; /**< Pid of the main process */
121 static const char *pidfile = _CRYWRAP_PIDFILE; /**< File to log our PID
122 into. */
124 /** GNUTLS server credentials.
126 static gnutls_certificate_server_credentials cred;
127 static gnutls_dh_params dh_params; /**< GNUTLS DH parameters. */
128 static gnutls_datum dh_file = { (void*)_crywrap_prime_dh_1024, sizeof(_crywrap_prime_dh_1024) }; /**< Diffie Hellman parameters */
130 /** Bugreport address.
131 * Used by the argp suite.
133 const char *argp_program_bug_address = "<bugs-gnutls@gnu.org>";
134 /** Porgram version.
135 * Used by the argp suite.
137 const char *argp_program_version = __CRYWRAP__ " " _CRYWRAP_VERSION;
139 /* The certificate and key files */
140 static char *pem_cert = NULL;
141 static char *pem_key = NULL;
144 /** The options CryWrap takes.
145 * Used by the argp suite.
147 static const struct argp_option _crywrap_options[] = {
148 {NULL, 0, NULL, 0, "Mandatory options:", 1},
149 {"destination", 'd', "IP/PORT", 0, "IP and port to connect to", 1},
150 {"listen", 'l', "IP/PORT", 0, "IP and port to listen on", 1},
151 {NULL, 0, NULL, 0, "TLS certificates:", 2},
152 {"key", 'k', "FILE", 0, "Server key", 2},
153 {"cert", 'c', "FILE", 0, "Server certificate", 2},
154 {"ca", 'z', "FILE", 0, "CA certificate", 2},
155 {"anon", 'a', NULL, 0, "Enable anonymous authentication (no certificates)", 2},
156 {"verify", 'v', "LEVEL", OPTION_ARG_OPTIONAL,
157 "Verify clients certificate (1: verify if exists, 2: require)", 2},
158 {NULL, 0, NULL, 0, "Other options:", 3},
159 {"dhparams", 'r', "FILE", 0, "Diffie Hellman (PKCS #3) parameters file", 3},
160 {"user", 'u', "UID", 0, "User ID to run as", 3},
161 {"pidfile", 'P', "PATH", 0, "File to log the PID into", 3},
162 {"priority", 'p', "STRING", 0, "GnuTLS ciphersuite priority string", 3},
163 {"inetd", 'i', NULL, 0, "Enable inetd mode", 3},
164 {"debug", 'D', NULL, 0, "Run the server into foreground", 3},
165 {0, 0, 0, 0, NULL, 0}
168 static error_t _crywrap_config_parse_opt (int key, char *arg,
169 struct argp_state *state);
170 /** The main argp structure for Crywrap.
172 static const struct argp _crywrap_argp =
173 {_crywrap_options, _crywrap_config_parse_opt, 0,
174 __CRYWRAP__ " -- Security for the masses\v"
175 "The --destination option is mandatory, as is --listen if --inetd "
176 "was not used.",
177 NULL, NULL, NULL};
179 /** @} */
181 /** @defgroup signal Signal handlers & co.
182 * @{
185 /** SIGCHLD handler
187 static void
188 _crywrap_sigchld_handler (int sig)
190 pid_t child;
191 int status;
193 while ((child = waitpid (-1, &status, WNOHANG)) > (pid_t) 0)
194 signal (sig, _crywrap_sigchld_handler);
197 /* Helper functions to load a certificate and key
198 * files into memory.
200 static gnutls_datum_t
201 load_file (const char *file)
203 gnutls_datum_t loaded_file = { NULL, 0 };
204 size_t length;
206 loaded_file.data = (void*)read_binary_file (file, &length);
207 if (loaded_file.data)
208 loaded_file.size = (unsigned int) length;
210 return loaded_file;
213 /** Generic signal handler.
214 * This one removes the #pidfile, if necessary.
216 static void
217 _crywrap_sighandler (int sig)
219 if (getpid () == main_pid)
221 cry_log ("Exiting on signal %d", sig);
222 if (pidfile && *pidfile)
223 unlink (pidfile);
224 closelog ();
225 exit (0);
228 /** @} */
230 /** @defgroup parsing Option parsing
231 * @{
234 /** Service resolver.
235 * Resolves a service - be it a name or a number.
237 * @param serv is the port to resolve.
239 * @returns The purt number, or -1 on error.
241 static int
242 _crywrap_port_get (const char *serv)
244 int port;
245 struct servent *se;
247 if (!serv)
248 return -1;
250 se = getservbyname (serv, "tcp");
251 if (!se)
252 port = atoi (serv);
253 else
254 port = ntohs (se->s_port);
256 return port;
259 /** Address resolver.
260 * Resolves an address - be it numeric or a hostname, IPv4 or IPv6.
262 * @param hostname is the host to resolve.
263 * @param addr is the structure to put the result into.
265 * @returns Zero on success, -1 on error.
267 static int
268 _crywrap_addr_get (const char *hostname, struct sockaddr_storage **addr)
270 struct addrinfo *res;
271 struct addrinfo hints;
272 ssize_t len;
273 char *lz = NULL;
275 if (idna_to_ascii_lz (hostname, &lz, 0) != IDNA_SUCCESS)
276 return -1;
278 memset (&hints, 0, sizeof (hints));
279 hints.ai_family = PF_UNSPEC;
280 hints.ai_socktype = SOCK_STREAM;
281 hints.ai_protocol = IPPROTO_IP;
282 *addr = calloc (1, sizeof (struct sockaddr_storage));
283 if (*addr == NULL)
285 free(lz);
286 return -1;
289 if (getaddrinfo (lz, NULL, &hints, &res) != 0)
291 free (lz);
292 return -1;
295 free (lz);
297 switch (res->ai_addr->sa_family)
299 case AF_INET:
300 len = sizeof (struct sockaddr_in);
301 break;
302 case AF_INET6:
303 len = sizeof (struct sockaddr_in6);
304 break;
305 default:
306 freeaddrinfo (res);
307 return -1;
310 if (len < (ssize_t)res->ai_addrlen)
312 freeaddrinfo (res);
313 return -1;
316 memcpy (*addr, res->ai_addr, res->ai_addrlen);
317 freeaddrinfo (res);
319 return 0;
322 /** Parse a HOST/IP pair.
323 * Splits up a given HOST/IP pair, and converts them into structures
324 * directly usable by libc routines.
326 * @param ip is the HOST/IP pair to parse.
327 * @param port is a pointer to an integer where the port number should
328 * go.
329 * @param addr is the destination of the resolved and parsed IP.
331 * @returns Zero on success, -1 on error.
333 static int
334 _crywrap_parse_ip (const char *ip, in_port_t *port,
335 struct sockaddr_storage **addr, char **host)
337 char *s_ip;
338 char *tmp;
340 tmp = strchr (ip, '/');
342 if (!tmp)
343 return -1;
345 if (tmp == ip)
347 s_ip = strdup ("0.0.0.0");
348 *port = (in_port_t)_crywrap_port_get (&ip[1]);
350 else
352 *port = (in_port_t)_crywrap_port_get (&tmp[1]);
353 s_ip = strndup (ip, tmp - ip);
356 if (!*port)
357 return -1;
359 if (host)
360 *host = strdup (s_ip);
362 return _crywrap_addr_get (s_ip, addr);
365 /** Argument parsing routine.
366 * Used by the argp suite.
368 static error_t
369 _crywrap_config_parse_opt (int key, char *arg, struct argp_state *state)
371 crywrap_config_t *cfg = (crywrap_config_t *)state->input;
372 int ret;
374 switch (key)
376 case 'D':
377 cfg->debug = 1;
378 cry_log = debug_log;
379 cry_error = debug_log;
380 break;
381 case 'd':
382 if (_crywrap_parse_ip (arg, &cfg->dest.port, &cfg->dest.addr,
383 &cfg->dest.host) < 0)
384 argp_error (state, "Could not resolve address: `%s'", arg);
385 break;
386 case 'l':
387 if (_crywrap_parse_ip (arg, &cfg->listen.port,
388 &cfg->listen.addr, NULL) < 0)
389 argp_error (state, "Could not resolve address: `%s'", arg);
390 break;
391 case 'u':
392 cfg->uid = atoi (arg);
393 break;
394 case 'P':
395 if (arg && *arg)
396 cfg->pidfile = strdup (arg);
397 else
398 cfg->pidfile = NULL;
399 break;
400 case 'r':
401 if (arg && *arg)
403 dh_file = load_file(arg);
404 if (dh_file.data == NULL)
405 argp_error (state, "error loading Diffie Hellman parameters file: %s.", arg);
407 break;
408 case 'p':
409 if (arg && *arg)
411 const char* pos;
412 ret = gnutls_priority_init(&cfg->priority, arg, &pos);
413 if (ret < 0)
414 argp_error (state, "error in priority string at: %s.", pos);
416 break;
417 case 'c':
418 if (arg && *arg)
419 pem_cert = strdup (arg);
420 break;
421 case 'k':
422 if (arg && *arg)
423 pem_key = strdup (arg);
424 break;
426 break;
427 case 'i':
428 cfg->inetd = 1;
429 break;
430 case 'a':
432 const char* pos;
433 ret = gnutls_priority_init(&cfg->priority, "NORMAL:+ANON-ECDH:+ANON-DH", &pos);
434 if (ret < 0)
435 argp_error (state, "error in priority string at: %s.", pos);
437 cfg->verify = 0;
438 cfg->anon = 1;
439 break;
440 case 'v':
441 cfg->verify = (arg) ? atoi (arg) : 1;
442 break;
443 case 'z':
444 ret = gnutls_certificate_set_x509_trust_file (cred, arg,
445 GNUTLS_X509_FMT_PEM);
446 if (ret < 0)
447 argp_error (state, "error reading X.509 CA file: %s.", gnutls_strerror(ret));
448 break;
450 case ARGP_KEY_END:
451 if (!cfg->inetd)
453 if (!cfg->listen.addr || !cfg->dest.addr)
454 argp_error
455 (state,
456 "a listening and a destination address must be set!");
458 else
459 if (!cfg->dest.addr)
460 argp_error (state, "a destination address must be set!");
461 if (cfg->anon)
462 break;
463 if (pem_cert == NULL || pem_key == NULL)
464 ret = gnutls_certificate_set_x509_key_file (cred, _CRYWRAP_PEMFILE,
465 _CRYWRAP_PEMFILE,
466 GNUTLS_X509_FMT_PEM);
467 else
468 ret = gnutls_certificate_set_x509_key_file (cred, pem_cert, pem_key,
469 GNUTLS_X509_FMT_PEM);
471 if (ret < 0)
472 argp_error (state, "Error reading X.509 key or certificate file: %s", gnutls_strerror(ret));
473 break;
474 default:
475 return ARGP_ERR_UNKNOWN;
478 return 0;
481 /** Configuration parsing.
482 * Sets up the default values, and parses the command-line options
483 * using argp.
485 * @note Does not return if an error occurred.
487 static crywrap_config_t *
488 _crywrap_config_parse (int argc, char **argv)
490 crywrap_config_t *config =
491 (crywrap_config_t *)malloc (sizeof (crywrap_config_t));
493 if (config == NULL)
494 return NULL;
496 config->listen.port = 0;
497 config->listen.addr = NULL;
498 config->dest.port = 0;
499 config->dest.addr = NULL;
500 config->priority = NULL;
501 config->uid = _CRYWRAP_UID;
502 config->pidfile = _CRYWRAP_PIDFILE;
503 config->inetd = 0;
504 config->anon = 0;
505 config->verify = 0;
507 argp_parse (&_crywrap_argp, argc, argv, 0, 0, config);
509 if (config->priority == NULL)
510 gnutls_priority_init(&config->priority, "NORMAL", NULL);
512 return config;
514 /** @} */
516 /** @defgroup tls Lower-level TLS routines.
517 * @{
520 /** Create a GNUTLS session.
521 * Initialises the cyphers and the session database for a new TLS
522 * session.
524 * @returns The newly created TLS session.
526 static gnutls_session_t
527 _crywrap_tls_session_create (const crywrap_config_t *config)
529 gnutls_session_t session;
530 int ret;
532 gnutls_init (&session, GNUTLS_SERVER);
534 if (config->anon) {
535 gnutls_credentials_set (session, GNUTLS_CRD_ANON, cred);
536 } else {
537 gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred);
540 ret = gnutls_priority_set(session, config->priority);
541 if (ret < 0)
543 cry_error ("Error setting priority %s: ", gnutls_strerror(ret));
544 exit (4);
547 if (config->verify==1)
548 gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
549 else if (config->verify==2)
550 gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE);
552 return session;
555 /** Generate initial DH and RSA params.
556 * Loads the pre-generated DH primes.
558 static void
559 _crywrap_tls_init (void)
562 gnutls_dh_params_init (&dh_params);
563 gnutls_dh_params_import_pkcs3 (dh_params, &dh_file, GNUTLS_X509_FMT_PEM);
565 gnutls_certificate_set_dh_params (cred, dh_params);
567 /** @} */
569 /** @defgroup networking Networking
570 * @{
573 /** Bind to an address.
574 * This one binds to an address, handles errors and anything that may
575 * arise.
577 * @param ai is the address information.
578 * @param listen_port is the port to bind to, and listen on.
580 * @returns The bound filedescriptor, or -1 on error.
582 static int
583 _crywrap_bind (const struct addrinfo *ai, int listen_port)
585 int ret;
586 const int one = 1;
587 int listenfd;
588 char sock_name[NI_MAXHOST];
590 listenfd = socket (ai->ai_family, SOCK_STREAM, IPPROTO_IP);
591 if (listenfd == -1)
593 cry_error ("socket: %s", strerror (errno));
594 return -1;
597 memset (sock_name, 0, sizeof (sock_name));
598 getnameinfo ((struct sockaddr *)ai->ai_addr, ai->ai_addrlen, sock_name,
599 sizeof (sock_name), NULL, 0, NI_NUMERICHOST);
601 switch (ai->ai_family)
603 case AF_INET6:
604 ((struct sockaddr_in6 *)(ai->ai_addr))->sin6_port = listen_port;
605 break;
606 case AF_INET:
607 ((struct sockaddr_in *)(ai->ai_addr))->sin_port = listen_port;
608 break;
611 ret = setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR,
612 &one, sizeof (one));
613 if (ret != 0)
615 cry_error ("setsockopt: %s (%s)", strerror (errno), sock_name);
616 return -1;
619 ret = bind (listenfd, ai->ai_addr, ai->ai_addrlen);
620 if (ret != 0)
622 cry_error ("bind to %s failed: %s", sock_name, strerror (errno));
623 return -1;
626 if (listen (listenfd, _CRYWRAP_MAXCONN) != 0)
628 cry_error ("listen on %s failed: %s", sock_name, strerror (errno));
629 return -1;
632 cry_log ("Socket bound to port %d on %s.", ntohs (listen_port), sock_name);
634 return listenfd;
637 /** Set up a listening socket.
638 * Sets up a listening socket on all the required addresses.
640 * @param config holds the CryWrap configuration, from where the
641 * listen address and port will be extracted.
643 * @returns The listening FD on success, -1 on error.
645 static int
646 _crywrap_listen (const crywrap_config_t *config)
648 struct addrinfo *cur;
649 int ret;
651 cur = calloc (1, sizeof (struct addrinfo));
652 if (cur == NULL)
653 return -1;
655 cur->ai_family = config->listen.addr->ss_family;
657 switch (cur->ai_family)
659 case AF_INET6:
660 cur->ai_addrlen = sizeof (struct sockaddr_in6);
661 break;
662 case AF_INET:
663 cur->ai_addrlen = sizeof (struct sockaddr_in);
664 break;
667 cur->ai_addr = malloc (cur->ai_addrlen);
668 if (cur->ai_addr == NULL)
669 return -1;
671 memcpy (cur->ai_addr, config->listen.addr, cur->ai_addrlen);
673 ret = _crywrap_bind (cur, htons (config->listen.port));
674 free (cur->ai_addr);
675 free (cur);
677 return ret;
680 /** Connect to a remote server.
681 * Estabilishes a connection to a remote server, and handles all
682 * errors and anything that may arise during this process.
684 * @param addr is the address of the remote server.
685 * @param port is the port to connect to.
687 * @returns the connected socket on success, otherwise it exits.
689 static int
690 _crywrap_remote_connect (const struct sockaddr_storage *addr, int port)
692 struct addrinfo *cur;
693 int sock;
695 cur = calloc (1, sizeof (struct addrinfo));
696 if (cur == NULL)
697 return -1;
699 cur->ai_family = addr->ss_family;
701 switch (cur->ai_family)
703 case AF_INET6:
704 cur->ai_addrlen = sizeof (struct sockaddr_in6);
705 break;
706 case AF_INET:
707 cur->ai_addrlen = sizeof (struct sockaddr_in);
708 break;
711 cur->ai_addr = malloc (cur->ai_addrlen);
712 if (cur->ai_addr == NULL)
713 return -1;
715 memcpy (cur->ai_addr, addr, cur->ai_addrlen);
717 switch (cur->ai_family)
719 case AF_INET6:
720 ((struct sockaddr_in6 *)(cur->ai_addr))->sin6_port = port;
721 break;
722 case AF_INET:
723 ((struct sockaddr_in *)(cur->ai_addr))->sin_port = port;
724 break;
727 sock = socket (cur->ai_family, SOCK_STREAM, IPPROTO_IP);
728 if (sock < 0)
730 cry_error ("socket(): %s", strerror (errno));
731 exit (1);
734 if (connect (sock, cur->ai_addr, cur->ai_addrlen) < 0)
736 cry_error ("connect(): %s", strerror (errno));
737 exit (1);
740 free (cur->ai_addr);
741 free (cur);
743 return sock;
746 /** @} */
748 /** @defgroup crywrap Main CryWrap code.
749 * @{
752 /** Drop privileges.
753 * Drop privileges, if running as root.
754 * Upon failure, it will make CryWrap exit.
756 static void
757 _crywrap_privs_drop (const crywrap_config_t *config)
759 struct passwd *pwd;
761 if (getuid () != 0)
763 cry_log ("%s", "Not running as root, not dropping privileges.");
764 return;
767 if ((pwd = getpwuid (config->uid)) == NULL)
769 cry_error ("getpwuid(): %s", strerror (errno));
770 exit (1);
773 if (initgroups (pwd->pw_name, pwd->pw_gid) == -1)
775 cry_error ("initgroups(): %s", strerror (errno));
776 exit (1);
779 if (setgid (pwd->pw_gid) == -1)
781 cry_error ("setgid(): %s", strerror (errno));
782 exit (1);
785 if (setuid (config->uid))
787 cry_error ("setuid(): %s", strerror (errno));
788 exit (1);
792 /** Set up the PID file.
793 * Checks if a #pidfile already exists, and create one - containing the
794 * current PID - if one does not.
796 * @note Exits upon error.
798 static void
799 _crywrap_setup_pidfile (const crywrap_config_t *config)
801 char mypid[128];
802 int pidfilefd;
804 if (!config->pidfile || !*(config->pidfile))
805 return;
807 if (!access (config->pidfile, F_OK))
809 cry_error ("Pidfile (%s) already exists. Exiting.", config->pidfile);
810 exit (1);
812 if ((pidfilefd = open (config->pidfile,
813 O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
815 cry_error ("Cannot create pidfile (%s): %s.\n", config->pidfile,
816 strerror (errno));
817 exit (1);
819 fchown (pidfilefd, config->uid, (gid_t)-1);
821 main_pid = getpid ();
822 snprintf (mypid, sizeof (mypid), "%d\n", main_pid);
823 write (pidfilefd, mypid, strlen (mypid));
824 close (pidfilefd);
825 pidfile = config->pidfile;
829 /** Handles one client.
830 * This one connects to the remote server, and proxies every traffic
831 * between our client and the server.
833 * @param config is the main CryWrap configuration structure.
834 * @param insock is the socket through which the client sends input.
835 * @param outsock is the socket through which we send output.
837 * @note Exits on error.
839 static int
840 _crywrap_do_one (const crywrap_config_t *config, int insock, int outsock)
842 int sock, ret, tls_pending;
843 gnutls_session_t session;
844 char buffer[_CRYWRAP_MAXBUF + 2];
845 fd_set fdset;
846 unsigned int status = 0;
847 struct sockaddr_storage faddr;
848 socklen_t socklen = sizeof (struct sockaddr_storage);
849 char peer_name[NI_MAXHOST];
851 /* Log the connection */
852 if (getpeername (insock, (struct sockaddr *)&faddr, &socklen) != 0)
853 cry_error ("getpeername(): %s", strerror (errno));
854 else
856 getnameinfo ((struct sockaddr *)&faddr,
857 sizeof (struct sockaddr_storage), peer_name,
858 sizeof (peer_name), NULL, 0, NI_NUMERICHOST);
859 cry_log ("Accepted connection from %s on %d to %s/%d",
860 peer_name, insock, config->dest.host,
861 config->dest.port);
864 /* Do the handshake with our peer */
865 session = _crywrap_tls_session_create (config);
866 gnutls_transport_set_ptr2 (session,
867 (gnutls_transport_ptr_t)insock,
868 (gnutls_transport_ptr_t)outsock);
872 ret = gnutls_handshake(session);
874 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
876 if (ret < 0)
878 cry_error ("Handshake failed: %s", gnutls_strerror (ret));
879 gnutls_alert_send_appropriate(session, ret);
880 goto error;
883 /* Verify the client's certificate, if any. */
884 if (config->verify)
886 ret = gnutls_certificate_verify_peers2 (session, &status);
887 if (ret < 0)
888 cry_log ("Error getting certificate from client: %s",
889 gnutls_strerror (ret));
891 if (ret == 0 && status != 0)
893 if (status & GNUTLS_CERT_INVALID)
894 cry_log ("%s", "Client certificate not trusted or invalid");
897 if (config->verify > 0 && status != 0)
899 ret = -1;
900 gnutls_alert_send( session, GNUTLS_AL_FATAL, GNUTLS_A_INSUFFICIENT_SECURITY);
901 goto error;
905 /* Connect to the remote host */
906 sock = _crywrap_remote_connect (config->dest.addr,
907 htons (config->dest.port));
909 for (;;)
911 FD_ZERO (&fdset);
912 FD_SET (insock, &fdset);
913 FD_SET (sock, &fdset);
915 memset (buffer, 0, _CRYWRAP_MAXBUF + 1);
917 tls_pending = 0;
919 if (gnutls_record_check_pending(session) > 0)
920 tls_pending = 1;
921 else
923 select (sock + 1, &fdset, NULL, NULL, NULL);
924 if (FD_ISSET (insock, &fdset))
925 tls_pending = 1;
927 /* TLS client */
928 if (tls_pending != 0)
930 ret = gnutls_record_recv (session, buffer, _CRYWRAP_MAXBUF);
931 if (ret == 0)
933 cry_log ("%s", "Peer has closed the GNUTLS connection");
934 break;
936 else if (ret < 0)
938 cry_log ("Received corrupted data: %s.",
939 gnutls_strerror (ret));
940 break;
942 else
943 send (sock, buffer, ret, 0);
946 /* Remote server */
947 if (FD_ISSET (sock, &fdset))
949 ret = recv (sock, buffer, _CRYWRAP_MAXBUF, 0);
950 if (ret == 0)
952 cry_log ("%s", "Server has closed the connection");
953 break;
955 else if (ret < 0)
957 cry_log ("Received corrupted data: %s.", strerror (errno));
958 break;
960 else
962 int r, o = 0;
966 r = gnutls_record_send (session, &buffer[o], ret - o);
967 o += r;
968 } while (r > 0 && ret > o);
970 if (r < 0)
971 cry_log ("Received corrupt data: %s", gnutls_strerror (r));
976 error:
977 gnutls_bye (session, GNUTLS_SHUT_WR);
978 gnutls_deinit (session);
979 close (insock);
980 close (outsock);
982 return (ret == 0) ? 0 : 1;
985 /** CryWrap entry point.
986 * This is the main entry point - controls the whole program and so
987 * on...
990 main (int argc, char **argv, char **envp)
992 crywrap_config_t *config;
993 int server_socket;
995 openlog (__CRYWRAP__, LOG_PID, LOG_DAEMON);
997 gnutls_global_set_audit_log_function (tls_audit_log_func);
999 if (gnutls_global_init () < 0)
1001 cry_error ("%s", "Global TLS state initialisation failed.");
1002 exit (1);
1004 if (gnutls_certificate_allocate_credentials (&cred) < 0)
1006 cry_error ("%s", "Couldn't allocate credentials.");
1007 exit (1);
1010 stringprep_locale_charset ();
1012 config = _crywrap_config_parse (argc, argv);
1013 set_program_name(__CRYWRAP__);
1015 _crywrap_tls_init ();
1017 if (config->inetd)
1019 _crywrap_privs_drop (config);
1020 exit (_crywrap_do_one (config, 0, 1));
1023 if (!config->debug)
1024 if (daemon (0, 0))
1026 cry_error ("daemon: %s", strerror (errno));
1027 exit (1);
1030 cry_log ("%s", "Crywrap starting...");
1032 server_socket = _crywrap_listen (config);
1033 if (server_socket < 0)
1034 exit (1);
1036 if (!config->debug) _crywrap_setup_pidfile (config);
1037 _crywrap_privs_drop (config);
1039 signal (SIGTERM, _crywrap_sighandler);
1040 signal (SIGQUIT, _crywrap_sighandler);
1041 signal (SIGSEGV, _crywrap_sighandler);
1042 signal (SIGPIPE, SIG_IGN);
1043 signal (SIGHUP, SIG_IGN);
1044 signal (SIGCHLD, _crywrap_sigchld_handler);
1046 cry_log ("%s", "Accepting connections");
1049 for (;;)
1051 int csock;
1052 int child;
1054 csock = accept (server_socket, NULL, NULL);
1055 if (csock < 0)
1056 continue;
1058 child = fork ();
1059 switch (child)
1061 case 0:
1062 exit (_crywrap_do_one (config, csock, csock));
1063 break;
1064 case -1:
1065 cry_error ("%s", "Forking error.");
1066 exit (1);
1067 break;
1069 close(csock);
1072 return 0;
1075 static int system_log(const char* fmt, ...)
1077 va_list args;
1079 va_start (args, fmt);
1080 vsyslog(LOG_NOTICE, fmt, args);
1081 va_end (args);
1083 return 0;
1086 static int system_log_error(const char* fmt, ...)
1088 va_list args;
1090 va_start (args, fmt);
1091 vsyslog(LOG_ERR, fmt, args);
1092 va_end (args);
1094 return 0;
1097 static int debug_log(const char* fmt, ...)
1099 va_list args;
1101 va_start (args, fmt);
1102 vprintf(fmt, args);
1103 puts("");
1104 va_end (args);
1106 return 0;
1109 /** @} */