diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-11-08 22:14:07 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-11-08 22:17:10 +0100 |
commit | 76c93d23c073ef8b885503b7d28a31ffe2add6d8 (patch) | |
tree | 1dd2d22a197bc40c5330e516969a7cb1ae9bc96f /src/crywrap/crywrap.c | |
parent | 559a144f6bbcbb611453f82e655dd7438c14d1a7 (diff) | |
download | gnutls-76c93d23c073ef8b885503b7d28a31ffe2add6d8.tar.gz |
reindented code
Diffstat (limited to 'src/crywrap/crywrap.c')
-rw-r--r-- | src/crywrap/crywrap.c | 1496 |
1 files changed, 742 insertions, 754 deletions
diff --git a/src/crywrap/crywrap.c b/src/crywrap/crywrap.c index b0b0799a22..f1b822cb6d 100644 --- a/src/crywrap/crywrap.c +++ b/src/crywrap/crywrap.c @@ -52,53 +52,52 @@ #include "crywrap.h" #include "primes.h" -static int system_log(const char* fmt, ...) +static int system_log(const char *fmt, ...) #ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) + __attribute__ ((format(printf, 1, 2))) #endif -; + ; -static int system_log_error(const char* fmt, ...) +static int system_log_error(const char *fmt, ...) #ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) + __attribute__ ((format(printf, 1, 2))) #endif -; + ; -static int debug_log(const char* fmt, ...) +static int debug_log(const char *fmt, ...) #ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) + __attribute__ ((format(printf, 1, 2))) #endif -; + ; -typedef int (*cry_log_func)(const char *format, ...) +typedef int (*cry_log_func) (const char *format, ...) #ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) + __attribute__ ((format(printf, 1, 2))) #endif -; + ; static cry_log_func cry_log = system_log; static cry_log_func cry_error = system_log_error; -static void -tls_audit_log_func (gnutls_session_t session, const char *str) +static void tls_audit_log_func(gnutls_session_t session, const char *str) { - char peer_name[NI_MAXHOST] = "Unknown"; - gnutls_transport_ptr_t r, s; - struct sockaddr_storage faddr; - socklen_t socklen = sizeof (struct sockaddr_storage); - - if (session != NULL) - { - gnutls_transport_get_ptr2(session, &r, &s); - - /* Log the connection */ - if (getpeername ((int)(long)r, (struct sockaddr *)&faddr, &socklen) != 0) - cry_error ("getpeername(): %s", strerror (errno)); - - cry_log ("Peer %s: %s", peer_name, str); - } - else - cry_log ("%s", str); + char peer_name[NI_MAXHOST] = "Unknown"; + gnutls_transport_ptr_t r, s; + struct sockaddr_storage faddr; + socklen_t socklen = sizeof(struct sockaddr_storage); + + if (session != NULL) { + gnutls_transport_get_ptr2(session, &r, &s); + + /* Log the connection */ + if (getpeername + ((int) (long) r, (struct sockaddr *) &faddr, + &socklen) != 0) + cry_error("getpeername(): %s", strerror(errno)); + + cry_log("Peer %s: %s", peer_name, str); + } else + cry_log("%s", str); } @@ -118,7 +117,8 @@ static const char *pidfile = _CRYWRAP_PIDFILE; /**< File to log our PID */ static gnutls_certificate_server_credentials cred; static gnutls_dh_params dh_params; /**< GNUTLS DH parameters. */ -static gnutls_datum dh_file = { (void*)_crywrap_prime_dh_1024, sizeof(_crywrap_prime_dh_1024) }; /**< Diffie Hellman parameters */ +static gnutls_datum dh_file = { (void *) _crywrap_prime_dh_1024, sizeof(_crywrap_prime_dh_1024) }; + /**< Diffie Hellman parameters */ /** Bugreport address. * Used by the argp suite. @@ -138,36 +138,41 @@ static char *pem_key = NULL; * Used by the argp suite. */ static const struct argp_option _crywrap_options[] = { - {NULL, 0, NULL, 0, "Mandatory options:", 1}, - {"destination", 'd', "IP/PORT", 0, "IP and port to connect to", 1}, - {"listen", 'l', "IP/PORT", 0, "IP and port to listen on", 1}, - {NULL, 0, NULL, 0, "TLS certificates:", 2}, - {"key", 'k', "FILE", 0, "Server key", 2}, - {"cert", 'c', "FILE", 0, "Server certificate", 2}, - {"ca", 'z', "FILE", 0, "CA certificate", 2}, - {"anon", 'a', NULL, 0, "Enable anonymous authentication (no certificates)", 2}, - {"verify", 'v', "LEVEL", OPTION_ARG_OPTIONAL, - "Verify clients certificate (1: verify if exists, 2: require)", 2}, - {NULL, 0, NULL, 0, "Other options:", 3}, - {"dhparams", 'r', "FILE", 0, "Diffie Hellman (PKCS #3) parameters file", 3}, - {"user", 'u', "UID", 0, "User ID to run as", 3}, - {"pidfile", 'P', "PATH", 0, "File to log the PID into", 3}, - {"priority", 'p', "STRING", 0, "GnuTLS ciphersuite priority string", 3}, - {"inetd", 'i', NULL, 0, "Enable inetd mode", 3}, - {"debug", 'D', NULL, 0, "Run the server into foreground", 3}, - {0, 0, 0, 0, NULL, 0} + {NULL, 0, NULL, 0, "Mandatory options:", 1}, + {"destination", 'd', "IP/PORT", 0, "IP and port to connect to", 1}, + {"listen", 'l', "IP/PORT", 0, "IP and port to listen on", 1}, + {NULL, 0, NULL, 0, "TLS certificates:", 2}, + {"key", 'k', "FILE", 0, "Server key", 2}, + {"cert", 'c', "FILE", 0, "Server certificate", 2}, + {"ca", 'z', "FILE", 0, "CA certificate", 2}, + {"anon", 'a', NULL, 0, + "Enable anonymous authentication (no certificates)", 2}, + {"verify", 'v', "LEVEL", OPTION_ARG_OPTIONAL, + "Verify clients certificate (1: verify if exists, 2: require)", + 2}, + {NULL, 0, NULL, 0, "Other options:", 3}, + {"dhparams", 'r', "FILE", 0, + "Diffie Hellman (PKCS #3) parameters file", 3}, + {"user", 'u', "UID", 0, "User ID to run as", 3}, + {"pidfile", 'P', "PATH", 0, "File to log the PID into", 3}, + {"priority", 'p', "STRING", 0, + "GnuTLS ciphersuite priority string", 3}, + {"inetd", 'i', NULL, 0, "Enable inetd mode", 3}, + {"debug", 'D', NULL, 0, "Run the server into foreground", 3}, + {0, 0, 0, 0, NULL, 0} }; -static error_t _crywrap_config_parse_opt (int key, char *arg, - struct argp_state *state); +static error_t _crywrap_config_parse_opt(int key, char *arg, + struct argp_state *state); /** The main argp structure for Crywrap. */ static const struct argp _crywrap_argp = - {_crywrap_options, _crywrap_config_parse_opt, 0, - __CRYWRAP__ " -- Security for the masses\v" - "The --destination option is mandatory, as is --listen if --inetd " - "was not used.", - NULL, NULL, NULL}; + { _crywrap_options, _crywrap_config_parse_opt, 0, + __CRYWRAP__ " -- Security for the masses\v" + "The --destination option is mandatory, as is --listen if --inetd " + "was not used.", + NULL, NULL, NULL +}; /** @} */ @@ -177,44 +182,41 @@ static const struct argp _crywrap_argp = /** SIGCHLD handler */ -static void -_crywrap_sigchld_handler (int sig) +static void _crywrap_sigchld_handler(int sig) { -pid_t child; -int status; + pid_t child; + int status; - while ((child = waitpid (-1, &status, WNOHANG)) > (pid_t) 0) - signal (sig, _crywrap_sigchld_handler); + while ((child = waitpid(-1, &status, WNOHANG)) > (pid_t) 0) + signal(sig, _crywrap_sigchld_handler); } /* Helper functions to load a certificate and key * files into memory. */ -static gnutls_datum_t -load_file (const char *file) +static gnutls_datum_t load_file(const char *file) { - gnutls_datum_t loaded_file = { NULL, 0 }; + gnutls_datum_t loaded_file = { NULL, 0 }; - gnutls_load_file(file, &loaded_file); + gnutls_load_file(file, &loaded_file); - return loaded_file; + return loaded_file; } /** Generic signal handler. * This one removes the #pidfile, if necessary. */ -static void -_crywrap_sighandler (int sig) +static void _crywrap_sighandler(int sig) { - if (getpid () == main_pid) - { - cry_log ("Exiting on signal %d", sig); - if (pidfile && *pidfile) - unlink (pidfile); - closelog (); - exit (0); - } + if (getpid() == main_pid) { + cry_log("Exiting on signal %d", sig); + if (pidfile && *pidfile) + unlink(pidfile); + closelog(); + exit(0); + } } + /** @} */ /** @defgroup parsing Option parsing @@ -228,22 +230,21 @@ _crywrap_sighandler (int sig) * * @returns The purt number, or -1 on error. */ -static int -_crywrap_port_get (const char *serv) +static int _crywrap_port_get(const char *serv) { - int port; - struct servent *se; + int port; + struct servent *se; - if (!serv) - return -1; + if (!serv) + return -1; - se = getservbyname (serv, "tcp"); - if (!se) - port = atoi (serv); - else - port = ntohs (se->s_port); + se = getservbyname(serv, "tcp"); + if (!se) + port = atoi(serv); + else + port = ntohs(se->s_port); - return port; + return port; } /** Address resolver. @@ -255,58 +256,54 @@ _crywrap_port_get (const char *serv) * @returns Zero on success, -1 on error. */ static int -_crywrap_addr_get (const char *hostname, struct sockaddr_storage **addr) +_crywrap_addr_get(const char *hostname, struct sockaddr_storage **addr) { - struct addrinfo *res; - struct addrinfo hints; - ssize_t len; - char *lz = NULL; - - if (idna_to_ascii_lz (hostname, &lz, 0) != IDNA_SUCCESS) - return -1; - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_IP; - *addr = calloc (1, sizeof (struct sockaddr_storage)); - if (*addr == NULL) - { - free(lz); - return -1; - } - - if (getaddrinfo (lz, NULL, &hints, &res) != 0) - { - free (lz); - return -1; - } - - free (lz); - - switch (res->ai_addr->sa_family) - { - case AF_INET: - len = sizeof (struct sockaddr_in); - break; - case AF_INET6: - len = sizeof (struct sockaddr_in6); - break; - default: - freeaddrinfo (res); - return -1; - } - - if (len < (ssize_t)res->ai_addrlen) - { - freeaddrinfo (res); - return -1; - } - - memcpy (*addr, res->ai_addr, res->ai_addrlen); - freeaddrinfo (res); - - return 0; + struct addrinfo *res; + struct addrinfo hints; + ssize_t len; + char *lz = NULL; + + if (idna_to_ascii_lz(hostname, &lz, 0) != IDNA_SUCCESS) + return -1; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_IP; + *addr = calloc(1, sizeof(struct sockaddr_storage)); + if (*addr == NULL) { + free(lz); + return -1; + } + + if (getaddrinfo(lz, NULL, &hints, &res) != 0) { + free(lz); + return -1; + } + + free(lz); + + switch (res->ai_addr->sa_family) { + case AF_INET: + len = sizeof(struct sockaddr_in); + break; + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; + default: + freeaddrinfo(res); + return -1; + } + + if (len < (ssize_t) res->ai_addrlen) { + freeaddrinfo(res); + return -1; + } + + memcpy(*addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + + return 0; } /** Parse a HOST/IP pair. @@ -321,151 +318,166 @@ _crywrap_addr_get (const char *hostname, struct sockaddr_storage **addr) * @returns Zero on success, -1 on error. */ static int -_crywrap_parse_ip (const char *ip, in_port_t *port, - struct sockaddr_storage **addr, char **host) +_crywrap_parse_ip(const char *ip, in_port_t * port, + struct sockaddr_storage **addr, char **host) { - char *s_ip; - char *tmp; + char *s_ip; + char *tmp; - tmp = strchr (ip, '/'); + tmp = strchr(ip, '/'); - if (!tmp) - return -1; + if (!tmp) + return -1; - if (tmp == ip) - { - s_ip = strdup ("0.0.0.0"); - *port = (in_port_t)_crywrap_port_get (&ip[1]); - } - else - { - *port = (in_port_t)_crywrap_port_get (&tmp[1]); - s_ip = strndup (ip, tmp - ip); - } + if (tmp == ip) { + s_ip = strdup("0.0.0.0"); + *port = (in_port_t) _crywrap_port_get(&ip[1]); + } else { + *port = (in_port_t) _crywrap_port_get(&tmp[1]); + s_ip = strndup(ip, tmp - ip); + } - if (!*port) - return -1; + if (!*port) + return -1; - if (host) - *host = strdup (s_ip); + if (host) + *host = strdup(s_ip); - return _crywrap_addr_get (s_ip, addr); + return _crywrap_addr_get(s_ip, addr); } /** Argument parsing routine. * Used by the argp suite. */ static error_t -_crywrap_config_parse_opt (int key, char *arg, struct argp_state *state) +_crywrap_config_parse_opt(int key, char *arg, struct argp_state *state) { - crywrap_config_t *cfg = (crywrap_config_t *)state->input; - int ret; - - switch (key) - { - case 'D': - cfg->debug = 1; - cry_log = debug_log; - cry_error = debug_log; - break; - case 'd': - if (_crywrap_parse_ip (arg, &cfg->dest.port, &cfg->dest.addr, - &cfg->dest.host) < 0) - argp_error (state, "Could not resolve address: `%s'", arg); - break; - case 'l': - if (_crywrap_parse_ip (arg, &cfg->listen.port, - &cfg->listen.addr, NULL) < 0) - argp_error (state, "Could not resolve address: `%s'", arg); - break; - case 'u': - cfg->uid = atoi (arg); - break; - case 'P': - if (arg && *arg) - cfg->pidfile = strdup (arg); - else - cfg->pidfile = NULL; - break; - case 'r': - if (arg && *arg) - { - dh_file = load_file(arg); - if (dh_file.data == NULL) - argp_error (state, "error loading Diffie Hellman parameters file: %s.", arg); - } - break; - case 'p': - if (arg && *arg) - { - const char* pos; - ret = gnutls_priority_init(&cfg->priority, arg, &pos); - if (ret < 0) - argp_error (state, "error in priority string at: %s.", pos); - } - break; - case 'c': - if (arg && *arg) - pem_cert = strdup (arg); - break; - case 'k': - if (arg && *arg) - pem_key = strdup (arg); - break; - - break; - case 'i': - cfg->inetd = 1; - break; - case 'a': - { - const char* pos; - ret = gnutls_priority_init(&cfg->priority, "NORMAL:+ANON-ECDH:+ANON-DH", &pos); - if (ret < 0) - argp_error (state, "error in priority string at: %s.", pos); - } - cfg->verify = 0; - cfg->anon = 1; - break; - case 'v': - cfg->verify = (arg) ? atoi (arg) : 1; - break; - case 'z': - ret = gnutls_certificate_set_x509_trust_file (cred, arg, - GNUTLS_X509_FMT_PEM); - if (ret < 0) - argp_error (state, "error reading X.509 CA file: %s.", gnutls_strerror(ret)); - break; - - case ARGP_KEY_END: - if (!cfg->inetd) - { - if (!cfg->listen.addr || !cfg->dest.addr) - argp_error - (state, - "a listening and a destination address must be set!"); + crywrap_config_t *cfg = (crywrap_config_t *) state->input; + int ret; + + switch (key) { + case 'D': + cfg->debug = 1; + cry_log = debug_log; + cry_error = debug_log; + break; + case 'd': + if (_crywrap_parse_ip + (arg, &cfg->dest.port, &cfg->dest.addr, + &cfg->dest.host) < 0) + argp_error(state, + "Could not resolve address: `%s'", arg); + break; + case 'l': + if (_crywrap_parse_ip(arg, &cfg->listen.port, + &cfg->listen.addr, NULL) < 0) + argp_error(state, + "Could not resolve address: `%s'", arg); + break; + case 'u': + cfg->uid = atoi(arg); + break; + case 'P': + if (arg && *arg) + cfg->pidfile = strdup(arg); + else + cfg->pidfile = NULL; + break; + case 'r': + if (arg && *arg) { + dh_file = load_file(arg); + if (dh_file.data == NULL) + argp_error(state, + "error loading Diffie Hellman parameters file: %s.", + arg); + } + break; + case 'p': + if (arg && *arg) { + const char *pos; + ret = + gnutls_priority_init(&cfg->priority, arg, + &pos); + if (ret < 0) + argp_error(state, + "error in priority string at: %s.", + pos); + } + break; + case 'c': + if (arg && *arg) + pem_cert = strdup(arg); + break; + case 'k': + if (arg && *arg) + pem_key = strdup(arg); + break; + + break; + case 'i': + cfg->inetd = 1; + break; + case 'a': + { + const char *pos; + ret = + gnutls_priority_init(&cfg->priority, + "NORMAL:+ANON-ECDH:+ANON-DH", + &pos); + if (ret < 0) + argp_error(state, + "error in priority string at: %s.", + pos); + } + cfg->verify = 0; + cfg->anon = 1; + break; + case 'v': + cfg->verify = (arg) ? atoi(arg) : 1; + break; + case 'z': + ret = gnutls_certificate_set_x509_trust_file(cred, arg, + GNUTLS_X509_FMT_PEM); + if (ret < 0) + argp_error(state, + "error reading X.509 CA file: %s.", + gnutls_strerror(ret)); + break; + + case ARGP_KEY_END: + if (!cfg->inetd) { + if (!cfg->listen.addr || !cfg->dest.addr) + argp_error + (state, + "a listening and a destination address must be set!"); + } else if (!cfg->dest.addr) + argp_error(state, + "a destination address must be set!"); + if (cfg->anon) + break; + if (pem_cert == NULL || pem_key == NULL) + ret = + gnutls_certificate_set_x509_key_file(cred, + _CRYWRAP_PEMFILE, + _CRYWRAP_PEMFILE, + GNUTLS_X509_FMT_PEM); + else + ret = + gnutls_certificate_set_x509_key_file(cred, + pem_cert, + pem_key, + GNUTLS_X509_FMT_PEM); + + if (ret < 0) + argp_error(state, + "Error reading X.509 key or certificate file: %s", + gnutls_strerror(ret)); + break; + default: + return ARGP_ERR_UNKNOWN; } - else - if (!cfg->dest.addr) - argp_error (state, "a destination address must be set!"); - if (cfg->anon) - break; - if (pem_cert == NULL || pem_key == NULL) - ret = gnutls_certificate_set_x509_key_file (cred, _CRYWRAP_PEMFILE, - _CRYWRAP_PEMFILE, - GNUTLS_X509_FMT_PEM); - else - ret = gnutls_certificate_set_x509_key_file (cred, pem_cert, pem_key, - GNUTLS_X509_FMT_PEM); - - if (ret < 0) - argp_error (state, "Error reading X.509 key or certificate file: %s", gnutls_strerror(ret)); - break; - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; + + return 0; } /** Configuration parsing. @@ -474,33 +486,33 @@ _crywrap_config_parse_opt (int key, char *arg, struct argp_state *state) * * @note Does not return if an error occurred. */ -static crywrap_config_t * -_crywrap_config_parse (int argc, char **argv) +static crywrap_config_t *_crywrap_config_parse(int argc, char **argv) { - crywrap_config_t *config = - (crywrap_config_t *)malloc (sizeof (crywrap_config_t)); + crywrap_config_t *config = + (crywrap_config_t *) malloc(sizeof(crywrap_config_t)); - if (config == NULL) - return NULL; + if (config == NULL) + return NULL; - config->listen.port = 0; - config->listen.addr = NULL; - config->dest.port = 0; - config->dest.addr = NULL; - config->priority = NULL; - config->uid = _CRYWRAP_UID; - config->pidfile = _CRYWRAP_PIDFILE; - config->inetd = 0; - config->anon = 0; - config->verify = 0; + config->listen.port = 0; + config->listen.addr = NULL; + config->dest.port = 0; + config->dest.addr = NULL; + config->priority = NULL; + config->uid = _CRYWRAP_UID; + config->pidfile = _CRYWRAP_PIDFILE; + config->inetd = 0; + config->anon = 0; + config->verify = 0; - argp_parse (&_crywrap_argp, argc, argv, 0, 0, config); + argp_parse(&_crywrap_argp, argc, argv, 0, 0, config); - if (config->priority == NULL) - gnutls_priority_init(&config->priority, "NORMAL", NULL); + if (config->priority == NULL) + gnutls_priority_init(&config->priority, "NORMAL", NULL); - return config; + return config; } + /** @} */ /** @defgroup tls Lower-level TLS routines. @@ -514,46 +526,50 @@ _crywrap_config_parse (int argc, char **argv) * @returns The newly created TLS session. */ static gnutls_session_t -_crywrap_tls_session_create (const crywrap_config_t *config) +_crywrap_tls_session_create(const crywrap_config_t * config) { - gnutls_session_t session; - int ret; - - gnutls_init (&session, GNUTLS_SERVER); - - if (config->anon) { - gnutls_credentials_set (session, GNUTLS_CRD_ANON, cred); - } else { - gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); - } - - ret = gnutls_priority_set(session, config->priority); - if (ret < 0) - { - cry_error ("Error setting priority %s: ", gnutls_strerror(ret)); - exit (4); - } - - if (config->verify==1) - gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST); - else if (config->verify==2) - gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE); - - return session; + gnutls_session_t session; + int ret; + + gnutls_init(&session, GNUTLS_SERVER); + + if (config->anon) { + gnutls_credentials_set(session, GNUTLS_CRD_ANON, cred); + } else { + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + cred); + } + + ret = gnutls_priority_set(session, config->priority); + if (ret < 0) { + cry_error("Error setting priority %s: ", + gnutls_strerror(ret)); + exit(4); + } + + if (config->verify == 1) + gnutls_certificate_server_set_request(session, + GNUTLS_CERT_REQUEST); + else if (config->verify == 2) + gnutls_certificate_server_set_request(session, + GNUTLS_CERT_REQUIRE); + + return session; } /** Generate initial DH and RSA params. * Loads the pre-generated DH primes. */ -static void -_crywrap_tls_init (void) +static void _crywrap_tls_init(void) { - gnutls_dh_params_init (&dh_params); - gnutls_dh_params_import_pkcs3 (dh_params, &dh_file, GNUTLS_X509_FMT_PEM); + gnutls_dh_params_init(&dh_params); + gnutls_dh_params_import_pkcs3(dh_params, &dh_file, + GNUTLS_X509_FMT_PEM); - gnutls_certificate_set_dh_params (cred, dh_params); + gnutls_certificate_set_dh_params(cred, dh_params); } + /** @} */ /** @defgroup networking Networking @@ -569,59 +585,59 @@ _crywrap_tls_init (void) * * @returns The bound filedescriptor, or -1 on error. */ -static int -_crywrap_bind (const struct addrinfo *ai, int listen_port) +static int _crywrap_bind(const struct addrinfo *ai, int listen_port) { - int ret; - const int one = 1; - int listenfd; - char sock_name[NI_MAXHOST]; - - listenfd = socket (ai->ai_family, SOCK_STREAM, IPPROTO_IP); - if (listenfd == -1) - { - cry_error ("socket: %s", strerror (errno)); - return -1; - } - - memset (sock_name, 0, sizeof (sock_name)); - getnameinfo ((struct sockaddr *)ai->ai_addr, ai->ai_addrlen, sock_name, - sizeof (sock_name), NULL, 0, NI_NUMERICHOST); - - switch (ai->ai_family) - { - case AF_INET6: - ((struct sockaddr_in6 *)(ai->ai_addr))->sin6_port = listen_port; - break; - case AF_INET: - ((struct sockaddr_in *)(ai->ai_addr))->sin_port = listen_port; - break; - } - - ret = setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, - &one, sizeof (one)); - if (ret != 0) - { - cry_error ("setsockopt: %s (%s)", strerror (errno), sock_name); - return -1; - } - - ret = bind (listenfd, ai->ai_addr, ai->ai_addrlen); - if (ret != 0) - { - cry_error ("bind to %s failed: %s", sock_name, strerror (errno)); - return -1; - } - - if (listen (listenfd, _CRYWRAP_MAXCONN) != 0) - { - cry_error ("listen on %s failed: %s", sock_name, strerror (errno)); - return -1; - } - - cry_log ("Socket bound to port %d on %s.", ntohs (listen_port), sock_name); - - return listenfd; + int ret; + const int one = 1; + int listenfd; + char sock_name[NI_MAXHOST]; + + listenfd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_IP); + if (listenfd == -1) { + cry_error("socket: %s", strerror(errno)); + return -1; + } + + memset(sock_name, 0, sizeof(sock_name)); + getnameinfo((struct sockaddr *) ai->ai_addr, ai->ai_addrlen, + sock_name, sizeof(sock_name), NULL, 0, NI_NUMERICHOST); + + switch (ai->ai_family) { + case AF_INET6: + ((struct sockaddr_in6 *) (ai->ai_addr))->sin6_port = + listen_port; + break; + case AF_INET: + ((struct sockaddr_in *) (ai->ai_addr))->sin_port = + listen_port; + break; + } + + ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, + &one, sizeof(one)); + if (ret != 0) { + cry_error("setsockopt: %s (%s)", strerror(errno), + sock_name); + return -1; + } + + ret = bind(listenfd, ai->ai_addr, ai->ai_addrlen); + if (ret != 0) { + cry_error("bind to %s failed: %s", sock_name, + strerror(errno)); + return -1; + } + + if (listen(listenfd, _CRYWRAP_MAXCONN) != 0) { + cry_error("listen on %s failed: %s", sock_name, + strerror(errno)); + return -1; + } + + cry_log("Socket bound to port %d on %s.", ntohs(listen_port), + sock_name); + + return listenfd; } /** Set up a listening socket. @@ -632,39 +648,37 @@ _crywrap_bind (const struct addrinfo *ai, int listen_port) * * @returns The listening FD on success, -1 on error. */ -static int -_crywrap_listen (const crywrap_config_t *config) +static int _crywrap_listen(const crywrap_config_t * config) { - struct addrinfo *cur; - int ret; - - cur = calloc (1, sizeof (struct addrinfo)); - if (cur == NULL) - return -1; - - cur->ai_family = config->listen.addr->ss_family; - - switch (cur->ai_family) - { - case AF_INET6: - cur->ai_addrlen = sizeof (struct sockaddr_in6); - break; - case AF_INET: - cur->ai_addrlen = sizeof (struct sockaddr_in); - break; - } - - cur->ai_addr = malloc (cur->ai_addrlen); - if (cur->ai_addr == NULL) - return -1; - - memcpy (cur->ai_addr, config->listen.addr, cur->ai_addrlen); - - ret = _crywrap_bind (cur, htons (config->listen.port)); - free (cur->ai_addr); - free (cur); - - return ret; + struct addrinfo *cur; + int ret; + + cur = calloc(1, sizeof(struct addrinfo)); + if (cur == NULL) + return -1; + + cur->ai_family = config->listen.addr->ss_family; + + switch (cur->ai_family) { + case AF_INET6: + cur->ai_addrlen = sizeof(struct sockaddr_in6); + break; + case AF_INET: + cur->ai_addrlen = sizeof(struct sockaddr_in); + break; + } + + cur->ai_addr = malloc(cur->ai_addrlen); + if (cur->ai_addr == NULL) + return -1; + + memcpy(cur->ai_addr, config->listen.addr, cur->ai_addrlen); + + ret = _crywrap_bind(cur, htons(config->listen.port)); + free(cur->ai_addr); + free(cur); + + return ret; } /** Connect to a remote server. @@ -677,60 +691,56 @@ _crywrap_listen (const crywrap_config_t *config) * @returns the connected socket on success, otherwise it exits. */ static int -_crywrap_remote_connect (const struct sockaddr_storage *addr, int port) +_crywrap_remote_connect(const struct sockaddr_storage *addr, int port) { - struct addrinfo *cur; - int sock; - - cur = calloc (1, sizeof (struct addrinfo)); - if (cur == NULL) - return -1; - - cur->ai_family = addr->ss_family; - - switch (cur->ai_family) - { - case AF_INET6: - cur->ai_addrlen = sizeof (struct sockaddr_in6); - break; - case AF_INET: - cur->ai_addrlen = sizeof (struct sockaddr_in); - break; - } - - cur->ai_addr = malloc (cur->ai_addrlen); - if (cur->ai_addr == NULL) - return -1; - - memcpy (cur->ai_addr, addr, cur->ai_addrlen); - - switch (cur->ai_family) - { - case AF_INET6: - ((struct sockaddr_in6 *)(cur->ai_addr))->sin6_port = port; - break; - case AF_INET: - ((struct sockaddr_in *)(cur->ai_addr))->sin_port = port; - break; - } - - sock = socket (cur->ai_family, SOCK_STREAM, IPPROTO_IP); - if (sock < 0) - { - cry_error ("socket(): %s", strerror (errno)); - exit (1); - } - - if (connect (sock, cur->ai_addr, cur->ai_addrlen) < 0) - { - cry_error ("connect(): %s", strerror (errno)); - exit (1); - } - - free (cur->ai_addr); - free (cur); - - return sock; + struct addrinfo *cur; + int sock; + + cur = calloc(1, sizeof(struct addrinfo)); + if (cur == NULL) + return -1; + + cur->ai_family = addr->ss_family; + + switch (cur->ai_family) { + case AF_INET6: + cur->ai_addrlen = sizeof(struct sockaddr_in6); + break; + case AF_INET: + cur->ai_addrlen = sizeof(struct sockaddr_in); + break; + } + + cur->ai_addr = malloc(cur->ai_addrlen); + if (cur->ai_addr == NULL) + return -1; + + memcpy(cur->ai_addr, addr, cur->ai_addrlen); + + switch (cur->ai_family) { + case AF_INET6: + ((struct sockaddr_in6 *) (cur->ai_addr))->sin6_port = port; + break; + case AF_INET: + ((struct sockaddr_in *) (cur->ai_addr))->sin_port = port; + break; + } + + sock = socket(cur->ai_family, SOCK_STREAM, IPPROTO_IP); + if (sock < 0) { + cry_error("socket(): %s", strerror(errno)); + exit(1); + } + + if (connect(sock, cur->ai_addr, cur->ai_addrlen) < 0) { + cry_error("connect(): %s", strerror(errno)); + exit(1); + } + + free(cur->ai_addr); + free(cur); + + return sock; } /** @} */ @@ -743,40 +753,35 @@ _crywrap_remote_connect (const struct sockaddr_storage *addr, int port) * Drop privileges, if running as root. * Upon failure, it will make CryWrap exit. */ -static void -_crywrap_privs_drop (const crywrap_config_t *config) +static void _crywrap_privs_drop(const crywrap_config_t * config) { - struct passwd *pwd; - - if (getuid () != 0) - { - cry_log ("%s", "Not running as root, not dropping privileges."); - return; - } - - if ((pwd = getpwuid (config->uid)) == NULL) - { - cry_error ("getpwuid(): %s", strerror (errno)); - exit (1); - } - - if (initgroups (pwd->pw_name, pwd->pw_gid) == -1) - { - cry_error ("initgroups(): %s", strerror (errno)); - exit (1); - } - - if (setgid (pwd->pw_gid) == -1) - { - cry_error ("setgid(): %s", strerror (errno)); - exit (1); - } - - if (setuid (config->uid)) - { - cry_error ("setuid(): %s", strerror (errno)); - exit (1); - } + struct passwd *pwd; + + if (getuid() != 0) { + cry_log("%s", + "Not running as root, not dropping privileges."); + return; + } + + if ((pwd = getpwuid(config->uid)) == NULL) { + cry_error("getpwuid(): %s", strerror(errno)); + exit(1); + } + + if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { + cry_error("initgroups(): %s", strerror(errno)); + exit(1); + } + + if (setgid(pwd->pw_gid) == -1) { + cry_error("setgid(): %s", strerror(errno)); + exit(1); + } + + if (setuid(config->uid)) { + cry_error("setuid(): %s", strerror(errno)); + exit(1); + } } /** Set up the PID file. @@ -785,34 +790,32 @@ _crywrap_privs_drop (const crywrap_config_t *config) * * @note Exits upon error. */ -static void -_crywrap_setup_pidfile (const crywrap_config_t *config) +static void _crywrap_setup_pidfile(const crywrap_config_t * config) { - char mypid[128]; - int pidfilefd; - - if (!config->pidfile || !*(config->pidfile)) - return; - - if (!access (config->pidfile, F_OK)) - { - cry_error ("Pidfile (%s) already exists. Exiting.", config->pidfile); - exit (1); - } - if ((pidfilefd = open (config->pidfile, - O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) - { - cry_error ("Cannot create pidfile (%s): %s.\n", config->pidfile, - strerror (errno)); - exit (1); - } - fchown (pidfilefd, config->uid, (gid_t)-1); - - main_pid = getpid (); - snprintf (mypid, sizeof (mypid), "%d\n", main_pid); - write (pidfilefd, mypid, strlen (mypid)); - close (pidfilefd); - pidfile = config->pidfile; + char mypid[128]; + int pidfilefd; + + if (!config->pidfile || !*(config->pidfile)) + return; + + if (!access(config->pidfile, F_OK)) { + cry_error("Pidfile (%s) already exists. Exiting.", + config->pidfile); + exit(1); + } + if ((pidfilefd = open(config->pidfile, + O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { + cry_error("Cannot create pidfile (%s): %s.\n", + config->pidfile, strerror(errno)); + exit(1); + } + fchown(pidfilefd, config->uid, (gid_t) - 1); + + main_pid = getpid(); + snprintf(mypid, sizeof(mypid), "%d\n", main_pid); + write(pidfilefd, mypid, strlen(mypid)); + close(pidfilefd); + pidfile = config->pidfile; } @@ -827,273 +830,258 @@ _crywrap_setup_pidfile (const crywrap_config_t *config) * @note Exits on error. */ static int -_crywrap_do_one (const crywrap_config_t *config, int insock, int outsock) +_crywrap_do_one(const crywrap_config_t * config, int insock, int outsock) { - int sock, ret, tls_pending; - gnutls_session_t session; - char buffer[_CRYWRAP_MAXBUF + 2]; - fd_set fdset; - unsigned int status = 0; - struct sockaddr_storage faddr; - socklen_t socklen = sizeof (struct sockaddr_storage); - char peer_name[NI_MAXHOST]; - - /* Log the connection */ - if (getpeername (insock, (struct sockaddr *)&faddr, &socklen) != 0) - cry_error ("getpeername(): %s", strerror (errno)); - else - { - getnameinfo ((struct sockaddr *)&faddr, - sizeof (struct sockaddr_storage), peer_name, - sizeof (peer_name), NULL, 0, NI_NUMERICHOST); - cry_log ("Accepted connection from %s on %d to %s/%d", - peer_name, insock, config->dest.host, - config->dest.port); - } - - /* Do the handshake with our peer */ - session = _crywrap_tls_session_create (config); - gnutls_transport_set_ptr2 (session, - (gnutls_transport_ptr_t)insock, - (gnutls_transport_ptr_t)outsock); - - do - { - ret = gnutls_handshake(session); - } - while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); - - if (ret < 0) - { - cry_error ("Handshake failed: %s", gnutls_strerror (ret)); - gnutls_alert_send_appropriate(session, ret); - goto error; - } - - /* Verify the client's certificate, if any. */ - if (config->verify) - { - ret = gnutls_certificate_verify_peers2 (session, &status); - if (ret < 0) - cry_log ("Error getting certificate from client: %s", - gnutls_strerror (ret)); - - if (ret == 0 && status != 0) - { - if (status & GNUTLS_CERT_INVALID) - cry_log ("%s", "Client certificate not trusted or invalid"); - } - - if (config->verify > 0 && status != 0) - { - ret = -1; - gnutls_alert_send( session, GNUTLS_AL_FATAL, GNUTLS_A_INSUFFICIENT_SECURITY); - goto error; - } - } - - /* Connect to the remote host */ - sock = _crywrap_remote_connect (config->dest.addr, - htons (config->dest.port)); - - for (;;) - { - FD_ZERO (&fdset); - FD_SET (insock, &fdset); - FD_SET (sock, &fdset); - - memset (buffer, 0, _CRYWRAP_MAXBUF + 1); - - tls_pending = 0; - - if (gnutls_record_check_pending(session) > 0) - tls_pending = 1; - else - { - select (sock + 1, &fdset, NULL, NULL, NULL); - if (FD_ISSET (insock, &fdset)) - tls_pending = 1; - } - /* TLS client */ - if (tls_pending != 0) - { - ret = gnutls_record_recv (session, buffer, _CRYWRAP_MAXBUF); - if (ret == 0) - { - cry_log ("%s", "Peer has closed the GNUTLS connection"); - break; - } - else if (ret < 0) - { - cry_log ("Received corrupted data: %s.", - gnutls_strerror (ret)); - break; - } - else - send (sock, buffer, ret, 0); + int sock, ret, tls_pending; + gnutls_session_t session; + char buffer[_CRYWRAP_MAXBUF + 2]; + fd_set fdset; + unsigned int status = 0; + struct sockaddr_storage faddr; + socklen_t socklen = sizeof(struct sockaddr_storage); + char peer_name[NI_MAXHOST]; + + /* Log the connection */ + if (getpeername(insock, (struct sockaddr *) &faddr, &socklen) != 0) + cry_error("getpeername(): %s", strerror(errno)); + else { + getnameinfo((struct sockaddr *) &faddr, + sizeof(struct sockaddr_storage), peer_name, + sizeof(peer_name), NULL, 0, NI_NUMERICHOST); + cry_log("Accepted connection from %s on %d to %s/%d", + peer_name, insock, config->dest.host, + config->dest.port); } - /* Remote server */ - if (FD_ISSET (sock, &fdset)) - { - ret = recv (sock, buffer, _CRYWRAP_MAXBUF, 0); - if (ret == 0) - { - cry_log ("%s", "Server has closed the connection"); - break; - } - else if (ret < 0) - { - cry_log ("Received corrupted data: %s.", strerror (errno)); - break; - } - else - { - int r, o = 0; - - do - { - r = gnutls_record_send (session, &buffer[o], ret - o); - o += r; - } while (r > 0 && ret > o); + /* Do the handshake with our peer */ + session = _crywrap_tls_session_create(config); + gnutls_transport_set_ptr2(session, + (gnutls_transport_ptr_t) insock, + (gnutls_transport_ptr_t) outsock); - if (r < 0) - cry_log ("Received corrupt data: %s", gnutls_strerror (r)); - } + do { + ret = gnutls_handshake(session); } - } + while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); -error: - gnutls_bye (session, GNUTLS_SHUT_WR); - gnutls_deinit (session); - close (insock); - close (outsock); + if (ret < 0) { + cry_error("Handshake failed: %s", gnutls_strerror(ret)); + gnutls_alert_send_appropriate(session, ret); + goto error; + } - return (ret == 0) ? 0 : 1; + /* Verify the client's certificate, if any. */ + if (config->verify) { + ret = gnutls_certificate_verify_peers2(session, &status); + if (ret < 0) + cry_log + ("Error getting certificate from client: %s", + gnutls_strerror(ret)); + + if (ret == 0 && status != 0) { + if (status & GNUTLS_CERT_INVALID) + cry_log("%s", + "Client certificate not trusted or invalid"); + } + + if (config->verify > 0 && status != 0) { + ret = -1; + gnutls_alert_send(session, GNUTLS_AL_FATAL, + GNUTLS_A_INSUFFICIENT_SECURITY); + goto error; + } + } + + /* Connect to the remote host */ + sock = _crywrap_remote_connect(config->dest.addr, + htons(config->dest.port)); + + for (;;) { + FD_ZERO(&fdset); + FD_SET(insock, &fdset); + FD_SET(sock, &fdset); + + memset(buffer, 0, _CRYWRAP_MAXBUF + 1); + + tls_pending = 0; + + if (gnutls_record_check_pending(session) > 0) + tls_pending = 1; + else { + select(sock + 1, &fdset, NULL, NULL, NULL); + if (FD_ISSET(insock, &fdset)) + tls_pending = 1; + } + /* TLS client */ + if (tls_pending != 0) { + ret = + gnutls_record_recv(session, buffer, + _CRYWRAP_MAXBUF); + if (ret == 0) { + cry_log("%s", + "Peer has closed the GNUTLS connection"); + break; + } else if (ret < 0) { + cry_log("Received corrupted data: %s.", + gnutls_strerror(ret)); + break; + } else + send(sock, buffer, ret, 0); + } + + /* Remote server */ + if (FD_ISSET(sock, &fdset)) { + ret = recv(sock, buffer, _CRYWRAP_MAXBUF, 0); + if (ret == 0) { + cry_log("%s", + "Server has closed the connection"); + break; + } else if (ret < 0) { + cry_log("Received corrupted data: %s.", + strerror(errno)); + break; + } else { + int r, o = 0; + + do { + r = gnutls_record_send(session, + &buffer[o], + ret - o); + o += r; + } while (r > 0 && ret > o); + + if (r < 0) + cry_log + ("Received corrupt data: %s", + gnutls_strerror(r)); + } + } + } + + error: + gnutls_bye(session, GNUTLS_SHUT_WR); + gnutls_deinit(session); + close(insock); + close(outsock); + + return (ret == 0) ? 0 : 1; } /** CryWrap entry point. * This is the main entry point - controls the whole program and so * on... */ -int -main (int argc, char **argv, char **envp) +int main(int argc, char **argv, char **envp) { - crywrap_config_t *config; - int server_socket; - - openlog (__CRYWRAP__, LOG_PID, LOG_DAEMON); - - gnutls_global_set_audit_log_function (tls_audit_log_func); - - if (gnutls_global_init () < 0) - { - cry_error ("%s", "Global TLS state initialisation failed."); - exit (1); - } - if (gnutls_certificate_allocate_credentials (&cred) < 0) - { - cry_error ("%s", "Couldn't allocate credentials."); - exit (1); - } - - stringprep_locale_charset (); - - config = _crywrap_config_parse (argc, argv); - - _crywrap_tls_init (); - - if (config->inetd) - { - _crywrap_privs_drop (config); - exit (_crywrap_do_one (config, 0, 1)); - } - - if (!config->debug) - if (daemon (0, 0)) - { - cry_error ("daemon: %s", strerror (errno)); - exit (1); - } - - cry_log ("%s", "Crywrap starting..."); - - server_socket = _crywrap_listen (config); - if (server_socket < 0) - exit (1); - - if (!config->debug) _crywrap_setup_pidfile (config); - _crywrap_privs_drop (config); - - signal (SIGTERM, _crywrap_sighandler); - signal (SIGQUIT, _crywrap_sighandler); - signal (SIGSEGV, _crywrap_sighandler); - signal (SIGPIPE, SIG_IGN); - signal (SIGHUP, SIG_IGN); - signal (SIGCHLD, _crywrap_sigchld_handler); - - cry_log ("%s", "Accepting connections"); - - - for (;;) - { - int csock; - int child; - - csock = accept (server_socket, NULL, NULL); - if (csock < 0) - continue; - - child = fork (); - switch (child) - { - case 0: - exit (_crywrap_do_one (config, csock, csock)); - break; - case -1: - cry_error ("%s", "Forking error."); - exit (1); - break; + crywrap_config_t *config; + int server_socket; + + openlog(__CRYWRAP__, LOG_PID, LOG_DAEMON); + + gnutls_global_set_audit_log_function(tls_audit_log_func); + + if (gnutls_global_init() < 0) { + cry_error("%s", "Global TLS state initialisation failed."); + exit(1); + } + if (gnutls_certificate_allocate_credentials(&cred) < 0) { + cry_error("%s", "Couldn't allocate credentials."); + exit(1); } - close(csock); - } - return 0; + stringprep_locale_charset(); + + config = _crywrap_config_parse(argc, argv); + + _crywrap_tls_init(); + + if (config->inetd) { + _crywrap_privs_drop(config); + exit(_crywrap_do_one(config, 0, 1)); + } + + if (!config->debug) + if (daemon(0, 0)) { + cry_error("daemon: %s", strerror(errno)); + exit(1); + } + + cry_log("%s", "Crywrap starting..."); + + server_socket = _crywrap_listen(config); + if (server_socket < 0) + exit(1); + + if (!config->debug) + _crywrap_setup_pidfile(config); + _crywrap_privs_drop(config); + + signal(SIGTERM, _crywrap_sighandler); + signal(SIGQUIT, _crywrap_sighandler); + signal(SIGSEGV, _crywrap_sighandler); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGCHLD, _crywrap_sigchld_handler); + + cry_log("%s", "Accepting connections"); + + + for (;;) { + int csock; + int child; + + csock = accept(server_socket, NULL, NULL); + if (csock < 0) + continue; + + child = fork(); + switch (child) { + case 0: + exit(_crywrap_do_one(config, csock, csock)); + break; + case -1: + cry_error("%s", "Forking error."); + exit(1); + break; + } + close(csock); + } + + return 0; } -static int system_log(const char* fmt, ...) +static int system_log(const char *fmt, ...) { - va_list args; + va_list args; - va_start (args, fmt); - vsyslog(LOG_NOTICE, fmt, args); - va_end (args); + va_start(args, fmt); + vsyslog(LOG_NOTICE, fmt, args); + va_end(args); - return 0; + return 0; } -static int system_log_error(const char* fmt, ...) +static int system_log_error(const char *fmt, ...) { - va_list args; + va_list args; - va_start (args, fmt); - vsyslog(LOG_ERR, fmt, args); - va_end (args); + va_start(args, fmt); + vsyslog(LOG_ERR, fmt, args); + va_end(args); - return 0; + return 0; } -static int debug_log(const char* fmt, ...) +static int debug_log(const char *fmt, ...) { - va_list args; + va_list args; - va_start (args, fmt); - vprintf(fmt, args); - puts(""); - va_end (args); + va_start(args, fmt); + vprintf(fmt, args); + puts(""); + va_end(args); - return 0; + return 0; } /** @} */ - |