1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-30 13:01:23 +03:00

misc: Introduce ssh_log_hexdump()

The introduced internal function is intended to be a replacement for the
deprecated function ssh_print_hexa().

Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Anderson Toshiyuki Sasaki
2019-07-29 17:16:28 +02:00
committed by Andreas Schneider
parent c03c9b88d1
commit 33927f3ae8
2 changed files with 188 additions and 0 deletions

View File

@@ -83,4 +83,5 @@ int ssh_match_group(const char *group, const char *object);
void uint64_inc(unsigned char *counter);
void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len);
#endif /* MISC_H_ */

View File

@@ -389,6 +389,193 @@ void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
free(hexa);
}
/**
* @brief Log the content of a buffer in hexadecimal format, similar to the
* output of 'hexdump -C' command.
*
* The first logged line is the given description followed by the length.
* Then the content of the buffer is logged 16 bytes per line in the following
* format:
*
* (offset) (first 8 bytes) (last 8 bytes) (the 16 bytes as ASCII char values)
*
* The output for a 16 bytes array containing values from 0x00 to 0x0f would be:
*
* "Example (16 bytes):"
* " 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................"
*
* The value for each byte as corresponding ASCII character is printed at the
* end if the value is printable. Otherwise it is replace with '.'.
*
* @param[in] descr A description for the content to be logged
* @param[in] what The buffer to be logged
* @param[in] len The length of the buffer given in what
*
* @note If a too long description is provided (which would result in a first
* line longer than 80 bytes), the function will fail.
*/
void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len)
{
size_t i;
char ascii[17];
const unsigned char *pc = NULL;
size_t count = 0;
ssize_t printed = 0;
/* The required buffer size is calculated from:
*
* 2 bytes for spaces at the beginning
* 8 bytes for the offset
* 2 bytes for spaces
* 24 bytes to print the first 8 bytes + spaces
* 1 byte for an extra space
* 24 bytes to print next 8 bytes + spaces
* 2 bytes for extra spaces
* 16 bytes for the content as ASCII characters at the end
* 1 byte for the ending '\0'
*
* Resulting in 80 bytes.
*
* Except for the first line (description + size), all lines have fixed
* length. If a too long description is used, the function will fail.
* */
char buffer[80];
/* Print description */
if (descr != NULL) {
printed = snprintf(buffer, sizeof(buffer), "%s ", descr);
if (printed < 0) {
goto error;
}
count += printed;
} else {
printed = snprintf(buffer, sizeof(buffer), "(NULL description) ");
if (printed < 0) {
goto error;
}
count += printed;
}
if (len == 0) {
printed = snprintf(buffer + count, sizeof(buffer) - count,
"(zero length):");
if (printed < 0) {
goto error;
}
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
return;
} else {
printed = snprintf(buffer + count, sizeof(buffer) - count,
"(%zu bytes):", len);
if (printed < 0) {
goto error;
}
count += printed;
}
if (what == NULL) {
printed = snprintf(buffer + count, sizeof(buffer) - count,
"(NULL)");
if (printed < 0) {
goto error;
}
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
return;
}
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
/* Reset state */
count = 0;
pc = what;
for (i = 0; i < len; i++) {
/* Add one space after printing 8 bytes */
if ((i % 8) == 0) {
if (i != 0) {
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
if (printed < 0) {
goto error;
}
count += printed;
}
}
/* Log previous line and reset state for new line */
if ((i % 16) == 0) {
if (i != 0) {
printed = snprintf(buffer + count, sizeof(buffer) - count,
" %s", ascii);
if (printed < 0) {
goto error;
}
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
count = 0;
}
/* Start a new line with the offset */
printed = snprintf(buffer, sizeof(buffer),
" %08zx ", i);
if (printed < 0) {
goto error;
}
count += printed;
}
/* Print the current byte hexadecimal representation */
printed = snprintf(buffer + count, sizeof(buffer) - count,
" %02x", pc[i]);
if (printed < 0) {
goto error;
}
count += printed;
/* If printable, store the ASCII character */
if (isprint(pc[i])) {
ascii[i % 16] = pc[i];
} else {
ascii[i % 16] = '.';
}
ascii[(i % 16) + 1] = '\0';
}
/* Add padding if not exactly 16 characters */
while ((i % 16) != 0) {
/* Add one space after printing 8 bytes */
if ((i % 8) == 0) {
if (i != 0) {
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
if (printed < 0) {
goto error;
}
count += printed;
}
}
printed = snprintf(buffer + count, sizeof(buffer) - count, " ");
if (printed < 0) {
goto error;
}
count += printed;
i++;
}
/* Print the last printable part */
printed = snprintf(buffer + count, sizeof(buffer) - count,
" %s", ascii);
if (printed < 0) {
goto error;
}
SSH_LOG(SSH_LOG_DEBUG, "%s", buffer);
return;
error:
SSH_LOG(SSH_LOG_WARN, "Could not print to buffer");
return;
}
/**
* @brief Check if libssh is the required version or get the version
* string.