aboutsummaryrefslogtreecommitdiffstats
path: root/packet-http.c
diff options
context:
space:
mode:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2003-11-06 08:54:31 +0000
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2003-11-06 08:54:31 +0000
commit8b74005c3d7ea95a64f0e2fc903ba3c4ec024ed4 (patch)
treef6c6cb9d2044e438a1f6c4053a75f1bf71f83391 /packet-http.c
parent9c7b49f5f0481b68541126204c7ba8785f4f3337 (diff)
Add a mechanism to handle various entity headers, allowing their
(string) values to be put into the protocol tree as fields and allowing some headers to get special treatment, and use it for Authorization, Proxy-Authorization, WWW-Authenticate, and Proxy-Authenticate. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@8892 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'packet-http.c')
-rw-r--r--packet-http.c338
1 files changed, 257 insertions, 81 deletions
diff --git a/packet-http.c b/packet-http.c
index 04dd8ad304..ee8bb9f40a 100644
--- a/packet-http.c
+++ b/packet-http.c
@@ -6,7 +6,7 @@
* Copyright 2002, Tim Potter <tpot@samba.org>
* Copyright 1999, Andrew Tridgell <tridge@samba.org>
*
- * $Id: packet-http.c,v 1.69 2003/11/04 08:16:02 guy Exp $
+ * $Id: packet-http.c,v 1.70 2003/11/06 08:54:31 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -60,6 +60,10 @@ static int hf_http_request = -1;
static int hf_http_basic = -1;
static int hf_http_request_method = -1;
static int hf_http_response_code = -1;
+static int hf_http_authorization = -1;
+static int hf_http_proxy_authenticate = -1;
+static int hf_http_proxy_authorization = -1;
+static int hf_http_www_authenticate = -1;
static gint ett_http = -1;
static gint ett_http_ntlmssp = -1;
@@ -104,6 +108,14 @@ typedef void (*RequestDissector)(tvbuff_t*, proto_tree*, int);
static int is_http_request_or_reply(const guchar *data, int linelen, http_type_t *type,
RequestDissector *req_dissector, int *req_strlen);
+static void process_entity_header(tvbuff_t *tvb, int offset, int next_offset,
+ const guchar *line, int linelen, int colon_offset,
+ packet_info *pinfo, proto_tree *tree);
+static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
+static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
+ packet_info *pinfo, gchar *value);
+static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
+ gchar *value);
static dissector_table_t subdissector_table;
static heur_dissector_list_t heur_subdissector_list;
@@ -142,73 +154,6 @@ dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
}
-/*
- * Some headers that we dissect more deeply:
- *
- * Microsoft's abomination called NTLMSSP over HTTP
- * HTTP Basic authorization
- */
-static gboolean
-check_auth(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
- const char *text)
-{
- static const char *ntlm_headers[] = {
- "Authorization: NTLM ",
- "Authorization: Negotiate ",
- "WWW-Authenticate: NTLM ",
- "WWW-Authenticate: Negotiate ",
- "Proxy-Authenticate: NTLM ",
- "Proxy-Authorization: NTLM ",
- NULL
- };
- static const char *basic_headers[] = {
- "Authorization: Basic ",
- "Proxy-Authorization: Basic ",
- "Proxy-authorization: Basic ",
- NULL
- };
- const char **header;
- size_t hdrlen;
- proto_tree *hdr_tree;
- char *data;
- size_t len;
-
- for (header = &ntlm_headers[0]; *header != NULL; header++) {
- hdrlen = strlen(*header);
- if (strncmp(text, *header, hdrlen) == 0) {
- if (hdr_item != NULL) {
- hdr_tree = proto_item_add_subtree(hdr_item,
- ett_http_ntlmssp);
- } else
- hdr_tree = NULL;
- text += hdrlen;
- dissect_http_ntlmssp(tvb, pinfo, hdr_tree, text);
- return TRUE;
- }
- }
- for (header = &basic_headers[0]; *header != NULL; header++) {
- hdrlen = strlen(*header);
- if (strncmp(text, *header, hdrlen) == 0) {
- if (hdr_item != NULL) {
- hdr_tree = proto_item_add_subtree(hdr_item,
- ett_http_ntlmssp);
- } else
- hdr_tree = NULL;
- text += hdrlen;
-
- data = g_strdup(text);
- len = base64_decode(data);
- data[len] = '\0';
- proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
- 0, 0, data);
- g_free(data);
-
- return TRUE;
- }
- }
- return FALSE;
-}
-
/* TODO: remove this ugly global variable */
http_info_value_t *stat_info;
static void
@@ -228,11 +173,11 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guchar c;
http_type_t http_type;
int datalen;
- char *text;
proto_item *hdr_item;
RequestDissector req_dissector;
int req_strlen;
proto_tree *req_tree;
+ int colon_offset;
long int content_length;
gboolean content_length_found = FALSE;
@@ -425,12 +370,15 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
*/
line = tvb_get_ptr(tvb, offset, linelen);
lineend = line + linelen;
+ colon_offset = -1;
/*
* OK, does it look like an HTTP request or response?
*/
req_dissector = NULL;
- if (is_http_request_or_reply(line, linelen, &http_type, &req_dissector, &req_strlen))
+ is_request_or_reply = is_http_request_or_reply(line, linelen,
+ &http_type, &req_dissector, &req_strlen);
+ if (is_request_or_reply)
goto is_http;
/*
@@ -444,6 +392,7 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* No. Does it look like a MIME header?
*/
linep = line;
+ colon_offset = offset;
while (linep < lineend) {
c = *linep++;
@@ -501,6 +450,10 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* to be a MIME header.
*/
goto is_http;
+
+ default:
+ colon_offset++;
+ break;
}
}
@@ -515,19 +468,36 @@ dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
is_http:
/*
- * Put this line.
+ * Process this line.
*/
- text = tvb_format_text(tvb, offset, next_offset - offset);
- if (tree) {
- hdr_item = proto_tree_add_text(http_tree, tvb, offset,
- next_offset - offset, "%s", text);
- if (req_dissector) {
- req_tree = proto_item_add_subtree(hdr_item, ett_http_request);
- req_dissector(tvb, req_tree, req_strlen);
+ if (is_request_or_reply) {
+ if (tree) {
+ hdr_item = proto_tree_add_text(http_tree, tvb,
+ offset, next_offset - offset, "%s",
+ tvb_format_text(tvb, offset,
+ next_offset - offset));
+ if (req_dissector) {
+ req_tree = proto_item_add_subtree(
+ hdr_item, ett_http_request);
+ req_dissector(tvb, req_tree,
+ req_strlen);
+ }
}
- } else
- hdr_item = NULL;
- check_auth(hdr_item, tvb, pinfo, text);
+ } else if (linelen != 0) {
+ /*
+ * Entity header.
+ */
+ process_entity_header(tvb, offset, next_offset,
+ line, linelen, colon_offset, pinfo, http_tree);
+ } else {
+ /*
+ * Blank line.
+ */
+ proto_tree_add_text(http_tree, tvb,
+ offset, next_offset - offset, "%s",
+ tvb_format_text(tvb, offset,
+ next_offset - offset));
+ }
offset = next_offset;
}
@@ -768,6 +738,196 @@ is_http_request_or_reply(const guchar *data, int linelen, http_type_t *type,
return isHttpRequestOrReply;
}
+/*
+ * Process entity-headers.
+ */
+typedef struct {
+ char *name;
+ gint *hf;
+ int special;
+} entity_header_info;
+
+#define EH_NO_SPECIAL 0
+#define EH_AUTHORIZATION 1
+#define EH_AUTHENTICATE 2
+
+static const entity_header_info headers[] = {
+ { "Authorization", &hf_http_authorization, EH_AUTHORIZATION },
+ { "Proxy-Authorization", &hf_http_proxy_authorization, EH_AUTHORIZATION },
+ { "Proxy-Authenticate", &hf_http_proxy_authenticate, EH_AUTHENTICATE },
+ { "WWW-Authenticate", &hf_http_www_authenticate, EH_AUTHENTICATE },
+};
+
+static void
+process_entity_header(tvbuff_t *tvb, int offset, int next_offset,
+ const guchar *line, int linelen, int colon_offset,
+ packet_info *pinfo, proto_tree *tree)
+{
+ int len;
+ int line_end_offset;
+ int header_len;
+ gint hf_index;
+ guchar c;
+ int value_offset;
+ int value_len;
+ char *value;
+ proto_item *hdr_item;
+
+ len = next_offset - offset;
+ line_end_offset = offset + linelen;
+ header_len = colon_offset - offset;
+ hf_index = find_header_hf_value(tvb, offset, header_len);
+
+ if (hf_index == -1) {
+ /*
+ * Not a header we know anything about. Just put it into
+ * the tree as text.
+ */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "%s", format_text(line, len));
+ }
+ } else {
+ /*
+ * Skip whitespace after the colon.
+ */
+ value_offset = colon_offset + 1;
+ while (value_offset < line_end_offset
+ && ((c = line[value_offset - offset]) == ' ' || c == '\t'))
+ value_offset++;
+
+ /*
+ * Fetch the value.
+ */
+ value_len = line_end_offset - value_offset;
+ value = g_malloc(value_len + 1);
+ memcpy(value, &line[value_offset - offset], value_len);
+ value[value_len] = '\0';
+ CLEANUP_PUSH(g_free, value);
+
+ /*
+ * Add it to the protocol tree as a particular field,
+ * but display the line as is.
+ */
+ if (tree) {
+ hdr_item = proto_tree_add_string_format(tree,
+ *headers[hf_index].hf, tvb, offset, len,
+ value, "%s", format_text(line, len));
+ } else
+ hdr_item = NULL;
+
+ /*
+ * Do any special processing that particular headers
+ * require.
+ */
+ switch (headers[hf_index].special) {
+
+ case EH_AUTHORIZATION:
+ if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
+ break; /* dissected NTLMSSP */
+ check_auth_basic(hdr_item, tvb, value);
+ break;
+
+ case EH_AUTHENTICATE:
+ check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
+ break;
+ }
+
+ /*
+ * Free the value, by calling and popping the cleanup
+ * handler for it.
+ */
+ CLEANUP_CALL_AND_POP;
+ }
+}
+
+/* Returns index of entity-header tag in headers */
+static gint
+find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
+{
+ guint i;
+
+ for (i = 0; i < array_length(headers); i++) {
+ if (header_len == strlen(headers[i].name) &&
+ tvb_strncaseeql(tvb, offset, headers[i].name, header_len) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+/*
+ * Dissect Microsoft's abomination called NTLMSSP over HTTP.
+ */
+static gboolean
+check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
+ gchar *value)
+{
+ static const char *ntlm_headers[] = {
+ "NTLM ",
+ "Negotiate ",
+ NULL
+ };
+ const char **header;
+ size_t hdrlen;
+ proto_tree *hdr_tree;
+
+ /*
+ * Check for NTLM credentials and challenge; those can
+ * occur with WWW-Authenticate.
+ */
+ for (header = &ntlm_headers[0]; *header != NULL; header++) {
+ hdrlen = strlen(*header);
+ if (strncmp(value, *header, hdrlen) == 0) {
+ if (hdr_item != NULL) {
+ hdr_tree = proto_item_add_subtree(hdr_item,
+ ett_http_ntlmssp);
+ } else
+ hdr_tree = NULL;
+ value += hdrlen;
+ dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Dissect HTTP Basic authorization.
+ */
+static gboolean
+check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, gchar *value)
+{
+ static const char *basic_headers[] = {
+ "Basic ",
+ NULL
+ };
+ const char **header;
+ size_t hdrlen;
+ proto_tree *hdr_tree;
+ size_t len;
+
+ for (header = &basic_headers[0]; *header != NULL; header++) {
+ hdrlen = strlen(*header);
+ if (strncmp(value, *header, hdrlen) == 0) {
+ if (hdr_item != NULL) {
+ hdr_tree = proto_item_add_subtree(hdr_item,
+ ett_http_ntlmssp);
+ } else
+ hdr_tree = NULL;
+ value += hdrlen;
+
+ len = base64_decode(value);
+ value[len] = '\0';
+ proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
+ 0, 0, value);
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
void
proto_register_http(void)
{
@@ -795,6 +955,22 @@ proto_register_http(void)
{ "Response Code", "http.response.code",
FT_UINT16, BASE_DEC, NULL, 0x0,
"HTTP Response Code", HFILL }},
+ { &hf_http_authorization,
+ { "Authorization", "http.authorization",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Authorization header", HFILL }},
+ { &hf_http_proxy_authenticate,
+ { "Proxy-Authenticate", "http.proxy_authenticate",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Proxy-Authenticate header", HFILL }},
+ { &hf_http_proxy_authorization,
+ { "Proxy-Authorization", "http.proxy_authorization",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Proxy-Authorization header", HFILL }},
+ { &hf_http_www_authenticate,
+ { "WWW-Authenticate", "http.www_authenticate",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP WWW-Authenticate header", HFILL }},
};
static gint *ett[] = {
&ett_http,