diff --git a/ipmitool/lib/ipmi_lanp.c b/ipmitool/lib/ipmi_lanp.c index 69df74b..0f25eab 100644 --- a/ipmitool/lib/ipmi_lanp.c +++ b/ipmitool/lib/ipmi_lanp.c @@ -930,6 +930,85 @@ get_cmdline_macaddr(char * arg, uint8_t * buf) return 0; } + +static int +get_cmdline_cipher_suite_priv_data(char * arg, uint8_t * buf) +{ + int i, ret = 0; + + if (strlen(arg) != 15) + { + lprintf(LOG_ERR, "Invalid privilege specification length: %d", + strlen(arg)); + return -1; + } + + /* + * The first byte is reservered (0). The resst of the buffer is setup + * so that each nibble holds the maximum privilege level available for + * that cipher suite number. The number of nibbles (15) matches the number + * of fixed cipher suite IDs. This command documentation mentions 16 IDs + * but table 22-19 shows that there are only 15 (0-14). + * + * data 1 - reserved + * data 2 - maximum priv level for first (LSN) and second (MSN) ciphers + * data 3 - maximum priv level for third (LSN) and fourth (MSN) ciphers + * data 9 - maximum priv level for 15th (LSN) cipher. + */ + bzero(buf, 9); + + for (i = 0; i < 15; ++i) + { + unsigned char priv_level; + + switch (arg[i]) + { + case 'X': + priv_level = IPMI_SESSION_PRIV_UNSPECIFIED; /* 0 */ + break; + case 'c': + priv_level = IPMI_SESSION_PRIV_CALLBACK; /* 1 */ + break; + case 'u': + priv_level = IPMI_SESSION_PRIV_USER; /* 2 */ + break; + case 'o': + priv_level = IPMI_SESSION_PRIV_OPERATOR; /* 3 */ + break; + case 'a': + priv_level = IPMI_SESSION_PRIV_ADMIN; /* 4 */ + break; + case 'O': + priv_level = IPMI_SESSION_PRIV_OEM; /* 5 */ + break; + default: + lprintf(LOG_ERR, "Invalid privilege specification char: %c", + arg[i]); + ret = -1; + break; + } + + if (ret != 0) + break; + else + { + if ((i + 1) % 2) + { + // Odd number cipher suites will be in the LSN + buf[1 + (i / 2)] += priv_level; + } + else + { + // Even number cipher suites will be in the MSN + buf[1 + (i / 2)] += (priv_level << 4); + } + } + } + + return ret; +} + + static int get_cmdline_ipaddr(char * arg, uint8_t * buf) { @@ -969,7 +1048,14 @@ static void ipmi_lan_set_usage(void) lprintf(LOG_NOTICE, " none = unspecified source"); lprintf(LOG_NOTICE, " static = address manually configured to be static"); lprintf(LOG_NOTICE, " dhcp = address obtained by BMC running DHCP"); - lprintf(LOG_NOTICE, " bios = address loaded by BIOS or system software\n"); + lprintf(LOG_NOTICE, " bios = address loaded by BIOS or system software"); + lprintf(LOG_NOTICE, " cipher_privs XXXXXXXXXXXXXXX Set RMCP+ cipher suite privilege levels"); + lprintf(LOG_NOTICE, " X = Cipher Suite Unused"); + lprintf(LOG_NOTICE, " c = CALLBACK"); + lprintf(LOG_NOTICE, " u = USER"); + lprintf(LOG_NOTICE, " o = OPERATOR"); + lprintf(LOG_NOTICE, " a = ADMIN"); + lprintf(LOG_NOTICE, " O = OEM\n"); } static int @@ -1188,9 +1274,31 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) } } + /* RMCP+ cipher suite privilege levels */ + else if (strncmp(argv[1], "cipher_privs", 12) == 0) + { + if ((argc != 3) || + (strncmp(argv[2], "help", 4) == 0) || + get_cmdline_cipher_suite_priv_data(argv[2], data)) + { + lprintf(LOG_NOTICE, "lan set cipher_privs XXXXXXXXXXXXXXX"); + lprintf(LOG_NOTICE, " X = Cipher Suite Unused"); + lprintf(LOG_NOTICE, " c = CALLBACK"); + lprintf(LOG_NOTICE, " u = USER"); + lprintf(LOG_NOTICE, " o = OPERATOR"); + lprintf(LOG_NOTICE, " a = ADMIN"); + lprintf(LOG_NOTICE, " O = OEM\n"); + } + else + { + rc = set_lan_param(intf, chan, IPMI_LANP_RMCP_PRIV_LEVELS, data, 9); + } + } + return rc; } + int ipmi_lanp_main(struct ipmi_intf * intf, int argc, char ** argv) {