diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2014-09-20 18:10:29 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2014-09-20 22:03:55 +0200 | 
| commit | 2b74a188332f152e8952725812e086968a41e925 (patch) | |
| tree | e895a69b6e04d70bbb98f6b6ad6446837bdc1891 | |
| parent | b9571ec01ff2a23475ca1a8a6b9910f49206b4ff (diff) | |
| download | ponymap-2b74a188332f152e8952725812e086968a41e925.tar.gz ponymap-2b74a188332f152e8952725812e086968a41e925.tar.xz ponymap-2b74a188332f152e8952725812e086968a41e925.zip | |
Implement more of the services
 - SSH: ready for action
 - IRC: ready for action
 - HTTP: needs some work
| -rw-r--r-- | plugin-api.h | 8 | ||||
| -rw-r--r-- | plugins/http.c | 23 | ||||
| -rw-r--r-- | plugins/irc.c | 101 | ||||
| -rw-r--r-- | plugins/ssh.c | 13 | ||||
| -rw-r--r-- | ponymap.c | 42 | 
5 files changed, 157 insertions, 30 deletions
| diff --git a/plugin-api.h b/plugin-api.h index 96056ee..3406308 100644 --- a/plugin-api.h +++ b/plugin-api.h @@ -44,9 +44,14 @@ struct service  	/// Destroy the handle created for the scan  	void (*scan_free) (void *handle); +	// XXX: maybe force the service to store a reference to the unit? +  	/// We have received some data from the peer +	// FIXME: the dependency on `struct str' is not very good  	void (*on_data) (void *handle, struct unit *u, struct str *data); +	// XXX: do we need these at all?  Is there any use for them? +  	/// Server has closed the connection  	void (*on_eof) (void *handle, struct unit *u); @@ -62,6 +67,9 @@ struct plugin_api  	/// Register the plugin for a service  	void (*register_service) (void *ctx, struct service *info); +	/// Get the IP address of the target as a string +	const char *(*unit_get_address) (struct unit *u); +  	/// Send some data to the peer  	ssize_t (*unit_write) (struct unit *u, const void *buf, size_t len); diff --git a/plugins/http.c b/plugins/http.c index 2b16462..b350fee 100644 --- a/plugins/http.c +++ b/plugins/http.c @@ -30,23 +30,38 @@ static struct plugin_data  }  g_data; +struct scan_data +{ +	struct str input;                   ///< Input buffer +}; +  static void *  scan_init (struct unit *u)  { -	// TODO -	return NULL; +	struct str hello; +	str_init (&hello); +	str_append_printf (&hello, "GET / HTTP/1.0\r\n" +		"Host: %s\r\n\r\n", g_data.api->unit_get_address (u)); +	g_data.api->unit_write (u, hello.str, hello.len); +	str_free (&hello); + +	struct scan_data *scan = xcalloc (1, sizeof *scan); +	str_init (&scan->input); +	return scan;  }  static void  scan_free (void *handle)  { -	// TODO +	struct scan_data *scan = handle; +	str_free (&scan->input); +	free (scan);  }  static void  on_data (void *handle, struct unit *u, struct str *data)  { -	// TODO +	// TODO: implement a state machine to parse the headers  }  static struct service g_http_service = diff --git a/plugins/irc.c b/plugins/irc.c index 58f594a..7732b73 100644 --- a/plugins/irc.c +++ b/plugins/irc.c @@ -191,6 +191,13 @@ irc_fnmatch (const char *pattern, const char *string)  	return fnmatch (x_pattern, x_string, 0);  } +// --- Other selected IRC stuff ------------------------------------------------ + +#define IRC_MAX_NICKNAME  9             ///< The limit from RFC 2812 + +#define IRC_RPL_WELCOME   1 +#define IRC_RPL_MYINFO    4 +  // --- Service detection -------------------------------------------------------  static struct plugin_data @@ -200,11 +207,103 @@ static struct plugin_data  }  g_data; +struct scan_data +{ +	struct str input;                   ///< Input buffer +	struct unit *u;                     ///< Scan unit +}; + +static void * +scan_init (struct unit *u) +{ +	char nick[IRC_MAX_NICKNAME + 1]; +	for (size_t i = 0; i < sizeof nick - 1; i++) +		nick[i] = 'a' + rand () % ('z' - 'a' + 1); + +	struct str hello; +	str_init (&hello); +	str_append_printf (&hello, +		"NICK %s\r\nUSER %s 8 * :%s\r\n", nick, nick, nick); +	g_data.api->unit_write (u, hello.str, hello.len); +	str_free (&hello); + +	struct scan_data *scan = xcalloc (1, sizeof *scan); +	str_init (&scan->input); +	scan->u = u; +	return scan; +} + +static void +scan_free (void *handle) +{ +	struct scan_data *scan = handle; +	str_free (&scan->input); +	free (scan); +} + +static void +on_irc_message (const struct irc_message *msg, const char *raw, void *user_data) +{ +	(void) raw; +	struct scan_data *scan = user_data; + +	unsigned long code; +	if (!irc_strcmp (msg->command, "PING")) +	{ +		// Without this we might be unable to finish registration +		struct str pong; +		str_init (&pong); +		str_append_printf (&pong, "PONG :%s\r\n", +			msg->params.len > 0 ? msg->params.vector[0] : ""); +		g_data.api->unit_write (scan->u, pong.str, pong.len); +	} +	else if (strlen (msg->command) == 3 && xstrtoul (&code, msg->command, 10)) +	{ +		// It looks like we've successfully registered +		if (msg->prefix && code == IRC_RPL_WELCOME) +			g_data.api->unit_set_success (scan->u, true); + +		// Extract the server name at least +		if (code == IRC_RPL_MYINFO && msg->params.len > 0) +		{ +			char *info = xstrdup_printf ("%s: %s", +				"server name", msg->params.vector[0]); +			g_data.api->unit_add_info (scan->u, info); +			free (info); + +			g_data.api->unit_abort (scan->u); +		} +	} +} + +static void +on_data (void *handle, struct unit *u, struct str *data) +{ +	(void) u; + +	struct scan_data *scan = handle; +	str_append_str (&scan->input, data); +	irc_process_buffer (&scan->input, on_irc_message, scan); +} + +static struct service g_irc_service = +{ +	.name        = "IRC", +	.flags       = SERVICE_SUPPORTS_TLS, + +	.scan_init   = scan_init, +	.scan_free   = scan_free, +	.on_data     = on_data, +	.on_eof      = NULL, +	.on_error    = NULL, +	.on_aborted  = NULL +}; +  static bool  initialize (void *ctx, struct plugin_api *api)  {  	g_data = (struct plugin_data) { .ctx = ctx, .api = api }; -	// TODO: register a service +	api->register_service (ctx, &g_irc_service);  	return true;  } diff --git a/plugins/ssh.c b/plugins/ssh.c index 3a32223..cf18c3c 100644 --- a/plugins/ssh.c +++ b/plugins/ssh.c @@ -56,20 +56,25 @@ scan_free (void *handle)  static void  on_data (void *handle, struct unit *u, struct str *data)  { -	// TODO: don't let the input buffer grow too much +	// See RFC 4253 -- we check for a valid SSH banner  	struct scan_data *scan = handle; -	str_append_str (&scan->input, data); +	if (scan->input.len + data->len > 255) +		goto end_scan; +	str_append_str (&scan->input, data);  	char *input = scan->input.str;  	char *nl = strstr (input, "\r\n");  	if (!nl)  		return; -	// TODO: parse the reply, make sure that it's actually SSH, -	//   don't put just any garbage in the output info +	if (strncmp (input, "SSH-", 4)) +		goto end_scan; +  	*nl = '\0';  	g_data.api->unit_add_info (u, input);  	g_data.api->unit_set_success (u, true); + +end_scan:  	g_data.api->unit_abort (u);  } @@ -189,6 +189,7 @@ struct target  	struct app_context *ctx;            ///< Application context  	uint32_t ip;                        ///< IP address +	char ip_string[INET_ADDRSTRLEN];    ///< IP address as a string  	char *hostname;                     ///< Hostname  	/// All units that have ended, successfully finding a service.  These don't @@ -773,6 +774,12 @@ plugin_api_register_service (void *app_context, struct service *info)  		str_map_set (&ctx->services, info->name, info);  } +static const char * +plugin_api_unit_get_address (struct unit *u) +{ +	return u->target->ip_string; +} +  static ssize_t  plugin_api_unit_write (struct unit *u, const void *buf, size_t len)  { @@ -804,6 +811,7 @@ plugin_api_unit_abort (struct unit *u)  static struct plugin_api g_plugin_vtable =  {  	.register_service  = plugin_api_register_service, +	.unit_get_address  = plugin_api_unit_get_address,  	.unit_write        = plugin_api_unit_write,  	.unit_set_success  = plugin_api_unit_set_success,  	.unit_add_info     = plugin_api_unit_add_info, @@ -1180,7 +1188,7 @@ node_escape_text (const char *text)  	struct str filtered;  	str_init (&filtered); -	char c; +	int c;  	while ((c = *text++))  		str_append_c (&filtered,  			(isascii (c) && (isgraph (c) || c == ' ')) ? c : '.'); @@ -1251,8 +1259,6 @@ node_print_tree (struct node *self)  struct target_dump_data  { -	char address[INET_ADDRSTRLEN];      ///< The IP address as a string -  	struct unit **results;              ///< Results sorted by service  	size_t results_len;                 ///< Number of results  }; @@ -1263,7 +1269,7 @@ target_dump_json (struct target *self, struct target_dump_data *data)  	json_t *o = json_object ();  	json_array_append_new (self->ctx->json_results, o); -	json_object_set_new (o, "address", json_string (data->address)); +	json_object_set_new (o, "address", json_string (self->ip_string));  	if (self->hostname)  		json_object_set_new (o, "hostname", json_string (self->hostname));  	if (self->ctx->quitting) @@ -1310,7 +1316,7 @@ target_dump_terminal (struct target *self, struct target_dump_data *data)  	struct str tmp;  	str_init (&tmp); -	str_append (&tmp, data->address); +	str_append (&tmp, self->ip_string);  	if (self->hostname)  		str_append_printf (&tmp, " (%s)", self->hostname);  	if (self->ctx->quitting) @@ -1363,13 +1369,6 @@ target_dump_results (struct target *self)  	struct app_context *ctx = self->ctx;  	struct target_dump_data data; -	uint32_t address = htonl (self->ip); -	if (!inet_ntop (AF_INET, &address, data.address, sizeof data.address)) -	{ -		print_error ("%s: %s", "inet_ntop", strerror (errno)); -		return; -	} -  	size_t len = 0;  	for (struct unit *iter = self->results; iter; iter = iter->next)  		len++; @@ -1392,15 +1391,7 @@ target_dump_results (struct target *self)  static void  target_update_indicator (struct target *self)  { -	char buf[INET_ADDRSTRLEN]; -	uint32_t address = htonl (self->ip); -	if (!inet_ntop (AF_INET, &address, buf, sizeof buf)) -	{ -		print_error ("%s: %s", "inet_ntop", strerror (errno)); -		return; -	} - -	char *status = xstrdup_printf ("Scanning %s", buf); +	char *status = xstrdup_printf ("Scanning %s", self->ip_string);  	struct indicator *indicator = &self->ctx->indicator;  	if (!indicator->status || strcmp (status, indicator->status))  		indicator_set_status (&self->ctx->indicator, status); @@ -1464,6 +1455,14 @@ generator_make_target (struct app_context *ctx)  	if (g->ip_iter == g->ip_range_iter->original_address)  		target->hostname = xstrdup (g->ip_range_iter->original_name); +	uint32_t address = htonl (target->ip); +	if (!inet_ntop (AF_INET, &address, +		target->ip_string, sizeof target->ip_string)) +	{ +		print_error ("%s: %s", "inet_ntop", strerror (errno)); +		*target->ip_string = '\0'; +	} +  	LIST_APPEND_WITH_TAIL (ctx->running_targets, ctx->running_tail, target);  	target_update_indicator (ctx->running_targets);  } @@ -1908,6 +1907,7 @@ main (int argc, char *argv[])  	parse_program_arguments (&ctx, argc, argv);  	setup_signal_handlers (); +	srand (time (NULL));  	// Set the maximum count of file descriptorts to the hard limit  	struct rlimit limit; | 
