Exemplo n.º 1
0
void connect_grabbanners(ip_report_t *r) {
	union {
		void *ptr;
		connection_status_t *c;
	} c_u;
	uint64_t state_key=0;
	uint8_t *c_ptr=NULL;
	output_data_t *e_out=NULL;
	char pchars[256];
	size_t p_off=0, j=0;

	state_key=get_connectionkey(r);

	if (rbfind(state_tbl, state_key, &c_u.ptr) > 0) {

		memset(pchars, 0, sizeof(pchars));

		for (j=0, p_off=0, c_ptr=c_u.c->recv_buf; j < c_u.c->recv_len; j++, c_ptr++) {
			if (isgraph(*c_ptr) || *c_ptr == ' ') {
				pchars[p_off++]=(char )*c_ptr;
			}
			if (p_off > (sizeof(pchars) -2)) break;
		}

		if (p_off > 0) {
			e_out=(output_data_t *)xmalloc(sizeof(output_data_t));
			e_out->type=OD_TYPE_BANNER;
			e_out->t_u.banner=xstrdup(pchars);

			fifo_push(r->od_q, (void *)e_out);
		}
	}

	return;
}
Exemplo n.º 2
0
void connect_do(void *pri_work, const ip_report_t *r) {
	char shost_s[32];
	union {
		void *ptr;
		send_pri_workunit_t *w;
		uint8_t *inc;
	} w_u;
	union {
		void *ptr;
		connection_status_t *c;
	} c_u;
	union {
		const uint8_t *packet;
		const ip_report_t *r;
		const uint16_t *len;
	} r_u;
	struct in_addr ia;
	uint64_t state_key=0;
	size_t dlen=0, pk_len=0;
	uint32_t dhost=0, shost=0;
	uint16_t sport=0, dport=0;

	if (r == NULL) {
		PANIC("r ptr NULL");
	}
	if (state_tbl == NULL) {
		PANIC("state table null");
	}
	if (pri_work == NULL) {
		PANIC("pri_work NULL");
	}

	if (r->magic != IP_REPORT_MAGIC) {
		ERR("wrong magic number for IP report");
		return;
	}

	state_key=get_connectionkey(r);

	dhost=r->host_addr;
	dport=r->sport;
	sport=r->dport;
	shost=r->send_addr;

	if (rbfind(state_tbl, state_key, &c_u.ptr) > 0) {
		DBG(M_CON, "connection with flags are %s status is %d", strtcpflgs(r->type), c_u.c->status);

		r_u.r=r;

		if (r_u.r->doff) {
			pk_len=r_u.r->doff;
			r_u.packet += sizeof(ip_report_t);
			if (*r_u.len != pk_len) {
				ERR("report is damaged?, packet seems broken");
				return;
			}
			else {
				r_u.len++;

				dlen=try_and_extract_tcp_data(r_u.packet, pk_len, c_u.c);
				if (dlen > 0) {
					c_u.c->tseq += dlen;
				}
			}
		}

		if (c_u.c->m_tstamp == 0 || c_u.c->t_tstamp == 0) {
			c_u.c->m_tstamp=0;
			c_u.c->t_tstamp=0;
		}
		else {
			c_u.c->m_tstamp++; /* XXX good enough for testing */
		}


		if (dlen < c_u.c->window) c_u.c->window -= dlen;

		if (r->type & TH_RST) {
			c_u.c->status=U_TCP_CLOSE;
			s->stats.stream_remote_abort++;
			a_conns--;
		}

		switch (c_u.c->status) {
			case U_TCP_ESTABLISHED:

				if (r->type & TH_PSH) {
					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK|TH_FIN;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;
					c_u.c->m_tstamp++;

					DBG(M_CON, "setting connection state into FIN_WAIT2 and sending ACK|FIN");

					c_u.c->status=U_TCP_FIN_WAIT2;

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;
					c_u.c->mseq++;
					w_u.ptr=NULL;
				}
				else if (r->type & TH_FIN) {

					c_u.c->tseq += 1; /* FIN eats a seq ;] */

					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;

					DBG(M_CON, "acking FIN");

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;

					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK|TH_FIN;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;

					c_u.c->m_tstamp++;

					DBG(M_CON, "setting connection into state closed and sending ACK|FIN");
					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;

					c_u.c->status=U_TCP_CLOSE;

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;
					w_u.ptr=NULL;
					c_u.c->mseq++;
					a_conns--;
				}
				break; /* U_TCP_ESTABLISHED: */

			case U_TCP_CLOSE:
				if (r->type == TH_ACK) {
					break;
				}

				DBG(M_CON, "reseting a packet type %s (no connection entry)", strtcpflgs(r->type));

				s->stats.stream_closed_alien_pkt++;

				w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
				w_u.w->magic=PRI_4SEND_MAGIC;
				w_u.w->dhost=dhost;
				w_u.w->dport=dport;
				w_u.w->sport=sport;
				w_u.w->shost=c_u.c->send_ip;
				w_u.w->tseq=c_u.c->tseq;
				w_u.w->mseq=c_u.c->mseq;
				w_u.w->window_size=c_u.c->window;
				w_u.w->flags=TH_RST;
				w_u.w->doff=0;
				w_u.w->t_tstamp=c_u.c->t_tstamp;
				w_u.w->m_tstamp=c_u.c->m_tstamp;
				c_u.c->m_tstamp++;

				DBG(M_CON, "reseting packed to closed connection");
				fifo_push(pri_work, w_u.ptr);
				s->stats.stream_segments_sent++;
				w_u.ptr=NULL;
				break; /* U_TCP_CLOSE */

			case U_TCP_FIN_WAIT2:

				if (r->type & TH_FIN) {
					/* ok its closed both ways, lets ack the fin and be done with it */

					c_u.c->tseq += 1;

					w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
					w_u.w->magic=PRI_4SEND_MAGIC;
					w_u.w->dhost=dhost;
					w_u.w->dport=dport;
					w_u.w->sport=sport;
					w_u.w->shost=c_u.c->send_ip;
					w_u.w->tseq=c_u.c->tseq;
					w_u.w->mseq=c_u.c->mseq;
					w_u.w->window_size=c_u.c->window;
					w_u.w->flags=TH_ACK;
					w_u.w->doff=0;
					w_u.w->t_tstamp=c_u.c->t_tstamp;
					w_u.w->m_tstamp=c_u.c->m_tstamp;
					c_u.c->m_tstamp++;

					c_u.c->status=U_TCP_CLOSE;

					fifo_push(pri_work, w_u.ptr);
					s->stats.stream_segments_sent++;
					w_u.ptr=NULL;
					DBG(M_CON, "Setting connection to closed and acking final fin");
				}
				break; /* U_TCP_FIN_WAIT2 */
# if 0
				if (r->type & (TH_ACK|TH_SYN)) {
				}
				break;
			case U_TCP_FIN_WAIT1:
			case U_TCP_FIN_WAIT2:
			case U_TCP_CLOSING:
			case U_TCP_TIME_WAIT:
			case U_TCP_CLOSE_WAIT:
			case U_TCP_LAST_ACK:
			case U_TCP_CLOSE:
# endif
			default:
				ERR("I have no code. I have no code");
				break;
		}

	} /* found in state table */
	else if ((r->type & (TH_ACK|TH_SYN)) == (TH_ACK|TH_SYN)) { /* should it be in state table */
		DBG(M_CON, "Connection with flags %s", strtcpflgs(r->type));

		/* yes this is a new connection */
		c_u.ptr=xmalloc(sizeof(connection_status_t));
		memset(c_u.ptr, 0, sizeof(connection_status_t));

		c_u.c->status=U_TCP_ESTABLISHED;

		c_u.c->send_ip=shost; /* Our IP */
		c_u.c->recv_len=0;
		c_u.c->send_len=0;
		c_u.c->send_buf=NULL;
		c_u.c->recv_buf=NULL;
		c_u.c->recv_stseq=0;
		c_u.c->tseq=r->tseq;
		c_u.c->mseq=r->mseq;
		c_u.c->window=r->window_size; /* XXX wscale */
		c_u.c->t_tstamp=r->t_tstamp;
		c_u.c->m_tstamp=r->m_tstamp;
		c_u.c->ack_pending=1;

		if (GET_IMMEDIATE()) {
			ia.s_addr=shost;
			snprintf(shost_s, sizeof(shost_s) -1, "%s", inet_ntoa(ia));
			ia.s_addr=dhost;
			VRB(0, "connected %s:%u -> %s:%u", shost_s, sport, inet_ntoa(ia), dport);
		}

		s->stats.stream_connections_est++;

		rbinsert(state_tbl, state_key, c_u.ptr);
		a_conns++;

		send_connect(state_key, c_u.c, pri_work, r);
	} /* looks like something we want to connect to ;] */
	else {
		s->stats.stream_completely_alien_packet++;
		DBG(M_CON, "ignoring packet with flags %s", strtcpflgs(r->type));
	}

	return;
}
Exemplo n.º 3
0
static void do_connect(ip_report_t *r) {
	char tcpflags[32];
	union {
		void *ptr;
		send_pri_workunit_t *w;
	} w_u;
	union {
		void *ptr;
		connection_status_t *c;
	} c_u;
	union {
		uint8_t *packet;
		ip_report_t *r;
		uint16_t *len;
	} r_u;
	struct in_addr ia;
	size_t pk_len=0;
	uint64_t state_key=0;

	assert(r != NULL);

	state_key=get_connectionkey((const ip_report_t *)r);

	str_tcpflags(&tcpflags[0], r->type);

	if (TBLFIND(state_tbl, state_key, &c_u.ptr) > 0) {
		if (c_u.ptr == NULL) PANIC("state table is a liar");

		if (s->verbose > 5) MSG(M_DBG2, "### I should (reset|ignore) this packet, flags are %s status is %d", tcpflags, c_u.c->status);

		w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
		w_u.w->magic=PRI_SEND_MAGIC;
		w_u.w->dhost=r->host_addr;
		w_u.w->dport=r->sport;
		w_u.w->sport=r->dport;

		r_u.r=r;

		if (r_u.r->doff) {
			pk_len=r_u.r->doff;
			r_u.packet += sizeof(ip_report_t);
			if (*r_u.len != pk_len) {
				MSG(M_ERR, "report is damaged?!?!?, packet seems broken, sad bunny both ears down");
			}
			else {
				r_u.len++;
				if (pk_len > (sizeof(struct mytcphdr) + sizeof(struct myiphdr))) {
					try_and_extract_tcp_data(r_u.packet, pk_len, c_u.c);
				}
			}
		}

		switch (r->type) {
			case TH_ACK|TH_PSH:
				w_u.w->flags=TH_RST;
				break;
			case TH_ACK:
			case TH_ACK|TH_SYN:
				//xfree(w_u.ptr);
				return;
			default:
				w_u.w->flags=TH_RST;
				if (s->verbose > 4) MSG(M_ERR, "reseting, nothing better to do here yet, flags are `%s'", tcpflags);
				break;
		}

		w_u.w->mseq=r->mseq;
		w_u.w->tseq=r->tseq + (r->window_size / 2); /* increment inside the window somewhere */
		w_u.w->window_size=r->window_size;

		fifo_push(pri_work, w_u.ptr);
	}
	else if ((r->type & (TH_ACK|TH_SYN)) == (TH_ACK|TH_SYN)) {
		if (s->verbose > 5) MSG(M_DBG2, "I should ack this packet, flags are %s", tcpflags);

		w_u.ptr=xmalloc(sizeof(send_pri_workunit_t));
		w_u.w->magic=PRI_SEND_MAGIC;
		w_u.w->dhost=r->host_addr;
		w_u.w->dport=r->sport;
		w_u.w->sport=r->dport;
		w_u.w->tseq=r->tseq + 1;
		w_u.w->mseq=r->mseq;
		w_u.w->window_size=r->window_size;
		w_u.w->flags=TH_ACK;
		fifo_push(pri_work, w_u.ptr);

		c_u.ptr=xmalloc(sizeof(connection_status_t));
		memset(c_u.ptr, 0, sizeof(connection_status_t));

		c_u.c->status=U_TCP_ESTABLISHED;

		c_u.c->recv_len=0;
		c_u.c->send_len=0;
		c_u.c->send_buf=NULL;
		c_u.c->recv_buf=NULL;

		ia.s_addr=w_u.w->dhost;

		if (s->verbose) MSG(M_VERB, "connected %u -> %s:%u", w_u.w->sport, inet_ntoa(ia), w_u.w->dport);

		TBLINSERT(state_tbl, state_key, c_u.ptr);
	}
	else {
		if (s->verbose > 6) MSG(M_DBG2, "do_connect Ignoring packet with flags %s", tcpflags);
	}

	return;
}
Exemplo n.º 4
0
/* destructive */
static char *get_report_extra(ip_report_t *r) {
	static char out[512];
	size_t out_off=0;
	int sret=0;
	union {
		void *ptr;
		output_data_t *d;
	} d_u;

	assert(r != NULL);

	CLEAR(out);

	if (r->od_q == NULL) {
		PANIC("i have no legs");
	}

	while ((d_u.ptr=fifo_pop(r->od_q)) != NULL) {
		/* XXX this needs to be a bit more flexable than what it is (only checking 1 type, etc) */
		sret=snprintf(&out[out_off], (sizeof(out) - (out_off + 1)), "%s", (d_u.d->type == OD_TYPE_OS ? d_u.d->t_u.os : d_u.d->t_u.banner));
		if (sret < 1) break;
		out_off += sret;
		if (out_off >= (sizeof(out) -1)) {
			/* malloc is for girls ;] hide rms this function has serious limits */
			MSG(M_ERR, "Report Buffer is overflowing, breaking, ask author to not be so wordy next time");
			break;
		}
		xfree(d_u.ptr);
	}

	if (GET_DOCONNECT()) {
		uint64_t state_key=0;
		union {
			void *ptr;
			connection_status_t *c;
		} c_u;
		uint8_t pchars[256], *c_ptr=NULL;
		size_t p_off=0;
		size_t j=0;

		state_key=get_connectionkey(r);

		if (TBLFIND(state_tbl, state_key, &c_u.ptr) > 0) {
			memset(pchars, 0, sizeof(pchars));

			for (j=0, p_off=0, c_ptr=c_u.c->recv_buf ; j < c_u.c->recv_len ; j++, c_ptr++) {
				if (isprint(*c_ptr)) {
					pchars[p_off++]=*c_ptr;
				}
				if (p_off > (sizeof(pchars) -1)) break;
			}

			if (p_off > 0) {
				snprintf(&out[out_off], sizeof(out) - (out_off + 1), " `%s'", pchars);
			}
		}
	}

	if (strlen(out)) return &out[0];

	return NULL;
}