Пример #1
0
static int analyzer_multipart_pload_close(void *obj, void *p) {


	struct analyzer_multipart_pload_priv *priv = p;

	if (!priv)
		return POM_OK;

	if (priv->boundary)
		free(priv->boundary);

	if (priv->pload)
		pload_end(priv->pload);

	if (priv->last_line)
		free(priv->last_line);


	while (priv->pload_data.items) {
		struct data_item *itm = priv->pload_data.items;
		priv->pload_data.items = itm->next;

		if (itm->key)
			free(itm->key);
		if (itm->value)
			ptype_cleanup(itm->value);

		free(itm);
	}

	free(priv);

	return POM_OK;
}
Пример #2
0
static int analyzer_smtp_evt_msg_cleanup(struct event *evt) {

	struct pload *pload = event_get_priv(evt);
	if (!pload)
		return POM_OK;

	pload_end(pload);
	return POM_OK;
}
Пример #3
0
static int analyzer_tftp_conntrack_priv_cleanup(void *obj, void *priv) {

	struct analyzer_tftp_file *f = priv;

	int res = POM_OK;
	if (f->pload)
		res += pload_end(f->pload);

	if (f->evt)
		res += event_process_end(f->evt);

	free(f);

	return res;
}
Пример #4
0
static int analyzer_rtp_ce_cleanup(void *obj, void *priv) {

	struct analyzer_rtp_ce_priv *cp = priv;

	int i;
	for (i = 0; i < POM_DIR_TOT; i++) {
		if (cp->pload[i])
			pload_end(cp->pload[i]);
		if (cp->evt[i])
			event_process_end(cp->evt[i]);
	}

	free(cp);

	return POM_OK;
}
Пример #5
0
static int analyzer_tftp_pkt_process(void *obj, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) {

	struct analyzer_tftp_priv *priv = obj;

	struct proto_process_stack *s = &stack[stack_index];
	struct proto_process_stack *s_prev = &stack[stack_index - 1];

	uint16_t opcode = *PTYPE_UINT16_GETVAL(s_prev->pkt_info->fields_value[proto_tftp_field_opcode]);

	// Get the session
	struct conntrack_session *session = conntrack_session_get(s_prev->ce);
	if (!session)
		return POM_ERR;

	struct analyzer_tftp_session_priv *spriv = conntrack_session_get_priv(session, obj);

	if (!spriv) {
		// Add session priv if it is not done yet
		spriv = malloc(sizeof(struct analyzer_tftp_session_priv));
		if (!spriv) {
			pom_oom(sizeof(struct analyzer_tftp_session_priv));
			goto err;
		}
		memset(spriv, 0, sizeof(struct analyzer_tftp_session_priv));

		if (conntrack_session_add_priv(session, obj, spriv, analyzer_tftp_session_priv_cleanup) != POM_OK) {
			free(spriv);
			goto err;
		}
	}

	void *pload = s->pload;
	uint32_t plen = s->plen;

	switch (opcode) {
		case tftp_rrq:
		case tftp_wrq: {

			if (plen < 3)
				return POM_OK; // Invalid packet

			// Find the filename
			// The below should always be valid as proto_tftp already checked this
			char *filename = pload; 
			char *mode = memchr(filename, 0, plen - 1) + 1;

			struct analyzer_tftp_file *fq = malloc(sizeof(struct analyzer_tftp_file));
			if (!fq) {
				pom_oom(sizeof(struct analyzer_tftp_file));
				goto err;
			}
			memset(fq, 0, sizeof(struct analyzer_tftp_file));

			// Get the port on which we expect this file
			// No need to check the IP as we got the session biding
			struct proto_process_stack *s_l4 = &stack[stack_index - 2];
			unsigned int i;
			for (i = 0; !fq->port ; i++) {
				struct proto_reg_info *pinfo = proto_get_info(s_l4->proto);
				char *name = pinfo->pkt_fields[i].name;
				if (!name) {
					pomlog(POMLOG_ERR "Source port not found in RRQ/WRQ packets");
					goto err;
				}
				if (!strcmp(name, "sport")) {
					fq->port = *PTYPE_UINT16_GETVAL(s_l4->pkt_info->fields_value[i]);
					break;
				}
			}

			fq->evt = event_alloc(priv->evt_file);
			if (!fq->evt) {
				free(fq);
				goto err;
			}
			struct data *evt_data = event_get_data(fq->evt);

			PTYPE_STRING_SETVAL(evt_data[analyzer_tftp_file_filename].value, filename);
			data_set(evt_data[analyzer_tftp_file_filename]);
			PTYPE_STRING_SETVAL(evt_data[analyzer_tftp_file_mode].value, mode);
			data_set(evt_data[analyzer_tftp_file_mode]);
			PTYPE_BOOL_SETVAL(evt_data[analyzer_tftp_file_write].value, opcode == tftp_wrq);
			data_set(evt_data[analyzer_tftp_file_write]);



			fq->next = spriv->files;
			if (fq->next)
				fq->next->prev = fq;
			spriv->files = fq;
			conntrack_session_unlock(session);

			event_process_begin(fq->evt, stack, stack_index, p->ts);

			break;
		}

		case tftp_data: {

			if (plen < sizeof(uint16_t))
				return POM_OK; // Invalid packet

			struct analyzer_tftp_file *f = conntrack_get_priv(s_prev->ce, obj);
			struct data *evt_data = NULL;

			if (!f) {
				// The file is not yet associated to this connection
				// Find it in the queue
				
				struct proto_process_stack *s_l4 = &stack[stack_index - 2];
				unsigned int i;
				uint16_t sport = 0, dport = 0;
				for (i = 0; !sport || !dport ; i++) {
					struct proto_reg_info *pinfo = proto_get_info(s_l4->proto);
					char *name = pinfo->pkt_fields[i].name;
					if (!name) {
						pomlog(POMLOG_ERR "Source port not found in data packets");
						goto err;
					}
					if (!strcmp(name, "sport"))
						sport = *PTYPE_UINT16_GETVAL(s_l4->pkt_info->fields_value[i]);

					if (!strcmp(name, "dport"))
						dport = *PTYPE_UINT16_GETVAL(s_l4->pkt_info->fields_value[i]);
				}

				// Find the file in the session list
				for (f = spriv->files; ; f = f->next) {
					evt_data = event_get_data(f->evt);
					if (*PTYPE_BOOL_GETVAL(evt_data[analyzer_tftp_file_write].value)) {
						if (f->port == sport)
							break;
					} else {
						if (f->port == dport)
							break;
					}
				}

				if (!f) {
					pomlog(POMLOG_DEBUG "File not found in queued file request.");
					conntrack_session_unlock(session);
					return POM_OK;
				}
				
				// Remove the file from the queue and assign it to the conntrack
				if (f->prev)
					f->prev->next = f->next;
				else
					spriv->files = f->next;
				if (f->next)
					f->next->prev = f->prev;
				
				f->prev = NULL;
				f->next = NULL;

				// Create the payload buffer
				f->pload = pload_alloc(f->evt, PLOAD_FLAG_NEED_MAGIC);
				if (!f->pload)
					goto err;

				conntrack_add_priv(s_prev->ce, obj, f, analyzer_tftp_conntrack_priv_cleanup);
			} else {
				evt_data = event_get_data(f->evt);
			}
			conntrack_session_unlock(session);
		
			if (!f->pload) {
				pomlog(POMLOG_DEBUG "Ignoring extra packet");
				return POM_OK;
			}

			// Discard the block ID
			pload += sizeof(uint16_t);
			plen -= sizeof(uint16_t);

			if (pload_append(f->pload, pload, plen) != POM_OK)
				goto err;

			uint32_t *size = PTYPE_UINT32_GETVAL(evt_data[analyzer_tftp_file_size].value);
			*size += plen;

			if (plen < ANALYZER_TFTP_BLK_SIZE) {
				// Got last packet !
				data_set(evt_data[analyzer_tftp_file_size]);
				
				int res = pload_end(f->pload);
				res += event_process_end(f->evt);
				f->evt = NULL;	
				f->pload = NULL;
				if (res)
					goto err;
			}

			break;
		}

		case tftp_error: {
			conntrack_session_unlock(session);

			struct analyzer_tftp_file *f = conntrack_get_priv(s_prev->ce, obj);
			if (f && f->pload) {
				int res = pload_end(f->pload);
				res += event_process_end(f->evt);
				f->pload = NULL;
				f->evt = NULL;
				if (res)
					goto err;
			}
			break;
		}

		default:
			conntrack_session_unlock(session);
			break;
	}
	
	return POM_OK;

err:
	conntrack_session_unlock(session);
	return POM_ERR;
}
Пример #6
0
static int analyzer_multipart_pload_write(void *obj, void *p, void *data, size_t len) {

	struct analyzer_multipart_pload_priv *priv = p;

	if (priv->state == analyzer_multipart_pload_state_end)
		return POM_OK;

	if (priv->state == analyzer_multipart_pload_state_error)
		return POM_ERR;

	unsigned int line_len, remaining_len = len;

	while (remaining_len > 0) {
	
		// Because of the NOTE in RFC 2046 section 5.1.1, line start at CR 

		void *cr = memchr(data + 1, '\r', remaining_len - 1);
		if (!cr || priv->last_line) {

			size_t add_len = remaining_len;
			if (cr)
				add_len = cr - data;

			size_t new_len = add_len + 1;
			if (priv->last_line)
				new_len += strlen(priv->last_line);
			if (priv->last_line_len < new_len) {
				char *new_last_line = realloc(priv->last_line, new_len);
				if (!new_last_line) {
					pom_oom(new_len);
					goto err;
				}
				if (!priv->last_line_len)
					new_last_line[0] = 0;
				priv->last_line_len = new_len;
				priv->last_line = new_last_line;
			}
			strncat(priv->last_line, data, add_len);
			priv->last_line[new_len - 1] = 0;

			if (!cr)
				break;

			// Process this line and continue to the next
			if (analyzer_multipart_pload_process_line(priv, priv->last_line, strlen(priv->last_line)) != POM_OK)
				goto err;

			// We need to process this part of the payload
			if (priv->state == analyzer_multipart_pload_state_content && priv->pload_start) {
				if (pload_append(priv->pload, priv->pload_start, priv->pload_end - priv->pload_start) != POM_OK)
					goto err;
			}

			priv->pload_start = NULL;
			priv->pload_end = NULL;
			
			free(priv->last_line);
			priv->last_line = NULL;
			priv->last_line_len = 0;
			data = cr;
			remaining_len -= add_len;
			
			continue;
		}

		line_len = cr - data;
		
		if (analyzer_multipart_pload_process_line(priv, data, line_len) != POM_OK)
			goto err;

		remaining_len -= line_len;
		data = cr;
	}

	if (priv->state == analyzer_multipart_pload_state_content && priv->pload_start) {
		if (pload_append(priv->pload, priv->pload_start, priv->pload_end - priv->pload_start) != POM_OK)
			goto err;
	}

	priv->pload_start = NULL;
	priv->pload_end = NULL;

	return POM_OK;

err:
	if (priv->pload) {
		pload_end(priv->pload);
		priv->pload = NULL;
	}

	priv->state = analyzer_multipart_pload_state_error;
	return POM_ERR;
}
Пример #7
0
static int analyzer_multipart_pload_process_line(struct analyzer_multipart_pload_priv *priv, char *line, size_t len) {

	char *my_line = line;
	size_t my_len = len;
	while (my_len > 0 && (*my_line == '\r' || *my_line == '\n')) {
		my_line++;
		my_len--;
	}

	if (my_len >= priv->boundary_len && !memcmp(my_line, priv->boundary, priv->boundary_len)) {
		// Process the rest of the payload

		if (priv->pload) {
			if (priv->pload_start && pload_append(priv->pload, priv->pload_start, priv->pload_end - priv->pload_start) != POM_OK)
				return POM_ERR;

			pload_end(priv->pload);
			priv->pload = NULL;
		}
		priv->pload_start = NULL;
		priv->pload_end = NULL;

		if (my_len >= priv->boundary_len + 2 && my_line[priv->boundary_len] == '-' && my_line[priv->boundary_len + 1] == '-')
			priv->state = analyzer_multipart_pload_state_end;
		else
			priv->state = analyzer_multipart_pload_state_header;
	
		return POM_OK;
	} else if (priv->state == analyzer_multipart_pload_state_header) {

		if (!my_len) {
			// End of the headers
			priv->state = analyzer_multipart_pload_state_content;
			return POM_OK;
		}

		if (mime_header_parse(&priv->pload_data, my_line, my_len) != POM_OK) {
			priv->state = analyzer_multipart_pload_state_error;
			return POM_OK;
		}


	} else if (priv->state == analyzer_multipart_pload_state_content) {

		if (!priv->pload) {
			struct event *rel_event = pload_get_related_event(priv->parent_pload);
			priv->pload = pload_alloc(rel_event, 0);
			if (!priv->pload)
				return POM_ERR;
			
			pload_set_parent(priv->pload, priv->parent_pload);

			// Parse the headers
			while (priv->pload_data.items) {
				struct data_item *itm = priv->pload_data.items;
				priv->pload_data.items = itm->next;

				if (!strcasecmp(itm->key, "Content-Type")) {
					pload_set_mime_type(priv->pload, PTYPE_STRING_GETVAL(itm->value));
				} else if (!strcasecmp(itm->key, "Content-Transfer-Encoding")) {
					pload_set_encoding(priv->pload, PTYPE_STRING_GETVAL(itm->value));
				}
				free(itm->key);
				ptype_cleanup(itm->value);
				free(itm);
			}

			// If it's the begining, discard CRLF
			line = my_line;
			len = my_len;
		}

		if (priv->pload_end != line) {
			// Process the payload we had and queue the this one
			if (priv->pload_start && pload_append(priv->pload, priv->pload_start, priv->pload_end - priv->pload_start) != POM_OK)
				return POM_ERR;
			priv->pload_start = line;
			priv->pload_end = line + len;
		} else {
			priv->pload_end += len;
		}
	}

	return POM_OK;
}