Exemple #1
0
void parse_http_content_form(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	struct TCP_STREAM *stream = &sess->to_server;
	unsigned offset=0;
	struct HTTPREQUEST *req = &stream->app.httpreq;

	enum {
	POST_NAME_PRE,
	POST_NAME,
	POST_NAME_AFTER,
	POST_VALUE
	};


	while (offset<length)
	switch (req->value_state) {
	case POST_NAME_PRE:
		req->tmp_length = 0;
		req->value_state = POST_NAME;
		break;
	case POST_NAME:
		while (offset<length && px[offset] != '=') {
			if (req->tmp_length < sizeof(req->tmp))
				req->tmp[req->tmp_length++] = px[offset];
			offset++;
		}
		if (offset<length) {
			req->value_state = POST_NAME_AFTER;
			offset++;
			req->parm_name = stringtab_lookup(sess->eng->stringtab, req->tmp, req->tmp_length);
			req->tmp_length = 0;
		}
		break;
	case POST_NAME_AFTER:
		req->value_state = POST_VALUE;
		break;
	case POST_VALUE:
		while (offset<length && px[offset] != '&') {
			if (req->tmp_length < sizeof(req->tmp))
				req->tmp[req->tmp_length++] = px[offset];
			offset++;
		}
		if (offset<length) {
			req->value_state = POST_NAME_PRE;
			offset++;

			http_parse_form_field(sess, frame,
				req->parm_name,
				req->tmp,
				req->tmp_length
				);
		}
		break;
	}

}
Exemple #2
0
/**
 * This code analyzes a <name=value> pair within a cookie, within the
 * context of an HTTP request, which includes relavent information
 * about the host that it comes from
 */
void parse_http_cookie(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *name, unsigned name_length, const unsigned char *value, unsigned value_length)
{
	struct HTTPREQUEST *req = &sess->layer7.httpreq;
	unsigned char *dec;
	unsigned dec_length = value_length;

	if (dec_length > 1000)
		dec_length = 1000;


	switch (toupper(name[0])) {
	case 'C':
		/* MYSPACE COUNTRY CODE 
		 * Example:
		 * COUNTRYCODE=MFMGCisGAQQBgjdYA%2FmgRTBDBgorBgEEAYI3WAMBoDUwMwIDAgABAgJmAwICAMAECOOUmLvDDv%2BRBBB6gRxsNuYMZ2M7SXM7N4fdBAgyFGPRkgkD7Q%3D%3D;
		 */
		if (match_name("COUNTRYCODE", name, name_length) && ends_with_t(".myspace.com", req->host)) {
			unsigned char *dec0;
			unsigned dec0_length;
			unsigned i;

			/* First, "uudecode" this */
			dec0 = alloca(value_length);
			dec0_length = 0;
			for (i=0; i<value_length; i++) {
				if (value[i] != '%')
					dec0[dec0_length++] = value[i];
				else {
					unsigned c=0;
					i++;
					if (i<value_length && isxdigit(value[i]))
						c = hexval(value[i++])<<4;
					if (i<value_length && isxdigit(value[i]))
						c |= hexval(value[i++]);
					dec0[dec0_length++] = (unsigned char)c;
					i--;
				}
			}

			/* Second, "base64 decode" this */
			dec = alloca(dec0_length);
			dec_length = base64_decode(dec, dec_length, value, value_length);

			/* Third, "asn.1 decode" this */
			{
				unsigned tag, len;
				const unsigned char *px = dec;
				unsigned offset = 0;
				unsigned length = dec_length;
				unsigned max_offset;

				tag = asn1_tag(px,length,&offset);
				len = asn1_length(frame,px,length, &offset);

				/* Process the big object */
				if (tag == 0x30 && len != 0xFFFFFFFF) {
					max_offset = offset+len;

					tag = asn1_tag(px,max_offset,&offset);
					len = asn1_length(frame,px,max_offset, &offset);

					/* Process the OID */
					if (tag == 0x06) {
						JOTDOWN(sess->eng->ferret,
							JOT_SRC("ID-IP", frame),
							JOT_OID("MySpace-CountryCode", px+offset, len),
							0);
					}
					offset += len;


				}


			}
		}
		break;
	case 'D':
		/*
		 go.com (including such properties as espn.com) put in their cookies 
		 some sort of location information. Here are some examples that were googled
		 from the web:

		Z2JyO2VuZztsb25kb247YnJvYWRiYW5kOzU7NTs0Oy0xOzA1MS41MDA7LTAwMC4xMTc7ODI2OzEwMTk4OzQ3ODI7NTsK
		Z2JyO2VuZztsb25kb247YnJvYWRiYW5kOzU7NTs1Oy0xOzA1MS41MDA7LTAwMC4xMTc7ODI2OzEwMTk4OzQ3ODI7NTsK
		dXNhO21kO2NvbGxlZ2UgcGFyazt0MTs1OzQ7NDs1MTE7MDM4Ljk5NzstMDc2LjkyODs4NDA7MjE7MTU7NjsK
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzQ7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzQ7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		dXNhO2dhO2F0bGFudGE7YnJvYWRiYW5kOzU7NTs1OzUyNDswMzMuNzQ5Oy0wODQuMzg4Ozg0MDsxMTszOzY7Cg==
		dXNhO29yO2JlYXZlcnRvbjticm9hZGJhbmQ7NTszOzM7ODIwOzA0NS40OTE7LTEyMi44MDU7ODQwOzM4OzYyOzY7Cg==
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzQ7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzM7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		*/
		if (match_name("DE2", name, name_length) && ends_with_t(".go.com", req->host)) {
			dec = alloca(dec_length);
			dec_length = base64_decode(dec, dec_length, value, value_length);
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("GO-LOC", dec, dec_length),
				0);
		}
		break;
	case 'E':
		if (starts_with("EMAIL", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("e-mail", value, value_length),
				0);
		}
		if (starts_with("E-MAIL", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("e-mail", value, value_length),
				0);
		}
		break;

	case 'G':
		/*
		d78da8e7eb998e8f571c4c641b104c60cxsAAABVUyxnYSxsYXdyZW5jZXZpbGxlLCwsLCw1MjQ=
		bf8e3d7c0474fa9da14b6551e6846ec7cxUAAABVUyxnYSxhdGxhbnRhLCwsLCw1MjQ=

		*/
		if (match_name("GEO", name, name_length) && ends_with_t(".youtube.com", req->host)) {
			unsigned i;
			unsigned comma_count=0;
			dec = alloca(dec_length);
			dec_length = base64_decode(dec, dec_length, value, value_length);

			for (i=dec_length; i>0; i--) {
				if (dec[i-1] == ',') {
					/*US,ga,lawrenceville,,,,,524*/
					if (++comma_count == 7)
						break;
				}
			}
			if (i>3 && isalpha(dec[i-2]) && isalpha(dec[i-3])) {
				unsigned offset=i-3;
				while (i<dec_length && comma_count > 5) {
					if (dec[i] == ',')
						comma_count--;
					i++;
				}
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("YouTube-Loc", dec+offset, i-offset-1),
					0);
			}
		}
		/*Example:
		 * [email protected]/769779 
		 */
		if (match_name("GMAILCHAT", name, name_length) && ends_with_t("mail.google.com", req->host)) {
			unsigned j;
			for (j=0; j<value_length && value[j] != '/'; j++)
				;
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("e-mail", value, j),
				0);
		}
		break;
	case 'I':
		if (match_name("ID", name, name_length) && ends_with_t(".doubleclick.net", req->host)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("DoubleClick", value, value_length),
				0);
		}
		break;
	case 'L':
		if (match_name("LOGIN", name, name_length) || match_name("LOGIN_X", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("login", value, value_length),
				0);

			if (ends_with_t(".facebook.com", req->host)) {
				req->login = stringtab_lookup(sess->eng->stringtab, value, value_length);
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("Facebook-user", req->login->str, req->login->length),
					0);
			}

			if (contains("@", value, value_length)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			} else if (contains("%40", value, value_length)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			}
		}
		break;
	case 'M':
		/*http://facebook.com
		 *m_user = warnerc2%40gpc.edu%3A71101757%3ASwUchOEuvzIbYo7E*/
		if (match_name("M_USER", name, name_length)) {
			if (ends_with_t(".facebook.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			}
		}

		/* http://login.live.com/login.srf
		 * [email protected] */
		if (match_name("MSPPRE", name, name_length)) {
			if (ends_with_t(".live.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("e-mail", value, value_length),
					0);
			}
		}

		/* Canadian Broadcasting */
		if (match_name("MyCBCSignIn", name, name_length)) {
			if (ends_with_t(".cbc.ca", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("e-mail", value, value_length),
					0);
			}
		}
		if (match_name("ME", name, name_length)) {
			if (ends_with_t(".myspace.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			}
		}
		 
		break;
	case 'P':
		if (starts_with("PASSWORD", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("password", value, value_length),
				0);
		}
		break;
	case 'U':
		if (starts_with("USERNAME", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("username", value, value_length),
				0);
		}
		break;
	case 'W':
		if (starts_with("WATCHED_VIDEO_ID_LIST_", name, name_length)) {
			size_t l = sizeof("WATCHED_VIDEO_ID_LIST_")-1;
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("YouTube-ID", name+l, name_length-l),
				0);
		}
		break;
	}
}
Exemple #3
0
static unsigned
parse_ssi_entry(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	enum {
		SSI_BUDDYLEN_HI, SSI_BUDDYLEN_LOW, SSI_BUDDY, SSI_BUDDY_DONE,
		SSI_GROUPID_HI, SSI_GROUPID_LO,
		SSI_BUDDYID_HI, SSI_BUDDYID_LO,
		SSI_TYPE_HI, SSI_TYPE_LOW,
		SSI_TLVLEN_HI, SSI_TLVLEN_LO,

		SNAC_TLV_START,
		SNAC_TLV_TAG_HI, SNAC_TLV_TAG_LO, SNAC_TLV_LEN_HI, SNAC_TLV_LEN_LO,
		SNAC_TLV_DATA,
		SNAC_TLV_DONE,
		SNAC_IGNORE,
	};
	struct AIMPARSER *aim = &sess->layer7.aim;
	unsigned offset = 0;
	
	
	while (offset<length)
	switch (aim->ssi_state) {
	case SSI_BUDDYLEN_HI:
		aim->tlv_len = px[offset++];
		aim->ssi_state++;
		break;
	case SSI_BUDDYLEN_LOW: 
		aim->tlv_len <<= 8;
		aim->tlv_len |= px[offset++];
		aim->ssi_state++;
		strfrag_init(sess->str);
		strfrag_init(sess->str+1);
		break;
	case SSI_BUDDY:
		if (aim->tlv_len) {
			unsigned sublen;
			if (aim->tlv_len < length-offset)
				sublen = aim->tlv_len;
			else
				sublen = length-offset;
			strfrag_append(sess->str+1, px+offset, sublen);
			offset += sublen;
			aim->tlv_len -= sublen;
		}
		if (aim->tlv_len == 0) {
			aim->ssi_state = SSI_BUDDY_DONE;
		}
		break;
	case SSI_BUDDY_DONE:
		aim->ssi_state++;
		break;
	case SSI_GROUPID_HI: 
	case SSI_GROUPID_LO:
		/* just ignore these fields */
		aim->ssi_state++;
		offset++;
		break;
	case SSI_BUDDYID_HI: 
	case SSI_BUDDYID_LO:
		/* just ignore these fields */
		aim->ssi_state++;
		offset++;
		break;
	case SSI_TYPE_HI:
		aim->ssi_buddy_type = px[offset++];
		aim->ssi_state++;
		break;
	case SSI_TYPE_LOW:
		aim->ssi_buddy_type <<= 8;
		aim->ssi_buddy_type |= px[offset++];
		aim->ssi_state++;
		if (sess->str[1].length)
		switch (aim->ssi_buddy_type) {
		case 0x0000: /* individual */
			/* TODO: I should also remember what group it is in */
			if (aim->ssi_group)
				JOTDOWN(sess->eng->ferret, 
					JOT_DST("ID-IP",frame),
					JOT_PRINT("AIM-Buddy", sess->str[1].the_string, sess->str[1].length),
					JOT_PRINT("AIM-Group", aim->ssi_group->str, aim->ssi_group->length),
					0);
			else
				JOTDOWN(sess->eng->ferret, 
					JOT_DST("ID-IP",frame),
					JOT_PRINT("AIM-Buddy", sess->str[1].the_string, sess->str[1].length),
					0);
			break;
		case 0x0001: /* group */
			aim->ssi_group = stringtab_lookup(sess->eng->stringtab, sess->str[1].the_string, sess->str[1].length);
			strfrag_finish(&sess->str[1]);
			break;
		default:
			/*TODO: add SAMPLE */
			break;
		}
		break;
	case SSI_TLVLEN_HI:
		aim->ssi_len = px[offset++];
		aim->ssi_state++;
		break;
	case SSI_TLVLEN_LO:
		aim->ssi_len <<= 8;
		aim->ssi_len |= px[offset++];
		aim->ssi_state++;
		break;
	case SNAC_TLV_START:
	case SNAC_TLV_TAG_HI:
	case SNAC_TLV_TAG_LO:
	case SNAC_TLV_LEN_HI:
	case SNAC_TLV_LEN_LO:
	case SNAC_TLV_DATA:
	case SNAC_TLV_DONE:
		while (offset<length && aim->ssi_len > 0)
		switch (aim->ssi_state) {
		case SNAC_TLV_START:
			strfrag_init(sess->str);
			aim->ssi_state++;
			break;
		case SNAC_TLV_TAG_HI:
			aim->tlv_tag = px[offset++];
			aim->ssi_len--;
			aim->ssi_state++;
			break;
		case SNAC_TLV_TAG_LO:
			aim->tlv_tag <<= 8;
			aim->tlv_tag |= px[offset++];
			aim->ssi_len--;
			aim->ssi_state++;
			break;
		case SNAC_TLV_LEN_HI:
			aim->tlv_len = px[offset++];
			aim->ssi_len--;
			aim->ssi_state++;
			break;
		case SNAC_TLV_LEN_LO:
			aim->tlv_len <<= 8;
			aim->tlv_len |= px[offset++];
			aim->ssi_len--;
			aim->ssi_state++;
			break;
		case SNAC_TLV_DATA:
			if (aim->tlv_len && aim->ssi_len) {
				unsigned sublen;

				if (aim->tlv_len < length-offset)
					sublen = aim->tlv_len;
				else
					sublen = length-offset;
				if (sublen > aim->ssi_len)
					sublen = aim->ssi_len;

				parse_tlv(sess, frame, px+offset, sublen);

				offset += sublen;
				aim->tlv_len -= sublen;
				aim->ssi_len -= sublen;
			}

			/* We can get here 3 ways.
			 * #1 - the TLV len could have started at zero, in
			 *      which case there is no real data to process.
			 * #2 - the TLV len had a value that crossed packets,
			 *      and we slowly decremented it by bits
			 # #3 - we got here right after processing a chunk
			 */
			if (aim->tlv_len == 0 || aim->ssi_len == 0) {
				/* If done parsing the TLV, then do a 'close' operation by
				 * sending a NULL data pointer */
				parse_tlv(sess, frame, 0, 0);
				aim->ssi_state = SNAC_TLV_DONE;
			}
			break;
		case SNAC_TLV_DONE:
			aim->ssi_state = SNAC_TLV_START;
			break;
		}
		if (aim->ssi_len == 0)
			return offset; /* return the number of bytes we analyzed */
		break;
	case SNAC_IGNORE:
		/* Just ignore the remainder of the data from this point on */
		offset = length;
		break;
	}

	return offset;
}
Exemple #4
0
/**
 * Parses the <name=value> pairs in HTTP URLs and HTTP POST content data
 */
void  http_parse_form_field(struct TCPRECORD *sess, struct NetFrame *frame,
				struct StringT *name,
				const unsigned char *value,
				unsigned value_length)
{
	struct TCP_STREAM *stream = &sess->to_server;
	struct HTTPREQUEST *req = &stream->app.httpreq;

	if (name == NULL)
		return;

	switch (toupper(name->str[0])) {
	case 'E':
		if (match_name_t("EMAIL", name)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("e-mail", value, value_length),
				0);

			if (ends_with_t(".myspace.com", req->host)) {
				req->login = stringtab_lookup(sess->eng->stringtab, value, value_length);
				if (req->password) {
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("ID-IP", frame),
						JOT_URLENC("MySpace-user", req->login->str, req->login->length),
						JOT_URLENC("password", req->password->str, req->password->length),
						0);
				} else
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("ID-IP", frame),
						JOT_URLENC("MySpace-user", req->login->str, req->login->length),
						0);

			}
		}
		break;
	case 'P':
		if (match_name_t("PASSWORD", name)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("form-password", value, value_length),
				0);

			if (ends_with_t(".myspace.com", req->host)) {
				req->password = stringtab_lookup(sess->eng->stringtab, value, value_length);
				if (req->login) {
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("ID-IP", frame),
						JOT_URLENC("MySpace-user", req->login->str, req->login->length),
						JOT_URLENC("password", req->password->str, req->password->length),
						0);
				}
			}
		}
		if (match_name_t("PASSWD", name)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("password", value, value_length),
				0);
		}
		break;
	case 'Q':
		if (match_name_t("Q", name)) {
			if (ends_with_t(".google.com", req->host)) {
				if (!starts_with("cache:", req->url, req->url_length)) {
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("IP", frame),
						JOT_URLENC("search", value, value_length),
						0);

				}
			}

		}
		break;
	case 'V':
		if (match_name_t("VIDEO_ID", name)) {
			if (ends_with_t(".youtube.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("Watches", frame),
					JOT_URLENC("YouTube", value, value_length),
					0);
				req->youtube_video_id = stringtab_lookup(sess->eng->stringtab, value, value_length);
			}
		}
		break;
	}
}