Index: common/src/ipmi-common.c =================================================================== RCS file: /sources/freeipmi/freeipmi/common/src/ipmi-common.c,v retrieving revision 1.13 diff -u -5 -r1.13 ipmi-common.c --- common/src/ipmi-common.c 13 Sep 2006 21:23:56 -0000 1.13 +++ common/src/ipmi-common.c 27 Apr 2007 00:07:56 -0000 @@ -34,12 +34,14 @@ #include #ifdef HAVE_ERROR_H #include #endif #include +#include #include "ipmi-common.h" +#include "freeipmi/ipmi-messaging-support-cmds.h" #define IPMI_DPRINTF_MAX_BUF_LEN 65536 int ipmi_is_root () @@ -101,5 +103,110 @@ while (n--) *p++=c; return s; } + +/* a k_g key should be specified in hexadecimal, or given the prefix + * of s: which will cause it to be interpreted as ascii instead + */ +int +parse_kg(unsigned char *outbuf, int outsz, char *instr) +{ + char *p, *q; + int i, j; + char buf[3] = {0, 0, 0}; + + assert(outbuf != NULL); + assert(instr != NULL); + assert(outsz == IPMI_MAX_K_G_LENGTH); + + if (strlen(instr) == 0) + return 0; + + if (strncmp(instr, "0x", 2) == 0) + { + if (strlen(instr) > IPMI_MAX_K_G_LENGTH*2+2) + return -1; + p = instr + 2; + guaranteed_memset(outbuf, 0, IPMI_MAX_K_G_LENGTH); + for (i = j = 0; i < strlen(p); i+=2, j++) + { + if (p[i+1] == '\0') + return -1; + buf[0] = p[i]; buf[1] = p[i+1]; buf[2] = 0; + q = buf; + errno = 0; + outbuf[j] = strtoul(buf, &q, 16); + if (errno || (q != buf + 2)) + return -1; + } + } + else + { + if (strlen(instr) > IPMI_MAX_K_G_LENGTH) + return -1; + guaranteed_memset(outbuf, 0, IPMI_MAX_K_G_LENGTH); + memcpy(outbuf, instr, strlen(instr)); + } + + return 1; +} + +char * +format_kg(char *outstr, int outsz, unsigned char *k_g) +{ + int i; + int printable = 1; + int foundnull = 0; + char *p; + + assert(outstr != NULL); + assert(k_g != NULL); + + /* Are there any characters that would prevent printing this as a + string on a single line? */ + for (i = 0; i < IPMI_MAX_K_G_LENGTH; i++) + { + if (k_g[i] == 0) + { + ++foundnull; + continue; + } + if (!(isgraph(k_g[i]) || k_g[i] == ' ') || foundnull) + { + printable = 0; + break; + } + } + + if (foundnull == IPMI_MAX_K_G_LENGTH) + printable = 0; + + if (printable) + { + if (outsz < IPMI_MAX_K_G_LENGTH+1) + return NULL; + p = outstr; + for (i = 0; i < IPMI_MAX_K_G_LENGTH; i++) + { + if (k_g[i] == 0) + break; + p[i] = k_g[i]; + } + p[i] = 0; + } + else + { + if (outsz < IPMI_MAX_K_G_LENGTH*2+1) + return NULL; + p = outstr; + p[0] = '0'; p[1] = 'x'; + p+=2; + for (i = 0; i < IPMI_MAX_K_G_LENGTH; i++, p+=2) + { + sprintf(p, "%02x", k_g[i]); + } + } + + return outstr; +} Index: common/src/ipmi-common.h =================================================================== RCS file: /sources/freeipmi/freeipmi/common/src/ipmi-common.h,v retrieving revision 1.9 diff -u -5 -r1.9 ipmi-common.h --- common/src/ipmi-common.h 21 Jul 2006 18:09:05 -0000 1.9 +++ common/src/ipmi-common.h 27 Apr 2007 00:07:56 -0000 @@ -68,6 +68,12 @@ int ipmi_dprintf(int fd, char *fmt, ...); /* From David Wheeler's Secure Programming Guide */ void *guaranteed_memset(void *s, int c, size_t n); +/* Turn an input string into a 20-byte binary k_g key */ +int parse_kg(unsigned char *outbuf, int outsz, char *instr); + +/* Turn a 20-byte binary k_g key into an output string */ +char *format_kg(char *outstr, int outsz, unsigned char *k_g); + #endif Index: ipmipower/src/Makefile.am =================================================================== RCS file: /sources/freeipmi/freeipmi/ipmipower/src/Makefile.am,v retrieving revision 1.12.2.2 diff -u -5 -r1.12.2.2 Makefile.am --- ipmipower/src/Makefile.am 7 Mar 2007 04:11:04 -0000 1.12.2.2 +++ ipmipower/src/Makefile.am 27 Apr 2007 00:07:58 -0000 @@ -21,10 +21,11 @@ wrappers.c ipmipower_LDADD = \ ../../common/src/libcbuf.la \ ../../common/src/libllnlcommon.la \ + ../../common/src/libipmicommon.la \ ../../libfreeipmi/src/libfreeipmi.la ipmipower_CPPFLAGS = \ -I$(srcdir)/../../common/src \ -I$(srcdir)/../../libfreeipmi/include \ @@ -56,9 +57,12 @@ $(MAKE) -C $(dir $@) $(notdir $@) ../../common/src/libllnlcommon.la: force-dependency-check $(MAKE) -C $(dir $@) $(notdir $@) +../../common/src/libipmicommon.la: force-dependency-check + $(MAKE) -C $(dir $@) $(notdir $@) + ../../libfreeipmi/src/libfreeipmi.la: force-dependency-check $(MAKE) -C $(dir $@) $(notdir $@) force-dependency-check: Index: ipmipower/src/ipmipower.h =================================================================== RCS file: /sources/freeipmi/freeipmi/ipmipower/src/ipmipower.h,v retrieving revision 1.65 diff -u -5 -r1.65 ipmipower.h --- ipmipower/src/ipmipower.h 21 Oct 2006 01:36:27 -0000 1.65 +++ ipmipower/src/ipmipower.h 27 Apr 2007 00:07:58 -0000 @@ -550,11 +550,11 @@ { hostlist_t hosts; int hosts_count; char username[IPMI_MAX_USER_NAME_LENGTH+1]; char password[IPMI_2_0_MAX_PASSWORD_LENGTH+1]; - char k_g[IPMI_MAX_K_G_LENGTH+1]; + char k_g[IPMI_MAX_K_G_LENGTH]; power_cmd_t powercmd; char configfile[MAXPATHLEN+1]; authentication_type_t authentication_type; privilege_type_t privilege; @@ -592,10 +592,11 @@ /* Flags indicating if option was set on the command line */ ipmipower_bool_t hosts_set; ipmipower_bool_t username_set; ipmipower_bool_t password_set; ipmipower_bool_t k_g_set; + ipmipower_bool_t k_g_configured; ipmipower_bool_t authentication_type_set; ipmipower_bool_t privilege_set; ipmipower_bool_t ipmi_version_set; ipmipower_bool_t cipher_suite_id_set; ipmipower_bool_t on_if_off_set; Index: ipmipower/src/ipmipower_config.c =================================================================== RCS file: /sources/freeipmi/freeipmi/ipmipower/src/ipmipower_config.c,v retrieving revision 1.44.2.3 diff -u -5 -r1.44.2.3 ipmipower_config.c --- ipmipower/src/ipmipower_config.c 28 Mar 2007 23:24:42 -0000 1.44.2.3 +++ ipmipower/src/ipmipower_config.c 27 Apr 2007 00:07:58 -0000 @@ -51,10 +51,11 @@ #include "ipmipower_privilege.h" #include "ipmipower_util.h" #include "ipmipower_wrappers.h" #include "secure.h" +#include "ipmi-common.h" extern struct ipmipower_config *conf; extern struct ipmipower_connection *ics; void @@ -87,11 +88,11 @@ conf->hosts = NULL; conf->hosts_count = 0; memset(conf->username, '\0', IPMI_MAX_USER_NAME_LENGTH+1); memset(conf->password, '\0', IPMI_2_0_MAX_PASSWORD_LENGTH+1); - memset(conf->k_g, '\0', IPMI_MAX_K_G_LENGTH+1); + memset(conf->k_g, '\0', IPMI_MAX_K_G_LENGTH); conf->powercmd = POWER_CMD_NONE; memset(conf->configfile, '\0', MAXPATHLEN+1); conf->authentication_type = AUTHENTICATION_TYPE_AUTO; conf->privilege = PRIVILEGE_TYPE_AUTO; @@ -265,10 +266,11 @@ { char c; char *ptr; char *pw; char *kg; + int rv; /* achu: Here's are what options are left and available lower case: de upper case: EGJNOQZ */ @@ -380,13 +382,19 @@ err_exit("password too long"); strcpy(conf->password, pw); conf->password_set = IPMIPOWER_TRUE; break; case 'k': /* --k-g */ - if (strlen(optarg) > IPMI_MAX_K_G_LENGTH) - err_exit("Command Line Error: K_g too long"); - strcpy(conf->k_g, optarg); + if (rv = parse_kg(conf->k_g, IPMI_MAX_K_G_LENGTH, optarg) < 0) + { + err_exit("Command Line Error: Invalid K_g"); + } + else + { + if (rv > 0) + conf->k_g_configured = IPMIPOWER_TRUE; + } conf->k_g_set = IPMIPOWER_TRUE; if (optarg) { int n; n = strlen(optarg); @@ -394,13 +402,19 @@ } break; case 'K': /* --k-g-prompt */ if (!(kg = getpass("K_g: "))) err_exit("getpass: %s", strerror(errno)); - if (strlen(kg) > IPMI_MAX_K_G_LENGTH) - err_exit("K_g too long"); - strcpy(conf->k_g, kg); + if (rv = parse_kg(conf->k_g, IPMI_MAX_K_G_LENGTH, kg) < 0) + { + err_exit("K_g invalid"); + } + else + { + if (rv > 0) + conf->k_g_configured = IPMIPOWER_TRUE; + } conf->k_g_set = IPMIPOWER_TRUE; break; case 'n': /* --on */ conf->powercmd = POWER_CMD_POWER_ON; break; @@ -732,17 +746,24 @@ static int _cb_k_g(conffile_t cf, struct conffile_data *data, char *optionname, int option_type, void *option_ptr, int option_data, void *app_ptr, int app_data) { + int rv; + if (conf->k_g_set == IPMIPOWER_TRUE) return 0; - if (strlen(data->string) > IPMI_MAX_K_G_LENGTH) - err_exit("Config File Error: K_g too long"); - - strcpy(conf->k_g, data->string); + if (rv = parse_kg(conf->k_g, IPMI_MAX_K_G_LENGTH, data->string) != 0) + { + err_exit("Config File Error: K_g invalid"); + } + else + { + if (rv > 0) + conf->k_g_configured = IPMIPOWER_TRUE; + } return 0; } void ipmipower_config_conffile_parse(char *configfile) @@ -874,11 +895,11 @@ err_exit("Error: password cannot be set for authentication type \"%s\"", ipmipower_authentication_type_string(conf->authentication_type)); if (conf->ipmi_version != IPMI_VERSION_AUTO && conf->ipmi_version != IPMI_VERSION_2_0 - && strlen(conf->k_g) > 0) + && conf->k_g_configured == IPMIPOWER_TRUE) err_exit("Error: k_g is only used for IPMI 2.0"); if (conf->ipmi_version == IPMI_VERSION_1_5 && strlen(conf->password) >= IPMI_1_5_MAX_PASSWORD_LENGTH) err_exit("Error: password too long"); Index: ipmipower/src/ipmipower_powercmd.c =================================================================== RCS file: /sources/freeipmi/freeipmi/ipmipower/src/ipmipower_powercmd.c,v retrieving revision 1.98.2.1 diff -u -5 -r1.98.2.1 ipmipower_powercmd.c --- ipmipower/src/ipmipower_powercmd.c 20 Apr 2007 05:14:35 -0000 1.98.2.1 +++ ipmipower/src/ipmipower_powercmd.c 27 Apr 2007 00:07:59 -0000 @@ -1179,12 +1179,12 @@ ipmipower_output(MSG_TYPE_PERMISSION, ip->ic->hostname); #endif /* !NDEBUG */ return -1; } - if ((!strlen(conf->k_g) && authentication_status_k_g) - || (strlen(conf->k_g) && !authentication_status_k_g)) + if ((conf->k_g_configured != IPMIPOWER_TRUE && authentication_status_k_g) + || (conf->k_g_configured == IPMIPOWER_TRUE && !authentication_status_k_g)) { #ifndef NDEBUG ipmipower_output(MSG_TYPE_K_G, ip->ic->hostname); #else /* !NDEBUG */ ipmipower_output(MSG_TYPE_PERMISSION, ip->ic->hostname); @@ -1842,11 +1842,11 @@ if (conf->intel_2_0_session && ip->authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5 && password_len > IPMI_1_5_MAX_PASSWORD_LENGTH) password_len = IPMI_1_5_MAX_PASSWORD_LENGTH; - if (strlen(conf->k_g)) + if (conf->k_g_configured == IPMIPOWER_TRUE) k_g = (uint8_t *)conf->k_g; else k_g = NULL; managed_system_random_number_len = Fiid_obj_get_data(ip->obj_rakp_message_2_res, @@ -1858,11 +1858,11 @@ ip->integrity_algorithm, ip->confidentiality_algorithm, password, password_len, k_g, - (k_g) ? strlen((char *)k_g) : 0, + (k_g) ? IPMI_MAX_K_G_LENGTH : 0, ip->remote_console_random_number, IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH, managed_system_random_number, managed_system_random_number_len, ip->name_only_lookup, Index: ipmipower/src/ipmipower_prompt.c =================================================================== RCS file: /sources/freeipmi/freeipmi/ipmipower/src/ipmipower_prompt.c,v retrieving revision 1.38.2.1 diff -u -5 -r1.38.2.1 ipmipower_prompt.c --- ipmipower/src/ipmipower_prompt.c 15 Dec 2006 23:37:11 -0000 1.38.2.1 +++ ipmipower/src/ipmipower_prompt.c 27 Apr 2007 00:07:59 -0000 @@ -54,10 +54,12 @@ #include "ipmipower_powercmd.h" #include "ipmipower_output.h" #include "ipmipower_privilege.h" #include "ipmipower_wrappers.h" +#include "ipmi-common.h" + extern cbuf_t ttyout; extern cbuf_t ttyin; extern cbuf_t ttyerr; extern struct ipmipower_config *conf; extern struct ipmipower_connection *ics; @@ -342,32 +344,41 @@ } static void _cmd_k_g(char **argv) { + int rv = 0; + char buf[IPMI_MAX_K_G_LENGTH*2+1]; assert(argv != NULL); if (conf->ipmi_version != IPMI_VERSION_AUTO && conf->ipmi_version != IPMI_VERSION_2_0) cbuf_printf(ttyout, "k_g is only used for IPMI 2.0"); - else if (argv[1] == NULL - || (argv[1] && strlen(argv[1]) <= IPMI_MAX_K_G_LENGTH)) + else { - memset(conf->k_g, '\0', IPMI_MAX_K_G_LENGTH+1); + memset(conf->k_g, '\0', IPMI_MAX_K_G_LENGTH); if (argv[1]) - strcpy(conf->k_g, argv[1]); - + rv = parse_kg(conf->k_g, IPMI_MAX_K_G_LENGTH, argv[1]); + + if (rv < 0) + cbuf_printf(ttyout, "k_g invalid\n"); + else + { + if (rv == 0) + conf->k_g_configured = IPMIPOWER_FALSE; + else + conf->k_g_configured = IPMIPOWER_TRUE; #ifdef NDEBUG - cbuf_printf(ttyout, "k_g changed\n"); + cbuf_printf(ttyout, "k_g changed\n"); #else /* !NDEBUG */ - cbuf_printf(ttyout, "k_g: %s\n", - (strlen(conf->k_g)) ? conf->k_g : "NULL"); + cbuf_printf(ttyout, "k_g: %s\n", + (conf->k_g_configured == IPMIPOWER_TRUE) ? + format_kg(buf, IPMI_MAX_K_G_LENGTH*2+1, conf->k_g) : "NULL"); #endif /* !NDEBUG */ + } } - else - cbuf_printf(ttyout, "k_g invalid length\n"); } static void _cmd_authentication_type(char **argv) { @@ -568,10 +579,12 @@ #endif /* NDEBUG */ static void _cmd_config(void) { + char buf[IPMI_MAX_K_G_LENGTH*2+1]; + if (conf->hosts != NULL) { int rv; char buffer[IPMIPOWER_HOSTLIST_BUFLEN]; #ifndef NDEBUG @@ -647,11 +660,12 @@ #ifndef NDEBUG cbuf_printf(ttyout, "Password: %s\n", (strlen(conf->password)) ? conf->password : "NULL"); cbuf_printf(ttyout, "K_g: %s\n", - (strlen(conf->k_g)) ? conf->k_g : "NULL"); + (conf->k_g_configured == IPMIPOWER_TRUE) ? + format_kg(buf, IPMI_MAX_K_G_LENGTH*2+2, conf->k_g) : "NULL"); #else /* !NDEBUG */ cbuf_printf(ttyout, "Password: *****\n"); cbuf_printf(ttyout, "K_g: *****\n"); #endif /* !NDEBUG */