diff --git a/epan/dissectors/packet-smb-common.c b/epan/dissectors/packet-smb-common.c index e99e74f853..775882b17d 100644 --- a/epan/dissectors/packet-smb-common.c +++ b/epan/dissectors/packet-smb-common.c @@ -127,162 +127,6 @@ int dissect_ms_compressed_string(tvbuff_t *tvb, proto_tree *tree, int offset, in return offset + compr_len; } -/* Turn a little-endian Unicode '\0'-terminated string into a string we - can display. - XXX - for now, we just handle the ISO 8859-1 characters. - If exactlen==TRUE then us_lenp contains the exact len of the string in - bytes. It might not be null terminated ! - bc specifies the number of bytes in the byte parameters; Windows 2000, - at least, appears, in some cases, to put only 1 byte of 0 at the end - of a Unicode string if the byte count -*/ -static gchar * -unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen, - guint16 bc) -{ - gchar *cur; - gchar *p; - guint16 uchar; - int len; - int us_len; - gboolean overflow = FALSE; - - cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1); - p = cur; - len = MAX_UNICODE_STR_LEN; - us_len = 0; - for (;;) { - if (bc == 0) - break; - - if (bc == 1) { - /* XXX - explain this */ - if (!exactlen) - us_len += 1; /* this is a one-byte null terminator */ - break; - } - - uchar = tvb_get_letohs(tvb, offset); - if (uchar == 0) { - us_len += 2; /* this is a two-byte null terminator */ - break; - } - - if (len > 0) { - if ((uchar & 0xFF00) == 0) - *p++ = (gchar) uchar; /* ISO 8859-1 */ - else - *p++ = '?'; /* not 8859-1 */ - len--; - } else - overflow = TRUE; - - offset += 2; - bc -= 2; - us_len += 2; - - if(exactlen){ - if(us_len>= *us_lenp){ - break; - } - } - } - if (overflow) { - /* Note that we're not showing the full string. */ - *p++ = '.'; - *p++ = '.'; - *p++ = '.'; - } - - *p = '\0'; - *us_lenp = us_len; - - return cur; -} - -/* nopad == TRUE : Do not add any padding before this string - * exactlen == TRUE : len contains the exact len of the string in bytes. - * bc: pointer to variable with amount of data left in the byte parameters - * region - */ -const gchar * -get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp, - gboolean useunicode, int *len, gboolean nopad, gboolean exactlen, - guint16 *bcp) -{ - gchar *cur; - const gchar *string; - int string_len = 0; - int copylen; - gboolean overflow = FALSE; - - if (*bcp == 0) { - /* Not enough data in buffer */ - return NULL; - } - - if (useunicode) { - if ((!nopad) && (*offsetp % 2)) { - (*offsetp)++; /* Looks like a pad byte there sometimes */ - (*bcp)--; - - if (*bcp == 0) { - /* Not enough data in buffer */ - return NULL; - } - } - - if(exactlen){ - string_len = *len; - if (string_len < 0) { - /* This probably means it's a very large unsigned number; just set - it to the largest signed number, so that we throw the appropriate - exception. */ - string_len = INT_MAX; - } - } - - string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp); - - } else { - if(exactlen){ - /* - * The string we return must be null-terminated. - */ - cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1); - copylen = *len; - - if (copylen < 0) { - /* This probably means it's a very large unsigned number; just set - it to the largest signed number, so that we throw the appropriate - exception. */ - copylen = INT_MAX; - } - - tvb_ensure_bytes_exist(tvb, *offsetp, copylen); - - if (copylen > MAX_UNICODE_STR_LEN) { - copylen = MAX_UNICODE_STR_LEN; - overflow = TRUE; - } - - tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen); - cur[copylen] = '\0'; - - if (overflow) - g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1); - - string_len = *len; - string = cur; - } else { - string = tvb_get_const_stringz(tvb, *offsetp, &string_len); - } - } - - *len = string_len; - return string; -} - /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * diff --git a/epan/dissectors/packet-smb-common.h b/epan/dissectors/packet-smb-common.h index 4b5500750d..7de2a8a2bf 100644 --- a/epan/dissectors/packet-smb-common.h +++ b/epan/dissectors/packet-smb-common.h @@ -25,10 +25,6 @@ int display_ms_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, int dissect_ms_compressed_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, const char **data); -const gchar *get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp, - gboolean useunicode, int *len, gboolean nopad, gboolean exactlen, - guint16 *bcp); - extern const value_string share_type_vals[]; #endif diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c index b2a9c98c88..6d0fc69f63 100644 --- a/epan/dissectors/packet-smb.c +++ b/epan/dissectors/packet-smb.c @@ -1718,7 +1718,164 @@ static GSList *conv_tables = NULL; End of request/response matching functions XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +/* Max string length for displaying Unicode strings. */ +#define MAX_UNICODE_STR_LEN 256 +/* Turn a little-endian Unicode '\0'-terminated string into a string we + can display. + XXX - for now, we just handle the ISO 8859-1 characters. + If exactlen==TRUE then us_lenp contains the exact len of the string in + bytes. It might not be null terminated ! + bc specifies the number of bytes in the byte parameters; Windows 2000, + at least, appears, in some cases, to put only 1 byte of 0 at the end + of a Unicode string if the byte count +*/ +static gchar * +unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen, + guint16 bc) +{ + gchar *cur; + gchar *p; + guint16 uchar; + int len; + int us_len; + gboolean overflow = FALSE; + + cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1); + p = cur; + len = MAX_UNICODE_STR_LEN; + us_len = 0; + for (;;) { + if (bc == 0) + break; + + if (bc == 1) { + /* XXX - explain this */ + if (!exactlen) + us_len += 1; /* this is a one-byte null terminator */ + break; + } + + uchar = tvb_get_letohs(tvb, offset); + if (uchar == 0) { + us_len += 2; /* this is a two-byte null terminator */ + break; + } + + if (len > 0) { + if ((uchar & 0xFF00) == 0) + *p++ = (gchar) uchar; /* ISO 8859-1 */ + else + *p++ = '?'; /* not 8859-1 */ + len--; + } else + overflow = TRUE; + + offset += 2; + bc -= 2; + us_len += 2; + + if(exactlen){ + if(us_len>= *us_lenp){ + break; + } + } + } + if (overflow) { + /* Note that we're not showing the full string. */ + *p++ = '.'; + *p++ = '.'; + *p++ = '.'; + } + + *p = '\0'; + *us_lenp = us_len; + + return cur; +} + +/* nopad == TRUE : Do not add any padding before this string + * exactlen == TRUE : len contains the exact len of the string in bytes. + * bc: pointer to variable with amount of data left in the byte parameters + * region + */ +const gchar * +get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp, + gboolean useunicode, int *len, gboolean nopad, gboolean exactlen, + guint16 *bcp) +{ + gchar *cur; + const gchar *string; + int string_len = 0; + int copylen; + gboolean overflow = FALSE; + + if (*bcp == 0) { + /* Not enough data in buffer */ + return NULL; + } + + if (useunicode) { + if ((!nopad) && (*offsetp % 2)) { + (*offsetp)++; /* Looks like a pad byte there sometimes */ + (*bcp)--; + + if (*bcp == 0) { + /* Not enough data in buffer */ + return NULL; + } + } + + if(exactlen){ + string_len = *len; + if (string_len < 0) { + /* This probably means it's a very large unsigned number; just set + it to the largest signed number, so that we throw the appropriate + exception. */ + string_len = INT_MAX; + } + } + + string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp); + + } else { + if(exactlen){ + /* + * The string we return must be null-terminated. + */ + cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1); + copylen = *len; + + if (copylen < 0) { + /* This probably means it's a very large unsigned number; just set + it to the largest signed number, so that we throw the appropriate + exception. */ + copylen = INT_MAX; + } + + tvb_ensure_bytes_exist(tvb, *offsetp, copylen); + + if (copylen > MAX_UNICODE_STR_LEN) { + copylen = MAX_UNICODE_STR_LEN; + overflow = TRUE; + } + + tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen); + cur[copylen] = '\0'; + + if (overflow) + g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1); + + string_len = *len; + string = cur; + } else { + string = tvb_get_const_stringz(tvb, *offsetp, &string_len); + } + } + + *len = string_len; + return string; +} typedef struct _smb_uid_t { char *domain;