Patches applied are:
commit
85f5bbc39dda2eaf03ccb6111cbf5daf1c7b75f9
Author: Craig Forbes <cforbes@qualys.com>
Date: Wed Mar 21 16:45:04 2012 +0000
Backport of STREAM_STATE_TUNNEL fix to 0.2.x.
Return STREAM_STATE_TUNNEL after entering a tunnel.
commit
cfbe28cd4ddde6d77c5b0d5935c8717834971441
Author: Craig Forbes <cforbes@qualys.com>
Date: Wed Feb 29 16:52:44 2012 +0000
Backport of the fix for HTP_AMBIGUOUS_HOST flag.
The flag is only set when the URI host on the request line is different
than the value in the Host: request header.
Resolves https://github.com/ironbee/libhtp/issues/20
commit
196dfb1c8b7a5996389c719e2c912163c5607916
Author: Brian Rectanus <brectanus@qualys.com>
Date: Wed Feb 8 08:35:46 2012 -0600
Add missing function declaration in header.
commit
7878fec818167fcdf7c8c4852ac0dafa1ae445f1
Author: Brian Rectanus <brectanus@qualys.com>
Date: Wed Feb 8 08:35:07 2012 -0600
Revert part of previous patch, which was invalid.
commit
bafef3d4cbfc307960677c6bd682ae195fe986cd
Author: Brian Rectanus <brectanus@qualys.com>
Date: Wed Feb 8 08:36:06 2012 -0600
Update version to next dev release.
commit
62cfdb41ba84f2666c7526e2e5d9e10ab8e220f1
Author: William Metcalf <wmetcalf@qualys.com>
Date: Wed Feb 1 13:19:48 2012 -0600
Many thanks to Will, Brian and Craig.
}
}
+/**
+ * Case-insensitive comparison of two memory regions.
+ *
+ * @param s1
+ * @param l1
+ * @param s2
+ * @param l2
+ * @return 0 if the memory regions are identical, -1 or +1 if they're not
+ */
+int bstr_cmp_nocase_ex(char *s1, size_t l1, char *s2, size_t l2) {
+ size_t p1 = 0, p2 = 0;
+
+ while ((p1 < l1) && (p2 < l2)) {
+ if (tolower((int)s1[p1]) != tolower((int)s2[p2])) {
+ // Difference
+ return (tolower((int)s1[p1]) < tolower((int)s2[p2])) ? -1 : 1;
+ }
+
+ p1++;
+ p2++;
+ }
+
+ if ((p1 == l2) && (p2 == l1)) {
+ // They're identical
+ return 0;
+ } else {
+ // One string is shorter
+ if (p1 == l1) return -1;
+ else return 1;
+ }
+}
+
/**
* Compare a bstring with a NUL-terminated string.
*
return bstr_cmp_ex(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2));
}
+/**
+ * Case-insensitive comparison two bstrings.
+ *
+ * @param b1
+ * @param b2
+ * @return 0, -1 or +1
+ */
+int bstr_cmp_nocase(bstr *b1, bstr *b2) {
+ return bstr_cmp_nocase_ex(bstr_ptr(b1), bstr_len(b1), bstr_ptr(b2), bstr_len(b2));
+}
+
/**
* Convert bstring to lowercase.
*
int bstr_cmpc(bstr *, char *);
int bstr_cmp(bstr *, bstr *);
+int bstr_cmp_nocase(bstr *, bstr *);
bstr *bstr_dup_lower(bstr *);
bstr *bstr_tolowercase(bstr *);
// -- Defines -------------------------------------------------------------------------------------
-#define HTP_BASE_VERSION_TEXT "0.2.7"
+#define HTP_BASE_VERSION_TEXT "0.2.8-dev"
#define HTP_ERROR -1
#define HTP_OK 0
void htp_config_set_path_control_char_handling(htp_cfg_t *cfg, int control_char_handling);
void htp_config_set_path_convert_utf8(htp_cfg_t *cfg, int convert_utf8);
void htp_config_set_path_decode_separators(htp_cfg_t *cfg, int backslash_separators);
-void htp_config_set_path_decode_separators(htp_cfg_t *cfg, int decode_u_encoding);
+void htp_config_set_path_decode_u_encoding(htp_cfg_t *cfg, int decode_u_encoding);
void htp_config_set_path_invalid_encoding_handling(htp_cfg_t *cfg, int invalid_encoding_handling);
void htp_config_set_path_invalid_utf8_handling(htp_cfg_t *cfg, int invalid_utf8_handling);
void htp_config_set_path_nul_encoded_handling(htp_cfg_t *cfg, int nul_encoded_handling);
void htp_connp_set_user_data(htp_connp_t *connp, void *user_data);
void *htp_connp_get_user_data(htp_connp_t *connp);
-htp_conn_t *htp_conn_create();
+htp_conn_t *htp_conn_create(htp_connp_t *connp);
void htp_conn_destroy(htp_conn_t *conn);
int htp_conn_remove_tx(htp_conn_t *conn, htp_tx_t *tx);
* @return A copy of the configuration structure.
*/
htp_cfg_t *htp_config_copy(htp_cfg_t *cfg) {
- htp_cfg_t *copy = calloc(1, sizeof(htp_cfg_t));
+ htp_cfg_t *copy = malloc(sizeof(htp_cfg_t));
if (copy == NULL) return NULL;
+ *copy = *cfg;
+
// Create copies of the hooks' structures
if (cfg->hook_transaction_start != NULL) {
copy->hook_transaction_start = hook_copy(cfg->hook_transaction_start);
void htp_connp_set_user_data(htp_connp_t *connp, void *user_data) {
connp->user_data = user_data;
}
+
+void *htp_connp_get_user_data(htp_connp_t *connp) {
+ return(connp->user_data);
+}
// There is no host information in the URI. Place the
// hostname from the headers into the parsed_uri structure.
htp_replace_hostname(connp, connp->in_tx->parsed_uri, h->value);
- } else {
- // The host information is present both in the
+ } else if (bstr_cmp_nocase(h->value, connp->in_tx->parsed_uri->hostname) != 0) {
+ // The host information is different in the
// headers and the URI. The HTTP RFC states that
// we should ignore the headers copy.
connp->in_tx->flags |= HTP_AMBIGUOUS_HOST;
#ifdef HTP_DEBUG
fprintf(stderr, "htp_connp_req_data: returning STREAM_STATE_DATA (previous error)\n");
#endif
+
return STREAM_STATE_ERROR;
}
#ifdef HTP_DEBUG
fprintf(stderr, "htp_connp_req_data: returning STREAM_STATE_DATA (zero-length chunk)\n");
#endif
+
return STREAM_STATE_ERROR;
}
// mode (which it would be after an initial CONNECT transaction).
if (connp->in_status == STREAM_STATE_TUNNEL) {
#ifdef HTP_DEBUG
- fprintf(stderr, "htp_connp_req_data: returning STREAM_STATE_DATA (tunnel)\n");
+ fprintf(stderr, "htp_connp_req_data: returning STREAM_STATE_TUNNEL\n");
#endif
- return STREAM_STATE_DATA;
+ return STREAM_STATE_TUNNEL;
}
// Invoke a processor, in a loop, until an error
// on processors to add error messages, so we'll
// keep quiet here.
int rc = connp->in_state(connp);
- if (rc != HTP_OK) {
+ if (rc == HTP_OK) {
+ if (connp->in_status == STREAM_STATE_TUNNEL) {
+ #ifdef HTP_DEBUG
+ fprintf(stderr, "htp_connp_req_data: returning STREAM_STATE_TUNNEL\n");
+ #endif
+
+ return STREAM_STATE_TUNNEL;
+ }
+ } else {
// Do we need more data?
if (rc == HTP_DATA) {
#ifdef HTP_DEBUG
fprintf(stderr, "htp_connp_req_data: returning STREAM_STATE_DATA\n");
#endif
+
return STREAM_STATE_DATA;
}
#ifdef HTP_DEBUG
fprintf(stderr, "htp_connp_res_data: returning STREAM_STATE_DATA (previous error)\n");
#endif
+
return STREAM_STATE_ERROR;
}
#ifdef HTP_DEBUG
fprintf(stderr, "htp_connp_res_data: returning STREAM_STATE_DATA (zero-length chunk)\n");
#endif
+
return STREAM_STATE_ERROR;
}
// mode (which it would be after an initial CONNECT transaction.
if (connp->out_status == STREAM_STATE_TUNNEL) {
#ifdef HTP_DEBUG
- fprintf(stderr, "htp_connp_res_data: returning STREAM_STATE_DATA (tunnel)\n");
+ fprintf(stderr, "htp_connp_res_data: returning STREAM_STATE_TUNNEL\n");
#endif
- return STREAM_STATE_DATA;
+ return STREAM_STATE_TUNNEL;
}
// Invoke a processor, in a loop, until an error
// on processors to add error messages, so we'll
// keep quiet here.
int rc = connp->out_state(connp);
- if (rc != HTP_OK) {
+ if (rc == HTP_OK) {
+ if (connp->out_status == STREAM_STATE_TUNNEL) {
+ #ifdef HTP_DEBUG
+ fprintf(stderr, "htp_connp_res_data: returning STREAM_STATE_TUNNEL\n");
+ #endif
+
+ return STREAM_STATE_TUNNEL;
+ }
+ } else {
// Do we need more data?
if (rc == HTP_DATA) {
return STREAM_STATE_DATA;