diff --git a/epan/dissectors/packet-pgsql.c b/epan/dissectors/packet-pgsql.c index 54d06b5e69..91dbb0bacb 100644 --- a/epan/dissectors/packet-pgsql.c +++ b/epan/dissectors/packet-pgsql.c @@ -33,6 +33,10 @@ 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; @@ -79,12 +83,20 @@ static gint ett_values = -1; static gboolean pgsql_desegment = TRUE; static gboolean first_message = TRUE; +typedef enum { + PGSQL_AUTH_STATE_NONE, /* 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_GSSAPI_SSPI_DATA, /* GSSAPI/SSPI in use */ +} pgsql_auth_state_t; + typedef struct pgsql_conn_data { gboolean ssl_requested; + pgsql_auth_state_t auth_state; /* Current authentication state */ } pgsql_conn_data_t; static const value_string fe_messages[] = { - { 'p', "Password message" }, + { 'p', "Authentication message" }, { 'Q', "Simple query" }, { 'P', "Parse" }, { 'B', "Bind" }, @@ -127,21 +139,34 @@ static const value_string be_messages[] = { { 0, NULL } }; +#define PGSQL_AUTH_TYPE_SUCCESS 0 +#define PGSQL_AUTH_TYPE_KERBEROS4 1 +#define PGSQL_AUTH_TYPE_KERBEROS5 2 +#define PGSQL_AUTH_TYPE_PLAINTEXT 3 +#define PGSQL_AUTH_TYPE_CRYPT 4 +#define PGSQL_AUTH_TYPE_MD5 5 +#define PGSQL_AUTH_TYPE_SCM 6 +#define PGSQL_AUTH_TYPE_GSSAPI 7 +#define PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE 8 +#define PGSQL_AUTH_TYPE_SSPI 9 +#define PGSQL_AUTH_TYPE_SASL 10 +#define PGSQL_AUTH_TYPE_SASL_CONTINUE 11 +#define PGSQL_AUTH_TYPE_SASL_COMPLETE 12 static const value_string auth_types[] = { - { 0, "Success" }, - { 1, "Kerberos V4" }, - { 2, "Kerberos V5" }, - { 3, "Plaintext password" }, - { 4, "crypt()ed password" }, - { 5, "MD5 password" }, - { 6, "SCM credentials" }, - { 7, "GSSAPI" }, - { 8, "GSSAPI/SSPI continue" }, - { 9, "SSPI" }, - {10, "SASL" }, - {11, "SASL continue" }, - {12, "SASL complete" }, + { PGSQL_AUTH_TYPE_SUCCESS , "Success" }, + { PGSQL_AUTH_TYPE_KERBEROS4 , "Kerberos V4" }, + { PGSQL_AUTH_TYPE_KERBEROS5 , "Kerberos V5" }, + { PGSQL_AUTH_TYPE_PLAINTEXT , "Plaintext password" }, + { PGSQL_AUTH_TYPE_CRYPT , "crypt()ed password" }, + { PGSQL_AUTH_TYPE_MD5 , "MD5 password" }, + { PGSQL_AUTH_TYPE_SCM , "SCM credentials" }, + { PGSQL_AUTH_TYPE_GSSAPI , "GSSAPI" }, + { PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE , "GSSAPI/SSPI continue" }, + { PGSQL_AUTH_TYPE_SSPI , "SSPI" }, + { PGSQL_AUTH_TYPE_SASL , "SASL" }, + { PGSQL_AUTH_TYPE_SASL_CONTINUE , "SASL continue" }, + { PGSQL_AUTH_TYPE_SASL_COMPLETE , "SASL complete" }, { 0, NULL } }; @@ -166,12 +191,39 @@ static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, gint i, siz; char *s; proto_tree *shrub; + gint32 data_length; switch (type) { - /* Password */ + /* Password, SASL or GSSAPI Response, depending on context */ case 'p': - siz = tvb_strsize(tvb, n); - proto_tree_add_item(tree, hf_passwd, tvb, n, siz, ENC_ASCII|ENC_NA); + switch(conv_data->auth_state) { + + case PGSQL_AUTH_SASL_REQUESTED: + /* SASLInitResponse */ + siz = tvb_strsize(tvb, n); + proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII|ENC_NA); + n += siz; + proto_tree_add_item_ret_int(tree, hf_sasl_auth_data_length, tvb, n, 4, ENC_BIG_ENDIAN, &data_length); + n += 4; + if (data_length) { + proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, data_length, ENC_NA); + n += data_length; + } + break; + + case PGSQL_AUTH_SASL_CONTINUE: + proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-4, ENC_NA); + break; + + case PGSQL_AUTH_GSSAPI_SSPI_DATA: + proto_tree_add_item(tree, hf_gssapi_sspi_data, tvb, n, length-4, ENC_NA); + break; + + default: + siz = tvb_strsize(tvb, n); + proto_tree_add_item(tree, hf_passwd, tvb, n, siz, ENC_ASCII|ENC_NA); + break; + } break; /* Simple query */ @@ -349,26 +401,48 @@ 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) + gint n, proto_tree *tree, + pgsql_conn_data_t *conv_data) { guchar c; gint i, siz; char *s, *t; proto_item *ti; proto_tree *shrub; + guint32 auth_type; switch (type) { /* Authentication request */ case 'R': - proto_tree_add_item(tree, hf_authtype, tvb, n, 4, ENC_BIG_ENDIAN); - i = tvb_get_ntohl(tvb, n); - if (i == 4 || i == 5) { - /* i -= (6-i); :-) */ + proto_tree_add_item_ret_uint(tree, hf_authtype, tvb, n, 4, ENC_BIG_ENDIAN, &auth_type); + switch (auth_type) { + case PGSQL_AUTH_TYPE_CRYPT: + case PGSQL_AUTH_TYPE_MD5: n += 4; - siz = (i == 4 ? 2 : 4); + siz = (auth_type == PGSQL_AUTH_TYPE_CRYPT ? 2 : 4); proto_tree_add_item(tree, hf_salt, tvb, n, siz, ENC_NA); - }else if (i == 8) { - proto_tree_add_item(tree, hf_salt, tvb, n, length-8, ENC_NA); + break; + case PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE: + conv_data->auth_state = PGSQL_AUTH_GSSAPI_SSPI_DATA; + proto_tree_add_item(tree, hf_gssapi_sspi_data, tvb, n, length-8, ENC_NA); + break; + case PGSQL_AUTH_TYPE_SASL: + conv_data->auth_state = PGSQL_AUTH_SASL_REQUESTED; + n += 4; + while ((guint)n < length) { + siz = tvb_strsize(tvb, n); + proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII|ENC_NA); + n += siz; + } + break; + case PGSQL_AUTH_TYPE_SASL_CONTINUE: + case PGSQL_AUTH_TYPE_SASL_COMPLETE: + conv_data->auth_state = PGSQL_AUTH_SASL_CONTINUE; + n += 4; + if ((guint)n < length) { + proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-8, ENC_NA); + } + break; } break; @@ -569,6 +643,7 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat if (!conn_data) { conn_data = wmem_new(wmem_file_scope(), pgsql_conn_data_t); conn_data->ssl_requested = FALSE; + conn_data->auth_state = PGSQL_AUTH_STATE_NONE; conversation_add_proto_data(conversation, proto_pgsql, conn_data); } @@ -596,6 +671,21 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat typestr = "Startup message"; else typestr = "Unknown"; + } else if (type == 'p') { + switch (conn_data->auth_state) { + case PGSQL_AUTH_SASL_REQUESTED: + typestr = "SASLInitialResponse message"; + break; + case PGSQL_AUTH_SASL_CONTINUE: + typestr = "SASLResponse message"; + break; + case PGSQL_AUTH_GSSAPI_SSPI_DATA: + typestr = "GSSResponse message"; + break; + default: + typestr = "Password message"; + break; + } } else typestr = val_to_str_const(type, fe_messages, "Unknown"); } @@ -626,7 +716,7 @@ dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat if (fe) dissect_pgsql_fe_msg(type, length, tvb, n, ptree, conn_data); else - dissect_pgsql_be_msg(type, length, tvb, n, ptree); + dissect_pgsql_be_msg(type, length, tvb, n, ptree, conn_data); } return tvb_captured_length(tvb); @@ -710,7 +800,7 @@ proto_register_pgsql(void) "A password.", HFILL } }, { &hf_authtype, - { "Authentication type", "pgsql.authtype", FT_INT32, BASE_DEC, + { "Authentication type", "pgsql.authtype", FT_UINT32, BASE_DEC, VALS(auth_types), 0, "The type of authentication requested by the backend.", HFILL } }, @@ -718,6 +808,22 @@ proto_register_pgsql(void) { "Salt value", "pgsql.salt", FT_BYTES, BASE_NONE, NULL, 0, "The salt to use while encrypting a password.", HFILL } }, + { &hf_gssapi_sspi_data, + { "GSSAPI or SSPI data", "pgsql.auth.gssapi_sspi.data", FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_sasl_auth_mech, + { "SASL authentication mechanism", "pgsql.auth.sasl.mech", FT_STRINGZ, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_sasl_auth_data_length, + { "SASL authentication data length", "pgsql.auth.sasl.data.length", FT_INT32, BASE_DEC, NULL, 0, + NULL, HFILL } + }, + { &hf_sasl_auth_data, + { "SASL authentication data", "pgsql.auth.sasl.data", FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL } + }, { &hf_statement, { "Statement", "pgsql.statement", FT_STRINGZ, BASE_NONE, NULL, 0, "The name of a prepared statement.", HFILL }