Michal Toman
2013-09-12 14:39:30 UTC
Signed-off-by: Michal Toman <mtoman-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
---
src/plugins/abrt-retrace-client.c | 138 ++++++++++++++++++++++++++++++++++++--
1 file changed, 131 insertions(+), 7 deletions(-)
diff --git a/src/plugins/abrt-retrace-client.c b/src/plugins/abrt-retrace-client.c
index 1712702..8b35dbe 100644
--- a/src/plugins/abrt-retrace-client.c
+++ b/src/plugins/abrt-retrace-client.c
@@ -21,6 +21,7 @@
#define MAX_FORMATS 16
#define MAX_RELEASES 32
#define MAX_DOTS_PER_LINE 80
+#define MIN_EXPLOITABLE_RATING 4
enum
{
@@ -929,6 +930,93 @@ static void run_backtrace(const char *task_id, const char *task_password)
free(backtrace_text);
}
+/* This is not robust at all but will work for now */
+static int get_exploitable_rating(const char *exploitable_text)
+{
+ const char *colon = strrchr(exploitable_text, ':');
+ int result;
+ if (!colon || sscanf(colon, ": %d", &result) != 1)
+ {
+ VERB1 log_msg("Unable to determine exploitable rating");
+ return -1;
+ }
+
+ VERB1 log_msg("Exploitable rating: %d", result);
+ return result;
+}
+
+/* Caller must free exploitable_text */
+static void exploitable(const char *task_id, const char *task_password,
+ char **exploitable_text)
+{
+ PRFileDesc *tcp_sock, *ssl_sock;
+ ssl_connect(&cfg, &tcp_sock, &ssl_sock);
+ struct strbuf *http_request = strbuf_new();
+ strbuf_append_strf(http_request,
+ "GET /%s/exploitable HTTP/1.1\r\n"
+ "Host: %s\r\n"
+ "X-Task-Password: %s\r\n"
+ "Content-Length: 0\r\n"
+ "Connection: close\r\n"
+ "%s"
+ "%s"
+ "\r\n",
+ task_id, cfg.url, task_password,
+ lang.accept_charset,
+ lang.accept_language
+ );
+
+ PRInt32 written = PR_Send(tcp_sock, http_request->buf, http_request->len,
+ /*flags:*/0, PR_INTERVAL_NO_TIMEOUT);
+ if (written == -1)
+ {
+ alert_connection_error(cfg.url);
+ error_msg_and_die(_("Failed to send HTTP header of length %d: NSS error %d."),
+ http_request->len, PR_GetError());
+ }
+ strbuf_free(http_request);
+ char *http_response = tcp_read_response(tcp_sock);
+ char *http_body = http_get_body(http_response);
+ if (!http_body)
+ {
+ alert_server_error(cfg.url);
+ error_msg_and_die(_("Invalid response from server: missing HTTP message body."));
+ }
+ if (http_show_headers)
+ http_print_headers(stderr, http_response);
+ int response_code = http_get_response_code(http_response);
+
+ free(http_response);
+ ssl_disconnect(ssl_sock);
+
+ /* 404 = exploitability results not available
+ 200 = OK
+ anything else = error */
+ if (response_code == 404)
+ *exploitable_text = NULL;
+ else if (response_code == 200)
+ *exploitable_text = http_body;
+ else
+ {
+ alert_server_error(cfg.url);
+ error_msg_and_die(_("Unexpected HTTP response from server: %d\n%s"),
+ response_code, http_body);
+ }
+}
+
+static void run_exploitable(const char *task_id, const char *task_password)
+{
+ char *exploitable_text;
+ exploitable(task_id, task_password, &exploitable_text);
+ if (exploitable_text)
+ {
+ printf("%s\n", exploitable_text);
+ free(exploitable_text);
+ }
+ else
+ puts("No exploitability information available.");
+}
+
static void run_log(const char *task_id, const char *task_password)
{
PRFileDesc *tcp_sock, *ssl_sock;
@@ -1026,19 +1114,47 @@ static int run_batch(bool delete_temp_archive)
{
char *backtrace_text;
backtrace(task_id, task_password, &backtrace_text);
+ char *exploitable_text = NULL;
+ if (task_type == TASK_RETRACE)
+ {
+ exploitable(task_id, task_password, &exploitable_text);
+ if (!exploitable_text)
+ VERB1 log_msg("No exploitable data available");
+ }
+
if (dump_dir_name)
{
+ struct dump_dir *dd = dd_opendir(dump_dir_name, 0/* flags */);
+ if (!dd)
+ {
+ free(backtrace_text);
+ xfunc_die();
+ }
+
/* the result of TASK_VMCORE is not backtrace, but kernel log */
- char *backtrace_path = xasprintf("%s/%s", dump_dir_name,
- task_type == TASK_VMCORE ? FILENAME_KERNEL_LOG : FILENAME_BACKTRACE);
- int backtrace_fd = xopen3(backtrace_path, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_DUMP_DIR_MODE);
- xwrite(backtrace_fd, backtrace_text, strlen(backtrace_text));
- close(backtrace_fd);
- free(backtrace_path);
+ const char *target = task_type == TASK_VMCORE ? FILENAME_KERNEL_LOG : FILENAME_BACKTRACE;
+ dd_save_text(dd, target, backtrace_text);
+
+ if (exploitable_text)
+ {
+ int exploitable_rating = get_exploitable_rating(exploitable_text);
+ if (exploitable_rating >= MIN_EXPLOITABLE_RATING)
+ dd_save_text(dd, FILENAME_EXPLOITABLE, exploitable_text);
+ else
+ VERB1 log_msg("Not saving exploitable data, rating < %d",
+ MIN_EXPLOITABLE_RATING);
+ }
+
+ dd_close(dd);
}
else
- printf("%s", backtrace_text);
+ {
+ printf("%s\n", backtrace_text);
+ if (exploitable_text)
+ printf("%s\n", exploitable_text);
+ }
free(backtrace_text);
+ free(exploitable_text);
}
else
{
@@ -1198,6 +1314,14 @@ int main(int argc, char **argv)
error_msg_and_die(_("Task password is needed."));
run_log(task_id, task_password);
}
+ else if (0 == strcasecmp(operation, "exploitable"))
+ {
+ if (!task_id)
+ error_msg_and_die(_("Task id is needed."));
+ if (!task_password)
+ error_msg_and_die(_("Task password is needed."));
+ run_exploitable(task_id, task_password);
+ }
else
error_msg_and_die(_("Unknown operation: %s."), operation);
---
src/plugins/abrt-retrace-client.c | 138 ++++++++++++++++++++++++++++++++++++--
1 file changed, 131 insertions(+), 7 deletions(-)
diff --git a/src/plugins/abrt-retrace-client.c b/src/plugins/abrt-retrace-client.c
index 1712702..8b35dbe 100644
--- a/src/plugins/abrt-retrace-client.c
+++ b/src/plugins/abrt-retrace-client.c
@@ -21,6 +21,7 @@
#define MAX_FORMATS 16
#define MAX_RELEASES 32
#define MAX_DOTS_PER_LINE 80
+#define MIN_EXPLOITABLE_RATING 4
enum
{
@@ -929,6 +930,93 @@ static void run_backtrace(const char *task_id, const char *task_password)
free(backtrace_text);
}
+/* This is not robust at all but will work for now */
+static int get_exploitable_rating(const char *exploitable_text)
+{
+ const char *colon = strrchr(exploitable_text, ':');
+ int result;
+ if (!colon || sscanf(colon, ": %d", &result) != 1)
+ {
+ VERB1 log_msg("Unable to determine exploitable rating");
+ return -1;
+ }
+
+ VERB1 log_msg("Exploitable rating: %d", result);
+ return result;
+}
+
+/* Caller must free exploitable_text */
+static void exploitable(const char *task_id, const char *task_password,
+ char **exploitable_text)
+{
+ PRFileDesc *tcp_sock, *ssl_sock;
+ ssl_connect(&cfg, &tcp_sock, &ssl_sock);
+ struct strbuf *http_request = strbuf_new();
+ strbuf_append_strf(http_request,
+ "GET /%s/exploitable HTTP/1.1\r\n"
+ "Host: %s\r\n"
+ "X-Task-Password: %s\r\n"
+ "Content-Length: 0\r\n"
+ "Connection: close\r\n"
+ "%s"
+ "%s"
+ "\r\n",
+ task_id, cfg.url, task_password,
+ lang.accept_charset,
+ lang.accept_language
+ );
+
+ PRInt32 written = PR_Send(tcp_sock, http_request->buf, http_request->len,
+ /*flags:*/0, PR_INTERVAL_NO_TIMEOUT);
+ if (written == -1)
+ {
+ alert_connection_error(cfg.url);
+ error_msg_and_die(_("Failed to send HTTP header of length %d: NSS error %d."),
+ http_request->len, PR_GetError());
+ }
+ strbuf_free(http_request);
+ char *http_response = tcp_read_response(tcp_sock);
+ char *http_body = http_get_body(http_response);
+ if (!http_body)
+ {
+ alert_server_error(cfg.url);
+ error_msg_and_die(_("Invalid response from server: missing HTTP message body."));
+ }
+ if (http_show_headers)
+ http_print_headers(stderr, http_response);
+ int response_code = http_get_response_code(http_response);
+
+ free(http_response);
+ ssl_disconnect(ssl_sock);
+
+ /* 404 = exploitability results not available
+ 200 = OK
+ anything else = error */
+ if (response_code == 404)
+ *exploitable_text = NULL;
+ else if (response_code == 200)
+ *exploitable_text = http_body;
+ else
+ {
+ alert_server_error(cfg.url);
+ error_msg_and_die(_("Unexpected HTTP response from server: %d\n%s"),
+ response_code, http_body);
+ }
+}
+
+static void run_exploitable(const char *task_id, const char *task_password)
+{
+ char *exploitable_text;
+ exploitable(task_id, task_password, &exploitable_text);
+ if (exploitable_text)
+ {
+ printf("%s\n", exploitable_text);
+ free(exploitable_text);
+ }
+ else
+ puts("No exploitability information available.");
+}
+
static void run_log(const char *task_id, const char *task_password)
{
PRFileDesc *tcp_sock, *ssl_sock;
@@ -1026,19 +1114,47 @@ static int run_batch(bool delete_temp_archive)
{
char *backtrace_text;
backtrace(task_id, task_password, &backtrace_text);
+ char *exploitable_text = NULL;
+ if (task_type == TASK_RETRACE)
+ {
+ exploitable(task_id, task_password, &exploitable_text);
+ if (!exploitable_text)
+ VERB1 log_msg("No exploitable data available");
+ }
+
if (dump_dir_name)
{
+ struct dump_dir *dd = dd_opendir(dump_dir_name, 0/* flags */);
+ if (!dd)
+ {
+ free(backtrace_text);
+ xfunc_die();
+ }
+
/* the result of TASK_VMCORE is not backtrace, but kernel log */
- char *backtrace_path = xasprintf("%s/%s", dump_dir_name,
- task_type == TASK_VMCORE ? FILENAME_KERNEL_LOG : FILENAME_BACKTRACE);
- int backtrace_fd = xopen3(backtrace_path, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_DUMP_DIR_MODE);
- xwrite(backtrace_fd, backtrace_text, strlen(backtrace_text));
- close(backtrace_fd);
- free(backtrace_path);
+ const char *target = task_type == TASK_VMCORE ? FILENAME_KERNEL_LOG : FILENAME_BACKTRACE;
+ dd_save_text(dd, target, backtrace_text);
+
+ if (exploitable_text)
+ {
+ int exploitable_rating = get_exploitable_rating(exploitable_text);
+ if (exploitable_rating >= MIN_EXPLOITABLE_RATING)
+ dd_save_text(dd, FILENAME_EXPLOITABLE, exploitable_text);
+ else
+ VERB1 log_msg("Not saving exploitable data, rating < %d",
+ MIN_EXPLOITABLE_RATING);
+ }
+
+ dd_close(dd);
}
else
- printf("%s", backtrace_text);
+ {
+ printf("%s\n", backtrace_text);
+ if (exploitable_text)
+ printf("%s\n", exploitable_text);
+ }
free(backtrace_text);
+ free(exploitable_text);
}
else
{
@@ -1198,6 +1314,14 @@ int main(int argc, char **argv)
error_msg_and_die(_("Task password is needed."));
run_log(task_id, task_password);
}
+ else if (0 == strcasecmp(operation, "exploitable"))
+ {
+ if (!task_id)
+ error_msg_and_die(_("Task id is needed."));
+ if (!task_password)
+ error_msg_and_die(_("Task password is needed."));
+ run_exploitable(task_id, task_password);
+ }
else
error_msg_and_die(_("Unknown operation: %s."), operation);
--
1.8.3.1
1.8.3.1