masscan-mark-ii/src/out-json.c

146 lines
4.8 KiB
C

#include "output.h"
#include "masscan-app.h"
#include "masscan-status.h"
#include "util-safefunc.h"
#include <ctype.h>
/****************************************************************************
****************************************************************************/
static void
json_out_open(struct Output *out, FILE *fp)
{
UNUSEDPARM(out);
fprintf(fp, "[\n"); // enclose the atomic {}'s into an []
}
/****************************************************************************
****************************************************************************/
static void
json_out_close(struct Output *out, FILE *fp)
{
UNUSEDPARM(out);
fprintf(fp, "]\n"); // enclose the atomic {}'s into an []
}
//{ ip: "124.53.139.201", ports: [ {port: 443, proto: "tcp", status: "open", reason: "syn-ack", ttl: 48} ] }
/****************************************************************************
****************************************************************************/
static void
json_out_status(struct Output *out, FILE *fp, time_t timestamp, int status,
ipaddress ip, unsigned ip_proto, unsigned port, unsigned reason, unsigned ttl)
{
char reason_buffer[128];
ipaddress_formatted_t fmt;
UNUSEDPARM(out);
//UNUSEDPARM(timestamp);
/* Trailing comma breaks some JSON parsers. We don't know precisely when
* we'll end, but we do know when we begin, so instead of appending
* a command to the record, we prepend it -- but not before first record */
if (out->is_first_record_seen)
fprintf(fp, ",\n");
else
out->is_first_record_seen = 1;
fprintf(fp, "{ ");
fmt = ipaddress_fmt(ip);
fprintf(fp, " \"ip\": \"%s\", ", fmt.string);
fprintf(fp, " \"timestamp\": \"%d\", \"ports\": [ {\"port\": %u, \"proto\": \"%s\", \"status\": \"%s\","
" \"reason\": \"%s\", \"ttl\": %u} ] ",
(int) timestamp,
port,
name_from_ip_proto(ip_proto),
status_string(status),
reason_string(reason, reason_buffer, sizeof(reason_buffer)),
ttl
);
fprintf(fp, "}\n");
}
/*****************************************************************************
* Remove bad characters from the banner, especially new lines and HTML
* control codes.
*****************************************************************************/
static const char *
normalize_json_string(const unsigned char *px, size_t length,
char *buf, size_t buf_len)
{
size_t i=0;
size_t offset = 0;
for (i=0; i<length; i++) {
unsigned char c = px[i];
if (isprint(c) && c != '<' && c != '>' && c != '&' && c != '\\' && c != '\"' && c != '\'') {
if (offset + 2 < buf_len)
buf[offset++] = px[i];
} else {
if (offset + 7 < buf_len) {
buf[offset++] = '\\';
buf[offset++] = 'u';
buf[offset++] = '0';
buf[offset++] = '0';
buf[offset++] = "0123456789abcdef"[px[i]>>4];
buf[offset++] = "0123456789abcdef"[px[i]&0xF];
}
}
}
buf[offset] = '\0';
return buf;
}
/******************************************************************************
******************************************************************************/
static void
json_out_banner(struct Output *out, FILE *fp, time_t timestamp,
ipaddress ip, unsigned ip_proto, unsigned port,
enum ApplicationProtocol proto,
unsigned ttl,
const unsigned char *px, unsigned length)
{
char banner_buffer[65536];
ipaddress_formatted_t fmt;
UNUSEDPARM(ttl);
/* Trailing comma breaks some JSON parsers. We don't know precisely when
* we'll end, but we do know when we begin, so instead of appending
* a command to the record, we prepend it -- but not before first record */
if (out->is_first_record_seen)
fprintf(fp, ",\n");
else
out->is_first_record_seen = 1;
fprintf(fp, "{ ");
fmt = ipaddress_fmt(ip);
fprintf(fp, " \"ip\": \"%s\", ", fmt.string);
fprintf(fp, " \"timestamp\": \"%d\", \"ports\": [ {\"port\": %u, \"proto\": \"%s\", \"service\": {\"name\": \"%s\", \"banner\": \"%s\"} } ] ",
(int) timestamp,
port,
name_from_ip_proto(ip_proto),
masscan_app_to_string(proto),
normalize_json_string(px, length, banner_buffer, sizeof(banner_buffer))
);
fprintf(fp, "}\n");
UNUSEDPARM(out);
}
/****************************************************************************
****************************************************************************/
const struct OutputType json_output = {
"json",
0,
json_out_open,
json_out_close,
json_out_status,
json_out_banner
};