From f9211f8ed977f20c4601f00d0cc56724ebdff04a Mon Sep 17 00:00:00 2001 From: Dmitry Rakhchev Date: Thu, 30 Jun 2016 21:25:25 +0300 Subject: [PATCH] Moved ipmi_parse_hex() to helper.c --- include/ipmitool/helper.h | 1 + lib/helper.c | 75 +++++++++++++++++++++++++++++++++++++ lib/ipmi_main.c | 79 +++++++++++++-------------------------- 3 files changed, 102 insertions(+), 53 deletions(-) diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h index 41a3fa5..81b8825 100644 --- a/include/ipmitool/helper.h +++ b/include/ipmitool/helper.h @@ -100,6 +100,7 @@ uint32_t buf2long(uint8_t * buf); #define BUF2STR_MAXIMUM_OUTPUT_SIZE (3*1024 + 1) const char * buf2str_extended(const uint8_t *buf, int len, const char *sep); const char * buf2str(const uint8_t *buf, int len); +int ipmi_parse_hex(const char *str, uint8_t *out, int size); void printbuf(const uint8_t * buf, int len, const char * desc); uint8_t ipmi_csum(uint8_t * d, int s); FILE * ipmi_open_file(const char * file, int rw); diff --git a/lib/helper.c b/lib/helper.c index 04a5e0d..ad5a898 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -51,6 +51,7 @@ #include #include #include +#include #if HAVE_CONFIG_H # include @@ -140,6 +141,80 @@ buf2str(const uint8_t *buf, int len) return buf2str_extended(buf, len, NULL); } +/* ipmi_parse_hex - convert hexadecimal numbers to ascii string + * Input string must be composed of two-characer + * hexadecimal numbers. + * There is no separator between the numbers. Each number + * results in one byte of the converted string. + * + * Example: ipmi_parse_hex("50415353574F5244") + * returns 'PASSWORD' + * + * @param str: input string. It must contain only even number + * of '0'-'9','a'-'f' and 'A-F' characters. + * @param out: pointer to output data + * @param size: size of the output buffer + * @returns 0 for empty input string + * -1 for string with odd length + * -2 if out is NULL + * -3 if there is non-hexadecimal char in string + * >0 length of resulting binary data even if it is > size + */ +int +ipmi_parse_hex(const char *str, uint8_t *out, int size) +{ + const char *p; + uint8_t *q; + uint8_t d = 0; + uint8_t b = 0; + int shift = 4; + int len; + + len = strlen(str); + if (len == 0) { + return 0; + } + + if (len % 2 != 0) { + return -1; + } + + len /= 2; /* out bytes */ + if (out == NULL) { + return -2; + } + + for (p = str, q = out; *p; p++) { + if (!isxdigit(*p)) { + return -3; + } + + if (*p < 'A') { + /* it must be 0-9 */ + d = *p - '0'; + } else { + /* it's A-F or a-f */ + /* convert to lowercase and to 10-15 */ + d = (*p | 0x20) - 'a' + 10; + } + + if (q < (out + size)) { + /* there is space, store */ + b += d << shift; + if (shift) { + shift = 0; + } else { + shift = 4; + *q = b; + b = 0; + q++; + } + } + } + + return len; +} + void printbuf(const uint8_t * buf, int len, const char * desc) { int i; diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c index e6f96f6..d029d0a 100644 --- a/lib/ipmi_main.c +++ b/lib/ipmi_main.c @@ -291,67 +291,40 @@ void ipmi_catch_sigint() exit(-1); } -/* ipmi_parse_hex - convert hexadecimal numbers to ascii string - * Input string must be composed of two-characer hexadecimal numbers. - * There is no separator between the numbers. Each number results in one character - * of the converted string. +/* ipmi_parse_hex_KG - get hexadecimal key value + * Input string must be composed of two-characer + * hexadecimal numbers. + * There is no separator between the numbers. Each number + * results in one byte of the converted string. * - * Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD' + * Example: ipmi_parse_hex("50415353574F5244") + * returns 'PASSWORD' * - * @param str: input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters. - * @returns converted ascii string - * @returns NULL on error + * @param str: input string. It must contain only even number + * of '0'-'9','a'-'f' and 'A-F' characters. + * @returns obtained key or NULL on error */ -static unsigned char * -ipmi_parse_hex(const char *str) +static uint8_t * +ipmi_parse_hex_KG(const char *str) { - const char * p; - unsigned char * out, *q; - unsigned char b = 0; - int shift = 4; + int rc; + uint8_t *out; - if (strlen(str) == 0) - return NULL; + out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(uint8_t)); + rc = ipmi_parse_hex(str, out, IPMI_KG_BUFFER_SIZE - 1); - if (strlen(str) % 2 != 0) { + if (rc == -1) { lprintf(LOG_ERR, "Number of hex_kg characters is not even"); - return NULL; - } - - if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) { - lprintf(LOG_ERR, "Kg key is too long"); - return NULL; - } - - out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char)); - if (out == NULL) { + } else if (rc == -2) { lprintf(LOG_ERR, "malloc failure"); - return NULL; + } else if (rc == -3) { + lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); + } else if (rc > (IPMI_KG_BUFFER_SIZE-1)) { + lprintf(LOG_ERR, "Kg key is too long"); + free(out); + out = NULL; } - - for (p = str, q = out; *p; p++) { - if (!isxdigit(*p)) { - lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); - free(out); - out = NULL; - return NULL; - } - - if (*p < 'A') /* it must be 0-9 */ - b = *p - '0'; - else /* it's A-F or a-f */ - b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */ - - *q = *q + (b << shift); - if (shift) - shift = 0; - else { - shift = 4; - q++; - } - } - - return out; + return (unsigned char *)out; } static uint8_t @@ -577,7 +550,7 @@ ipmi_main(int argc, char ** argv, free(kgkey); kgkey = NULL; } - kgkey = ipmi_parse_hex(optarg); + kgkey = ipmi_parse_hex_KG(optarg); if (kgkey == NULL) { goto out_free; }