Пример #1
0
int output_log_txt_init(struct output *o) {

	struct output_log_txt_priv *priv = malloc(sizeof(struct output_log_txt_priv));
	if (!priv) {
		pom_oom(sizeof(struct output_log_txt_priv));
		return POM_ERR;
	}
	memset(priv, 0, sizeof(struct output_log_txt_priv));
	output_set_priv(o, priv);

	priv->p_prefix = ptype_alloc("string");
	priv->p_template = ptype_alloc("string");
	if (!priv->p_prefix || !priv->p_template)
		goto err;

	struct registry_param *p = registry_new_param("prefix", "/tmp/", priv->p_prefix, "Log files prefix", 0);
	if (output_instance_add_param(o, p) != POM_OK)
		goto err;
	
	p = registry_new_param("template", "", priv->p_template, "Log template to use", 0);
	if (output_instance_add_param(o, p) != POM_OK)
		goto err;

	return POM_OK;
err:

	output_log_txt_cleanup(priv);
	return POM_ERR;
}
Пример #2
0
int output_file_init(struct output *o) {

	struct output_file_priv *priv = malloc(sizeof(struct output_file_priv));
	if (!priv) {
		pom_oom(sizeof(struct output_file_priv));
		return POM_ERR;
	}
	memset(priv, 0, sizeof(struct output_file_priv));

	output_set_priv(o, priv);

	priv->p_listen_pload_evt = ptype_alloc("bool");
	priv->p_path = ptype_alloc("string");

	if (!priv->p_path || !priv->p_listen_pload_evt)
		goto err;

	struct registry_param *p = registry_new_param("listen_pload_events", "no", priv->p_listen_pload_evt, "Listen to all events that generate payloads", 0);
	if (output_instance_add_param(o, p) != POM_OK)
		goto err;

	p = registry_new_param("path", "/tmp/", priv->p_path, "Path where to store the files", 0);
	if (output_instance_add_param(o, p) != POM_OK)
		goto err;
	
	priv->output_reg.open = output_file_pload_open;
	priv->output_reg.write = output_file_pload_write;
	priv->output_reg.close = output_file_pload_close;

	return POM_OK;
err:
	output_file_cleanup(priv);
	return POM_ERR;

}
Пример #3
0
static int input_kismet_drone_init(struct input *i) {


	struct input_kismet_drone_priv *priv;
	priv = malloc(sizeof(struct input_kismet_drone_priv));
	if (!priv) {
		pom_oom(sizeof(struct input_kismet_drone_priv));
		return POM_ERR;
	}
	memset(priv, 0, sizeof(struct input_kismet_drone_priv));
	priv->fd = -1;

	struct registry_param *p = NULL;

	priv->datalink_80211 = proto_get("80211");
	priv->datalink_radiotap = proto_get("radiotap");
	if (!priv->datalink_80211 || !priv->datalink_radiotap) {
		pomlog(POMLOG_ERR "Could not find datalink 80211 or radiotap");
		goto err;
	}

	priv->p_host = ptype_alloc("string");
	priv->p_port = ptype_alloc("uint16");
	if (!priv->p_host || !priv->p_port)
		goto err;

	p = registry_new_param("host", "localhost", priv->p_host, "Kismet drone host", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;
	
	p = registry_new_param("port", "2502", priv->p_port, "Kismet drone port", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;


	i->priv = priv;

	return POM_OK;
err:
	if (p)
		registry_cleanup_param(p);

	if (priv->p_host)
		ptype_cleanup(priv->p_host);

	if (priv->p_port)
		ptype_cleanup(priv->p_port);

	free(priv);

	return POM_ERR;
}
Пример #4
0
int output_file_init(struct output *o) {

	struct output_file_priv *priv = malloc(sizeof(struct output_file_priv));
	if (!priv) {
		pom_oom(sizeof(struct output_file_priv));
		return POM_ERR;
	}
	memset(priv, 0, sizeof(struct output_file_priv));

	output_set_priv(o, priv);

	priv->p_listen_pload_evt = ptype_alloc("bool");
	priv->p_path = ptype_alloc("string");
	priv->p_filter = ptype_alloc("string");

	if (!priv->p_path || !priv->p_listen_pload_evt || !priv->p_filter)
		goto err;

	struct registry_instance *inst = output_get_reg_instance(o);
	priv->perf_files_closed = registry_instance_add_perf(inst, "files_closed", registry_perf_type_counter, "Number of files fully written and closed", "files");
	priv->perf_files_open = registry_instance_add_perf(inst, "files_open", registry_perf_type_gauge, "Number of files currently open", "files");
	priv->perf_bytes_written = registry_instance_add_perf(inst, "bytes_written", registry_perf_type_counter, "Number of bytes written", "bytes");

	if (!priv->perf_files_closed || !priv->perf_files_open || !priv->perf_bytes_written)
		goto err;

	struct registry_param *p = registry_new_param("listen_pload_events", "no", priv->p_listen_pload_evt, "Listen to all events that generate payloads", 0);
	if (output_add_param(o, p) != POM_OK)
		goto err;

	p = registry_new_param("path", "/tmp/", priv->p_path, "Path where to store the files", 0);
	if (output_add_param(o, p) != POM_OK)
		goto err;

	p = registry_new_param("filter", "", priv->p_filter, "Payload filter", 0);
	if (output_add_param(o, p) != POM_OK)
		goto err;
	
	return POM_OK;
err:

	if (p)
		registry_cleanup_param(p);

	output_file_cleanup(priv);
	return POM_ERR;

}
Пример #5
0
int output_log_xml_init(struct output *o) {

    struct output_log_xml_priv *priv = log_xml_init();
    if (!priv)
        return POM_ERR;

    priv->p_source = ptype_alloc("string");
    if (!priv->p_source)
        goto err;

    output_set_priv(o, priv);

    struct registry_instance *inst = output_get_reg_instance(o);
    priv->perf_events = registry_instance_add_perf(inst, "events", registry_perf_type_counter, "Number of events process", "events");
    if (!priv->perf_events)
        goto err;

    struct registry_param *p = registry_new_param("filename", "log.xml", priv->p_filename, "XML log file", 0);
    if (output_add_param(o, p) != POM_OK)
        goto err;

    p = registry_new_param("source", "", priv->p_source, "Define the type of event being logged", 0);
    if (output_add_param(o, p) != POM_OK)
        goto err;

    return POM_OK;
err:
    output_log_xml_cleanup(priv);
    return POM_ERR;
}
Пример #6
0
static int input_pcap_file_init(struct input *i) {

	if (input_pcap_common_init(i) != POM_OK)
		return POM_ERR;

	struct input_pcap_priv *priv = i->priv;

	struct registry_param *p = NULL;

	priv->tpriv.file.p_file = ptype_alloc("string");
	if (!priv->tpriv.file.p_file)
		goto err;

	p = registry_new_param("filename", "dump.cap", priv->tpriv.file.p_file, "File in PCAP format", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;

	priv->type = input_pcap_type_file;

	return POM_OK;

err:

	if (priv->tpriv.file.p_file)
		ptype_cleanup(priv->tpriv.file.p_file);

	if (p)
		registry_cleanup_param(p);

	free(priv);

	return POM_ERR;
}
Пример #7
0
static int input_pcap_common_init(struct input *i) {

	struct input_pcap_priv *priv;
	priv = malloc(sizeof(struct input_pcap_priv));
	if (!priv) {
		pom_oom(sizeof(struct input_pcap_priv));
		return POM_ERR;
	}
	memset(priv, 0, sizeof(struct input_pcap_priv));

	struct registry_param *p = NULL;

	priv->p_filter = ptype_alloc("string");
	if (!priv->p_filter)
		goto err;
		
	p = registry_new_param("bpf_filter", "", priv->p_filter, "BPF filter to use", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;

	i->priv = priv;
	
	return POM_OK;
err:

	if (p)
		registry_cleanup_param(p);

	if (priv->p_filter)
		ptype_cleanup(priv->p_filter);

	free(priv);

	return POM_ERR;
}
Пример #8
0
static int output_inject_init(struct output *o) {


	struct output_inject_priv *priv = malloc(sizeof(struct output_inject_priv));
	if (!priv) {
		pom_oom(sizeof(struct output_inject_priv));
		return POM_ERR;
	}
	memset(priv, 0, sizeof(struct output_inject_priv));
	output_set_priv(o, priv);

	priv->p_interface = ptype_alloc("string");
	priv->p_filter = ptype_alloc("string");

	if (!priv->p_interface || !priv->p_filter)
		goto err;

	struct registry_instance *inst = output_get_reg_instance(o);
	priv->perf_pkts_out = registry_instance_add_perf(inst, "pkts_out", registry_perf_type_counter, "Number of packets injected", "pkts");
	priv->perf_bytes_out = registry_instance_add_perf(inst, "bytes_out", registry_perf_type_counter, "Number of packet bytes injected", "bytes");

	char err[PCAP_ERRBUF_SIZE] = { 0 };
	char *dev = pcap_lookupdev(err);
	if (!dev) {
		pomlog(POMLOG_WARN,  "Warning, could not find a suitable interface to inject packets to : %s", err);
		dev = "none";
	}

	struct registry_param *p = registry_new_param("interface", dev, priv->p_interface, "Output interface", 0);
	if (output_add_param(o, p) != POM_OK)
		goto err;
	
	p = registry_new_param("filter", "", priv->p_filter, "Filter", REGISTRY_PARAM_FLAG_NOT_LOCKED_WHILE_RUNNING);
	if (output_add_param(o, p) != POM_OK)
		goto err;

	registry_param_set_callbacks(p, priv, output_inject_filter_parse, output_inject_filter_update);

	return POM_OK;

err:
	output_inject_cleanup(priv);
	return POM_ERR;

}
Пример #9
0
static struct output_tap_priv *tap_init() {

	struct output_tap_priv *priv = malloc(sizeof(struct output_tap_priv));
	if (!priv) {
		pom_oom(sizeof(struct output_tap_priv));
		return NULL;
	}
	memset(priv, 0, sizeof(struct output_tap_priv));

	priv->fd = -1;

	priv->p_ifname = ptype_alloc("string");
	priv->p_persistent = ptype_alloc("bool");
	priv->p_filter = ptype_alloc("string");

	if (!priv->p_ifname || !priv->p_persistent) {
		output_tap_cleanup(priv);
		return NULL;
	}

	return priv;
}
Пример #10
0
static int input_pcap_dir_init(struct input *i) {

	if (input_pcap_common_init(i) != POM_OK)
		return POM_ERR;

	struct input_pcap_priv *priv = i->priv;

	struct registry_param *p = NULL;
	priv->tpriv.dir.p_dir = ptype_alloc("string");
	priv->tpriv.dir.p_match = ptype_alloc("string");
	if (!priv->tpriv.dir.p_dir || !priv->tpriv.dir.p_match)
		goto err;

	p = registry_new_param("directory", "/tmp", priv->tpriv.dir.p_dir, "Directory containing pcap files", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;

	p = registry_new_param("match", "\\.p\\?cap[0-9]*$", priv->tpriv.dir.p_match, "Match files with the specific pattern (regex)", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;

	priv->type = input_pcap_type_dir;
	
	return POM_OK;

err:
	
	if (priv->tpriv.dir.p_dir)
		ptype_cleanup(priv->tpriv.dir.p_dir);

	if (p)
		registry_cleanup_param(p);

	free(priv); 

	return POM_ERR;
}
Пример #11
0
static struct output_log_xml_priv *log_xml_init() {


    struct output_log_xml_priv *priv = malloc(sizeof(struct output_log_xml_priv));
    if (!priv) {
        pom_oom(sizeof(struct output_log_xml_priv));
        return NULL;
    }
    memset(priv, 0, sizeof(struct output_log_xml_priv));

    priv->fd = -1;

    priv->p_filename = ptype_alloc("string");

    if (!priv->p_filename) {
        output_log_xml_cleanup(priv);
        return NULL;
    }

    return priv;
}
Пример #12
0
static int registry_uid_add(struct registry_instance *instance, uint32_t uid) {

	// Add the uid to the instance
	struct ptype *uid_ptype = ptype_alloc("uint32");
	if (!uid_ptype) 
		return POM_ERR;

	PTYPE_UINT32_SETVAL(uid_ptype, uid);
	struct registry_param* uid_param = registry_new_param("uid", NULL, uid_ptype, "Unique ID", REGISTRY_PARAM_FLAG_CLEANUP_VAL | REGISTRY_PARAM_FLAG_IMMUTABLE);

	if (!uid_param) {
		ptype_cleanup(uid_ptype);
		return POM_ERR;
	}

	// Add the new uid to the table

	registry_uid_table_size++;
	uint32_t *new_uid_table = realloc(registry_uid_table, sizeof(uint32_t) * registry_uid_table_size);
	if (!new_uid_table) {
		pom_oom(sizeof(uint32_t) * registry_uid_table_size);
		ptype_cleanup(uid_ptype);
		return POM_ERR;
	}
	registry_uid_table = new_uid_table;
	registry_uid_table[registry_uid_table_size - 1] = uid;


	if (registry_instance_add_param(instance, uid_param) != POM_OK) {
		registry_cleanup_param(uid_param);
		ptype_cleanup(uid_ptype);
		registry_uid_table_size--;
		return POM_ERR;
	}

	return POM_OK;

}
Пример #13
0
static int analyzer_smtp_event_process_begin(struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index) {

	struct analyzer *analyzer = obj;
	struct analyzer_smtp_priv *apriv = analyzer->priv;
	struct proto_process_stack *s = &stack[stack_index];
	if (!s->ce)
		return POM_ERR;

	// Only process stuff if we have the DATA event or if we already have an event
	struct event_reg *evt_reg = event_get_reg(evt);
	struct data *evt_data = event_get_data(evt);

	struct analyzer_smtp_ce_priv *cpriv = conntrack_get_priv(s->ce, analyzer);
	
	// It's expected that an SMTP connection will always contain at least one message
	// So we always create the cpriv and event, no matter what
	if (!cpriv) {
		cpriv = malloc(sizeof(struct analyzer_smtp_ce_priv));
		if (!cpriv) {
			pom_oom(sizeof(struct analyzer_smtp_ce_priv));
			return POM_ERR;
		}
		memset(cpriv, 0, sizeof(struct analyzer_smtp_ce_priv));

		if (conntrack_add_priv(s->ce, analyzer, cpriv, analyzer_smtp_ce_priv_cleanup) != POM_OK) {
			free(cpriv);
			return POM_ERR;
		}
	}

	if (!cpriv->evt_msg) {
		cpriv->evt_msg = event_alloc(apriv->evt_msg);
		if (!cpriv->evt_msg)
			return POM_ERR;

	}


	struct data *msg_data = event_get_data(cpriv->evt_msg);
	
	if (evt_reg == apriv->evt_cmd) {

		if (!cpriv->common_data_fetched)
			analyzer_smtp_event_fetch_common_data(cpriv, stack, stack_index, POM_DIR_REVERSE(s->direction));


		// Process commands


		// A message was being transmitted and we recevied a new command
		if (event_is_started(cpriv->evt_msg)) {
			event_process_end(cpriv->evt_msg);
			cpriv->evt_msg = NULL;
		}

		char *cmd = PTYPE_STRING_GETVAL(evt_data[proto_smtp_cmd_name].value);
		if (!cmd)
			return POM_OK;

		char *arg = PTYPE_STRING_GETVAL(evt_data[proto_smtp_cmd_arg].value);
		if (arg) {
			while (*arg == ' ')
				arg++;
		}

		if (!strcasecmp(cmd, "MAIL")) {
			if (strncasecmp(arg, "FROM:", strlen("FROM:"))) {
				pomlog(POMLOG_DEBUG "Unparseable MAIL command");
				return POM_OK;
			}
			arg += strlen("FROM:");
			while (*arg == ' ')
				arg++;

			if (*arg == '<')
				arg++;

			size_t len;
			char *end = strchr(arg, '>');
			if (end)
				len = end - arg;
			else
				len = strlen(arg);

			PTYPE_STRING_SETVAL_N(msg_data[analyzer_smtp_msg_from].value, arg, len);
			data_set(msg_data[analyzer_smtp_msg_from]);
			cpriv->last_cmd = analyzer_smtp_last_cmd_mail_from;
			
		} else if (!strcasecmp(cmd, "RCPT")) {
			if (strncasecmp(arg, "TO:", strlen("TO:"))) {
				pomlog(POMLOG_DEBUG "Unparseable RCPT command");
				return POM_OK;
			}
			arg += strlen("TO:");
			while (*arg == ' ')
				arg++;

			if (*arg == '<')
				arg++;

			size_t len;
			char *end = strchr(arg, '>');
			if (end)
				len = end - arg;
			else
				len = strlen(arg);

			struct ptype *to = ptype_alloc("string");
			if (!to)
				return POM_ERR;

			PTYPE_STRING_SETVAL_N(to, arg, len);
			if (data_item_add_ptype(msg_data, analyzer_smtp_msg_to, strdup("to"), to) != POM_OK) {
				ptype_cleanup(to);
				return POM_ERR;
			}
			cpriv->last_cmd = analyzer_smtp_last_cmd_rcpt_to;

		} else if (!strcasecmp(cmd, "DATA")) {
			cpriv->last_cmd = analyzer_smtp_last_cmd_data;

			if (!event_is_started(cpriv->evt_msg)) {
				analyzer_smtp_event_fill_common_data(cpriv, msg_data);
				event_process_begin(cpriv->evt_msg, stack, stack_index, event_get_timestamp(evt));
			} else {
				pomlog(POMLOG_DEBUG "Message event already started !");
			}

		} else if (!strcasecmp(cmd, "RSET")) {
			// Cleanup the event
			event_cleanup(cpriv->evt_msg);
			cpriv->evt_msg = NULL;
			cpriv->last_cmd = analyzer_smtp_last_cmd_other;
		} else if (!strcasecmp(cmd, "HELO") || !strcasecmp(cmd, "EHLO")) {
			if (cpriv->client_hello) {
				pomlog(POMLOG_DEBUG "We already have a client hello !");
				free(cpriv->client_hello);
			}

			cpriv->client_hello = strdup(arg);
			if (!cpriv->client_hello) {
				pom_oom(strlen(arg) + 1);
				return POM_ERR;
			}
			cpriv->last_cmd = analyzer_smtp_last_cmd_other;

		} else if (!strcasecmp(cmd, "AUTH")) {
			if (!strncasecmp(arg, "PLAIN", strlen("PLAIN"))) {
				arg += strlen("PLAIN");
				while (*arg == ' ')
					arg++;


				if (cpriv->evt_auth) {
					event_process_end(cpriv->evt_auth);
					cpriv->evt_auth = NULL;
				}

				if (strlen(arg)) {
					if (analyzer_smtp_parse_auth_plain(apriv, cpriv, arg) == POM_OK) {
						event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
						cpriv->last_cmd = analyzer_smtp_last_cmd_auth_plain_creds;
					}
				} else {
					cpriv->last_cmd = analyzer_smtp_last_cmd_auth_plain;
					
				}

			} else if (!strncasecmp(arg, "LOGIN", strlen("LOGIN"))) {
				arg += strlen("LOGIN");
				while (*arg == ' ')
					arg++;

				if (cpriv->evt_auth) {
					event_process_end(cpriv->evt_auth);
					cpriv->evt_auth = NULL;
				}

				cpriv->evt_auth = event_alloc(apriv->evt_auth);
				if (!cpriv->evt_auth)
					return POM_ERR;

				struct data *auth_data = event_get_data(cpriv->evt_auth);

				analyzer_smtp_event_fill_common_data(cpriv, auth_data);

				// Set the authentication type
				PTYPE_STRING_SETVAL(auth_data[analyzer_smtp_auth_type].value, "LOGIN");
				data_set(auth_data[analyzer_smtp_auth_type]);

				if (strlen(arg)) {
					char *username = NULL;
					size_t out_len = 0;
					struct ptype *username_pt = NULL;
					if (decoder_decode_simple("base64", arg, strlen(arg), &username, &out_len) == POM_OK) {
						username_pt = ptype_alloc("string");
						if (username_pt) {
							PTYPE_STRING_SETVAL_P(username_pt, username);
							if (data_item_add_ptype(auth_data, analyzer_smtp_auth_params, strdup("username"), username_pt) != POM_OK) {
								ptype_cleanup(username_pt);
								event_cleanup(cpriv->evt_auth);
								cpriv->evt_auth = NULL;
								username_pt = NULL;
							}
						} else {
							free(username);
						}
					}

					if (!username_pt) {
						cpriv->last_cmd = analyzer_smtp_last_cmd_other;
						event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
					}
				} else {
					cpriv->last_cmd = analyzer_smtp_last_cmd_auth_login;
				}
			}

		} else if (cpriv->last_cmd == analyzer_smtp_last_cmd_auth_plain) {
			// We are expecting the credentials right now
			if (analyzer_smtp_parse_auth_plain(apriv, cpriv, cmd) == POM_OK) {
				event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
				cpriv->last_cmd = analyzer_smtp_last_cmd_auth_plain_creds;
			} else {
				cpriv->last_cmd = analyzer_smtp_last_cmd_other;
			}
		} else if (cpriv->last_cmd == analyzer_smtp_last_cmd_auth_login) {
			char *username = NULL;
			size_t out_len = 0;
			struct ptype *username_pt = NULL;
			if (decoder_decode_simple("base64", cmd, strlen(cmd), &username, &out_len) == POM_OK) {
				username_pt = ptype_alloc("string");
				if (username_pt) {
					PTYPE_STRING_SETVAL_P(username_pt, username);
					struct data *auth_data = event_get_data(cpriv->evt_auth);
					if (data_item_add_ptype(auth_data, analyzer_smtp_auth_params, strdup("username"), username_pt) != POM_OK) {
						ptype_cleanup(username_pt);
						event_process_end(cpriv->evt_auth);
						cpriv->evt_auth = NULL;
						username_pt = NULL;
					}
				} else {
					free(username);
				}
			}

			if (!username_pt) {
				cpriv->last_cmd = analyzer_smtp_last_cmd_other;
			} else {
				event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
				cpriv->last_cmd = analyzer_smtp_last_cmd_auth_login_user;
			}

		} else if (cpriv->last_cmd == analyzer_smtp_last_cmd_auth_login_user) {
			char *password = NULL;
			size_t out_len = 0;
			struct ptype *password_pt = NULL;
			if (decoder_decode_simple("base64", cmd, strlen(cmd), &password, &out_len) == POM_OK) {
				password_pt = ptype_alloc("string");
				if (password_pt) {
					PTYPE_STRING_SETVAL_P(password_pt, password);
					struct data *auth_data = event_get_data(cpriv->evt_auth);
					if (data_item_add_ptype(auth_data, analyzer_smtp_auth_params, strdup("password"), password_pt) != POM_OK) {
						ptype_cleanup(password_pt);
						event_process_end(cpriv->evt_auth);
						cpriv->evt_auth = NULL;
						password_pt = NULL;
					}
				} else {
					free(password);
				}
			}

			if (!password_pt) {
				cpriv->last_cmd = analyzer_smtp_last_cmd_other;
			} else {
				cpriv->last_cmd = analyzer_smtp_last_cmd_auth_login_pass;
			}
		} else {
			cpriv->last_cmd = analyzer_smtp_last_cmd_other;
		}

	} else if (evt_reg == apriv->evt_reply) {

		if (!cpriv->common_data_fetched)
			analyzer_smtp_event_fetch_common_data(cpriv, stack, stack_index, s->direction);

		// Process replies
		uint16_t code = *PTYPE_UINT16_GETVAL(evt_data[proto_smtp_reply_code].value);

		switch (cpriv->last_cmd) {

			default:
			case analyzer_smtp_last_cmd_other:
				if (code == 220 && evt_data[proto_smtp_reply_text].items && evt_data[proto_smtp_reply_text].items->value) {
					// STARTTLS returns 220 as well so ignore extra code 220
					if (!cpriv->server_hello) {
						char *helo = PTYPE_STRING_GETVAL(evt_data[proto_smtp_reply_text].items->value);
						cpriv->server_hello = strdup(helo);
						if (!cpriv->server_hello) {
							pom_oom(strlen(helo) + 1);
							return POM_ERR;
						}
					}
				}
				break;

			case analyzer_smtp_last_cmd_mail_from:
				if (code != 250) {
					// FROM is invalid
					data_unset(msg_data[analyzer_smtp_msg_from]);
				}
				break;
			case analyzer_smtp_last_cmd_rcpt_to:
				// For now just don't do anything
				// It's best to keep a destination in there even if it's invalid or denied
				break;
			
			case analyzer_smtp_last_cmd_data:
				if (code == 354) {
					// The message is starting, keep last_cmd intact
					return POM_OK;
				}

				// Message is over (if ever transmited)
				if (event_is_started(cpriv->evt_msg)) {
					struct data *msg_data = event_get_data(cpriv->evt_msg);
					PTYPE_UINT16_SETVAL(msg_data[analyzer_smtp_msg_result].value, code);
					data_set(msg_data[analyzer_smtp_msg_result]);
					event_process_end(cpriv->evt_msg);
					cpriv->evt_msg = NULL;
				}
				break;

			case analyzer_smtp_last_cmd_auth_plain:
			case analyzer_smtp_last_cmd_auth_login:
			case analyzer_smtp_last_cmd_auth_login_user:
				// Check if authentication phase can continue
				if (code == 334) {
					// Don't reset cpriv->last_cmd
					return POM_OK;
				} else {
					struct data *evt_data = event_get_data(cpriv->evt_auth);
					PTYPE_BOOL_SETVAL(evt_data[analyzer_smtp_auth_success].value, 0);
					data_set(evt_data[analyzer_smtp_auth_success]);
					event_process_end(cpriv->evt_auth);
					cpriv->evt_auth = NULL;
				}
				break;

			case analyzer_smtp_last_cmd_auth_plain_creds:
			case analyzer_smtp_last_cmd_auth_login_pass: {
				// We just processed the credentials
				struct data *auth_data = event_get_data(cpriv->evt_auth);
				char success = 0;
				if (code == 235)
					success = 1;
				PTYPE_BOOL_SETVAL(auth_data[analyzer_smtp_auth_success].value, success);
				data_set(auth_data[analyzer_smtp_auth_success]);
				event_process_end(cpriv->evt_auth);
				cpriv->evt_auth = NULL;
				break;
			}

		}

		cpriv->last_cmd = analyzer_smtp_last_cmd_other;

	}


	return POM_OK;
}
Пример #14
0
static int analyzer_smtp_parse_auth_plain(struct analyzer_smtp_priv *apriv, struct analyzer_smtp_ce_priv *cpriv, char *auth_plain) {

	// Parse SASL AUTH PLAIN as described in RFC 4616

	// The decoded arg must be at least 3 bytes
	if (strlen(auth_plain) < 4 || memchr(auth_plain, '=', 4)) {
		pomlog(POMLOG_DEBUG "AUTH PLAIN argument too short");
		return POM_OK;
	}

	// Allocate the event
	cpriv->evt_auth = event_alloc(apriv->evt_auth);
	if (!cpriv->evt_auth)
		return POM_ERR;

	struct data *evt_data = event_get_data(cpriv->evt_auth);

	analyzer_smtp_event_fill_common_data(cpriv, evt_data);

	// Set the authentication type
	PTYPE_STRING_SETVAL(evt_data[analyzer_smtp_auth_type].value, "PLAIN");
	data_set(evt_data[analyzer_smtp_auth_type]);

	// Parse the authentication stuff
	char *creds_str = NULL;
	size_t out_len = 0;
	if (decoder_decode_simple("base64", auth_plain, strlen(auth_plain), &creds_str, &out_len) != POM_OK) {
		pomlog(POMLOG_DEBUG "Unable to decode AUTH PLAIN message");
		return POM_OK;
	}

	if (out_len < 3) {
		pomlog(POMLOG_DEBUG "Invalid decoded AUTH PLAIN data");
		return POM_OK;
	}



	char *tmp = creds_str;

	// Add the identity
	if (strlen(tmp)) {
		// SASL AUTH PLAIN specifies 
		struct ptype *identity = ptype_alloc("string");
		if (!identity)
			goto err;
		PTYPE_STRING_SETVAL(identity, tmp);
		if (data_item_add_ptype(evt_data, analyzer_smtp_auth_params, strdup("identity"), identity) != POM_OK) {
			ptype_cleanup(identity);
			goto err;
		}
	}
	tmp += strlen(tmp) + 1;
	
	// Add the username
	struct ptype *username = ptype_alloc("string");
	if (!username)
		goto err;
	PTYPE_STRING_SETVAL(username, tmp);
	if (data_item_add_ptype(evt_data, analyzer_smtp_auth_params, strdup("username"), username) != POM_OK) {
		ptype_cleanup(username);
		goto err;
	}
	tmp += strlen(tmp) + 1;

	// Add the password
	struct ptype *password = ptype_alloc("string");
	if (!password)
		goto err;
	PTYPE_STRING_SETVAL(password, tmp);
	if (data_item_add_ptype(evt_data, analyzer_smtp_auth_params, strdup("password"), password) != POM_OK) {
		ptype_cleanup(password);
		goto err;
	}

	free(creds_str);
	return POM_OK;

err:

	event_cleanup(cpriv->evt_auth);
	cpriv->evt_auth = NULL;

	free(creds_str);

	return POM_ERR;
}
Пример #15
0
int core_init(unsigned int num_threads) {

	core_registry_class = registry_add_class(CORE_REGISTRY);
	if (!core_registry_class)
		return POM_ERR;

	perf_pkt_queue = registry_class_add_perf(core_registry_class, "pkt_queue", registry_perf_type_gauge, "Number of packets in the queue waiting to be processed", "pkts");
	perf_thread_active = registry_class_add_perf(core_registry_class, "active_thread", registry_perf_type_gauge, "Number of active threads", "threads");

	if (!perf_pkt_queue || !perf_thread_active)
		return POM_OK;

	core_param_dump_pkt = ptype_alloc("bool");
	if (!core_param_dump_pkt)
		return POM_ERR;

	core_param_offline_dns = ptype_alloc("bool");
	if (!core_param_offline_dns) {
		ptype_cleanup(core_param_dump_pkt);
		core_param_dump_pkt = NULL;
		return POM_ERR;
	}

	core_param_reset_perf_on_restart = ptype_alloc("bool");
	if (!core_param_reset_perf_on_restart) {
		ptype_cleanup(core_param_dump_pkt);
		core_param_dump_pkt = NULL;
		ptype_cleanup(core_param_offline_dns);
		core_param_offline_dns = NULL;
		return POM_ERR;
	}

	struct registry_param *param = registry_new_param("dump_pkt", "no", core_param_dump_pkt, "Dump packets to logs", REGISTRY_PARAM_FLAG_CLEANUP_VAL);
	if (registry_class_add_param(core_registry_class, param) != POM_OK)
		goto err;

	param = registry_new_param("offline_dns", "yes", core_param_offline_dns, "Enable offline DNS resolver", REGISTRY_PARAM_FLAG_CLEANUP_VAL);
	if (registry_class_add_param(core_registry_class, param) != POM_OK)
		goto err;

	param = registry_new_param("reset_perf_on_restart", "no", core_param_reset_perf_on_restart, "Reset performances when core restarts", REGISTRY_PARAM_FLAG_CLEANUP_VAL);
	if (registry_class_add_param(core_registry_class, param) != POM_OK)
		goto err;
	
	param = NULL;

	// Start the processing threads
	unsigned int num_cpu = sysconf(_SC_NPROCESSORS_ONLN) - 1;
	if (num_cpu < 1) {
		pomlog(POMLOG_WARN "Could not find the number of CPU, assuming %u", CORE_PROCESS_THREAD_DEFAULT);
		num_cpu = CORE_PROCESS_THREAD_DEFAULT;
	}

	if (num_threads < 1)
		num_threads = num_cpu;

	if (num_threads > num_cpu)
		pomlog(POMLOG_WARN "WARNING : Running more processing threads than available CPU is discouraged as it will cause issues by creating higher latencies and eventually dropping packets !!! You have been warned !");

	if (num_threads > CORE_PROCESS_THREAD_MAX)
		num_threads = CORE_PROCESS_THREAD_MAX;

	core_num_threads = num_threads;	
	pomlog(POMLOG_INFO "Starting %u processing thread(s)", core_num_threads);

	core_run = 1;

	memset(core_processing_threads, 0, sizeof(struct core_processing_thread*) * CORE_PROCESS_THREAD_MAX);

	unsigned int i;

	for (i = 0; i < core_num_threads; i++) {
		struct core_processing_thread *tmp = malloc(sizeof(struct core_processing_thread));
		if (!tmp) {
			pom_oom(sizeof(struct core_processing_thread));
			goto err;
		}
		memset(tmp, 0, sizeof(struct core_processing_thread));

		tmp->thread_id = i;

		int res = pthread_mutex_init(&tmp->pkt_queue_lock, NULL);
		if (res) {
			pomlog(POMLOG_ERR "Error while initializing a thread pkt_queue lock : %s", pom_strerror(res));
			free(tmp);
			goto err;
		}

		res = pthread_cond_init(&tmp->pkt_queue_cond, NULL);
		if (res) {
			pomlog(POMLOG_ERR "Error while initializing a thread pkt_queue condition : %s", pom_strerror(res));
			pthread_mutex_destroy(&tmp->pkt_queue_lock);
			free(tmp);
			goto err;
		}


		if (pthread_create(&tmp->thread, NULL, core_processing_thread_func, tmp)) {
			pomlog(POMLOG_ERR "Error while creating a new processing thread : %s", pom_strerror(errno));
			pthread_mutex_destroy(&tmp->pkt_queue_lock);
			pthread_cond_destroy(&tmp->pkt_queue_cond);
			free(tmp);
			goto err;
		}


		core_processing_threads[i] = tmp;
	}

	return POM_OK;

err:

	if (param)
		registry_cleanup_param(param);

	core_cleanup(0);
	return POM_ERR;

}
Пример #16
0
int addon_output_init(struct output *o) {

	struct addon *addon = o->info->reg_info->mod->priv;

	lua_State *L = addon_create_state(addon->filename); // Stack : empty

	if (!L) {
		pomlog(POMLOG_ERR "Error while creating new lua state for output %s", o->info->reg_info->name);
		return POM_ERR;
	}

	// Get the output from the outputs table
	lua_getfield(L, LUA_REGISTRYINDEX, ADDON_OUTPUTS_TABLE); // Stack : outputs
	lua_getfield(L, -1, o->info->reg_info->name); // Stack : outputs, output

	// Get rid of the outputs table
	lua_remove(L, -2); // Stack : output
	lua_pushnil(L); // Stack : output, nil
	lua_setfield(L, LUA_REGISTRYINDEX, ADDON_OUTPUTS_TABLE); // Stack : output

	// Add the output to the registry
	lua_pushvalue(L, -1); // Stack : output, output
	lua_setfield(L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : output


	// Create the private data
	// TODO make __priv read-only
	struct addon_instance_priv *p = lua_newuserdata(L, sizeof(struct addon_instance_priv)); // Stack : output, priv
	if (!p) {
		pom_oom(sizeof(struct addon_instance_priv));
		return POM_ERR;
	}
	memset(p, 0, sizeof(struct addon_instance_priv));
	o->priv = p;
	p->instance = o;
	p->L = L;
	if (pthread_mutex_init(&p->lock, NULL)) {
		pomlog(POMLOG_ERR "Error while initializing mutex : %s", pom_strerror(errno));
		abort();
		return POM_ERR;
	}

	// Assign the output_priv metatable
	luaL_getmetatable(L, ADDON_OUTPUT_PRIV_METATABLE); // Stack : output, priv, metatable
	lua_setmetatable(L, -2); // Stack : output, priv
	// Add it to __priv
	lua_setfield(L, -2, "__priv"); // Stack : output

	// Fetch the parameters table 
	lua_getfield(L, -1, "__params"); // Stack : output, params

	// Parse each param from the class
	lua_pushnil(L); // Stack : output, params, nil
	while (lua_next(L, -2) != 0) { // Stack : output, params, key, param
		if (!lua_istable(L, -1)) {
			pomlog(POMLOG_ERR "Parameters should be described in tables");
			goto err;
		}

		// Fetch the name
		lua_pushinteger(L, 1); // Stack : output, params, key, param, 1
		lua_gettable(L, -2); // Stack : output, params, key, param, name
		if (!lua_isstring(L, -1)) {
			pomlog(POMLOG_ERR "Parameter name is not a string");
			goto err;
		}
		const char *name = luaL_checkstring(L, -1);
		lua_pop(L, 1); // Stack : output, params, key, param

		// Fetch the ptype type
		lua_pushinteger(L, 2); // Stack : output, params, key, param, 2
		lua_gettable(L, -2); // Stack : output, params, key, param, type
		if (!lua_isstring(L, -1)) {
			pomlog(POMLOG_ERR "Parameter type is not a string");
			goto err;
		}
		const char *type = lua_tostring(L, -1);
		lua_pop(L, 1); // Stack : output, params, key, param

		// Fetch the default value
		lua_pushinteger(L, 3); // Stack : output, params, key, param, 3
		lua_gettable(L, -2); // Stack : output, params, key, param, defval
		if (!lua_isstring(L, -1)) {
			pomlog(POMLOG_ERR "Parameter default value is not a string");
			goto err;
		}
		const char *defval = lua_tostring(L, -1);
		lua_pop(L, 1); // Stack : output, params, key, param

		// Fetch the description
		lua_pushinteger(L, 4); // Stack : output, params, key, param, 4
		lua_gettable(L, -2); // Stack : output, params, key, param, descr
		if (!lua_isstring(L, -1)) {
			pomlog(POMLOG_ERR "Parameter description is not a string");
			goto err;
		}
		const char *descr = lua_tostring(L, -1);
		lua_pop(L, 1); // Stack : output, params, key, param

		// Allocate it
		struct addon_param *param = malloc(sizeof(struct addon_param));
		if (!param) {
			pom_oom(sizeof(struct addon_param));
			goto err;
		}
		param->name = strdup(name);
		if (!param->name) {
			free(param);
			pom_oom(strlen(name) + 1);
			goto err;
		}
		param->value = ptype_alloc(type);
		if (!param->value) {
			free(param->name);
			free(param);
			goto err;
		}
		
		struct registry_param *reg_param = registry_new_param((char*)name, (char*)defval, param->value, (char*)descr, 0);
		if (output_add_param(o, reg_param) != POM_OK) {
			pomlog(POMLOG_ERR "Error while adding parameter to the output instance");
			if (reg_param)
				registry_cleanup_param(reg_param);
			free(param->name);
			ptype_cleanup(param->value);
			free(param);
			goto err;
		}

		param->next = p->params;
		p->params = param;


		// Pop the value (the param table)
		lua_pop(L, 1); // Stack : output, params, key
	}
	// At this point the stack is : output, params
	lua_pop(L, 2); // Stack : empty

	pomlog(POMLOG_DEBUG "Output %s created", o->name);
	return POM_OK;

err:
	lua_close(L);
	p->L = NULL;
	return POM_ERR;
}
Пример #17
0
int output_instance_add(char *type, char *name) {

	struct output_reg *reg;
	for (reg = output_reg_head; reg && strcmp(reg->reg_info->name, type); reg = reg->next);

	if (!reg) {
		pomlog(POMLOG_ERR "Output type %s does not exists", type);
		return POM_ERR;
	}

	struct output *res = malloc(sizeof(struct output));
	if (!res) {
		pom_oom(sizeof(struct output));
		return POM_ERR;
	}
	memset(res, 0, sizeof(struct output));
	res->info = reg;
	res->name = strdup(name);
	if (!res->name) {
		pom_oom(strlen(name) + 1);
		goto err;
	}

	res->reg_instance = registry_add_instance(output_registry_class, name);
	if (!res->reg_instance)
		goto err;

	res->reg_instance->priv = res;

	res->perf_runtime = registry_instance_add_perf(res->reg_instance, "runtime", registry_perf_type_timeticks, "Runtime", NULL);
	if (!res->perf_runtime)
		goto err;

	struct ptype *param_running_val = ptype_alloc("bool");
	if (!param_running_val)
		goto err;

	struct registry_param *param_running = registry_new_param("running", "no", param_running_val, "Running state of the output",  REGISTRY_PARAM_FLAG_CLEANUP_VAL);
	if (!param_running) {
		ptype_cleanup(param_running_val);
		goto err;
	}

	if (registry_param_set_callbacks(param_running, res, NULL, output_instance_start_stop_handler) != POM_OK) {
		registry_cleanup_param(param_running);
		ptype_cleanup(param_running_val);
		goto err;
	}
	
	if (registry_instance_add_param(res->reg_instance, param_running) != POM_OK) {
		registry_cleanup_param(param_running);
		ptype_cleanup(param_running_val);
		goto err;
	}


	struct ptype *output_type = ptype_alloc("string");
	if (!output_type)
		goto err;

	struct registry_param *type_param = registry_new_param("type", type, output_type, "Type of the output", REGISTRY_PARAM_FLAG_CLEANUP_VAL | REGISTRY_PARAM_FLAG_IMMUTABLE);
	if (!type_param) {
		ptype_cleanup(output_type);
		goto err;
	}

	if (registry_instance_add_param(res->reg_instance, type_param) != POM_OK) {
		registry_cleanup_param(type_param);
		ptype_cleanup(output_type);
		goto err;
	}

	if (registry_uid_create(res->reg_instance) != POM_OK)
		goto err;

	if (reg->reg_info->init) {
		if (reg->reg_info->init(res) != POM_OK) {
			pomlog(POMLOG_ERR "Error while initializing the output %s", name);
			goto err;
		}
	}

	res->next = output_head;
	if (res->next)
		res->next->prev = res;
	output_head = res;

	return POM_OK;

err:
	if (res->reg_instance) {
		registry_remove_instance(res->reg_instance);
	} else {
		if (res->name)
			free(res->name);
		free(res);
	}

	return POM_ERR;
}
Пример #18
0
static int input_pcap_interface_init(struct input *i) {

	if (input_pcap_common_init(i) != POM_OK)
		return POM_ERR;

	struct input_pcap_priv *priv = i->priv;
	
	struct registry_param *p = NULL;

	priv->tpriv.iface.p_interface = ptype_alloc("string");
	priv->tpriv.iface.p_promisc = ptype_alloc("bool");
	priv->tpriv.iface.p_buff_size = ptype_alloc_unit("uint32", "bytes");
	if (!priv->tpriv.iface.p_interface || !priv->tpriv.iface.p_promisc || !priv->tpriv.iface.p_buff_size)
		goto err;

	priv->tpriv.iface.perf_dropped = registry_instance_add_perf(i->reg_instance, "dropped_pkt", registry_perf_type_counter, "Dropped packets", "pkts");
	if (!priv->tpriv.iface.perf_dropped)
		goto err;

	registry_perf_set_update_hook(priv->tpriv.iface.perf_dropped, input_pcap_interface_perf_dropped, priv);

	char err[PCAP_ERRBUF_SIZE] = { 0 };
	char *dev = "<none>";
	pcap_if_t *alldevsp = NULL;
	if (pcap_findalldevs(&alldevsp, err)) {
		pomlog(POMLOG_WARN "Warning, could not find a suitable interface to sniff packets from : %s", err);
		alldevsp = NULL;
	} else {
		dev = alldevsp->name;
	}

	p = registry_new_param("interface", dev, priv->tpriv.iface.p_interface, "Interface to capture packets from", 0);

	if (alldevsp) {
		pcap_if_t *tmp;
		for (tmp = alldevsp; tmp; tmp = tmp->next) {
			if (registry_param_info_add_value(p, tmp->name) != POM_OK) {
				pcap_freealldevs(alldevsp);
				goto err;
			}
		}
		pcap_freealldevs(alldevsp);
	}

	if (input_add_param(i, p) != POM_OK)
		goto err;

	p = registry_new_param("promisc", "no", priv->tpriv.iface.p_promisc, "Promiscious mode", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;

	p = registry_new_param("buff_size", "16777216", priv->tpriv.iface.p_buff_size, "PCAP ring buffer size", 0);
	if (input_add_param(i, p) != POM_OK)
		goto err;

	priv->type = input_pcap_type_interface;

	return POM_OK;

err:

	if (priv->tpriv.iface.p_interface)
		ptype_cleanup(priv->tpriv.iface.p_interface);

	if (priv->tpriv.iface.p_promisc)
		ptype_cleanup(priv->tpriv.iface.p_promisc);

	if (priv->tpriv.iface.p_buff_size)
		ptype_cleanup(priv->tpriv.iface.p_buff_size);

	if (p)
		registry_cleanup_param(p);

	free(priv);

	return POM_ERR;

}
Пример #19
0
static int proto_smtp_process(void *proto_priv, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) {

	struct proto_process_stack *s = &stack[stack_index];
	struct proto_process_stack *s_next = &stack[stack_index + 1];

	if (conntrack_get_unique_from_parent(stack, stack_index) != POM_OK) {
		pomlog(POMLOG_ERR "Could not get conntrack entry");
		return PROTO_ERR;
	}

	// There should no need to keep the lock here since we are in the packet_stream lock from proto_tcp
	conntrack_unlock(s->ce);

	struct proto_smtp_priv *ppriv = proto_priv;

	struct proto_smtp_conntrack_priv *priv = s->ce->priv;
	if (!priv) {
		priv = malloc(sizeof(struct proto_smtp_conntrack_priv));
		if (!priv) {
			pom_oom(sizeof(struct proto_smtp_conntrack_priv));
			return PROTO_ERR;
		}
		memset(priv, 0, sizeof(struct proto_smtp_conntrack_priv));

		priv->parser[POM_DIR_FWD] = packet_stream_parser_alloc(SMTP_MAX_LINE, PACKET_STREAM_PARSER_FLAG_TRIM);
		if (!priv->parser[POM_DIR_FWD]) {
			free(priv);
			return PROTO_ERR;
		}

		priv->parser[POM_DIR_REV] = packet_stream_parser_alloc(SMTP_MAX_LINE, PACKET_STREAM_PARSER_FLAG_TRIM);
		if (!priv->parser[POM_DIR_REV]) {
			packet_stream_parser_cleanup(priv->parser[POM_DIR_FWD]);
			free(priv);
			return PROTO_ERR;
		}

		priv->server_direction = POM_DIR_UNK;

		s->ce->priv = priv;
	}

	if (priv->flags & PROTO_SMTP_FLAG_INVALID)
		return PROTO_OK;

	struct packet_stream_parser *parser = priv->parser[s->direction];
	if (packet_stream_parser_add_payload(parser, s->pload, s->plen) != POM_OK)
		return PROTO_ERR;

	char *line = NULL;
	size_t len = 0;
	while (1) {

		// Some check to do prior to parse the payload
		
		if (s->direction == POM_DIR_REVERSE(priv->server_direction)) {
			if (priv->flags & PROTO_SMTP_FLAG_STARTTLS) {
				// Last command was a STARTTLS command, this is the TLS negociation
				// Since we can't parse this, mark it as invalid
				priv->flags |= PROTO_SMTP_FLAG_INVALID;
				return PROTO_OK;

			} else if (priv->flags & PROTO_SMTP_FLAG_CLIENT_DATA) {

				// We are receiving payload data, check where the end is
				void *pload;
				size_t plen;
				packet_stream_parser_get_remaining(parser, &pload, &plen);

				if (!plen)
					return PROTO_OK;

				// Look for the "<CR><LF>.<CR><LF>" sequence
				if (priv->data_end_pos > 0) {
					
					// The previous packet ended with something that might be the final sequence
					// Check if we have the rest
					int i, found = 1;
					for (i = 0; i < PROTO_SMTP_DATA_END_LEN - priv->data_end_pos && i <= plen; i++) {
						if (*(char*)(pload + i) != PROTO_SMTP_DATA_END[priv->data_end_pos + i]) {
							found = 0;
							break;
						}
					}
					if (found) {
						// If we have already processed the dot after <CR><LF> there is no way to remove it
						// Thus we mark this connection as invalid. Most MTA will send at worst the last
						// 3 bytes of the end sequence in a sequence packet
						if (i != plen || (priv->data_end_pos >= 2 && plen < 3)) {
							pomlog(POMLOG_DEBUG "The final line was not at the of a packet as expected !");
							priv->flags |= PROTO_SMTP_FLAG_INVALID;
							event_process_end(priv->data_evt);
							priv->data_evt = NULL;
							return PROTO_OK;
						}
						s_next->pload = pload;
						s_next->plen = plen - PROTO_SMTP_DATA_END_LEN + 2; // The last line return is part of the payload
						priv->flags |= PROTO_SMTP_FLAG_CLIENT_DATA_END;

						priv->flags &= ~PROTO_SMTP_FLAG_CLIENT_DATA;
						priv->data_end_pos = 0;

						return PROTO_OK;
					}
					priv->data_end_pos = 0;
				}


				char *dotline = pom_strnstr(pload, PROTO_SMTP_DATA_END, plen);
				if (dotline) {
					if (pload + plen - PROTO_SMTP_DATA_END_LEN != dotline) {
						pomlog(POMLOG_DEBUG "The final line was not at the of a packet as expected !");
						priv->flags |= PROTO_SMTP_FLAG_INVALID;
						event_process_end(priv->data_evt);
						priv->data_evt = NULL;
						return PROTO_OK;
					}
					s_next->pload = pload;
					s_next->plen = plen - PROTO_SMTP_DATA_END_LEN + 2; // The last line return is part of the payload
					priv->flags |= PROTO_SMTP_FLAG_CLIENT_DATA_END;

					priv->flags &= ~PROTO_SMTP_FLAG_CLIENT_DATA;

				} else {
					// Check if the end of the payload contains part of the "<CR><LF>.<CR><LF>" sequence
					int i, found = 0;
					for (i = 1 ; (i < PROTO_SMTP_DATA_END_LEN) && (i <= plen); i++) {
						if (!memcmp(pload + plen - i, PROTO_SMTP_DATA_END, i)) {
							found = 1;
							break;
						}
					}

					if (found)
						priv->data_end_pos = i;

					s_next->pload = pload;
					s_next->plen = plen;
				}

				return PROTO_OK;
			}
		}

		// Process commands
		if (packet_stream_parser_get_line(parser, &line, &len) != POM_OK)
			return PROTO_ERR;

		if (!line)
			return PROTO_OK;

		if (!len) // Probably a missed packet
			return PROTO_OK;

		// Try to find the server direction
		if (priv->server_direction == POM_DIR_UNK) {
			unsigned int code = atoi(line);
			if (code > 0) {
				priv->server_direction = s->direction;
			} else {
				priv->server_direction = POM_DIR_REVERSE(s->direction);
			}
		}

		if (s->direction == priv->server_direction) {

			// Parse the response code and generate the event
			if ((len < 5) || // Server response is 3 digit error code, a space or hyphen and then at least one letter of text
				(line[3] != ' ' && line[3] != '-')) {
				pomlog(POMLOG_DEBUG "Too short or invalid response from server");
				priv->flags |= PROTO_SMTP_FLAG_INVALID;
				return POM_OK;
			}

			int code = atoi(line);
			if (code == 0) {
				pomlog(POMLOG_DEBUG "Invalid response from server");
				priv->flags |= PROTO_SMTP_FLAG_INVALID;
				return POM_OK;
			}

			if (event_has_listener(ppriv->evt_reply)) {

				struct data *evt_data = NULL;
				if (priv->reply_evt) {
					evt_data = event_get_data(priv->reply_evt);
					uint16_t cur_code = *PTYPE_UINT16_GETVAL(evt_data[proto_smtp_reply_code].value);
					if (cur_code != code) {
						pomlog(POMLOG_WARN "Multiline code not the same as previous line : %hu -> %hu", cur_code, code);
						event_process_end(priv->reply_evt);
						priv->reply_evt = NULL;
					}
				}


				if (!priv->reply_evt) {
					priv->reply_evt = event_alloc(ppriv->evt_reply);
					if (!priv->reply_evt)
						return PROTO_ERR;

					evt_data = event_get_data(priv->reply_evt);
					PTYPE_UINT16_SETVAL(evt_data[proto_smtp_reply_code].value, code);
					data_set(evt_data[proto_smtp_reply_code]);

				}

				if (len > 4) {
					struct ptype *txt = ptype_alloc("string");
					if (!txt)
						return PROTO_ERR;
					PTYPE_STRING_SETVAL_N(txt, line + 4, len - 4);
					if (data_item_add_ptype(evt_data, proto_smtp_reply_text, strdup("text"), txt) != POM_OK)
						return PROTO_ERR;
				}
				
				if (!event_is_started(priv->reply_evt))
					event_process_begin(priv->reply_evt, stack, stack_index, p->ts);
			}


			if (line[3] != '-') {
				// Last line in the response
				if (priv->reply_evt) {
					event_process_end(priv->reply_evt);
					priv->reply_evt = NULL;
				}
			}
			
			if (priv->flags & PROTO_SMTP_FLAG_STARTTLS) {
				// The last command was STARTTLS
				priv->flags &= ~PROTO_SMTP_FLAG_STARTTLS;
				if (code == 220) {
					// TLS has the go, we can't parse  from now so mark as invalid
					priv->flags |= PROTO_SMTP_FLAG_INVALID;
					return POM_OK;
				}
			}

		} else {

			// Client command

			if (len < 4) { // Client commands are at least 4 bytes long
				pomlog(POMLOG_DEBUG "Too short or invalid query from client");
				priv->flags |= PROTO_SMTP_FLAG_INVALID;
				return POM_OK;
			}

			// Make sure it's a command by checking it's at least a four letter word
			int i;
			for (i = 0; i < 4; i++) {
				// In some case it can also be a base64 encoded word
				if (! ((line[i] >= 'A' && line[i] <= 'Z')
					|| (line[i] >= 'a' && line[i] <= 'z')
					|| (line[i] >= '0' && line [i] <= '9')
					|| line[i] == '='))
					break;
			}

			if ((i < 4)) {
				pomlog(POMLOG_DEBUG "Recieved invalid client command");
				priv->flags |= PROTO_SMTP_FLAG_INVALID;
				return POM_OK;
			}

			if (!strncasecmp(line, "DATA", strlen("DATA")) && len == strlen("DATA")) {
				priv->flags |= PROTO_SMTP_FLAG_CLIENT_DATA;
			} else if (!strncasecmp(line, "STARTTLS", strlen("STARTTLS")) && len == strlen("STARTTLS")) {
				priv->flags |= PROTO_SMTP_FLAG_STARTTLS;
			}


			if (event_has_listener(ppriv->evt_cmd)) {
				struct event *evt = event_alloc(ppriv->evt_cmd);
				if (!evt)
					return PROTO_ERR;

				size_t cmdlen = len;
				char *space = memchr(line, ' ', len);
				if (space)
					cmdlen = space - line;

				struct data *evt_data = event_get_data(evt);
				PTYPE_STRING_SETVAL_N(evt_data[proto_smtp_cmd_name].value, line, cmdlen);
				data_set(evt_data[proto_smtp_cmd_name]);
				if (space) {
					PTYPE_STRING_SETVAL_N(evt_data[proto_smtp_cmd_arg].value, space + 1, len - 1 - cmdlen);
					data_set(evt_data[proto_smtp_cmd_arg]);
				}

				if (priv->flags & PROTO_SMTP_FLAG_CLIENT_DATA) {
					// The event ends at the end of the message
					priv->data_evt = evt;
					return event_process_begin(evt, stack, stack_index, p->ts);
				} else {
					return event_process(evt, stack, stack_index, p->ts);
				}
			}

		}



	}

	return PROTO_OK;

}
Пример #20
0
static void analyzer_jpeg_exif_entry_analyze(ExifEntry *entry, void *pload) {

	ExifIfd ifd = exif_content_get_ifd(entry->parent);

	const char *tag_name = exif_tag_get_name_in_ifd(entry->tag, ifd);
	if (!tag_name) // Unknown tag
		return;

	struct ptype *value = NULL;
	// First parse ascii values
	if (entry->format == EXIF_FORMAT_ASCII) {
		char *str = malloc(entry->size);
		if (!str) {
			pom_oom(entry->size);
			return;
		}
		memcpy(str, entry->data, entry->size);
		// Make sure it's NULL terminated
		str[entry->size - 1] = 0;

		value = ptype_alloc("string");
		if (!value) {
			free(str);
			return;
		}
		PTYPE_STRING_SETVAL_P(value, str);
	} else if (entry->components == 1) {
		
		ExifByteOrder byte_order = exif_data_get_byte_order(entry->parent->parent);
		if (entry->format == EXIF_FORMAT_BYTE) {
			value = ptype_alloc("uint8");
			if (!value)
				return;
			PTYPE_UINT8_SETVAL(value, *entry->data);
		} else if (entry->format == EXIF_FORMAT_SHORT)	{
			value = ptype_alloc("uint16");
			if (!value)
				return;
			PTYPE_UINT16_SETVAL(value, exif_get_short(entry->data, byte_order));
		} else if (entry->format == EXIF_FORMAT_LONG) {
			value = ptype_alloc("uint32");
			if (!value)
				return;
			PTYPE_UINT32_SETVAL(value, exif_get_long(entry->data, byte_order));
		}

	}

	if (!value) {
		// Fallback for types not parsed by us yet
		// FIXME this is subject to the locale

		char buff[256];
		buff[sizeof(buff) - 1] = 0;
		exif_entry_get_value(entry, buff, sizeof(buff) - 1);

		value = ptype_alloc("string");
		if (!value)
			return;
		PTYPE_STRING_SETVAL(value, buff);

	}

	char *key = strdup(tag_name);
	if (!key) {
		pom_oom(strlen(tag_name) + 1);
		return;
	}

	struct data *data = analyzer_pload_buffer_get_data(pload);
	data_item_add_ptype(data, analyzer_jpeg_pload_exif, key, value);

}