diff options
Diffstat (limited to '')
-rw-r--r-- | epan/dissectors/packet-pgsql.c | 247 |
1 files changed, 133 insertions, 114 deletions
diff --git a/epan/dissectors/packet-pgsql.c b/epan/dissectors/packet-pgsql.c index 1bb5b757..b3d99535 100644 --- a/epan/dissectors/packet-pgsql.c +++ b/epan/dissectors/packet-pgsql.c @@ -27,80 +27,80 @@ static dissector_handle_t tls_handle; static dissector_handle_t gssapi_handle; static dissector_handle_t ntlmssp_handle; -static int proto_pgsql = -1; -static int hf_frontend = -1; -static int hf_type = -1; -static int hf_length = -1; -static int hf_version_major = -1; -static int hf_version_minor = -1; -static int hf_request_code = -1; -static int hf_supported_minor_version = -1; -static int hf_number_nonsupported_options = -1; -static int hf_nonsupported_option = -1; -static int hf_parameter_name = -1; -static int hf_parameter_value = -1; -static int hf_query = -1; -static int hf_authtype = -1; -static int hf_passwd = -1; -static int hf_salt = -1; -static int hf_gssapi_sspi_data = -1; -static int hf_sasl_auth_mech = -1; -static int hf_sasl_auth_data = -1; -static int hf_sasl_auth_data_length = -1; -static int hf_statement = -1; -static int hf_portal = -1; -static int hf_return = -1; -static int hf_tag = -1; -static int hf_status = -1; -static int hf_copydata = -1; -static int hf_error = -1; -static int hf_pid = -1; -static int hf_key = -1; -static int hf_condition = -1; -static int hf_text = -1; -static int hf_tableoid = -1; -static int hf_typeoid = -1; -static int hf_oid = -1; -static int hf_format = -1; -static int hf_field_count = -1; -static int hf_val_name = -1; -static int hf_val_idx = -1; -static int hf_val_length = -1; -static int hf_val_data = -1; -static int hf_val_mod = -1; -static int hf_severity = -1; -static int hf_code = -1; -static int hf_message = -1; -static int hf_detail = -1; -static int hf_hint = -1; -static int hf_position = -1; -static int hf_internal_position = -1; -static int hf_internal_query = -1; -static int hf_where = -1; -static int hf_schema_name = -1; -static int hf_table_name = -1; -static int hf_column_name = -1; -static int hf_type_name = -1; -static int hf_constraint_name = -1; -static int hf_file = -1; -static int hf_line = -1; -static int hf_routine = -1; -static int hf_ssl_response = -1; -static int hf_gssenc_response = -1; -static int hf_gssapi_encrypted_payload = -1; - -static gint ett_pgsql = -1; -static gint ett_values = -1; +static int proto_pgsql; +static int hf_frontend; +static int hf_type; +static int hf_length; +static int hf_version_major; +static int hf_version_minor; +static int hf_request_code; +static int hf_supported_minor_version; +static int hf_number_nonsupported_options; +static int hf_nonsupported_option; +static int hf_parameter_name; +static int hf_parameter_value; +static int hf_query; +static int hf_authtype; +static int hf_passwd; +static int hf_salt; +static int hf_gssapi_sspi_data; +static int hf_sasl_auth_mech; +static int hf_sasl_auth_data; +static int hf_sasl_auth_data_length; +static int hf_statement; +static int hf_portal; +static int hf_return; +static int hf_tag; +static int hf_status; +static int hf_copydata; +static int hf_error; +static int hf_pid; +static int hf_key; +static int hf_condition; +static int hf_text; +static int hf_tableoid; +static int hf_typeoid; +static int hf_oid; +static int hf_format; +static int hf_field_count; +static int hf_val_name; +static int hf_val_idx; +static int hf_val_length; +static int hf_val_data; +static int hf_val_mod; +static int hf_severity; +static int hf_code; +static int hf_message; +static int hf_detail; +static int hf_hint; +static int hf_position; +static int hf_internal_position; +static int hf_internal_query; +static int hf_where; +static int hf_schema_name; +static int hf_table_name; +static int hf_column_name; +static int hf_type_name; +static int hf_constraint_name; +static int hf_file; +static int hf_line; +static int hf_routine; +static int hf_ssl_response; +static int hf_gssenc_response; +static int hf_gssapi_encrypted_payload; + +static int ett_pgsql; +static int ett_values; #define PGSQL_PORT 5432 -static gboolean pgsql_desegment = TRUE; -static gboolean first_message = TRUE; +static bool pgsql_desegment = true; +static bool first_message = true; typedef enum { /* Reserve 0 (== GPOINTER_TO_UINT(NULL)) for no PGSQL detected */ PGSQL_AUTH_STATE_NONE = 1, /* No authentication seen or used */ PGSQL_AUTH_SASL_REQUESTED, /* Server sends SASL auth request with supported SASL mechanisms*/ - PGSQL_AUTH_SASL_CONTINUE, /* Server and/or client send further SASL challange-response messages */ + PGSQL_AUTH_SASL_CONTINUE, /* Server and/or client send further SASL challenge-response messages */ PGSQL_AUTH_GSSAPI_SSPI_DATA, /* GSSAPI/SSPI in use */ PGSQL_AUTH_SSL_REQUESTED, /* Client sends SSL encryption request */ PGSQL_AUTH_GSSENC_REQUESTED, /* Client sends GSSAPI encryption request */ @@ -108,7 +108,7 @@ typedef enum { typedef struct pgsql_conn_data { wmem_tree_t *state_tree; /* Tree of encryption and auth state changes */ - guint32 server_port; + uint32_t server_port; } pgsql_conn_data_t; static const value_string fe_messages[] = { @@ -223,15 +223,15 @@ static const value_string gssenc_response_vals[] = { { 0, NULL } }; -static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, - gint n, proto_tree *tree, packet_info *pinfo, +static void dissect_pgsql_fe_msg(unsigned char type, unsigned length, tvbuff_t *tvb, + int n, proto_tree *tree, packet_info *pinfo, pgsql_conn_data_t *conv_data) { - guchar c; - gint i, siz; + unsigned char c; + int i, siz; char *s; proto_tree *shrub; - gint32 data_length; + int32_t data_length; pgsql_auth_state_t state; tvbuff_t *next_tvb; dissector_handle_t payload_handle; @@ -368,7 +368,7 @@ static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, /* Describe, Close */ case 'D': case 'C': - c = tvb_get_guint8(tvb, n); + c = tvb_get_uint8(tvb, n); if (c == 'P') i = hf_portal; else @@ -401,7 +401,7 @@ static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, length -= i; n += siz+i; - if (length == 1 && tvb_get_guint8(tvb, n) == 0) + if (length == 1 && tvb_get_uint8(tvb, n) == 0) break; } break; @@ -469,17 +469,17 @@ static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, } -static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, - gint n, proto_tree *tree, packet_info *pinfo, +static void dissect_pgsql_be_msg(unsigned char type, unsigned length, tvbuff_t *tvb, + int n, proto_tree *tree, packet_info *pinfo, pgsql_conn_data_t *conv_data) { - guchar c; - gint i, siz; + unsigned char c; + int i, siz; char *s, *t; - gint32 num_nonsupported_options; + int32_t num_nonsupported_options; proto_item *ti; proto_tree *shrub; - guint32 auth_type; + uint32_t auth_type; switch (type) { /* Authentication request */ @@ -502,7 +502,7 @@ static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, case PGSQL_AUTH_TYPE_SASL: wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_SASL_REQUESTED)); n += 4; - while ((guint)n < length) { + while ((unsigned)n < length) { siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII); n += siz; @@ -512,7 +512,7 @@ static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, case PGSQL_AUTH_TYPE_SASL_COMPLETE: wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_SASL_CONTINUE)); n += 4; - if ((guint)n < length) { + if ((unsigned)n < length) { proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-8, ENC_NA); } break; @@ -605,9 +605,10 @@ static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, case 'N': length -= 4; while ((signed)length > 0) { - c = tvb_get_guint8(tvb, n); + c = tvb_get_uint8(tvb, n); if (c == '\0') break; + --length; s = tvb_get_stringz_enc(pinfo->pool, tvb, n+1, &siz, ENC_ASCII); i = hf_text; switch (c) { @@ -692,16 +693,16 @@ static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, /* This function is called by tcp_dissect_pdus() to find the size of the message starting at tvb[offset]. */ -static guint +static unsigned pgsql_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { - gint n = 0; - guchar type; - guint length; + int n = 0; + unsigned char type; + unsigned length; /* The length is either the four bytes after the type, or, if the type is 0, the first four bytes. */ - type = tvb_get_guint8(tvb, offset); + type = tvb_get_uint8(tvb, offset); if (type != '\0') n = 1; length = tvb_get_ntohl(tvb, offset+n); @@ -710,7 +711,7 @@ pgsql_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) /* This function is called by tcp_dissect_pdus() to find the size of the wrapped GSS-API message starting at tvb[offset] whe. */ -static guint +static unsigned pgsql_gssapi_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { /* The length of the GSS-API message is the first four bytes, and does @@ -730,11 +731,11 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat pgsql_conn_data_t *conn_data; pgsql_auth_state_t state; - gint n; - guchar type; + int n; + unsigned char type; const char *typestr; - guint length; - gboolean fe; + unsigned length; + bool fe; conversation = find_or_create_conversation(pinfo); conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql); @@ -749,7 +750,7 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat fe = (conn_data->server_port == pinfo->destport); n = 0; - type = tvb_get_guint8(tvb, 0); + type = tvb_get_uint8(tvb, 0); if (type != '\0') n += 1; length = tvb_get_ntohl(tvb, n); @@ -762,7 +763,7 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat We identify them by the fact that the first byte of their length must be zero, and that the next four bytes are a unique tag. */ if (type == '\0') { - guint tag = tvb_get_ntohl(tvb, 4); + unsigned tag = tvb_get_ntohl(tvb, 4); if (length == 16 && tag == PGSQL_CANCELREQUEST) typestr = "Cancel request"; @@ -802,7 +803,7 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat done any better? */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s%c", ( first_message ? "" : "/" ), g_ascii_isprint(type) ? type : '?'); - first_message = FALSE; + first_message = false; { ti = proto_tree_add_item(tree, proto_pgsql, tvb, 0, -1, ENC_NA); @@ -847,7 +848,7 @@ dissect_pgsql_gssapi_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v conversation_add_proto_data(conversation, proto_pgsql, conn_data); } - gboolean fe = (pinfo->destport == conn_data->server_port); + bool fe = (pinfo->destport == conn_data->server_port); col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGSQL"); col_set_str(pinfo->cinfo, COL_INFO, @@ -871,18 +872,26 @@ dissect_pgsql_gssapi_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v /* GSS-API couldn't do anything with it. */ return tvb_captured_length(tvb); } - if (encrypt.gssapi_decrypted_tvb) { - tvbuff_t *decr_tvb = encrypt.gssapi_decrypted_tvb; - add_new_data_source(pinfo, encrypt.gssapi_decrypted_tvb, "Decrypted GSS-API"); - dissect_pgsql_msg(decr_tvb, pinfo, ptree, data); - } else if (encrypt.gssapi_data_encrypted) { - /* Encrypted but couldn't be decrypted. */ - proto_tree_add_item(ptree, hf_gssapi_encrypted_payload, gssapi_tvb, ver_len, -1, ENC_NA); + if (encrypt.gssapi_data_encrypted) { + if (encrypt.gssapi_decrypted_tvb) { + tvbuff_t *decr_tvb = encrypt.gssapi_decrypted_tvb; + add_new_data_source(pinfo, encrypt.gssapi_decrypted_tvb, "Decrypted GSS-API"); + dissect_pgsql_msg(decr_tvb, pinfo, ptree, data); + } else { + /* Encrypted but couldn't be decrypted. */ + proto_tree_add_item(ptree, hf_gssapi_encrypted_payload, gssapi_tvb, ver_len, -1, ENC_NA); + } } else { /* No encrypted (sealed) payload. If any bytes are left, that is * signed-only payload. */ - if (tvb_reported_length_remaining(gssapi_tvb, ver_len)) { - dissect_pgsql_msg(tvb_new_subset_remaining(gssapi_tvb, ver_len), pinfo, ptree, data); + tvbuff_t *plain_tvb; + if (encrypt.gssapi_decrypted_tvb) { + plain_tvb = encrypt.gssapi_decrypted_tvb; + } else { + plain_tvb = tvb_new_subset_remaining(gssapi_tvb, ver_len); + } + if (tvb_reported_length(plain_tvb)) { + dissect_pgsql_msg(plain_tvb, pinfo, ptree, data); } } return tvb_captured_length(tvb); @@ -909,12 +918,24 @@ dissect_pgsql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) pgsql_conn_data_t *conn_data; pgsql_auth_state_t state; - first_message = TRUE; + first_message = true; conversation = find_or_create_conversation(pinfo); conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql); - if (!tvb_ascii_isprint(tvb, 0, 1) && tvb_get_guint8(tvb, 0) != '\0') { + bool fe = (pinfo->match_uint == pinfo->destport); + + if (fe && tvb_get_uint8(tvb, 0) == 0x16 && + (!conn_data || wmem_tree_lookup32_le(conn_data->state_tree, pinfo->num) == NULL)) + { + /* This is the first message in the conversation, and it looks + * like a TLS handshake. Assume the client is performing + * "direct SSL" negotiation. + */ + tls_set_appdata_dissector(tls_handle, pinfo, pgsql_handle); + } + + if (!tvb_ascii_isprint(tvb, 0, 1) && tvb_get_uint8(tvb, 0) != '\0') { /* Doesn't look like the start of a PostgreSQL packet. Have we * seen Postgres yet? */ @@ -933,8 +954,6 @@ dissect_pgsql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) */ } - gboolean fe = (pinfo->match_uint == pinfo->destport); - col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGSQL"); col_set_str(pinfo->cinfo, COL_INFO, fe ? ">" : "<"); @@ -948,7 +967,7 @@ dissect_pgsql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) ptree = proto_item_add_subtree(ti, ett_pgsql); proto_tree_add_string(ptree, hf_type, tvb, 0, 0, "SSL response"); proto_tree_add_item(ptree, hf_ssl_response, tvb, 0, 1, ENC_NA); - switch (tvb_get_guint8(tvb, 0)) { + switch (tvb_get_uint8(tvb, 0)) { case 'S': /* Willing to perform SSL */ /* Next packet will start using SSL. */ ssl_starttls_ack(tls_handle, pinfo, pgsql_handle); @@ -976,7 +995,7 @@ dissect_pgsql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) ptree = proto_item_add_subtree(ti, ett_pgsql); proto_tree_add_string(ptree, hf_type, tvb, 0, 0, "GSS encrypt response"); proto_tree_add_item(ptree, hf_gssenc_response, tvb, 0, 1, ENC_NA); - switch (tvb_get_guint8(tvb, 0)) { + switch (tvb_get_uint8(tvb, 0)) { case 'E': /* ErrorResponse; server does not support GSSAPI. */ /* Process normally. */ tcp_dissect_pdus(tvb, pinfo, tree, pgsql_desegment, 5, @@ -1253,7 +1272,7 @@ proto_register_pgsql(void) }, }; - static gint *ett[] = { + static int *ett[] = { &ett_pgsql, &ett_values }; |