diff --git a/ipmitool/doc/ipmitool.1 b/ipmitool/doc/ipmitool.1 index 9481b3d..78c7fd6 100644 --- a/ipmitool/doc/ipmitool.1 +++ b/ipmitool/doc/ipmitool.1 @@ -27,6 +27,7 @@ ipmitool [\fB\-c\fR|\fB\-h\fR|\fB\-v\fR|\fB\-V\fR] [\fB\-O\fR <\fIsel oem\fP>] [\fB\-C\fR <\fIciphersuite\fP>] [\fB\-K\fR|\fB\-k\fR <\fIkg_key\fP>] + [\fB\-y\fR <\fIhex_kg_key\fP>] [\fB\-e\fR <\fIesc_char\fP>] <\fIcommand\fP> .SH "DESCRIPTION" @@ -64,6 +65,13 @@ is to use \fI~\fP but this can conflict with ssh sessions. \fB\-k\fR <\fIkey\fP> Use supplied Kg key for IPMIv2 authentication. The default is not to use any Kg key. +.TP +\fB\-y\fR <\fIhex key\fP> +Use supplied Kg key for IPMIv2 authentication. The key is expected in +hexadecimal format and can be used to specify keys with non-printable +characters. E.g. '-k PASSWORD' and '-y 50415353574F5244' are +equivalent. +The default is not to use any Kg key. .TP \fB\-C\fR <\fIciphersuite\fP> The remote server authentication, integrity, and encryption algorithms diff --git a/ipmitool/lib/ipmi_main.c b/ipmitool/lib/ipmi_main.c index fe0d9ed..f4a4a4f 100644 --- a/ipmitool/lib/ipmi_main.c +++ b/ipmitool/lib/ipmi_main.c @@ -73,7 +73,7 @@ #endif #ifdef ENABLE_ALL_OPTIONS -# define OPTION_STRING "I:hVvcgsEKao:H:d:P:f:U:p:C:L:A:t:T:m:S:l:b:B:e:k:O:" +# define OPTION_STRING "I:hVvcgsEKao:H:d:P:f:U:p:C:L:A:t:T:m:S:l:b:B:e:k:y:O:" #else # define OPTION_STRING "I:hVvcH:f:U:p:d:S:" #endif @@ -230,6 +230,7 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ lprintf(LOG_NOTICE, " -e char Set SOL escape character"); lprintf(LOG_NOTICE, " -C ciphersuite Cipher suite to be used by lanplus interface"); lprintf(LOG_NOTICE, " -k key Use Kg key for IPMIv2 authentication"); + lprintf(LOG_NOTICE, " -y hex_key Use hexadecimal-encoded Kg key for IPMIv2 authentication"); lprintf(LOG_NOTICE, " -L level Remote session privilege level [default=ADMINISTRATOR]"); lprintf(LOG_NOTICE, " Append a '+' to use name/privilege lookup in RAKP1"); lprintf(LOG_NOTICE, " -A authtype Force use of auth type NONE, PASSWORD, MD2, MD5 or OEM"); @@ -253,6 +254,67 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_ ipmi_cmd_print(cmdlist); } +/* 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. + * + * 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 + */ +static unsigned char * +ipmi_parse_hex(const char *str) +{ + const char * p; + unsigned char * out, *q; + unsigned char b = 0; + int shift = 4; + + if (strlen(str) == 0) + return NULL; + + if (strlen(str) % 2 != 0) { + 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) { + lprintf(LOG_ERR, "malloc failure"); + return NULL; + } + + for (p = str, q = out; *p; p++) { + if (!isxdigit(*p)) { + lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); + free(out); + 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; +} /* ipmi_parse_options - helper function to handle parsing command line options * @@ -288,7 +350,7 @@ ipmi_main(int argc, char ** argv, char * progname = NULL; char * oemtype = NULL; char * sdrcache = NULL; - char * kgkey = NULL; + unsigned char * kgkey = NULL; char * seloem = NULL; int port = 0; int devnum = 0; @@ -402,6 +464,12 @@ ipmi_main(int argc, char ** argv, lprintf(LOG_WARN, "Unable to read kgkey from environment"); } break; + case 'y': + kgkey = ipmi_parse_hex(optarg); + if (kgkey == NULL) { + goto out_free; + } + break; case 'U': username = strdup(optarg); if (username == NULL) {