1 /* -*- mode: c; c-file-style: "gnu" -*-
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/>.
31 #include <arpa/inet.h>
34 #include <gnutls/gnutls.h>
35 #include <gnutls/x509.h>
39 #include <netinet/in.h>
45 #include <stringprep.h>
46 #include <sys/select.h>
47 #include <sys/socket.h>
48 #include <sys/types.h>
54 /* Gnulib portability files. */
57 #include <read-file.h>
62 static int system_log(const char* fmt
, ...)
64 __attribute__ ((format (printf
, 1, 2)))
68 static int system_log_error(const char* fmt
, ...)
70 __attribute__ ((format (printf
, 1, 2)))
74 static int debug_log(const char* fmt
, ...)
76 __attribute__ ((format (printf
, 1, 2)))
80 typedef int (*cry_log_func
)(const char *format
, ...)
82 __attribute__ ((format (printf
, 1, 2)))
86 static cry_log_func cry_log
= system_log
;
87 static cry_log_func cry_error
= system_log_error
;
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
);
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
);
112 /** @defgroup globals Global variables.
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
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>";
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 "
181 /** @defgroup signal Signal handlers & co.
188 _crywrap_sigchld_handler (int sig
)
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
200 static gnutls_datum_t
201 load_file (const char *file
)
203 gnutls_datum_t loaded_file
= { NULL
, 0 };
206 loaded_file
.data
= (void*)read_binary_file (file
, &length
);
207 if (loaded_file
.data
)
208 loaded_file
.size
= (unsigned int) length
;
213 /** Generic signal handler.
214 * This one removes the #pidfile, if necessary.
217 _crywrap_sighandler (int sig
)
219 if (getpid () == main_pid
)
221 cry_log ("Exiting on signal %d", sig
);
222 if (pidfile
&& *pidfile
)
230 /** @defgroup parsing Option parsing
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.
242 _crywrap_port_get (const char *serv
)
250 se
= getservbyname (serv
, "tcp");
254 port
= ntohs (se
->s_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.
268 _crywrap_addr_get (const char *hostname
, struct sockaddr_storage
**addr
)
270 struct addrinfo
*res
;
271 struct addrinfo hints
;
275 if (idna_to_ascii_lz (hostname
, &lz
, 0) != IDNA_SUCCESS
)
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
));
289 if (getaddrinfo (lz
, NULL
, &hints
, &res
) != 0)
297 switch (res
->ai_addr
->sa_family
)
300 len
= sizeof (struct sockaddr_in
);
303 len
= sizeof (struct sockaddr_in6
);
310 if (len
< (ssize_t
)res
->ai_addrlen
)
316 memcpy (*addr
, res
->ai_addr
, res
->ai_addrlen
);
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
329 * @param addr is the destination of the resolved and parsed IP.
331 * @returns Zero on success, -1 on error.
334 _crywrap_parse_ip (const char *ip
, in_port_t
*port
,
335 struct sockaddr_storage
**addr
, char **host
)
340 tmp
= strchr (ip
, '/');
347 s_ip
= strdup ("0.0.0.0");
348 *port
= (in_port_t
)_crywrap_port_get (&ip
[1]);
352 *port
= (in_port_t
)_crywrap_port_get (&tmp
[1]);
353 s_ip
= strndup (ip
, tmp
- ip
);
360 *host
= strdup (s_ip
);
362 return _crywrap_addr_get (s_ip
, addr
);
365 /** Argument parsing routine.
366 * Used by the argp suite.
369 _crywrap_config_parse_opt (int key
, char *arg
, struct argp_state
*state
)
371 crywrap_config_t
*cfg
= (crywrap_config_t
*)state
->input
;
379 cry_error
= debug_log
;
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
);
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
);
392 cfg
->uid
= atoi (arg
);
396 cfg
->pidfile
= strdup (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
);
412 ret
= gnutls_priority_init(&cfg
->priority
, arg
, &pos
);
414 argp_error (state
, "error in priority string at: %s.", pos
);
419 pem_cert
= strdup (arg
);
423 pem_key
= strdup (arg
);
433 ret
= gnutls_priority_init(&cfg
->priority
, "NORMAL:+ANON-ECDH:+ANON-DH", &pos
);
435 argp_error (state
, "error in priority string at: %s.", pos
);
441 cfg
->verify
= (arg
) ? atoi (arg
) : 1;
444 ret
= gnutls_certificate_set_x509_trust_file (cred
, arg
,
445 GNUTLS_X509_FMT_PEM
);
447 argp_error (state
, "error reading X.509 CA file: %s.", gnutls_strerror(ret
));
453 if (!cfg
->listen
.addr
|| !cfg
->dest
.addr
)
456 "a listening and a destination address must be set!");
460 argp_error (state
, "a destination address must be set!");
463 if (pem_cert
== NULL
|| pem_key
== NULL
)
464 ret
= gnutls_certificate_set_x509_key_file (cred
, _CRYWRAP_PEMFILE
,
466 GNUTLS_X509_FMT_PEM
);
468 ret
= gnutls_certificate_set_x509_key_file (cred
, pem_cert
, pem_key
,
469 GNUTLS_X509_FMT_PEM
);
472 argp_error (state
, "Error reading X.509 key or certificate file: %s", gnutls_strerror(ret
));
475 return ARGP_ERR_UNKNOWN
;
481 /** Configuration parsing.
482 * Sets up the default values, and parses the command-line options
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
));
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
;
507 argp_parse (&_crywrap_argp
, argc
, argv
, 0, 0, config
);
509 if (config
->priority
== NULL
)
510 gnutls_priority_init(&config
->priority
, "NORMAL", NULL
);
516 /** @defgroup tls Lower-level TLS routines.
520 /** Create a GNUTLS session.
521 * Initialises the cyphers and the session database for a new TLS
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
;
532 gnutls_init (&session
, GNUTLS_SERVER
);
535 gnutls_credentials_set (session
, GNUTLS_CRD_ANON
, cred
);
537 gnutls_credentials_set (session
, GNUTLS_CRD_CERTIFICATE
, cred
);
540 ret
= gnutls_priority_set(session
, config
->priority
);
543 cry_error ("Error setting priority %s: ", gnutls_strerror(ret
));
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
);
555 /** Generate initial DH and RSA params.
556 * Loads the pre-generated DH primes.
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
);
569 /** @defgroup networking Networking
573 /** Bind to an address.
574 * This one binds to an address, handles errors and anything that may
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.
583 _crywrap_bind (const struct addrinfo
*ai
, int listen_port
)
588 char sock_name
[NI_MAXHOST
];
590 listenfd
= socket (ai
->ai_family
, SOCK_STREAM
, IPPROTO_IP
);
593 cry_error ("socket: %s", strerror (errno
));
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
)
604 ((struct sockaddr_in6
*)(ai
->ai_addr
))->sin6_port
= listen_port
;
607 ((struct sockaddr_in
*)(ai
->ai_addr
))->sin_port
= listen_port
;
611 ret
= setsockopt (listenfd
, SOL_SOCKET
, SO_REUSEADDR
,
615 cry_error ("setsockopt: %s (%s)", strerror (errno
), sock_name
);
619 ret
= bind (listenfd
, ai
->ai_addr
, ai
->ai_addrlen
);
622 cry_error ("bind to %s failed: %s", sock_name
, strerror (errno
));
626 if (listen (listenfd
, _CRYWRAP_MAXCONN
) != 0)
628 cry_error ("listen on %s failed: %s", sock_name
, strerror (errno
));
632 cry_log ("Socket bound to port %d on %s.", ntohs (listen_port
), sock_name
);
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.
646 _crywrap_listen (const crywrap_config_t
*config
)
648 struct addrinfo
*cur
;
651 cur
= calloc (1, sizeof (struct addrinfo
));
655 cur
->ai_family
= config
->listen
.addr
->ss_family
;
657 switch (cur
->ai_family
)
660 cur
->ai_addrlen
= sizeof (struct sockaddr_in6
);
663 cur
->ai_addrlen
= sizeof (struct sockaddr_in
);
667 cur
->ai_addr
= malloc (cur
->ai_addrlen
);
668 if (cur
->ai_addr
== NULL
)
671 memcpy (cur
->ai_addr
, config
->listen
.addr
, cur
->ai_addrlen
);
673 ret
= _crywrap_bind (cur
, htons (config
->listen
.port
));
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.
690 _crywrap_remote_connect (const struct sockaddr_storage
*addr
, int port
)
692 struct addrinfo
*cur
;
695 cur
= calloc (1, sizeof (struct addrinfo
));
699 cur
->ai_family
= addr
->ss_family
;
701 switch (cur
->ai_family
)
704 cur
->ai_addrlen
= sizeof (struct sockaddr_in6
);
707 cur
->ai_addrlen
= sizeof (struct sockaddr_in
);
711 cur
->ai_addr
= malloc (cur
->ai_addrlen
);
712 if (cur
->ai_addr
== NULL
)
715 memcpy (cur
->ai_addr
, addr
, cur
->ai_addrlen
);
717 switch (cur
->ai_family
)
720 ((struct sockaddr_in6
*)(cur
->ai_addr
))->sin6_port
= port
;
723 ((struct sockaddr_in
*)(cur
->ai_addr
))->sin_port
= port
;
727 sock
= socket (cur
->ai_family
, SOCK_STREAM
, IPPROTO_IP
);
730 cry_error ("socket(): %s", strerror (errno
));
734 if (connect (sock
, cur
->ai_addr
, cur
->ai_addrlen
) < 0)
736 cry_error ("connect(): %s", strerror (errno
));
748 /** @defgroup crywrap Main CryWrap code.
753 * Drop privileges, if running as root.
754 * Upon failure, it will make CryWrap exit.
757 _crywrap_privs_drop (const crywrap_config_t
*config
)
763 cry_log ("%s", "Not running as root, not dropping privileges.");
767 if ((pwd
= getpwuid (config
->uid
)) == NULL
)
769 cry_error ("getpwuid(): %s", strerror (errno
));
773 if (initgroups (pwd
->pw_name
, pwd
->pw_gid
) == -1)
775 cry_error ("initgroups(): %s", strerror (errno
));
779 if (setgid (pwd
->pw_gid
) == -1)
781 cry_error ("setgid(): %s", strerror (errno
));
785 if (setuid (config
->uid
))
787 cry_error ("setuid(): %s", strerror (errno
));
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.
799 _crywrap_setup_pidfile (const crywrap_config_t
*config
)
804 if (!config
->pidfile
|| !*(config
->pidfile
))
807 if (!access (config
->pidfile
, F_OK
))
809 cry_error ("Pidfile (%s) already exists. Exiting.", config
->pidfile
);
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
,
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
));
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.
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];
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
));
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
,
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
);
878 cry_error ("Handshake failed: %s", gnutls_strerror (ret
));
879 gnutls_alert_send_appropriate(session
, ret
);
883 /* Verify the client's certificate, if any. */
886 ret
= gnutls_certificate_verify_peers2 (session
, &status
);
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)
900 gnutls_alert_send( session
, GNUTLS_AL_FATAL
, GNUTLS_A_INSUFFICIENT_SECURITY
);
905 /* Connect to the remote host */
906 sock
= _crywrap_remote_connect (config
->dest
.addr
,
907 htons (config
->dest
.port
));
912 FD_SET (insock
, &fdset
);
913 FD_SET (sock
, &fdset
);
915 memset (buffer
, 0, _CRYWRAP_MAXBUF
+ 1);
919 if (gnutls_record_check_pending(session
) > 0)
923 select (sock
+ 1, &fdset
, NULL
, NULL
, NULL
);
924 if (FD_ISSET (insock
, &fdset
))
928 if (tls_pending
!= 0)
930 ret
= gnutls_record_recv (session
, buffer
, _CRYWRAP_MAXBUF
);
933 cry_log ("%s", "Peer has closed the GNUTLS connection");
938 cry_log ("Received corrupted data: %s.",
939 gnutls_strerror (ret
));
943 send (sock
, buffer
, ret
, 0);
947 if (FD_ISSET (sock
, &fdset
))
949 ret
= recv (sock
, buffer
, _CRYWRAP_MAXBUF
, 0);
952 cry_log ("%s", "Server has closed the connection");
957 cry_log ("Received corrupted data: %s.", strerror (errno
));
966 r
= gnutls_record_send (session
, &buffer
[o
], ret
- o
);
968 } while (r
> 0 && ret
> o
);
971 cry_log ("Received corrupt data: %s", gnutls_strerror (r
));
977 gnutls_bye (session
, GNUTLS_SHUT_WR
);
978 gnutls_deinit (session
);
982 return (ret
== 0) ? 0 : 1;
985 /** CryWrap entry point.
986 * This is the main entry point - controls the whole program and so
990 main (int argc
, char **argv
, char **envp
)
992 crywrap_config_t
*config
;
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.");
1004 if (gnutls_certificate_allocate_credentials (&cred
) < 0)
1006 cry_error ("%s", "Couldn't allocate credentials.");
1010 stringprep_locale_charset ();
1012 config
= _crywrap_config_parse (argc
, argv
);
1013 set_program_name(__CRYWRAP__
);
1015 _crywrap_tls_init ();
1019 _crywrap_privs_drop (config
);
1020 exit (_crywrap_do_one (config
, 0, 1));
1026 cry_error ("daemon: %s", strerror (errno
));
1030 cry_log ("%s", "Crywrap starting...");
1032 server_socket
= _crywrap_listen (config
);
1033 if (server_socket
< 0)
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");
1054 csock
= accept (server_socket
, NULL
, NULL
);
1062 exit (_crywrap_do_one (config
, csock
, csock
));
1065 cry_error ("%s", "Forking error.");
1075 static int system_log(const char* fmt
, ...)
1079 va_start (args
, fmt
);
1080 vsyslog(LOG_NOTICE
, fmt
, args
);
1086 static int system_log_error(const char* fmt
, ...)
1090 va_start (args
, fmt
);
1091 vsyslog(LOG_ERR
, fmt
, args
);
1097 static int debug_log(const char* fmt
, ...)
1101 va_start (args
, fmt
);