diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | src/plugins/Makefile.am | 25 | ||||
-rw-r--r-- | src/plugins/abrt-retrace-client.c | 243 |
3 files changed, 267 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac index f1b08889..6aa95607 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_INIT([abrt], [1.2.0], [crash-catcher@fedorahosted.org]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign silent-rules]) +AM_INIT_AUTOMAKE([-Wall foreign silent-rules]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) AC_ARG_ENABLE(debug, @@ -17,7 +17,7 @@ AC_SYS_LARGEFILE CXXFLAGS="$CXXFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE \ -D_FILE_OFFSET_BITS=64 -fno-strict-aliasing " CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE \ - -D_FILE_OFFSET_BITS=64 -fno-strict-aliasing -std=gnu99 -Wall" + -D_FILE_OFFSET_BITS=64 -fno-strict-aliasing -std=gnu99" dnl ****** INTERNATIONALIZATION ********************** GETTEXT_PACKAGE=abrt diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index a7790e71..c7d8c1f7 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -74,7 +74,8 @@ libexec_PROGRAMS = \ abrt-action-kerneloops \ abrt-action-upload \ abrt-action-mailx \ - abrt-action-print + abrt-action-print \ + abrt-retrace-client abrt_action_analyze_c_SOURCES = \ abrt-action-analyze-c.c @@ -186,8 +187,7 @@ abrt_action_rhtsupport_CPPFLAGS = \ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ $(GLIB_CFLAGS) \ $(XMLRPC_CFLAGS) $(XMLRPC_CLIENT_CFLAGS) \ - -D_GNU_SOURCE \ - -Wall -Werror + -D_GNU_SOURCE abrt_action_rhtsupport_LDFLAGS = -ltar abrt_action_rhtsupport_LDADD = \ $(GLIB_LIBS) \ @@ -279,4 +279,23 @@ abrt_action_print_CPPFLAGS = \ abrt_action_print_LDADD = \ ../lib/libabrt.la +abrt_retrace_client_SOURCES = \ + abrt-retrace-client.c +abrt_retrace_client_CPPFLAGS = \ + -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ + -DBIN_DIR=\"$(bindir)\" \ + -DVAR_RUN=\"$(VAR_RUN)\" \ + -DCONF_DIR=\"$(CONF_DIR)\" \ + -DLOCALSTATEDIR='"$(localstatedir)"' \ + -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ + -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \ + -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ + -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ + -D_GNU_SOURCE \ + -Wall -Werror +abrt_retrace_client_LDADD = \ + ../lib/libabrt.la \ + ../btparser/libbtparser.la + DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ diff --git a/src/plugins/abrt-retrace-client.c b/src/plugins/abrt-retrace-client.c new file mode 100644 index 00000000..834c22d3 --- /dev/null +++ b/src/plugins/abrt-retrace-client.c @@ -0,0 +1,243 @@ +/* + Copyright (C) 2010 Red Hat, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +http://www.mail-archive.com/dev-tech-crypto@lists.mozilla.org/msg01921.html +*/ +#include "abrtlib.h" +#include "parse_options.h" +#include <nspr.h> +#include <nss.h> +#include <pk11pub.h> +#include <ssl.h> +#include <sslproto.h> + +static const char *dump_dir_name = "."; +static const char abrt_retrace_client_usage[] = "abrt-retrace-client [options] -d DIR"; + +enum { + OPT_v = 1 << 0, + OPT_d = 1 << 1, + OPT_s = 1 << 2, +}; + +/* Keep enum above and order of options below in sync! */ +static struct options abrt_retrace_client_options[] = { + OPT__VERBOSE(&g_verbose), + OPT_STRING( 'd', NULL, &dump_dir_name, "DIR", "Crash dump directory"), + OPT_BOOL( 's', NULL, NULL, "Log to syslog"), + OPT_END() +}; + +void add_if_exists(struct dump_dir *dd, + const char *name, + const char *args[], + int *argindex) +{ + if (dd_exist(dd, name)) + { + args[*argindex] = name; + *argindex += 1; + } +} + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + unsigned opts = parse_opts(argc, argv, abrt_retrace_client_options, + abrt_retrace_client_usage); + + if (opts & OPT_s) + { + openlog(msg_prefix, 0, LOG_DAEMON); + logmode = LOGMODE_SYSLOG; + } + + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + return 1; + + const char *args[10]; + args[0] = "tar"; + args[1] = "cJvO"; + int argindex = 2; + args[argindex++] = xasprintf("--directory=%s", dump_dir_name); + args[argindex++] = FILENAME_COREDUMP; + add_if_exists(dd, FILENAME_ANALYZER, args, &argindex); + add_if_exists(dd, FILENAME_ARCHITECTURE, args, &argindex); + add_if_exists(dd, FILENAME_EXECUTABLE, args, &argindex); + add_if_exists(dd, FILENAME_PACKAGE, args, &argindex); + add_if_exists(dd, FILENAME_RELEASE, args, &argindex); + args[argindex] = NULL; + + int tempfd = mkstemp("/tmp/abrt-retrace-client-archive.tar.xz.XXXXXX"); + if (tempfd == -1) + perror_msg_and_die("Cannot open temporary file"); + + int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT; + int pipeout[2]; + pid_t child = fork_execv_on_steroids(flags, (char**)args, + pipeout, NULL, NULL, 0); + + while (1) + { + struct pollfd pfd; + pfd.fd = pipeout[0]; + pfd.events = POLLIN; + poll(&pfd, 1, 1000); + + char buf[32768]; + int r = read(pipeout[0], buf, sizeof(buf)); + if (r <= 0) + { + if (r == -1) + { + if (EINTR == errno || EAGAIN == errno || EWOULDBLOCK == errno) + continue; + perror_msg_and_die("Failed to read from a pipe"); + } + break; + } + + int w = 0; + while (r) + { + w += write(tempfd, buf + w, r); + if (w == -1) + { + if (EINTR == errno) + continue; + + perror_msg_and_die("Failed to write to a temp file"); + } + if (w < r) + { + r -= w; + continue; + } + } + } + + close(pipeout[0]); + close(tempfd); + + /* Prevent having zombie child process, and maybe collect status + * (note that status == NULL is ok too) */ + int status; + waitpid(child, &status, 0); + free((void*)args[2]); + + dd_close(dd); + + + /* Upload the archive. */ +#define HOST "coding.debuntu.org" +#define PAGE "/" +#define PORT 443 +#define USERAGENT "HTMLGET 1.0" + + NSS_Init("path"); + PRFileDesc *tcp_sock = PR_NewTCPSocket(); + if (!sock) + error_msg_and_die("Failed to create a TCP socket"); + + PRSocketOptionData sock_option; + sock_option.option = PR_SockOpt_Nonblocking; + sock_option.value.non_blocking = PR_FALSE; + + PRStatus pr_status = PR_SetSocketOption(tcp_sock, &sock_option); + if (PR_SUCCESS != pr_status) + { + PR_Close(tcp_sock); + error_msg_and_die("Failed to set socket blocking mode."); + } + + PRFileDesc *ssl_sock = SSL_ImportFD(NULL, tcp_sock); + if (!ssl_sock) + { + PR_Close(tcp_sock); + error_msg_and_die("Failed to wrap TCP socket by SSL"); + } + + SECStatus sec_status = SSL_OptionSet(ssl_sock, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); + if (SECSuccess != sec_status) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to enable client handshake to SSL socket."); + } + + sec_status = SSL_OptionSet(ssl_sock, SSL_ENABLE_FDX, PR_TRUE); + if (SECSuccess != sec_status) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to set full duplex to SSL socket."); + } + + sec_status = SSL_SetURL(ssl_sock, HOST); + if (SECSuccess != sec_status) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to set URL to SSL socket."); + } + + char buffer[256]; + PRHostEnt host_entry; + pr_status = PR_GetHostByName(HOST, buffer, sizeof(buffer), &host_entry); + if (PR_SUCCESS != pr_status) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to get host by name."); + } + + PRNetAddr addr; + PRInt32 rv = PR_EnumerateHostEnt(0, &host_entry, PORT, &addr); + if (rv < 0) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to enumerate host ent."); + } + + pr_status = PR_Connect(ssl_sock, &addr, PR_INTERVAL_NO_TIMEOUT); + if (PR_SUCCESS != pr_status) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to connect SSL address"); + } + + sec_status = SSL_ResetHandshake(ssl_sock, PR_FALSE); + if (SECSuccess != sec_status) + { + PR_Close(ssl_sock); + error_msg_and_die("Failed to reset handshake."); + } + + pr_status = PR_Close(ssl_sock); + if (PR_SUCCESS != pr_status) + error_msg("Failed to close SSL socket."); + + SSL_ClearSessionCache(); + + sec_status = NSS_Shutdown(); + if (SECSuccess != sec_status) + error_msg("Failed to shutdown NSS."); + + PR_Cleanup(); + + return 0; +} |