From 2ee32d635b4bddcd4ebe8408d9acc69ab74645a3 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Mon, 12 Jan 2009 20:43:59 -0500 Subject: [PATCH] SIGHUP will stop or start the tcp_accept_thread() depending on the configuration. --- src/pwmd.c | 441 ++++++++++++++++++++++++++++++++++--------------------------- src/pwmd.h | 4 + 2 files changed, 249 insertions(+), 196 deletions(-) diff --git a/src/pwmd.c b/src/pwmd.c index 6ca1abbf..7bbabccd 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -97,6 +97,7 @@ static void clear_rcfile_keys() g_strfreev(groups); } +static gboolean startStopTcp(gboolean term); static void reload_rcfile() { gboolean b = disable_list_and_dump; @@ -113,6 +114,7 @@ static void reload_rcfile() parse_rcfile_keys(); clear_rcfile_keys(); disable_list_and_dump = b; + startStopTcp(FALSE); send_status_all(STATUS_CONFIG); } @@ -1691,12 +1693,9 @@ static pth_event_t keepalive_event_iterate(pth_event_t keepalive_ev, return ev; } -static void server_loop(gint sockfd, gint sockfd_r, gchar **socketpath) +static void server_loop(gint sockfd, gchar **socketpath) { pth_t accept_tid; -#ifdef WITH_GNUTLS - pth_t tcp_accept_tid; -#endif guint n; sigset_t set; gint n_clients = 0; @@ -1725,18 +1724,6 @@ static void server_loop(gint sockfd, gint sockfd_r, gchar **socketpath) goto done; } -#ifdef WITH_GNUTLS - if (sockfd_r != -1) { - pth_attr_set(attr, PTH_ATTR_NAME, "tcp_accept"); - tcp_accept_tid = pth_spawn(attr, tcp_accept_thread, (void *)sockfd_r); - - if (!tcp_accept_tid) { - log_write("pth_spawn(): %s", strerror(errno)); - goto done; - } - } -#endif - pth_attr_init(attr); pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MAX); @@ -1784,9 +1771,9 @@ static void server_loop(gint sockfd, gint sockfd_r, gchar **socketpath) shutdown(sockfd, SHUT_RDWR); close(sockfd); - if (sockfd_r != -1) { - shutdown(sockfd_r, SHUT_RDWR); - close(sockfd_r); + if (tcpSockFd != -1) { + shutdown(tcpSockFd, SHUT_RDWR); + close(tcpSockFd); } break; } @@ -1801,9 +1788,9 @@ static void server_loop(gint sockfd, gint sockfd_r, gchar **socketpath) pth_join(accept_tid, &value); #ifdef WITH_GNUTLS - if (sockfd_r != -1) { - pth_cancel(tcp_accept_tid); - pth_join(tcp_accept_tid, &value); + if (tcpSockFd != -1) { + pth_cancel(tcpAcceptTid); + pth_join(tcpAcceptTid, &value); } #endif @@ -1955,6 +1942,234 @@ done: return rc; } +#ifdef WITH_GNUTLS +static gboolean initTlsParams() +{ + int n; + gchar *tmp, *tmp2; + + n = gnutls_certificate_allocate_credentials(&x509_cred); + + if (n != GNUTLS_E_SUCCESS) { + log_write("%s", gnutls_strerror(n)); + x509_cred = NULL; + goto fail; + } + + tmp = expand_homedir("~/.pwmd/ca-cert.pem"); + + if (!tmp) { + log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); + goto fail; + } + + n = gnutls_certificate_set_x509_trust_file(x509_cred, tmp, + GNUTLS_X509_FMT_PEM); + g_free(tmp); + + if (n < 0) { + log_write("%s", gnutls_strerror(n)); + goto fail; + } + + tmp = expand_homedir("~/.pwmd/server-cert.pem"); + + if (!tmp) { + log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); + goto fail; + } + + tmp2 = expand_homedir("~/.pwmd/server-key.pem"); + + if (!tmp2) { + g_free(tmp); + log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); + goto fail; + } + + n = gnutls_certificate_set_x509_key_file (x509_cred, tmp, tmp2, + GNUTLS_X509_FMT_PEM); + g_free(tmp); + g_free(tmp2); + + if (n != GNUTLS_E_SUCCESS) { + log_write("%s", gnutls_strerror(n)); + goto fail; + } + + log_write("%s", N_("Generating key exchange parameters...")); + n = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); + + if (n) { + log_write("%s", gpg_strerror(n)); + goto fail; + } + + n = gnutls_dh_params_init(&dh_params); + + if (n != GNUTLS_E_SUCCESS) { + log_write("%s", gnutls_strerror(n)); + goto fail; + } + + n = gnutls_dh_params_generate2(dh_params, 1024); + + if (n != GNUTLS_E_SUCCESS) { + log_write("%s", gnutls_strerror(n)); + goto fail; + } + + gnutls_certificate_set_dh_params(x509_cred, dh_params); + n = gnutls_rsa_params_init(&rsa_params); + + if (n != GNUTLS_E_SUCCESS) { + log_write("%s", gnutls_strerror(n)); + goto fail; + } + + n = gnutls_rsa_params_generate2(rsa_params, 512); + + if (n != GNUTLS_E_SUCCESS) { + log_write("%s", gnutls_strerror(n)); + goto fail; + } + + gnutls_certificate_set_rsa_export_params(x509_cred, rsa_params); + gnutls_certificate_set_params_function(x509_cred, tls_get_params); + return TRUE; + +fail: + return FALSE; +} + +static void deinitTlsParams() +{ + if (dh_params) + gnutls_dh_params_deinit(dh_params); + + if (rsa_params) + gnutls_rsa_params_deinit(rsa_params); + + if (x509_cred) { + gnutls_certificate_free_credentials(x509_cred); + x509_cred = NULL; + } +} + +static gboolean startStopTcp(gboolean term) +{ + struct addrinfo hints, *servinfo, *p; + gint port = get_key_file_integer("global", "tcp_port"); + char buf[7]; + int n; + gpointer value; + pth_attr_t attr; + + if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) { + if (tcpSockFd != -1) { + pth_cancel(tcpAcceptTid); + pth_join(tcpAcceptTid, &value); + close(tcpSockFd); + tcpSockFd = -1; + deinitTlsParams(); + } + + return TRUE; + } + + if (tcpSockFd != -1) + return TRUE; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port), + &hints, &servinfo)) == -1) { + log_write("getaddrinfo(): %s", gai_strerror(n)); + return FALSE; + } + + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((tcpSockFd = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + log_write("socket(): %s", strerror(errno)); + continue; + } + + n = 1; + + if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n, + sizeof(int)) == -1) { + log_write("setsockopt(): %s", strerror(errno)); + freeaddrinfo(servinfo); + goto fail; + } + + if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) { + close(tcpSockFd); + log_write("bind(): %s", strerror(errno)); + continue; + } + + n++; + break; + } + + freeaddrinfo(servinfo); + + if (!p) { + log_write("%s", N_("could not bind")); + goto fail; + } + + if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) { + gchar *tmp = get_key_file_string("global", "tcp_interface"); + + if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1) + == -1) { + log_write("setsockopt(): %s", strerror(errno)); + g_free(tmp); + goto fail; + } + + g_free(tmp); + } + + if (!initTlsParams()) + goto fail; + + if (listen(tcpSockFd, 0) == -1) { + log_write("listen(): %s", strerror(errno)); + goto fail; + } + + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MIN); + pth_attr_set(attr, PTH_ATTR_NAME, "tcp_accept"); + tcpAcceptTid = pth_spawn(attr, tcp_accept_thread, (void *)tcpSockFd); + pth_attr_destroy(attr); + + if (!tcpAcceptTid) { + log_write("pth_spawn(): %s", strerror(errno)); + goto fail; + } + + return TRUE; + +fail: + deinitTlsParams(); + + if (tcpSockFd != -1) + close(tcpSockFd); + + tcpSockFd = -1; + return FALSE; +} +#endif + int main(int argc, char *argv[]) { gint opt; @@ -1973,7 +2188,7 @@ int main(int argc, char *argv[]) gint default_timeout; gboolean rcfile_spec = FALSE; gint estatus = EXIT_FAILURE; - gint sockfd, sockfd_r = -1; + gint sockfd; gchar *outfile = NULL; #ifndef MEM_DEBUG GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL }; @@ -1989,7 +2204,6 @@ int main(int argc, char *argv[]) #endif #ifdef WITH_GNUTLS struct assuan_io_hooks io_hooks = {read_hook, write_hook}; - gint ret; #endif #if 0 #ifndef DEBUG @@ -2045,6 +2259,7 @@ int main(int argc, char *argv[]) rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir); cmdline = TRUE; + tcpSockFd = -1; while ((opt = getopt(argc, argv, "Po:C:bnI:i:k:hvf:D")) != EOF) { switch (opt) { @@ -2325,118 +2540,10 @@ int main(int argc, char *argv[]) goto do_exit; } -#ifdef WITH_GNUTLS - if (get_key_file_boolean("global", "enable_tcp")) { - gchar *tmp, *tmp2; - struct addrinfo hints, *servinfo, *p; - gint port = get_key_file_integer("global", "tcp_port"); - char buf[7]; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - if ((opt = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port), - &hints, &servinfo)) == -1) { - log_write("getaddrinfo(): %s", gai_strerror(opt)); - goto do_exit; - } - - for(p = servinfo; p != NULL; p = p->ai_next) { - if ((sockfd_r = socket(p->ai_family, p->ai_socktype, - p->ai_protocol)) == -1) { - log_write("socket(): %s", strerror(errno)); - continue; - } - - opt = 1; - - if (setsockopt(sockfd_r, SOL_SOCKET, SO_REUSEADDR, &opt, - sizeof(int)) == -1) { - log_write("setsockopt(): %s", strerror(errno)); - goto do_exit; - } - - if (bind(sockfd_r, p->ai_addr, p->ai_addrlen) == -1) { - close(sockfd_r); - log_write("bind(): %s", strerror(errno)); - continue; - } - - opt++; - break; - } - - freeaddrinfo(servinfo); - - if (!p) { - log_write("%s", N_("could not bind")); - goto do_exit; - } - - if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) { - gchar *tmp = get_key_file_string("global", "tcp_interface"); - - if (setsockopt(sockfd_r, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1) - == -1) { - log_write("setsockopt(): %s", strerror(errno)); - g_free(tmp); - goto do_exit; - } - - g_free(tmp); - } - - ret = gnutls_certificate_allocate_credentials(&x509_cred); - - if (ret != GNUTLS_E_SUCCESS) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - - tmp = expand_homedir("~/.pwmd/ca-cert.pem"); - - if (!tmp) { - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); - goto do_exit; - } - - ret = gnutls_certificate_set_x509_trust_file(x509_cred, tmp, - GNUTLS_X509_FMT_PEM); - g_free(tmp); - - if (ret < 0) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - - tmp = expand_homedir("~/.pwmd/server-cert.pem"); - - if (!tmp) { - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); - goto do_exit; - } - - tmp2 = expand_homedir("~/.pwmd/server-key.pem"); - - if (!tmp2) { - xfree(tmp); - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); - goto do_exit; - } - - ret = gnutls_certificate_set_x509_key_file (x509_cred, tmp, tmp2, - GNUTLS_X509_FMT_PEM); - g_free(tmp); - g_free(tmp2); + cmdline = FALSE; - if (ret != GNUTLS_E_SUCCESS) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - } -#endif + if (startStopTcp(FALSE) == FALSE) + goto do_exit; if (background) { switch (fork()) { @@ -2454,57 +2561,6 @@ int main(int argc, char *argv[]) } } - cmdline = FALSE; - -#ifdef WITH_GNUTLS - if (get_key_file_boolean("global", "enable_tcp")) { - log_write("%s", N_("Generating key exchange parameters...")); - ret = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); - - if (ret) { - log_write("%s", gpg_strerror(ret)); - goto do_exit; - } - - ret = gnutls_dh_params_init(&dh_params); - - if (ret != GNUTLS_E_SUCCESS) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - - ret = gnutls_dh_params_generate2(dh_params, 1024); - - if (ret != GNUTLS_E_SUCCESS) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - - gnutls_certificate_set_dh_params(x509_cred, dh_params); - ret = gnutls_rsa_params_init(&rsa_params); - - if (ret != GNUTLS_E_SUCCESS) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - - ret = gnutls_rsa_params_generate2(rsa_params, 512); - - if (ret != GNUTLS_E_SUCCESS) { - log_write("%s", gnutls_strerror(ret)); - goto do_exit; - } - - gnutls_certificate_set_rsa_export_params(x509_cred, rsa_params); - gnutls_certificate_set_params_function(x509_cred, tls_get_params); - - if (listen(sockfd_r, 0) == -1) { - log_write("listen(): %s", strerror(errno)); - goto do_exit; - } - } -#endif - /* * These are the signals that we use in threads. libpth can catch signals * itself so ignore them everywhere else. Note that using @@ -2530,7 +2586,7 @@ int main(int argc, char *argv[]) * for rcs even after the client disconnects. */ signal(SIGPIPE, SIG_IGN); pth_sigmask(SIG_BLOCK, &set, NULL); - server_loop(sockfd, sockfd_r, &socketpath); + server_loop(sockfd, &socketpath); estatus = EXIT_SUCCESS; do_exit: @@ -2540,15 +2596,8 @@ do_exit: } #ifdef WITH_GNUTLS - if (sockfd_r != -1) { - gnutls_dh_params_deinit(dh_params); - gnutls_rsa_params_deinit(rsa_params); - - if (x509_cred) - gnutls_certificate_free_credentials(x509_cred); - - gnutls_global_deinit(); - } + startStopTcp(TRUE); + gnutls_global_deinit(); #endif g_key_file_free(keyfileh); diff --git a/src/pwmd.h b/src/pwmd.h index 685e96aa..5a861157 100644 --- a/src/pwmd.h +++ b/src/pwmd.h @@ -28,6 +28,10 @@ static gint quit; static GSList *cn_thread_list; static pth_mutex_t cn_mutex; static gboolean cmdline; +#ifdef WITH_GNUTLS +static int tcpSockFd; +pth_t tcpAcceptTid; +#endif static gboolean do_cache_push(const gchar *filename, const gchar *password); static GKeyFile *parse_rcfile(); -- 2.11.4.GIT