Compare commits

...

No commits in common. "c10s" and "c8" have entirely different histories.
c10s ... c8

33 changed files with 3193 additions and 246450 deletions

15
.gitignore vendored
View File

@ -1,14 +1 @@
ipmitool-1.8.11.tar.bz2
/ipmitool-1.8.12.tar.bz2
/exchange-bmc-os-info
/exchange-bmc-os-info.service
/exchange-bmc-os-info.sysconf
/set-bmc-url.sh
/ipmitool-1.8.12-130731.tar.bz2
/ipmitool-1.8.13.tar.bz2
/ipmitool-1.8.15.tar.bz2
/ipmitool-1.8.16.tar.bz2
/ipmitool-1.8.17.tar.bz2
/ipmitool-1.8.18.tar.bz2
/ipmitool-1.8.18.tar.gz
/ipmitool-1.8.19.tar.gz
SOURCES/ipmitool-1.8.18.tar.bz2

View File

@ -1,12 +0,0 @@
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/ipmi_sdr.h ipmitool-IPMITOOL_1_8_19/include/ipmitool/ipmi_sdr.h
--- ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/ipmi_sdr.h 2022-09-01 11:42:31.000000000 -0700
+++ ipmitool-IPMITOOL_1_8_19/include/ipmitool/ipmi_sdr.h 2022-12-20 14:12:47.675994549 -0800
@@ -799,7 +799,7 @@
#define SENSOR_TYPE_MAX 0x2C
struct sensor_reading {
- char s_id[17]; /* name of the sensor */
+ char s_id[33]; /* name of the sensor */
struct sdr_record_full_sensor *full;
struct sdr_record_compact_sensor *compact;
uint8_t s_reading_valid; /* read value valididity */

View File

@ -1,22 +0,0 @@
Description: fix buffer overflow
based on 101_fix_buf_overflow from Leo Iannacone <l3on@ubuntu.com>
Author: Jörg Frings-Fürst <debian@jff-webhosting.net>
Bug: TSOL buffer overflow
Bug-ubuntu: https://bugs.launchpad.net/ubuntu/+source/ipmitool/+bug/633054
Forwarded: https://sourceforge.net/p/ipmitool/patches/100/
Last-Update: 2014-12-01
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: trunk/lib/ipmi_tsol.c
===================================================================
--- trunk.orig/lib/ipmi_tsol.c
+++ trunk/lib/ipmi_tsol.c
@@ -374,7 +374,7 @@ ipmi_tsol_main(struct ipmi_intf *intf, i
char *recvip = NULL;
char in_buff[IPMI_BUF_SIZE];
char out_buff[IPMI_BUF_SIZE * 8];
- char buff[IPMI_BUF_SIZE + 4];
+ char buff[IPMI_BUF_SIZE * 8 + 4];
int fd_socket, result, i;
size_t out_buff_fill, in_buff_fill;
int ip1, ip2, ip3, ip4;

View File

@ -1,35 +0,0 @@
Description: Fix soensor reading
Author: mareedu srinivasa rao
Origin: upstream, https://sourceforge.net/p/ipmitool/bugs/490/
Bug: https://sourceforge.net/p/ipmitool/bugs/490/
Bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=983082
Forwarded: not-needed
Last-Update: 2022-10-29
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: trunk/lib/ipmi_sdr.c
===================================================================
--- trunk.orig/lib/ipmi_sdr.c
+++ trunk/lib/ipmi_sdr.c
@@ -1799,7 +1799,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_int
sr->s_a_units);
} else /* Discrete */
snprintf(sval, sizeof(sval),
- "0x%02x", sr->s_reading);
+ "0x%02x", sr->s_data2);
}
else if (sr->s_scanning_disabled)
snprintf(sval, sizeof (sval), sr->full ? "disabled" : "Not Readable");
Index: trunk/lib/ipmi_sensor.c
===================================================================
--- trunk.orig/lib/ipmi_sensor.c
+++ trunk/lib/ipmi_sensor.c
@@ -201,7 +201,7 @@ ipmi_sensor_print_fc_discrete(struct ipm
sr->s_a_str, sr->s_a_units, "ok");
} else {
printf("| 0x%-8x | %-10s | 0x%02x%02x",
- sr->s_reading, "discrete",
+ sr->s_data2, "discrete",
sr->s_data2, sr->s_data3);
}
} else {

View File

@ -0,0 +1,25 @@
From 152efd46931a70ab4e3d81e99d312df7dcd666e6 Mon Sep 17 00:00:00 2001
From: Boris Ranto <branto@redhat.com>
Date: Tue, 10 May 2016 19:12:08 +0200
Subject: [PATCH] CVE-2011-4339 OpenIPMI
IPMI event daemon creates PID file with world writeable permissions
---
lib/helper.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/helper.c b/lib/helper.c
index de91438..c3a1c80 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -829,7 +829,6 @@ ipmi_start_daemon(struct ipmi_intf *intf)
#endif
chdir("/");
- umask(0);
for (fd=0; fd<64; fd++) {
if (fd != intf->fd)
--
2.7.4

View File

@ -0,0 +1,89 @@
diff -urNp old/src/plugins/lanplus/lanplus_crypt_impl.c new/src/plugins/lanplus/lanplus_crypt_impl.c
--- old/src/plugins/lanplus/lanplus_crypt_impl.c 2016-05-28 10:20:20.000000000 +0200
+++ new/src/plugins/lanplus/lanplus_crypt_impl.c 2017-02-21 10:50:21.634873466 +0100
@@ -164,10 +164,10 @@ lanplus_encrypt_aes_cbc_128(const uint8_
uint8_t * output,
uint32_t * bytes_written)
{
- EVP_CIPHER_CTX ctx;
- EVP_CIPHER_CTX_init(&ctx);
- EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
*bytes_written = 0;
@@ -191,7 +191,7 @@ lanplus_encrypt_aes_cbc_128(const uint8_
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
- if(!EVP_EncryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
+ if(!EVP_EncryptUpdate(ctx, output, (int *)bytes_written, input, input_length))
{
/* Error */
*bytes_written = 0;
@@ -201,7 +201,7 @@ lanplus_encrypt_aes_cbc_128(const uint8_
{
uint32_t tmplen;
- if(!EVP_EncryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
+ if(!EVP_EncryptFinal_ex(ctx, output + *bytes_written, (int *)&tmplen))
{
*bytes_written = 0;
return; /* Error */
@@ -210,7 +210,8 @@ lanplus_encrypt_aes_cbc_128(const uint8_
{
/* Success */
*bytes_written += tmplen;
- EVP_CIPHER_CTX_cleanup(&ctx);
+ EVP_CIPHER_CTX_cleanup(ctx);
+ EVP_CIPHER_CTX_free(ctx);
}
}
}
@@ -239,10 +240,10 @@ lanplus_decrypt_aes_cbc_128(const uint8_
uint8_t * output,
uint32_t * bytes_written)
{
- EVP_CIPHER_CTX ctx;
- EVP_CIPHER_CTX_init(&ctx);
- EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
if (verbose >= 5)
@@ -266,7 +267,7 @@ lanplus_decrypt_aes_cbc_128(const uint8_
assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
- if (!EVP_DecryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
+ if (!EVP_DecryptUpdate(ctx, output, (int *)bytes_written, input, input_length))
{
/* Error */
lprintf(LOG_DEBUG, "ERROR: decrypt update failed");
@@ -277,7 +278,7 @@ lanplus_decrypt_aes_cbc_128(const uint8_
{
uint32_t tmplen;
- if (!EVP_DecryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
+ if (!EVP_DecryptFinal_ex(ctx, output + *bytes_written, (int *)&tmplen))
{
char buffer[1000];
ERR_error_string(ERR_get_error(), buffer);
@@ -290,7 +291,8 @@ lanplus_decrypt_aes_cbc_128(const uint8_
{
/* Success */
*bytes_written += tmplen;
- EVP_CIPHER_CTX_cleanup(&ctx);
+ EVP_CIPHER_CTX_cleanup(ctx);
+ EVP_CIPHER_CTX_free(ctx);
}
}

View File

@ -0,0 +1,240 @@
diff -urNp old/doc/ipmitool.1 new/doc/ipmitool.1
--- old/doc/ipmitool.1 2017-02-06 10:20:02.254362909 +0100
+++ new/doc/ipmitool.1 2017-02-06 10:33:41.729294474 +0100
@@ -372,6 +372,20 @@ Configure user access information on the
Displays the list of cipher suites supported for the given
application (ipmi or sol) on the given channel.
+.TP
+\fIsetkg\fP <\fIhex\fP|\fIplain\fP> <\fBkey\fP> [<\fBchannel\fR>]
+.br
+
+Sets K_g key to given value. Use \fIplain\fP to specify \fBkey\fR as simple ASCII string.
+Use \fIhex\fP to specify \fBkey\fR as sequence of hexadecimal codes of ASCII charactes.
+I.e. following two examples are equivalent:
+
+.RS
+ipmitool channel setkg plain PASSWORD
+
+ipmitool channel setkg hex 50415353574F5244
+.RE
+
.RE
.RE
.TP
diff -urNp old/include/ipmitool/helper.h new/include/ipmitool/helper.h
--- old/include/ipmitool/helper.h 2017-02-06 10:20:02.254362909 +0100
+++ new/include/ipmitool/helper.h 2017-02-06 10:40:07.336136844 +0100
@@ -58,6 +58,8 @@
# define IPMI_UID_MAX 63
#endif
+#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
+
struct ipmi_intf;
struct valstr {
diff -urNp old/include/ipmitool/ipmi_channel.h new/include/ipmitool/ipmi_channel.h
--- old/include/ipmitool/ipmi_channel.h 2017-02-06 10:20:02.253316684 +0100
+++ new/include/ipmitool/ipmi_channel.h 2017-02-06 10:58:15.291287621 +0100
@@ -49,6 +49,10 @@
#define IPMI_GET_USER_NAME 0x46
#define IPMI_SET_USER_PASSWORD 0x47
#define IPMI_GET_CHANNEL_CIPHER_SUITES 0x54
+#define IPMI_SET_CHANNEL_SECURITY_KEYS 0x56
+
+#define IPMI_KG_KEY_ID 1
+#define IPMI_SET_CHANNEL_SECURITY_KEYS_OP_SET 1
/* These are for channel_info_t.session_support */
#define IPMI_CHANNEL_SESSION_LESS 0x00
@@ -137,6 +141,40 @@ int _ipmi_set_channel_access(struct ipmi
struct channel_access_t channel_access, uint8_t access_option,
uint8_t privilege_option);
+struct set_channel_security_keys_req {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 :4;
+ uint8_t channel :4;
+
+ uint8_t __reserved2 :6;
+ uint8_t operation :2;
+
+ uint8_t key_id;
+ unsigned char key_value[IPMI_KG_BUFFER_SIZE-1]; /* we don't want space for '\0' at the end */
+#else
+ uint8_t channel :4;
+ uint8_t __reserved1 :4;
+
+ uint8_t operation :2;
+ uint8_t __reserved2 :6;
+
+ uint8_t key_id;
+ unsigned char key_value[IPMI_KG_BUFFER_SIZE-1]; /* we don't want space for '\0' at the end */
+#endif
+} __attribute__ ((packed));
+
+struct set_channel_security_keys_rsp {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 :6;
+ uint8_t lock_status :2;
+ unsigned char key_value; /* just the first character, use &key_value to explore the rest */
+#else
+ uint8_t lock_status :2;
+ uint8_t __reserved1 :6;
+ unsigned char key_value; /* just the first character, use &key_value to explore the rest */
+#endif
+} __attribute__ ((packed));
+
uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
uint8_t ipmi_current_channel_medium(struct ipmi_intf * intf);
int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv);
diff -urNp old/include/ipmitool/ipmi_intf.h new/include/ipmitool/ipmi_intf.h
--- old/include/ipmitool/ipmi_intf.h 2017-02-06 10:20:02.254362909 +0100
+++ new/include/ipmitool/ipmi_intf.h 2017-02-06 10:40:40.264577602 +0100
@@ -60,7 +60,6 @@ enum LANPLUS_SESSION_STATE {
#define IPMI_AUTHCODE_BUFFER_SIZE 20
#define IPMI_SIK_BUFFER_SIZE IPMI_MAX_MD_SIZE
-#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
struct ipmi_session_params {
char * hostname;
diff -urNp old/lib/ipmi_channel.c new/lib/ipmi_channel.c
--- old/lib/ipmi_channel.c 2017-02-06 10:20:02.255409134 +0100
+++ new/lib/ipmi_channel.c 2017-02-06 12:32:14.222282317 +0100
@@ -821,6 +821,92 @@ ipmi_set_user_access(struct ipmi_intf *i
return 0;
}
+int
+ipmi_set_channel_security_keys (struct ipmi_intf *intf, uint8_t channel, const char *method, const char *key)
+{
+ uint8_t kgkey[IPMI_KG_BUFFER_SIZE];
+ struct ipmi_rs *rsp;
+ struct ipmi_rq req;
+ struct set_channel_security_keys_req req_data;
+ int rc = -1;
+
+ /* convert provided key to array of bytes */
+ if (strcmp(method, "hex") == 0) {
+ if (strlen(key) > (IPMI_KG_BUFFER_SIZE-1)*2) {
+ lprintf(LOG_ERR, "Provided key is too long, max. length is %d bytes", (IPMI_KG_BUFFER_SIZE-1));
+ printf_channel_usage();
+ return -1;
+ }
+
+ rc = ipmi_parse_hex(key, kgkey, sizeof(kgkey)-1);
+ if (rc == -1) {
+ lprintf(LOG_ERR, "Number of Kg key characters is not even");
+ return rc;
+ } else if (rc == -3) {
+ lprintf(LOG_ERR, "Kg key is not hexadecimal number");
+ return rc;
+ } else if (rc > (IPMI_KG_BUFFER_SIZE-1)) {
+ lprintf(LOG_ERR, "Kg key is too long");
+ return rc;
+ }
+
+ } else if (strcmp(method, "plain") == 0) {
+ if (strlen(key) > IPMI_KG_BUFFER_SIZE-1) {
+ lprintf(LOG_ERR, "Provided key is too long, max. length is %d bytes", (IPMI_KG_BUFFER_SIZE -1));
+ printf_channel_usage();
+ return rc;
+ }
+
+ strncpy(kgkey, key, IPMI_KG_BUFFER_SIZE-1);
+ } else {
+ printf_channel_usage();
+ return rc;
+ }
+
+ /* assemble and send request to set kg key */
+ memset(&req_data, 0, sizeof(req_data));
+ req_data.channel = channel;
+ req_data.operation = IPMI_SET_CHANNEL_SECURITY_KEYS_OP_SET;
+ req_data.key_id = IPMI_KG_KEY_ID;
+ memcpy(req_data.key_value, kgkey, IPMI_KG_BUFFER_SIZE-1);
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = IPMI_SET_CHANNEL_SECURITY_KEYS;
+ req.msg.data = (uint8_t*) &req_data;
+ req.msg.data_len = sizeof(req_data);
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Set Channel Security Keys command failed");
+ return rc;
+ }
+ if (rsp->ccode > 0) {
+ const char *error = NULL;
+ switch (rsp->ccode) {
+ case 0x80:
+ error = "Key is locked";
+ break;
+ case 0x81:
+ error = "Insufficient key bytes";
+ break;
+ case 0x82:
+ error = "Too many key bytes";
+ break;
+ case 0x83:
+ error = "Key value does not meet criteria for K_g key";
+ break;
+ default:
+ error = val2str(rsp->ccode, completion_code_vals);
+ }
+ lprintf(LOG_ERR, "Error setting security key: %X (%s)", rsp->ccode, error);
+ return rc;
+ }
+
+ lprintf(LOG_NOTICE, "Set Channel Security Keys command succeeded");
+ return 0;
+}
+
int
ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv)
{
@@ -890,6 +976,19 @@ ipmi_channel_main(struct ipmi_intf *intf
retval = ipmi_get_channel_cipher_suites(intf,
argv[1], /* ipmi | sol */
channel);
+ } else if (strncmp(argv[0], "setkg", 5) == 0) {
+ if (argc < 3 || argc > 4)
+ printf_channel_usage();
+ else {
+ uint8_t ch = 0xe;
+ char *method = argv[1];
+ char *key = argv[2];
+ if (argc == 4) {
+ ch = (uint8_t)strtol(argv[3], NULL, 0);
+ }
+
+ retval = ipmi_set_channel_security_keys(intf, ch, method, key);
+ }
} else {
lprintf(LOG_ERR, "Invalid CHANNEL command: %s\n", argv[0]);
printf_channel_usage();
@@ -916,6 +1015,10 @@ printf_channel_usage()
lprintf(LOG_NOTICE,
"");
lprintf(LOG_NOTICE,
+" setkg hex|plain <key> [channel]");
+ lprintf(LOG_NOTICE,
+"");
+ lprintf(LOG_NOTICE,
"Possible privilege levels are:");
lprintf(LOG_NOTICE,
" 1 Callback level");
diff -urNp old/src/plugins/ipmi_intf.c new/src/plugins/ipmi_intf.c
--- old/src/plugins/ipmi_intf.c 2017-02-06 10:20:02.257501584 +0100
+++ new/src/plugins/ipmi_intf.c 2017-02-06 10:42:12.585257810 +0100
@@ -55,6 +55,7 @@
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/log.h>
+#include <ipmitool/helper.h>
#define IPMI_DEFAULT_PAYLOAD_SIZE 25

View File

@ -0,0 +1,16 @@
diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h
index ccf0cf0..47d3949 100644
--- a/include/ipmitool/ipmi_sdr.h
+++ b/include/ipmitool/ipmi_sdr.h
@@ -819,7 +819,7 @@ static const char *sensor_type_desc[] __attribute__ ((unused)) = {
"Version Change", "FRU State" };
struct sensor_reading {
- char s_id[17]; /* name of the sensor */
+ char s_id[33]; /* name of the sensor */
struct sdr_record_full_sensor *full;
struct sdr_record_compact_sensor *compact;
uint8_t s_reading_valid; /* read value valididity */
--
2.1.0

View File

@ -0,0 +1,21 @@
diff -urNp old/configure.ac new/configure.ac
--- old/configure.ac 2017-02-02 14:20:33.230784269 +0100
+++ new/configure.ac 2017-02-02 14:22:53.528510336 +0100
@@ -63,7 +63,7 @@ xenable_intf_imb=yes
xenable_intf_lipmi=yes
xenable_intf_open=yes
#xenable_intf_serial=yes
-xenable_intf_usb=no
+xenable_intf_usb=yes
xenable_ipmishell=yes
dnl set some things so we build with GNU tools on Solaris
@@ -209,7 +209,7 @@ fi
dnl enable IPMI USB interface
AC_ARG_ENABLE([intf-usb],
[AC_HELP_STRING([--enable-intf-usb],
- [enable IPMI USB interface [default=auto]])],
+ [enable IPMI USB interface [default=yes]])],
[xenable_intf_usb=$enableval],
[xenable_intf_usb=$xenable_intf_usb])
if test "x$xenable_intf_usb" = "xstatic" || test "x$xenable_intf_usb" = "xplugin"; then

View File

@ -1,6 +1,6 @@
diff -urNp old/doc/ipmitool.1.in new/doc/ipmitool.1.in
--- old/doc/ipmitool.1.in 2017-10-03 16:10:50.446539988 +0200
+++ new/doc/ipmitool.1.in 2017-10-03 16:16:37.039673239 +0200
diff -urNp old/doc/ipmitool.1 new/doc/ipmitool.1
--- old/doc/ipmitool.1 2017-10-03 16:10:50.446539988 +0200
+++ new/doc/ipmitool.1 2017-10-03 16:16:37.039673239 +0200
@@ -3170,13 +3170,14 @@ SOL configuration data for the currently
Enable, disable or show status of SOL payload for the user on the specified channel.

View File

@ -0,0 +1,864 @@
From 260293c0ee5a268bc7fc1483e5304546745122a6 Mon Sep 17 00:00:00 2001
From: Vernon Mauery <vernon.mauery@intel.com>
Date: Mon, 9 Apr 2018 12:28:57 -0700
Subject: [PATCH] lanplus: Auto-select 'best' cipher suite available
Current cipher suites could be ranked as this:
17 > 3 >> all the rest
Cherry-picked-from: 7772254b62826b894ca629df8c597030a98f4f72
Cherry-picked-from: f9c699c712f884c82fc1a62f1f61a8d597ac0cfd
Also fetched some functions/macros for helper.h
Equals to getting include/ipmitool/helper.h changes from commits:
(oldest first)
6c00d44 mc: watchdog get: Update to match IPMI 2.0 spec
e8e94d8 mc: watchdog set: Refactor to reduce complexity
0310208 mc: Code refactor to reduce copy-paste ratio
249e092 general: Make byteswapping arch-independent
5491b12 refix 249e0929: Fix byteswapping helpers
bb1a4cc Refactoring. Improve code reuse ratio.
---
include/ipmitool/helper.h | 58 ++++++++
include/ipmitool/ipmi_channel.h | 47 +++++++
include/ipmitool/ipmi_intf.h | 39 ++++-
lib/ipmi_channel.c | 242 +++++++++++++++-----------------
lib/ipmi_main.c | 23 +--
src/plugins/ipmi_intf.c | 5 +-
src/plugins/lanplus/lanplus.c | 114 +++++++++++----
7 files changed, 360 insertions(+), 168 deletions(-)
diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h
index c53736f..6a2e5f4 100644
--- a/include/ipmitool/helper.h
+++ b/include/ipmitool/helper.h
@@ -38,6 +38,8 @@
#include <stdio.h>
#include <string.h>
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
#ifndef TRUE
#define TRUE 1
#endif
@@ -111,6 +113,62 @@ FILE * ipmi_open_file(const char * file, int rw);
void ipmi_start_daemon(struct ipmi_intf *intf);
uint16_t ipmi_get_oem_id(struct ipmi_intf *intf);
+#define IS_SET(v, b) ((v) & (1 << (b)))
+
+/* le16toh(), hto16le(), et. al. don't exist for Windows or Apple */
+/* For portability, let's simply define our own versions here */
+
+/* IPMI is always little-endian */
+static inline uint16_t ipmi16toh(void *ipmi16)
+{
+ uint8_t *ipmi = (uint8_t *)ipmi16;
+ uint16_t h;
+
+ h = ipmi[1] << 8; /* MSB */
+ h |= ipmi[0]; /* LSB */
+
+ return h;
+}
+
+static inline void htoipmi16(uint16_t h, uint8_t *ipmi)
+{
+ ipmi[0] = h & 0xFF; /* LSB */
+ ipmi[1] = h >> 8; /* MSB */
+}
+
+static inline uint32_t ipmi24toh(void *ipmi24)
+{
+ uint8_t *ipmi = (uint8_t *)ipmi24;
+ uint32_t h = 0;
+
+ h = ipmi[2] << 16; /* MSB */
+ h |= ipmi[1] << 8;
+ h |= ipmi[0]; /* LSB */
+
+ return h;
+}
+
+static inline uint32_t ipmi32toh(void *ipmi32)
+{
+ uint8_t *ipmi = ipmi32;
+ uint32_t h;
+
+ h = ipmi[3] << 24; /* MSB */
+ h |= ipmi[2] << 16;
+ h |= ipmi[1] << 8;
+ h |= ipmi[0]; /* LSB */
+
+ return h;
+}
+
+static inline void htoipmi32(uint32_t h, uint8_t *ipmi)
+{
+ ipmi[0] = h & 0xFF; /* LSB */
+ ipmi[1] = (h >> 8) & 0xFF;
+ ipmi[2] = (h >> 16) & 0xFF;
+ ipmi[3] = (h >> 24) & 0xFF; /* MSB */
+}
+
#define ipmi_open_file_read(file) ipmi_open_file(file, 0)
#define ipmi_open_file_write(file) ipmi_open_file(file, 1)
diff --git a/include/ipmitool/ipmi_channel.h b/include/ipmitool/ipmi_channel.h
index 3ade2d5..324c0bb 100644
--- a/include/ipmitool/ipmi_channel.h
+++ b/include/ipmitool/ipmi_channel.h
@@ -37,6 +37,7 @@
# include <config.h>
#endif
#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
@@ -81,6 +82,50 @@ struct channel_access_t {
uint8_t user_level_auth;
};
+/*
+ * The Cipher Suite Record Format from table 22-18 of the IPMI v2.0 spec
+ */
+enum cipher_suite_format_tag {
+ STANDARD_CIPHER_SUITE = 0xc0,
+ OEM_CIPHER_SUITE = 0xc1,
+};
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct std_cipher_suite_record_t {
+ uint8_t start_of_record;
+ uint8_t cipher_suite_id;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+} ATTRIBUTE_PACKING;
+struct oem_cipher_suite_record_t {
+ uint8_t start_of_record;
+ uint8_t cipher_suite_id;
+ uint8_t iana[3];
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+#define CIPHER_ALG_MASK 0x3f
+#define MAX_CIPHER_SUITE_RECORD_OFFSET 0x40
+#define MAX_CIPHER_SUITE_DATA_LEN 0x10
+#define LIST_ALGORITHMS_BY_CIPHER_SUITE 0x80
+
+/* Below is the theoretical maximum number of cipher suites that could be
+ * reported by a BMC. That is with the Get Channel Cipher Suites Command, at 16
+ * bytes at a time and 0x40 requests, it can report 1024 bytes, which is about
+ * 204 standard records or 128 OEM records. Really, we probably don't need more
+ * than about 20, which is the full set of standard records plus a few OEM
+ * records.
+ */
+#define MAX_CIPHER_SUITE_COUNT (MAX_CIPHER_SUITE_RECORD_OFFSET * \
+ MAX_CIPHER_SUITE_DATA_LEN / \
+ sizeof(struct std_cipher_suite_record_t))
+
/*
* The Get Authentication Capabilities response structure
* From table 22-15 of the IPMI v2.0 spec
@@ -135,6 +180,8 @@ struct get_channel_auth_cap_rsp {
int _ipmi_get_channel_access(struct ipmi_intf *intf,
struct channel_access_t *channel_access,
uint8_t get_volatile_settings);
+int ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
+ uint8_t channel, struct cipher_suite_info *suites, size_t *count);
int _ipmi_get_channel_info(struct ipmi_intf *intf,
struct channel_info_t *channel_info);
int _ipmi_set_channel_access(struct ipmi_intf *intf,
diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h
index 0b8c64b..7a07d66 100644
--- a/include/ipmitool/ipmi_intf.h
+++ b/include/ipmitool/ipmi_intf.h
@@ -61,13 +61,45 @@ enum LANPLUS_SESSION_STATE {
#define IPMI_AUTHCODE_BUFFER_SIZE 20
#define IPMI_SIK_BUFFER_SIZE IPMI_MAX_MD_SIZE
+enum cipher_suite_ids {
+ IPMI_LANPLUS_CIPHER_SUITE_0 = 0,
+ IPMI_LANPLUS_CIPHER_SUITE_1 = 1,
+ IPMI_LANPLUS_CIPHER_SUITE_2 = 2,
+ IPMI_LANPLUS_CIPHER_SUITE_3 = 3,
+ IPMI_LANPLUS_CIPHER_SUITE_4 = 4,
+ IPMI_LANPLUS_CIPHER_SUITE_5 = 5,
+ IPMI_LANPLUS_CIPHER_SUITE_6 = 6,
+ IPMI_LANPLUS_CIPHER_SUITE_7 = 7,
+ IPMI_LANPLUS_CIPHER_SUITE_8 = 8,
+ IPMI_LANPLUS_CIPHER_SUITE_9 = 9,
+ IPMI_LANPLUS_CIPHER_SUITE_10 = 10,
+ IPMI_LANPLUS_CIPHER_SUITE_11 = 11,
+ IPMI_LANPLUS_CIPHER_SUITE_12 = 12,
+ IPMI_LANPLUS_CIPHER_SUITE_13 = 13,
+ IPMI_LANPLUS_CIPHER_SUITE_14 = 14,
+#ifdef HAVE_CRYPTO_SHA256
+ IPMI_LANPLUS_CIPHER_SUITE_15 = 15,
+ IPMI_LANPLUS_CIPHER_SUITE_16 = 16,
+ IPMI_LANPLUS_CIPHER_SUITE_17 = 17,
+#endif /* HAVE_CRYPTO_SHA256 */
+ IPMI_LANPLUS_CIPHER_SUITE_RESERVED = 0xff,
+};
+
+struct cipher_suite_info {
+ enum cipher_suite_ids cipher_suite_id;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+ uint32_t iana;
+};
+
struct ipmi_session_params {
char * hostname;
uint8_t username[17];
uint8_t authcode_set[IPMI_AUTHCODE_BUFFER_SIZE + 1];
uint8_t authtype_set;
uint8_t privlvl;
- uint8_t cipher_suite_id;
+ enum cipher_suite_ids cipher_suite_id;
char sol_escape_char;
int password;
int port;
@@ -217,7 +249,10 @@ void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username);
void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password);
void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t privlvl);
void ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit);
-void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id);
+#ifdef IPMI_INTF_LANPLUS
+void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf,
+ enum cipher_suite_ids cipher_suite_id);
+#endif /* IPMI_INTF_LANPLUS */
void ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char);
void ipmi_intf_session_set_kgkey(struct ipmi_intf *intf, const uint8_t *kgkey);
void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port);
diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c
index e1fc75f..3ae3104 100644
--- a/lib/ipmi_channel.c
+++ b/lib/ipmi_channel.c
@@ -342,86 +342,116 @@ ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv)
return 0;
}
-static int
+static size_t
+parse_channel_cipher_suite_data(uint8_t *cipher_suite_data, size_t data_len,
+ struct cipher_suite_info* suites, size_t nr_suites)
+{
+ size_t count = 0;
+ size_t offset = 0;
+ uint32_t iana;
+ uint8_t auth_alg, integrity_alg, crypt_alg;
+ uint8_t cipher_suite_id;
+
+ memset(suites, 0, sizeof(*suites) * nr_suites);
+
+ while (offset < data_len && count < nr_suites) {
+ auth_alg = IPMI_AUTH_RAKP_NONE;
+ integrity_alg = IPMI_INTEGRITY_NONE;
+ crypt_alg = IPMI_CRYPT_NONE;
+ if (cipher_suite_data[offset] == STANDARD_CIPHER_SUITE) {
+ struct std_cipher_suite_record_t *record =
+ (struct std_cipher_suite_record_t*)(&cipher_suite_data[offset]);
+ /* standard type */
+ iana = 0;
+
+ /* Verify that we have at least a full record left; id + 3 algs */
+ if ((data_len - offset) < sizeof(*record)) {
+ lprintf(LOG_INFO, "Incomplete data record in cipher suite data");
+ break;
+ }
+ cipher_suite_id = record->cipher_suite_id;
+ auth_alg = CIPHER_ALG_MASK & record->auth_alg;
+ integrity_alg = CIPHER_ALG_MASK & record->integrity_alg;
+ crypt_alg = CIPHER_ALG_MASK & record->crypt_alg;
+ offset += sizeof(*record);
+ } else if (cipher_suite_data[offset] == OEM_CIPHER_SUITE) {
+ /* OEM record type */
+ struct oem_cipher_suite_record_t *record =
+ (struct oem_cipher_suite_record_t*)(&cipher_suite_data[offset]);
+ /* Verify that we have at least a full record left
+ * id + iana + 3 algs
+ */
+ if ((data_len - offset) < sizeof(*record)) {
+ lprintf(LOG_INFO, "Incomplete data record in cipher suite data");
+ break;
+ }
+
+ cipher_suite_id = record->cipher_suite_id;
+
+ /* Grab the IANA */
+ iana = ipmi24toh(record->iana);
+ auth_alg = CIPHER_ALG_MASK & record->auth_alg;
+ integrity_alg = CIPHER_ALG_MASK & record->integrity_alg;
+ crypt_alg = CIPHER_ALG_MASK & record->crypt_alg;
+ offset += sizeof(*record);
+ } else {
+ lprintf(LOG_INFO, "Bad start of record byte in cipher suite data (offset %d, value %x)", offset, cipher_suite_data[offset]);
+ break;
+ }
+ suites[count].cipher_suite_id = cipher_suite_id;
+ suites[count].iana = iana;
+ suites[count].auth_alg = auth_alg;
+ suites[count].integrity_alg = integrity_alg;
+ suites[count].crypt_alg = crypt_alg;
+ count++;
+ }
+ return count;
+}
+
+int
ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
- uint8_t channel)
+ uint8_t channel, struct cipher_suite_info *suites, size_t *count)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
uint8_t rqdata[3];
- uint32_t iana;
- uint8_t auth_alg, integrity_alg, crypt_alg;
- uint8_t cipher_suite_id;
uint8_t list_index = 0;
/* 0x40 sets * 16 bytes per set */
- uint8_t cipher_suite_data[1024];
- uint16_t offset = 0;
- /* how much was returned, total */
- uint16_t cipher_suite_data_length = 0;
+ uint8_t cipher_suite_data[MAX_CIPHER_SUITE_RECORD_OFFSET *
+ MAX_CIPHER_SUITE_DATA_LEN];
+ size_t offset = 0;
+ size_t nr_suites = 0;
+ if (!suites || !count || !*count)
+ return -1;
+
+ nr_suites = *count;
+ *count = 0;
memset(cipher_suite_data, 0, sizeof(cipher_suite_data));
-
+
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES;
req.msg.data = rqdata;
- req.msg.data_len = 3;
+ req.msg.data_len = sizeof(rqdata);
rqdata[0] = channel;
rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1);
- /* Always ask for cipher suite format */
- rqdata[2] = 0x80;
-
- rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
- lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
- return -1;
- }
- if (rsp->ccode > 0) {
- lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
- val2str(rsp->ccode, completion_code_vals));
- return -1;
- }
-
-
- /*
- * Grab the returned channel number once. We assume it's the same
- * in future calls.
- */
- if (rsp->data_len >= 1) {
- channel = rsp->data[0];
- }
-
- while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) {
- /*
- * We got back cipher suite data -- store it.
- * printf("copying data to offset %d\n", offset);
- * printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
- */
- memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
- offset += rsp->data_len - 1;
-
- /*
- * Increment our list for the next call
- */
- ++list_index;
- rqdata[2] = (rqdata[2] & 0x80) + list_index;
+ do {
+ /* Always ask for cipher suite format */
+ rqdata[2] = LIST_ALGORITHMS_BY_CIPHER_SUITE | list_index;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
- if (rsp->ccode > 0) {
+ if (rsp->ccode || rsp->data_len < 1) {
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
- }
-
- /* Copy last chunk */
- if(rsp->data_len > 1) {
/*
* We got back cipher suite data -- store it.
* printf("copying data to offset %d\n", offset);
@@ -429,88 +459,46 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
*/
memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
offset += rsp->data_len - 1;
- }
- /* We can chomp on all our data now. */
- cipher_suite_data_length = offset;
- offset = 0;
+ /*
+ * Increment our list for the next call
+ */
+ ++list_index;
+ } while ((rsp->data_len == (sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN)) &&
+ (list_index < MAX_CIPHER_SUITE_RECORD_OFFSET));
- if (! csv_output) {
- printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
- }
- while (offset < cipher_suite_data_length) {
- if (cipher_suite_data[offset++] == 0xC0) {
- /* standard type */
- iana = 0;
+ *count = parse_channel_cipher_suite_data(cipher_suite_data, offset, suites,
+ nr_suites);
+ return 0;
+}
- /* Verify that we have at least a full record left; id + 3 algs */
- if ((cipher_suite_data_length - offset) < 4) {
- lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
- return -1;
- }
- cipher_suite_id = cipher_suite_data[offset++];
- } else if (cipher_suite_data[offset++] == 0xC1) {
- /* OEM record type */
- /* Verify that we have at least a full record left
- * id + iana + 3 algs
- */
- if ((cipher_suite_data_length - offset) < 4) {
- lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
- return -1;
- }
+static int
+ipmi_print_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
+ uint8_t channel)
+{
+ int rc;
+ size_t i = 0;
+ struct cipher_suite_info suites[MAX_CIPHER_SUITE_COUNT];
+ size_t nr_suites = sizeof(*suites);
- cipher_suite_id = cipher_suite_data[offset++];
+ rc = ipmi_get_channel_cipher_suites(intf, payload_type, channel,
+ suites, &nr_suites);
- /* Grab the IANA */
- iana =
- cipher_suite_data[offset] |
- (cipher_suite_data[offset + 1] << 8) |
- (cipher_suite_data[offset + 2] << 16);
- offset += 3;
- } else {
- lprintf(LOG_ERR, "Bad start of record byte in cipher suite data");
- return -1;
- }
+ if (rc < 0)
+ return rc;
- /*
- * Grab the algorithms for this cipher suite. I guess we can't be
- * sure of what order they'll come in. Also, I suppose we default
- * to the NONE algorithm if one were absent. This part of the spec is
- * poorly written -- I have read the errata document. For now, I'm only
- * allowing one algorithm per type (auth, integrity, crypt) because I
- * don't I understand how it could be otherwise.
- */
- auth_alg = IPMI_AUTH_RAKP_NONE;
- integrity_alg = IPMI_INTEGRITY_NONE;
- crypt_alg = IPMI_CRYPT_NONE;
-
- while (((cipher_suite_data[offset] & 0xC0) != 0xC0) &&
- ((cipher_suite_data_length - offset) > 0))
- {
- switch (cipher_suite_data[offset] & 0xC0)
- {
- case 0x00:
- /* Authentication algorithm specifier */
- auth_alg = cipher_suite_data[offset++] & 0x3F;
- break;
- case 0x40:
- /* Interity algorithm specifier */
- integrity_alg = cipher_suite_data[offset++] & 0x3F;
- break;
- case 0x80:
- /* Confidentiality algorithm specifier */
- crypt_alg = cipher_suite_data[offset++] & 0x3F;
- break;
- }
- }
+ if (! csv_output) {
+ printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
+ }
+ for (i = 0; i < nr_suites; i++) {
/* We have everything we need to spit out a cipher suite record */
printf((csv_output? "%d,%s,%s,%s,%s\n" :
"%-4d %-7s %-15s %-15s %-15s\n"),
- cipher_suite_id,
- iana_string(iana),
- val2str(auth_alg, ipmi_auth_algorithms),
- val2str(integrity_alg, ipmi_integrity_algorithms),
- val2str(crypt_alg, ipmi_encryption_algorithms));
+ suites[i].cipher_suite_id,
+ iana_string(suites[i].iana),
+ val2str(suites[i].auth_alg, ipmi_auth_algorithms),
+ val2str(suites[i].integrity_alg, ipmi_integrity_algorithms),
+ val2str(suites[i].crypt_alg, ipmi_encryption_algorithms));
}
return 0;
}
@@ -973,7 +961,7 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv)
return (-1);
}
}
- retval = ipmi_get_channel_cipher_suites(intf,
+ retval = ipmi_print_channel_cipher_suites(intf,
argv[1], /* ipmi | sol */
channel);
} else if (strncmp(argv[0], "setkg", 5) == 0) {
diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c
index 811c80b..6aee102 100644
--- a/lib/ipmi_main.c
+++ b/lib/ipmi_main.c
@@ -323,6 +323,7 @@ ipmi_main(int argc, char ** argv,
uint8_t target_addr = 0;
uint8_t target_channel = 0;
+ uint8_t u8tmp = 0;
uint8_t transit_addr = 0;
uint8_t transit_channel = 0;
uint8_t target_lun = 0;
@@ -347,7 +348,10 @@ ipmi_main(int argc, char ** argv,
char * seloem = NULL;
int port = 0;
int devnum = 0;
- int cipher_suite_id = 3; /* See table 22-19 of the IPMIv2 spec */
+#ifdef IPMI_INTF_LANPLUS
+ /* lookup best cipher suite available */
+ enum cipher_suite_ids cipher_suite_id = IPMI_LANPLUS_CIPHER_SUITE_RESERVED;
+#endif /* IPMI_INTF_LANPLUS */
int argflag, i, found;
int rc = -1;
int ai_family = AF_UNSPEC;
@@ -425,19 +429,18 @@ ipmi_main(int argc, char ** argv,
goto out_free;
}
break;
+#ifdef IPMI_INTF_LANPLUS
case 'C':
- if (str2int(optarg, &cipher_suite_id) != 0) {
- lprintf(LOG_ERR, "Invalid parameter given or out of range for '-C'.");
- rc = -1;
- goto out_free;
- }
- /* add check Cipher is -gt 0 */
- if (cipher_suite_id < 0) {
- lprintf(LOG_ERR, "Cipher suite ID %i is invalid.", cipher_suite_id);
+ /* Cipher Suite ID is a byte as per IPMI specification */
+ if (str2uchar(optarg, &u8tmp) != 0) {
+ lprintf(LOG_ERR, "Invalid parameter given or out of "
+ "range [0-255] for '-C'.");
rc = -1;
goto out_free;
}
+ cipher_suite_id = u8tmp;
break;
+#endif /* IPMI_INTF_LANPLUS */
case 'v':
verbose++;
break;
@@ -870,7 +873,9 @@ ipmi_main(int argc, char ** argv,
ipmi_intf_session_set_lookupbit(ipmi_main_intf, lookupbit);
ipmi_intf_session_set_sol_escape_char(ipmi_main_intf, sol_escape_char);
+#ifdef IPMI_INTF_LANPLUS
ipmi_intf_session_set_cipher_suite_id(ipmi_main_intf, cipher_suite_id);
+#endif /* IPMI_INTF_LANPLUS */
ipmi_main_intf->devnum = devnum;
diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c
index 1d9e87b..00b0918 100644
--- a/src/plugins/ipmi_intf.c
+++ b/src/plugins/ipmi_intf.c
@@ -252,11 +252,14 @@ ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
intf->ssn_params.lookupbit = lookupbit;
}
+#ifdef IPMI_INTF_LANPLUS
void
-ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
+ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf,
+ enum cipher_suite_ids cipher_suite_id)
{
intf->ssn_params.cipher_suite_id = cipher_suite_id;
}
+#endif /* IPMI_INTF_LANPLUS */
void
ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index a0e388c..3087348 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -164,114 +164,109 @@ extern int verbose;
* returns 0 on success
* 1 on failure
*/
-int lanplus_get_requested_ciphers(int cipher_suite_id,
+int lanplus_get_requested_ciphers(enum cipher_suite_ids cipher_suite_id,
uint8_t * auth_alg,
uint8_t * integrity_alg,
uint8_t * crypt_alg)
{
-#ifdef HAVE_CRYPTO_SHA256
- if ((cipher_suite_id < 0) || (cipher_suite_id > 17)) {
- return 1;
- }
-#else
- if ((cipher_suite_id < 0) || (cipher_suite_id > 14))
- return 1;
-#endif /* HAVE_CRYPTO_SHA256 */
/* See table 22-19 for the source of the statement */
switch (cipher_suite_id)
{
- case 0:
+ case IPMI_LANPLUS_CIPHER_SUITE_0:
*auth_alg = IPMI_AUTH_RAKP_NONE;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 1:
+ case IPMI_LANPLUS_CIPHER_SUITE_1:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 2:
+ case IPMI_LANPLUS_CIPHER_SUITE_2:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 3:
+ case IPMI_LANPLUS_CIPHER_SUITE_3:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
- case 4:
+ case IPMI_LANPLUS_CIPHER_SUITE_4:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_XRC4_128;
break;
- case 5:
+ case IPMI_LANPLUS_CIPHER_SUITE_5:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
*crypt_alg = IPMI_CRYPT_XRC4_40;
break;
- case 6:
+ case IPMI_LANPLUS_CIPHER_SUITE_6:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 7:
+ case IPMI_LANPLUS_CIPHER_SUITE_7:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 8:
+ case IPMI_LANPLUS_CIPHER_SUITE_8:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
- case 9:
+ case IPMI_LANPLUS_CIPHER_SUITE_9:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_128;
break;
- case 10:
+ case IPMI_LANPLUS_CIPHER_SUITE_10:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_40;
break;
- case 11:
+ case IPMI_LANPLUS_CIPHER_SUITE_11:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 12:
+ case IPMI_LANPLUS_CIPHER_SUITE_12:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
- case 13:
+ case IPMI_LANPLUS_CIPHER_SUITE_13:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_128;
break;
- case 14:
+ case IPMI_LANPLUS_CIPHER_SUITE_14:
*auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
*integrity_alg = IPMI_INTEGRITY_MD5_128;
*crypt_alg = IPMI_CRYPT_XRC4_40;
break;
#ifdef HAVE_CRYPTO_SHA256
- case 15:
+ case IPMI_LANPLUS_CIPHER_SUITE_15:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
*integrity_alg = IPMI_INTEGRITY_NONE;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 16:
+ case IPMI_LANPLUS_CIPHER_SUITE_16:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
*crypt_alg = IPMI_CRYPT_NONE;
break;
- case 17:
+ case IPMI_LANPLUS_CIPHER_SUITE_17:
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
break;
#endif /* HAVE_CRYPTO_SHA256 */
+ case IPMI_LANPLUS_CIPHER_SUITE_RESERVED:
+ default:
+ return 1;
}
return 0;
@@ -3441,6 +3436,57 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
return 0;
}
+static uint8_t
+ipmi_find_best_cipher_suite(struct ipmi_intf *intf)
+{
+ enum cipher_suite_ids best_suite = IPMI_LANPLUS_CIPHER_SUITE_RESERVED;
+#ifdef HAVE_CRYPTO_SHA256
+ struct cipher_suite_info suites[MAX_CIPHER_SUITE_COUNT];
+ size_t nr_suites = ARRAY_SIZE(suites);
+ /* cipher suite best order is chosen with this criteria:
+ * HMAC-MD5 and MD5 are BAD; xRC4 is bad; AES128 is required
+ * HMAC-SHA256 > HMAC-SHA1
+ * secure authentication > encrypted content
+ *
+ * With xRC4 out, all cipher suites with MD5 out, and cipher suite 3 being
+ * required by the spec, the only better defined standard cipher suite is
+ * 17. So if SHA256 is available, we should try to use that, otherwise,
+ * fall back to 3.
+ */
+ const enum cipher_suite_ids cipher_order_preferred[] = {
+ IPMI_LANPLUS_CIPHER_SUITE_17,
+ IPMI_LANPLUS_CIPHER_SUITE_3,
+ };
+ const size_t nr_preferred = ARRAY_SIZE(cipher_order_preferred);
+ size_t ipref, i;
+
+ if (ipmi_get_channel_cipher_suites(intf, "ipmi", IPMI_LAN_CHANNEL_E,
+ suites, &nr_suites) < 0)
+ {
+ /* default legacy behavior - cipher suite 3 if none is requested */
+ return IPMI_LANPLUS_CIPHER_SUITE_3;
+ }
+ for (ipref = 0; ipref < nr_preferred &&
+ IPMI_LANPLUS_CIPHER_SUITE_RESERVED == best_suite; ipref++)
+ {
+ for (i = 0; i < nr_suites; i++) {
+ if (cipher_order_preferred[ipref] == suites[i].cipher_suite_id) {
+ best_suite = cipher_order_preferred[ipref];
+ break;
+ }
+ }
+ }
+#endif /* HAVE_CRYPTO_SHA256 */
+ if (IPMI_LANPLUS_CIPHER_SUITE_RESERVED == best_suite) {
+ /* IPMI 2.0 spec requires that cipher suite 3 is implemented
+ * so we should always be able to fall back to that if better
+ * options are not available. */
+ best_suite = IPMI_LANPLUS_CIPHER_SUITE_3;
+ }
+ lprintf(LOG_INFO, "Using best available cipher suite %d\n", best_suite);
+ return best_suite;
+}
+
/**
* ipmi_lanplus_open
*/
@@ -3514,6 +3560,16 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
goto fail;
}
+ /*
+ * If no cipher suite was provided, query the channel cipher suite list and
+ * pick the best one available
+ */
+ if (IPMI_LANPLUS_CIPHER_SUITE_RESERVED ==
+ intf->ssn_params.cipher_suite_id)
+ {
+ ipmi_intf_session_set_cipher_suite_id(intf,
+ ipmi_find_best_cipher_suite(intf));
+ }
/*
* If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence
@@ -3728,7 +3784,7 @@ static int ipmi_lanplus_setup(struct ipmi_intf * intf)
static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
{
- if (intf->ssn_params.cipher_suite_id == 3) {
+ if (intf->ssn_params.cipher_suite_id == IPMI_LANPLUS_CIPHER_SUITE_3) {
/*
* encrypted payload can only be multiple of 16 bytes
*/
@@ -3746,7 +3802,7 @@ static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t siz
static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
{
- if (intf->ssn_params.cipher_suite_id == 3) {
+ if (intf->ssn_params.cipher_suite_id == IPMI_LANPLUS_CIPHER_SUITE_3) {
/*
* encrypted payload can only be multiple of 16 bytes
*/
--
2.20.1

View File

@ -0,0 +1,383 @@
From a1732e68bce148255785e67eb035520729274d86 Mon Sep 17 00:00:00 2001
From: Chrostoper Ertl <chertl@microsoft.com>
Date: Thu, 28 Nov 2019 16:33:59 +0000
Subject: [PATCH] Fixes for CVE-2020-5208
see https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp
This patch is combination of following commits:
pick e824c23316ae50beb7f7488f2055ac65e8b341f2 fru: Fix buffer overflow vulnerabilities
pick 840fb1cbb4fb365cb9797300e3374d4faefcdb10 fru: Fix buffer overflow in ipmi_spd_print_fru
pick 41d7026946fafbd4d1ec0bcaca3ea30a6e8eed22 session: Fix buffer overflow in ipmi_get_session_info
pick 9452be87181a6e83cfcc768b3ed8321763db50e4 channel: Fix buffer overflow
pick d45572d71e70840e0d4c50bf48218492b79c1a10 lanp: Fix buffer overflows in get_lan_param_select
pick 7ccea283dd62a05a320c1921e3d8d71a87772637 fru, sdr: Fix id_string buffer overflows
[vdolezal@redhat.com]: fixed memleak of `spd_data` in
lib/dimm_spd.c:ipmi_spd_print_fru()
---
lib/dimm_spd.c | 11 ++++++++++-
lib/ipmi_channel.c | 5 ++++-
lib/ipmi_fru.c | 35 ++++++++++++++++++++++++++++++++---
lib/ipmi_lanp.c | 14 +++++++-------
lib/ipmi_sdr.c | 40 ++++++++++++++++++++++++----------------
lib/ipmi_session.c | 12 ++++++++----
6 files changed, 85 insertions(+), 32 deletions(-)
diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c
index 41e30db..ebcc94c 100644
--- a/lib/dimm_spd.c
+++ b/lib/dimm_spd.c
@@ -1621,7 +1621,7 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
struct ipmi_rq req;
struct fru_info fru;
uint8_t *spd_data, msg_data[4];
- int len, offset;
+ uint32_t len, offset;
msg_data[0] = id;
@@ -1697,6 +1697,15 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
}
len = rsp->data[0];
+ if(rsp->data_len < 1
+ || len > rsp->data_len - 1
+ || len > fru.size - offset)
+ {
+ printf(" Not enough buffer size");
+ free(spd_data);
+ spd_data = NULL;
+ return -1;
+ }
memcpy(&spd_data[offset], rsp->data + 1, len);
offset += len;
} while (offset < fru.size);
diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c
index 3ae3104..80ba522 100644
--- a/lib/ipmi_channel.c
+++ b/lib/ipmi_channel.c
@@ -447,7 +447,10 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
- if (rsp->ccode || rsp->data_len < 1) {
+ if (rsp->ccode
+ || rsp->data_len < 1
+ || rsp->data_len > sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN)
+ {
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
index cf00eff..98bc984 100644
--- a/lib/ipmi_fru.c
+++ b/lib/ipmi_fru.c
@@ -615,7 +615,10 @@ int
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
uint32_t offset, uint32_t length, uint8_t *frubuf)
{
- uint32_t off = offset, tmp, finish;
+ uint32_t off = offset;
+ uint32_t tmp;
+ uint32_t finish;
+ uint32_t size_left_in_buffer;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
@@ -628,10 +631,12 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
finish = offset + length;
if (finish > fru->size) {
+ memset(frubuf + fru->size, 0, length - fru->size);
finish = fru->size;
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
"Adjusting to %d",
offset + length, finish - offset);
+ length = finish - offset;
}
memset(&req, 0, sizeof(req));
@@ -667,6 +672,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
}
+ size_left_in_buffer = length;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
@@ -707,9 +713,18 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
+ if(rsp->data_len < 1
+ || tmp > rsp->data_len - 1
+ || tmp > size_left_in_buffer)
+ {
+ printf(" Not enough buffer size");
+ return -1;
+ }
+
memcpy(frubuf, rsp->data + 1, tmp);
off += tmp;
frubuf += tmp;
+ size_left_in_buffer -= tmp;
/* sometimes the size returned in the Info command
* is too large. return 0 so higher level function
* still attempts to parse what was returned */
@@ -742,7 +757,9 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
uint32_t offset, uint32_t length, uint8_t *frubuf)
{
static uint32_t fru_data_rqst_size = 20;
- uint32_t off = offset, tmp, finish;
+ uint32_t off = offset;
+ uint32_t tmp, finish;
+ uint32_t size_left_in_buffer;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
@@ -755,10 +772,12 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
finish = offset + length;
if (finish > fru->size) {
+ memset(frubuf + fru->size, 0, length - fru->size);
finish = fru->size;
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
"Adjusting to %d",
offset + length, finish - offset);
+ length = finish - offset;
}
memset(&req, 0, sizeof(req));
@@ -773,6 +792,8 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
if (fru->access && fru_data_rqst_size > 16)
#endif
fru_data_rqst_size = 16;
+
+ size_left_in_buffer = length;
do {
tmp = fru->access ? off >> 1 : off;
msg_data[0] = id;
@@ -804,8 +825,16 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
}
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
+ if(rsp->data_len < 1
+ || tmp > rsp->data_len - 1
+ || tmp > size_left_in_buffer)
+ {
+ printf(" Not enough buffer size");
+ return -1;
+ }
memcpy((frubuf + off)-offset, rsp->data + 1, tmp);
off += tmp;
+ size_left_in_buffer -= tmp;
/* sometimes the size returned in the Info command
* is too large. return 0 so higher level function
@@ -3033,7 +3062,7 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
return 0;
memset(desc, 0, sizeof(desc));
- memcpy(desc, fru->id_string, fru->id_code & 0x01f);
+ memcpy(desc, fru->id_string, __min(fru->id_code & 0x01f, sizeof(desc)));
desc[fru->id_code & 0x01f] = 0;
printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c
index 65d881b..022c7f1 100644
--- a/lib/ipmi_lanp.c
+++ b/lib/ipmi_lanp.c
@@ -1809,7 +1809,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
/* set new ipaddr */
memcpy(data+3, temp, 4);
printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert,
@@ -1824,7 +1824,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
/* set new macaddr */
memcpy(data+7, temp, 6);
printf("Setting LAN Alert %d MAC Address to "
@@ -1838,7 +1838,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "def", 3) == 0 ||
strncasecmp(argv[1], "default", 7) == 0) {
@@ -1864,7 +1864,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "on", 2) == 0 ||
strncasecmp(argv[1], "yes", 3) == 0) {
@@ -1889,7 +1889,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (strncasecmp(argv[1], "pet", 3) == 0) {
printf("Setting LAN Alert %d destination to PET Trap\n", alert);
@@ -1917,7 +1917,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (str2uchar(argv[1], &data[2]) != 0) {
lprintf(LOG_ERR, "Invalid time: %s", argv[1]);
@@ -1933,7 +1933,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert,
if (p == NULL) {
return (-1);
}
- memcpy(data, p->data, p->data_len);
+ memcpy(data, p->data, __min(p->data_len, sizeof(data)));
if (str2uchar(argv[1], &data[3]) != 0) {
lprintf(LOG_ERR, "Invalid retry: %s", argv[1]);
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index fd2c02d..01d81f7 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -2086,7 +2086,7 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
return -1;
memset(desc, 0, sizeof (desc));
- snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (sensor->id_code & 0x1f) + 1, sensor->id_string);
if (verbose) {
printf("Sensor ID : %s (0x%x)\n",
@@ -2137,7 +2137,7 @@ ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf,
return -1;
memset(desc, 0, sizeof (desc));
- snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (mc->id_code & 0x1f) + 1, mc->id_string);
if (verbose == 0) {
if (csv_output)
@@ -2230,7 +2230,7 @@ ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf,
char desc[17];
memset(desc, 0, sizeof (desc));
- snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (dev->id_code & 0x1f) + 1, dev->id_string);
if (!verbose) {
if (csv_output)
@@ -2287,7 +2287,7 @@ ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf,
char desc[17];
memset(desc, 0, sizeof (desc));
- snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string);
+ snprintf(desc, sizeof(desc), "%.*s", (fru->id_code & 0x1f) + 1, fru->id_string);
if (!verbose) {
if (csv_output)
@@ -2491,35 +2491,43 @@ ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf, uint16_t id,
int rc =0;
char desc[17];
+ const char *id_string;
+ uint8_t id_code;
memset(desc, ' ', sizeof (desc));
switch ( type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
record.full = (struct sdr_record_full_sensor *) raw;
- snprintf(desc, (record.full->id_code & 0x1f) +1, "%s",
- (const char *)record.full->id_string);
+ id_code = record.full->id_code;
+ id_string = record.full->id_string;
break;
+
case SDR_RECORD_TYPE_COMPACT_SENSOR:
record.compact = (struct sdr_record_compact_sensor *) raw ;
- snprintf(desc, (record.compact->id_code & 0x1f) +1, "%s",
- (const char *)record.compact->id_string);
+ id_code = record.compact->id_code;
+ id_string = record.compact->id_string;
break;
+
case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
record.eventonly = (struct sdr_record_eventonly_sensor *) raw ;
- snprintf(desc, (record.eventonly->id_code & 0x1f) +1, "%s",
- (const char *)record.eventonly->id_string);
- break;
+ id_code = record.eventonly->id_code;
+ id_string = record.eventonly->id_string;
+ break;
+
case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
record.mcloc = (struct sdr_record_mc_locator *) raw ;
- snprintf(desc, (record.mcloc->id_code & 0x1f) +1, "%s",
- (const char *)record.mcloc->id_string);
+ id_code = record.mcloc->id_code;
+ id_string = record.mcloc->id_string;
break;
+
default:
rc = -1;
- break;
- }
+ }
+ if (!rc) {
+ snprintf(desc, sizeof(desc), "%.*s", (id_code & 0x1f) + 1, id_string);
+ }
- lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
+ lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
return rc;
}
diff --git a/lib/ipmi_session.c b/lib/ipmi_session.c
index 141f0f4..b9af1fd 100644
--- a/lib/ipmi_session.c
+++ b/lib/ipmi_session.c
@@ -309,8 +309,10 @@ ipmi_get_session_info(struct ipmi_intf * intf,
}
else
{
- memcpy(&session_info, rsp->data, rsp->data_len);
- print_session_info(&session_info, rsp->data_len);
+ memcpy(&session_info, rsp->data,
+ __min(rsp->data_len, sizeof(session_info)));
+ print_session_info(&session_info,
+ __min(rsp->data_len, sizeof(session_info)));
}
break;
@@ -341,8 +343,10 @@ ipmi_get_session_info(struct ipmi_intf * intf,
break;
}
- memcpy(&session_info, rsp->data, rsp->data_len);
- print_session_info(&session_info, rsp->data_len);
+ memcpy(&session_info, rsp->data,
+ __min(rsp->data_len, sizeof(session_info)));
+ print_session_info(&session_info,
+ __min(rsp->data_len, sizeof(session_info)));
} while (i <= session_info.session_slot_count);
break;
--
2.20.1

View File

@ -0,0 +1,420 @@
From 87a898756a7bd54898c1f6d2a5441efb1f810b67 Mon Sep 17 00:00:00 2001
From: qctbmc <qct.bmc@gmail.com>
Date: Tue, 10 Jul 2018 11:21:55 +0800
Subject: [PATCH] oem: Add basic support for Quanta
---
include/ipmitool/Makefile.am | 2 +-
include/ipmitool/ipmi_quantaoem.h | 55 +++++++++
lib/Makefile.am | 2 +-
lib/ipmi_main.c | 1 +
lib/ipmi_oem.c | 14 +++
lib/ipmi_quantaoem.c | 184 ++++++++++++++++++++++++++++++
lib/ipmi_sel.c | 21 +++-
src/ipmitool.c | 1 +
8 files changed, 274 insertions(+), 6 deletions(-)
create mode 100644 include/ipmitool/ipmi_quantaoem.h
create mode 100644 lib/ipmi_quantaoem.c
diff --git a/include/ipmitool/Makefile.am b/include/ipmitool/Makefile.am
index 9093a56..8bc584a 100644
--- a/include/ipmitool/Makefile.am
+++ b/include/ipmitool/Makefile.am
@@ -39,4 +39,4 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \
ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \
ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \
ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h \
- ipmi_cfgp.h ipmi_lanp6.h
+ ipmi_cfgp.h ipmi_lanp6.h ipmi_quantaoem.h
diff --git a/include/ipmitool/ipmi_quantaoem.h b/include/ipmitool/ipmi_quantaoem.h
new file mode 100644
index 0000000..544f510
--- /dev/null
+++ b/include/ipmitool/ipmi_quantaoem.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Quanta Computer Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Quanta Computer Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * Quanta Computer Inc. AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * Quanta Computer Inc. OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_QUANTAOEM_H
+#define IPMI_QUANTAOEM_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.h>
+
+#define OEM_QCT_NETFN 0x36
+#define OEM_QCT_GET_INFO 0x65
+
+typedef enum
+{
+ OEM_QCT_PLATFORM_UNKNOWN = 0,
+ OEM_QCT_PLATFORM_GRANTLEY,
+ OEM_QCT_PLATFORM_PURLEY
+} qct_platform_t;
+
+qct_platform_t oem_qct_get_platform_id(struct ipmi_intf *intf);
+char *oem_qct_get_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec);
+
+#endif /*IPMI_QUANTAOEM_H*/
diff --git a/lib/Makefile.am b/lib/Makefile.am
index cc69a8f..e7568f3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -41,7 +41,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \
ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \
ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c ipmi_vita.c \
- ipmi_lanp6.c ipmi_cfgp.c \
+ ipmi_lanp6.c ipmi_cfgp.c ipmi_quantaoem.c \
../src/plugins/lan/md5.c ../src/plugins/lan/md5.h
libipmitool_la_LDFLAGS = -export-dynamic
diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c
index 6aee102..9d4a148 100644
--- a/lib/ipmi_main.c
+++ b/lib/ipmi_main.c
@@ -75,6 +75,7 @@
#include <ipmitool/ipmi_picmg.h>
#include <ipmitool/ipmi_kontronoem.h>
#include <ipmitool/ipmi_vita.h>
+#include <ipmitool/ipmi_quantaoem.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
diff --git a/lib/ipmi_oem.c b/lib/ipmi_oem.c
index 96db2ea..86fd803 100644
--- a/lib/ipmi_oem.c
+++ b/lib/ipmi_oem.c
@@ -39,6 +39,7 @@
static int ipmi_oem_supermicro(struct ipmi_intf * intf);
static int ipmi_oem_ibm(struct ipmi_intf * intf);
+static int ipmi_oem_quanta(struct ipmi_intf * intf);
static struct ipmi_oem_handle ipmi_oem_list[] = {
{
@@ -71,6 +72,11 @@ static struct ipmi_oem_handle ipmi_oem_list[] = {
.name = "kontron",
.desc = "Kontron OEM big buffer support"
},
+ {
+ .name = "quanta",
+ .desc = "Quanta IPMIv1.5 BMC with OEM LAN authentication support",
+ .setup = ipmi_oem_quanta,
+ },
{ 0 }
};
@@ -93,6 +99,14 @@ ipmi_oem_ibm(struct ipmi_intf * intf)
return ipmi_sel_oem_init((const char *)filename);
}
+/* Quanta IPMIv2 BMCs use OEM authtype */
+static int
+ipmi_oem_quanta(struct ipmi_intf * intf)
+{
+ ipmi_intf_session_set_authtype(intf, IPMI_SESSION_AUTHTYPE_OEM);
+ return 0;
+}
+
/* ipmi_oem_print - print list of OEM handles
*/
void
diff --git a/lib/ipmi_quantaoem.c b/lib/ipmi_quantaoem.c
new file mode 100644
index 0000000..7b4c5c6
--- /dev/null
+++ b/lib/ipmi_quantaoem.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018 Quanta Computer Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Quanta Computer Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * Quanta Computer Inc. AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * Quanta Computer Inc. OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#define _XOPEN_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <termios.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_mc.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/ipmi_sel.h>
+#include <ipmitool/ipmi_sdr.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_channel.h>
+#include <ipmitool/ipmi_quantaoem.h>
+#include <ipmitool/ipmi_raw.h>
+
+/* Max Size of the description String to be displyed for the Each sel entry */
+#define SIZE_OF_DESC 128
+
+#define CPU_SHIFT 6
+#define CPU_MASK 0X03
+#define CPU_NUM(x) (((x) >> CPU_SHIFT) & CPU_MASK)
+
+#define CHANNEL_BASE 0x41
+#define CHANNEL_SHIFT 3
+#define CHANNEL_MASK 0x07
+#define CHANNEL_OFFSET(x) (((x) >> CHANNEL_SHIFT) & CHANNEL_MASK)
+#define CHANNEL_NUM(x) (CHANNEL_BASE + CHANNEL_OFFSET(x))
+
+#define DIMM_MASK 0x07
+#define DIMM_NUM(x) ((x) & DIMM_MASK)
+
+#define GET_PLATFORM_ID_DATA_SIZE 4
+
+// Magic code to check if it's valid command
+#define QCT_MAGIC_1 0x4C
+#define QCT_MAGIC_2 0x1C
+#define QCT_MAGIC_3 0x00
+#define QCT_MAGIC_4 0x02
+
+qct_platform_t
+oem_qct_get_platform_id(struct ipmi_intf *intf)
+{
+ /* Execute a Get platform ID command to determine the board */
+ struct ipmi_rs *rsp;
+ struct ipmi_rq req;
+ qct_platform_t platform_id;
+ uint8_t msg_data[GET_PLATFORM_ID_DATA_SIZE];
+
+ /* Ask for IPMI v2 data as well */
+ msg_data[0] = QCT_MAGIC_1;
+ msg_data[1] = QCT_MAGIC_2;
+ msg_data[2] = QCT_MAGIC_3;
+ msg_data[3] = QCT_MAGIC_4;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = OEM_QCT_NETFN;
+ req.msg.cmd = OEM_QCT_GET_INFO;
+ req.msg.data = msg_data;
+ req.msg.data_len = sizeof(msg_data);
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Get Platform ID command failed");
+ return 0;
+ }
+ if (rsp->ccode) {
+ lprintf(LOG_ERR, "Get Platform ID command failed: %#x %s",
+ rsp->ccode, val2str(rsp->ccode, completion_code_vals));
+ return 0;
+ }
+ platform_id = rsp->data[0];
+ lprintf(LOG_DEBUG,"Platform ID: %hhx", rsp->data[0]);
+ return platform_id;
+}
+
+char *
+oem_qct_get_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
+{
+ struct ipmi_rs *rsp;
+ struct ipmi_rq req;
+ char *desc = NULL;
+ int data;
+ int sensor_type;
+ qct_platform_t platform_id;
+
+ /* Get the OEM event Bytes of the SEL Records byte 15 to data */
+ data = rec->sel_type.standard_type.event_data[2];
+ /* Check for the Standard Event type == 0x6F */
+ if (rec->sel_type.standard_type.event_type != 0x6F) {
+ goto out;
+ }
+ /* Allocate mem for te Description string */
+ desc = malloc(SIZE_OF_DESC);
+ if (desc == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ goto out;
+ }
+ memset(desc, 0, SIZE_OF_DESC);
+ sensor_type = rec->sel_type.standard_type.sensor_type;
+ switch (sensor_type) {
+ case SENSOR_TYPE_MEMORY:
+ memset(&req, 0, sizeof (req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.lun = 0;
+ req.msg.cmd = BMC_GET_DEVICE_ID;
+ req.msg.data = NULL;
+ req.msg.data_len = 0;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, " Error getting system info");
+ goto out;
+ } else if (rsp->ccode) {
+ lprintf(LOG_ERR, " Error getting system info: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ goto out;
+ }
+ /* check the platform type */
+ platform_id = oem_qct_get_platform_id(intf);
+ if (OEM_QCT_PLATFORM_PURLEY == platform_id) {
+ snprintf(desc, SIZE_OF_DESC, "CPU%d_%c%d",
+ CPU_NUM(data),
+ CHANNEL_NUM(data),
+ DIMM_NUM(data));
+ }
+ break;
+ default:
+ goto out;
+ }
+ return desc;
+out:
+ if (desc) {
+ free(desc);
+ desc = NULL;
+ }
+ return desc;
+}
diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c
index 8b0395e..a54fefd 100644
--- a/lib/ipmi_sel.c
+++ b/lib/ipmi_sel.c
@@ -50,6 +50,7 @@
#include <ipmitool/ipmi_fru.h>
#include <ipmitool/ipmi_sensor.h>
#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_quantaoem.h>
extern int verbose;
static int sel_extended = 0;
@@ -1244,6 +1245,9 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
case IPMI_OEM_SUPERMICRO_47488:
desc = get_supermicro_evt_desc(intf, rec);
break;
+ case IPMI_OEM_QUANTA:
+ desc = oem_qct_get_evt_desc(intf, rec);
+ break;
case IPMI_OEM_UNKNOWN:
default:
break;
@@ -1349,6 +1353,9 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
sfx = ipmi_get_oem_desc(intf, rec);
break;
/* add your oem sensor assignation here */
+ case IPMI_OEM_QUANTA:
+ sfx = ipmi_get_oem_desc(intf, rec);
+ break;
default:
lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description",
rec->sel_type.standard_type.sensor_type );
@@ -1359,9 +1366,12 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
sfx = ipmi_get_oem_desc(intf, rec);
- break;
+ break;
+ case IPMI_OEM_QUANTA:
+ sfx = ipmi_get_oem_desc(intf, rec);
+ break;
default:
- break;
+ break;
}
}
/*
@@ -1986,9 +1996,12 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
case IPMI_OEM_SUPERMICRO:
case IPMI_OEM_SUPERMICRO_47488:
print_sensor = 0;
- break;
+ break;
+ case IPMI_OEM_QUANTA:
+ print_sensor = 0;
+ break;
default:
- break;
+ break;
}
/*
* Sensor-Specific Discrete
diff --git a/src/ipmitool.c b/src/ipmitool.c
index 5e19c6e..ec0b741 100644
--- a/src/ipmitool.c
+++ b/src/ipmitool.c
@@ -66,6 +66,7 @@
#include <ipmitool/ipmi_ime.h>
#include <ipmitool/ipmi_dcmi.h>
#include <ipmitool/ipmi_vita.h>
+#include <ipmitool/ipmi_quantaoem.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
--
2.20.1

View File

@ -0,0 +1,33 @@
From a365e624fff752bfe79438f6c177399492ccfdde Mon Sep 17 00:00:00 2001
From: Vaclav Dolezal <vdolezal@redhat.com>
Date: Fri, 1 Mar 2019 14:46:12 +0100
Subject: [PATCH] Fix "ipmitool pef {status,info}" not printing final newline
Signed-off-by: Vaclav Dolezal <vdolezal@redhat.com>
---
lib/ipmi_pef.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c
index bbf25f2..4be749e 100644
--- a/lib/ipmi_pef.c
+++ b/lib/ipmi_pef.c
@@ -1183,6 +1183,7 @@ ipmi_pef2_get_info(struct ipmi_intf *intf)
ipmi_pef_print_guid(guid_ptr);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, pcap.actions);
+ putchar('\n');
return 0;
}
@@ -1242,6 +1243,7 @@ ipmi_pef2_get_status(struct ipmi_intf *intf)
return (-1);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_ACTV, rsp->data[1]);
+ putchar('\n');
return 0;
}
--
2.25.4

View File

@ -17,7 +17,7 @@ diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index 3087348..c442c0e 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -3386,9 +3386,13 @@
@@ -3459,9 +3459,13 @@ ipmi_find_best_cipher_suite(struct ipmi_intf *intf)
};
const size_t nr_preferred = ARRAY_SIZE(cipher_order_preferred);
size_t ipref, i;
@ -31,9 +31,8 @@ index 3087348..c442c0e 100644
+ ipmi_intf_session_set_retry(intf, retry_old);
+ if (rc < 0)
{
/* default legacy behavior - fall back to cipher suite 3 */
/* default legacy behavior - cipher suite 3 if none is requested */
return IPMI_LANPLUS_CIPHER_SUITE_3;
--
2.25.4

View File

@ -0,0 +1,65 @@
From 646160e2175f9e0ba33e4f2bda12d84555e9c30e Mon Sep 17 00:00:00 2001
From: Alexander Amelkin <alexander@amelkin.msk.ru>
Date: Thu, 29 Nov 2018 13:10:53 +0300
Subject: [PATCH] lanplus: Cleanup. Refix 6dec83ff, fix be2c0c4b
This is a cleanup commit.
Commit 6dec83ff removed assignment of `rsp` pointer
in SOL-processing block of ipmi_lan_poll_single(),
but left the check for the pointer validity in place.
Although that has effectively fixed the bug of potentially
accessing the null `rsp` pointer in the `else` block introduced
with be2c0c4b, the resulting if/else looked suspicious and left
and impression that a NULL pointer could still be accessed.
This commit removes the check for `rsp` from the `if`
as it is checked at the start of the function where `rsp`
is initialized (and that is the only place where it is ever changed).
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
(cherry picked from commit 64727f59c4a1412fdb73e092fb838ae66e2aad1a)
lanplus: Fix segfault for truncated dcmi response
On occasion a dcmi power reading will return error C6, and a
truncated response payload. As the decrypted payload is shorter
than the expected length, lanplus_decrypt_aes_cbc_128() adjusts
the payload_size downward by one byte. In ipmi_lan_poll_single()
the calculation to determine if the payload size has increased
erroniously sets extra_data_length to -1, with a subsequent
segv when calling a memmove to shift response data.
The fix is to check for a positive value in the extra_data_length.
Resolves ipmitool/ipmitool#72
(cherry picked from commit 9ec2232321a7bca7e1fb8f939d071f12c8dfa7fd)
---
src/plugins/lanplus/lanplus.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index c442c0e..ef132f6 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -814,7 +814,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
* rsp->data_len becomes the length of that data
*/
extra_data_length = payload_size - (offset - payload_start) - 1;
- if (extra_data_length) {
+ if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
} else {
@@ -868,7 +868,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
}
read_sol_packet(rsp, &offset);
extra_data_length = payload_size - (offset - payload_start);
- if (rsp && extra_data_length) {
+ if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
} else {
--
2.26.3

View File

@ -0,0 +1,33 @@
From f222df3081d965051be76b85ea52b4aff222edf1 Mon Sep 17 00:00:00 2001
From: "William A. Kennington III" <wak@google.com>
Date: Fri, 15 Jun 2018 14:47:12 -0700
Subject: [PATCH] plugins/open: Fix for interrupted select
The select syscall can be interrupted for signals like SIGPROF. The IPMI
command sent will still be outstanding but the send_command will return
an error. When the next command is sent it will get the completion for
the previous command and has the tendency to break state of end users.
Signed-off-by: William A. Kennington III <wak@google.com>
---
src/plugins/open/open.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c
index 5beeac7..59b736d 100644
--- a/src/plugins/open/open.c
+++ b/src/plugins/open/open.c
@@ -335,7 +335,9 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
FD_SET(intf->fd, &rset);
read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT;
read_timeout.tv_usec = 0;
- retval = select(intf->fd+1, &rset, NULL, NULL, &read_timeout);
+ do {
+ retval = select(intf->fd+1, &rset, NULL, NULL, &read_timeout);
+ } while (retval < 0 && errno == EINTR);
if (retval < 0) {
lperror(LOG_ERR, "I/O Error");
if (data != NULL) {
--
2.40.1

View File

@ -0,0 +1,98 @@
diff -up ipmitool-1.8.18/src/plugins/open/open.c.checking-received ipmitool-1.8.18/src/plugins/open/open.c
--- ipmitool-1.8.18/src/plugins/open/open.c.checking-received 2023-07-25 17:14:22.112985375 +0200
+++ ipmitool-1.8.18/src/plugins/open/open.c 2023-07-25 17:14:22.115985324 +0200
@@ -336,48 +336,61 @@ ipmi_openipmi_send_cmd(struct ipmi_intf
read_timeout.tv_sec = IPMI_OPENIPMI_READ_TIMEOUT;
read_timeout.tv_usec = 0;
do {
- retval = select(intf->fd+1, &rset, NULL, NULL, &read_timeout);
- } while (retval < 0 && errno == EINTR);
- if (retval < 0) {
- lperror(LOG_ERR, "I/O Error");
- if (data != NULL) {
- free(data);
+ do {
+ retval = select(intf->fd + 1, &rset, NULL, NULL, &read_timeout);
+ } while (retval < 0 && errno == EINTR);
+ if (retval < 0) {
+ lperror(LOG_ERR, "I/O Error");
+ if (data != NULL) {
+ free(data);
data = NULL;
- }
- return NULL;
- } else if (retval == 0) {
- lprintf(LOG_ERR, "No data available");
- if (data != NULL) {
- free(data);
- data = NULL;
- }
- return NULL;
- }
- if (FD_ISSET(intf->fd, &rset) == 0) {
- lprintf(LOG_ERR, "No data available");
- if (data != NULL) {
- free(data);
+ }
+ return NULL;
+ } else if (retval == 0) {
+ lprintf(LOG_ERR, "No data available");
+ if (data != NULL) {
+ free(data);
data = NULL;
+ }
+ return NULL;
}
- return NULL;
- }
-
- recv.addr = (unsigned char *) &addr;
- recv.addr_len = sizeof(addr);
- recv.msg.data = rsp.data;
- recv.msg.data_len = sizeof(rsp.data);
-
- /* get data */
- if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
- lperror(LOG_ERR, "Error receiving message");
- if (errno != EMSGSIZE) {
+ if (FD_ISSET(intf->fd, &rset) == 0) {
+ lprintf(LOG_ERR, "No data available");
if (data != NULL) {
free(data);
data = NULL;
}
return NULL;
}
- }
+
+ recv.addr = (unsigned char *)&addr;
+ recv.addr_len = sizeof(addr);
+ recv.msg.data = rsp.data;
+ recv.msg.data_len = sizeof(rsp.data);
+
+ /* get data */
+ if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
+ lperror(LOG_ERR, "Error receiving message");
+ if (errno != EMSGSIZE) {
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ return NULL;
+ }
+ }
+
+ /* If the message received wasn't expected, try to grab the
+ * next message until it's out of messages. -EAGAIN is
+ * returned if the list empty, but basically if it returns a
+ * message, check if it's alright.
+ */
+ if (_req.msgid != recv.msgid) {
+ lprintf(LOG_NOTICE,
+ "Received a response with unexpected ID %ld vs. %ld",
+ recv.msgid, _req.msgid);
+ }
+ } while (_req.msgid != recv.msgid);
if (verbose > 4) {
fprintf(stderr, "Got message:");

View File

@ -0,0 +1,36 @@
Description: Add IANA ID for NVIDIA hardware
Add the NVIDIA IANA ID to the hardcoded list used in ipmitool <= 1.8.18.
After upstream commit "9d41136 ID:491 - Fetch vendor IDs from IANA", ipmitool
generates a list of vendor IDs dynamically at build time, so we can drop this
patch in future releases.
Author: dann frazier <dannf@debian.org>
Origin: backport
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=903616
Forwarded: not-needed
Last-Update: 2018-07-11
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: ipmitool-1.8.18/include/ipmitool/ipmi.h
===================================================================
--- ipmitool-1.8.18.orig/include/ipmitool/ipmi.h
+++ ipmitool-1.8.18/include/ipmitool/ipmi.h
@@ -279,6 +279,7 @@ typedef enum IPMI_OEM {
/* 4769 for [IBM Corporation] */
IPMI_OEM_IBM_4769 = 4769,
IPMI_OEM_MAGNUM = 5593,
+ IPMI_OEM_NVIDIA = 5703,
IPMI_OEM_TYAN = 6653,
IPMI_OEM_QUANTA = 7244,
IPMI_OEM_NEWISYS = 9237,
Index: ipmitool-1.8.18/lib/ipmi_strings.c
===================================================================
--- ipmitool-1.8.18.orig/lib/ipmi_strings.c
+++ ipmitool-1.8.18/lib/ipmi_strings.c
@@ -96,6 +96,7 @@ const struct valstr ipmi_oem_info[] = {
{ IPMI_OEM_IBM_4769, "IBM Corporation" },
{ IPMI_OEM_IBM_20301, "IBM eServer X" },
{ IPMI_OEM_ADLINK_24339, "ADLINK Technology Inc." },
+ { IPMI_OEM_NVIDIA, "NVIDIA Corporation" },
{ 0xffff , NULL },
};

View File

@ -0,0 +1,232 @@
From 3e0ecc5edcccc85654784d0888dbeb2f116204e0 Mon Sep 17 00:00:00 2001
From: Patrick Venture <venture@google.com>
Date: Thu, 22 Nov 2018 15:40:24 -0800
Subject: [PATCH] move static objects to source file
Move static objects declared in headers to the source files where
they're used.
Partially resolves ipmitool/ipmitool#13
Signed-off-by: Patrick Venture <venture@google.com>
---
include/ipmitool/ipmi_sdr.h | 43 -----------
lib/ipmi_sdr.c | 146 ++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+), 43 deletions(-)
diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h
index 9001e59..5e6afd3 100644
--- a/include/ipmitool/ipmi_sdr.h
+++ b/include/ipmitool/ipmi_sdr.h
@@ -773,50 +773,7 @@ struct sdr_record_list {
#pragma pack(0)
#endif
-
-/* unit description codes (IPMI v1.5 section 37.16) */
-#define UNIT_MAX 0x90
-static const char *unit_desc[] __attribute__ ((unused)) = {
-"unspecified",
- "degrees C", "degrees F", "degrees K",
- "Volts", "Amps", "Watts", "Joules",
- "Coulombs", "VA", "Nits",
- "lumen", "lux", "Candela",
- "kPa", "PSI", "Newton",
- "CFM", "RPM", "Hz",
- "microsecond", "millisecond", "second", "minute", "hour",
- "day", "week", "mil", "inches", "feet", "cu in", "cu feet",
- "mm", "cm", "m", "cu cm", "cu m", "liters", "fluid ounce",
- "radians", "steradians", "revolutions", "cycles",
- "gravities", "ounce", "pound", "ft-lb", "oz-in", "gauss",
- "gilberts", "henry", "millihenry", "farad", "microfarad",
- "ohms", "siemens", "mole", "becquerel", "PPM", "reserved",
- "Decibels", "DbA", "DbC", "gray", "sievert",
- "color temp deg K", "bit", "kilobit", "megabit", "gigabit",
- "byte", "kilobyte", "megabyte", "gigabyte", "word", "dword",
- "qword", "line", "hit", "miss", "retry", "reset",
- "overflow", "underrun", "collision", "packets", "messages",
- "characters", "error", "correctable error", "uncorrectable error",};
-
-/* sensor type codes (IPMI v1.5 table 36.3)
- / Updated to v2.0 Table 42-3, Sensor Type Codes */
#define SENSOR_TYPE_MAX 0x2C
-static const char *sensor_type_desc[] __attribute__ ((unused)) = {
-"reserved",
- "Temperature", "Voltage", "Current", "Fan",
- "Physical Security", "Platform Security", "Processor",
- "Power Supply", "Power Unit", "Cooling Device", "Other",
- "Memory", "Drive Slot / Bay", "POST Memory Resize",
- "System Firmwares", "Event Logging Disabled", "Watchdog1",
- "System Event", "Critical Interrupt", "Button",
- "Module / Board", "Microcontroller", "Add-in Card",
- "Chassis", "Chip Set", "Other FRU", "Cable / Interconnect",
- "Terminator", "System Boot Initiated", "Boot Error",
- "OS Boot", "OS Critical Stop", "Slot / Connector",
- "System ACPI Power State", "Watchdog2", "Platform Alert",
- "Entity Presence", "Monitor ASIC", "LAN",
- "Management Subsys Health", "Battery", "Session Audit",
- "Version Change", "FRU State" };
struct sensor_reading {
char s_id[33]; /* name of the sensor */
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index d51c174..eb40b36 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -68,6 +68,152 @@ static struct sdr_record_list *sdr_list_head = NULL;
static struct sdr_record_list *sdr_list_tail = NULL;
static struct ipmi_sdr_iterator *sdr_list_itr = NULL;
+/* unit description codes (IPMI v1.5 section 37.16) */
+#define UNIT_MAX 0x90
+static const char *unit_desc[] = {
+ "unspecified",
+ "degrees C",
+ "degrees F",
+ "degrees K",
+ "Volts",
+ "Amps",
+ "Watts",
+ "Joules",
+ "Coulombs",
+ "VA",
+ "Nits",
+ "lumen",
+ "lux",
+ "Candela",
+ "kPa",
+ "PSI",
+ "Newton",
+ "CFM",
+ "RPM",
+ "Hz",
+ "microsecond",
+ "millisecond",
+ "second",
+ "minute",
+ "hour",
+ "day",
+ "week",
+ "mil",
+ "inches",
+ "feet",
+ "cu in",
+ "cu feet",
+ "mm",
+ "cm",
+ "m",
+ "cu cm",
+ "cu m",
+ "liters",
+ "fluid ounce",
+ "radians",
+ "steradians",
+ "revolutions",
+ "cycles",
+ "gravities",
+ "ounce",
+ "pound",
+ "ft-lb",
+ "oz-in",
+ "gauss",
+ "gilberts",
+ "henry",
+ "millihenry",
+ "farad",
+ "microfarad",
+ "ohms",
+ "siemens",
+ "mole",
+ "becquerel",
+ "PPM",
+ "reserved",
+ "Decibels",
+ "DbA",
+ "DbC",
+ "gray",
+ "sievert",
+ "color temp deg K",
+ "bit",
+ "kilobit",
+ "megabit",
+ "gigabit",
+ "byte",
+ "kilobyte",
+ "megabyte",
+ "gigabyte",
+ "word",
+ "dword",
+ "qword",
+ "line",
+ "hit",
+ "miss",
+ "retry",
+ "reset",
+ "overflow",
+ "underrun",
+ "collision",
+ "packets",
+ "messages",
+ "characters",
+ "error",
+ "correctable error",
+ "uncorrectable error"
+};
+
+/* sensor type codes (IPMI v1.5 table 36.3)
+ / Updated to v2.0 Table 42-3, Sensor Type Codes */
+static const char *sensor_type_desc[] = {
+ "reserved",
+ "Temperature",
+ "Voltage",
+ "Current",
+ "Fan",
+ "Physical Security",
+ "Platform Security",
+ "Processor",
+ "Power Supply",
+ "Power Unit",
+ "Cooling Device",
+ "Other",
+ "Memory",
+ "Drive Slot / Bay",
+ "POST Memory Resize",
+ "System Firmwares",
+ "Event Logging Disabled",
+ "Watchdog1",
+ "System Event",
+ "Critical Interrupt",
+ "Button",
+ "Module / Board",
+ "Microcontroller",
+ "Add-in Card",
+ "Chassis",
+ "Chip Set",
+ "Other FRU",
+ "Cable / Interconnect",
+ "Terminator",
+ "System Boot Initiated",
+ "Boot Error",
+ "OS Boot",
+ "OS Critical Stop",
+ "Slot / Connector",
+ "System ACPI Power State",
+ "Watchdog2",
+ "Platform Alert",
+ "Entity Presence",
+ "Monitor ASIC",
+ "LAN",
+ "Management Subsys Health",
+ "Battery",
+ "Session Audit",
+ "Version Change",
+ "FRU State"
+};
+
void printf_sdr_usage();
/* From src/plugins/ipmi_intf.c: */
--
2.40.1

View File

@ -0,0 +1,201 @@
From 12e2f5da63fcfdb544f87ec492e5b1bc4f89868c Mon Sep 17 00:00:00 2001
From: Alexander Amelkin <alexander@amelkin.msk.ru>
Date: Fri, 19 Apr 2019 15:07:25 +0300
Subject: [PATCH] sdr: Fix segfault on invalid unit types
The program would crash if the BMC returned an out of range (>90)
unit type for a full sensor record. This commit adds a range check
and also add support for IPMI 2.0 additional unit types 91 and 92
("fatal error" and "grams").
Resolves ipmitool/ipmitool#118
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
---
include/ipmitool/ipmi_sdr.h | 32 ++++++++++++++---
lib/ipmi_sdr.c | 72 +++++++++++++++++++++++++------------
2 files changed, 78 insertions(+), 26 deletions(-)
diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h
index 5e6afd3..9f783c4 100644
--- a/include/ipmitool/ipmi_sdr.h
+++ b/include/ipmitool/ipmi_sdr.h
@@ -37,6 +37,7 @@
# include <config.h>
#endif
+#include <stdbool.h>
#include <inttypes.h>
#include <math.h>
#include <ipmitool/bswap.h>
@@ -381,6 +382,29 @@ struct sdr_record_common_sensor {
struct sdr_record_mask mask;
+/* IPMI 2.0, Table 43-1, byte 21[7:6] Analog (numeric) Data Format */
+#define SDR_UNIT_FMT_UNSIGNED 0 /* unsigned */
+#define SDR_UNIT_FMT_1S_COMPL 1 /* 1's complement (signed) */
+#define SDR_UNIT_FMT_2S_COMPL 2 /* 2's complement (signed) */
+#define SDR_UNIT_FMT_NA 3 /* does not return analog (numeric) reading */
+/* IPMI 2.0, Table 43-1, byte 21[5:3] Rate */
+#define SDR_UNIT_RATE_NONE 0 /* none */
+#define SDR_UNIT_RATE_MICROSEC 1 /* per us */
+#define SDR_UNIT_RATE_MILLISEC 2 /* per ms */
+#define SDR_UNIT_RATE_SEC 3 /* per s */
+#define SDR_UNIT_RATE_MIN 4 /* per min */
+#define SDR_UNIT_RATE_HR 5 /* per hour */
+#define SDR_UNIT_RATE_DAY 6 /* per day */
+#define SDR_UNIT_RATE_RSVD 7 /* reserved */
+/* IPMI 2.0, Table 43-1, byte 21[2:1] Modifier Unit */
+#define SDR_UNIT_MOD_NONE 0 /* none */
+#define SDR_UNIT_MOD_DIV 1 /* Basic Unit / Modifier Unit */
+#define SDR_UNIT_MOD_MUL 2 /* Basic Unit * Mofifier Unit */
+#define SDR_UNIT_MOD_RSVD 3 /* Reserved */
+/* IPMI 2.0, Table 43-1, byte 21[0] Percentage */
+#define SDR_UNIT_PCT_NO 0
+#define SDR_UNIT_PCT_YES 1
+
struct {
#if WORDS_BIGENDIAN
uint8_t analog:2;
@@ -394,8 +418,8 @@ struct sdr_record_common_sensor {
uint8_t analog:2;
#endif
struct {
- uint8_t base;
- uint8_t modifier;
+ uint8_t base; /* Base unit type code per IPMI 2.0 Table 43-15 */
+ uint8_t modifier; /* Modifier unit type code per Table 43-15 */
} ATTRIBUTE_PACKING type;
} ATTRIBUTE_PACKING unit;
} ATTRIBUTE_PACKING;
@@ -833,8 +857,8 @@ void ipmi_sdr_print_sensor_hysteresis(struct sdr_record_common_sensor *sensor,
struct sdr_record_full_sensor *full,
uint8_t hysteresis_value,
const char *hdrstr);
-const char *ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type,
- uint8_t base, uint8_t modifier);
+const char *ipmi_sdr_get_unit_string(bool pct, uint8_t type,
+ uint8_t base, uint8_t modifier);
struct sensor_reading *
ipmi_sdr_read_sensor_value(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index eb40b36..b43765a 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -68,8 +68,9 @@ static struct sdr_record_list *sdr_list_head = NULL;
static struct sdr_record_list *sdr_list_tail = NULL;
static struct ipmi_sdr_iterator *sdr_list_itr = NULL;
-/* unit description codes (IPMI v1.5 section 37.16) */
-#define UNIT_MAX 0x90
+/* IPMI 2.0 Table 43-15, Sensor Unit Type Codes */
+#define UNIT_TYPE_MAX 92 /* This is the ID of "grams" */
+#define UNIT_TYPE_LONGEST_NAME 19 /* This is the length of "color temp deg K" */
static const char *unit_desc[] = {
"unspecified",
"degrees C",
@@ -161,7 +162,9 @@ static const char *unit_desc[] = {
"characters",
"error",
"correctable error",
- "uncorrectable error"
+ "uncorrectable error",
+ "fatal error",
+ "grams"
};
/* sensor type codes (IPMI v1.5 table 36.3)
@@ -220,35 +223,60 @@ void printf_sdr_usage();
uint16_t
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf);
-/* ipmi_sdr_get_unit_string - return units for base/modifier
+/** ipmi_sdr_get_unit_string - return units for base/modifier
*
- * @pct: units are a percentage
- * @type: unit type
- * @base: base
- * @modifier: modifier
+ * @param[in] pct Indicates that units are a percentage
+ * @param[in] relation Modifier unit to base unit relation
+ * (SDR_UNIT_MOD_NONE, SDR_UNIT_MOD_MUL,
+ * or SDR_UNIT_MOD_DIV)
+ * @param[in] base The base unit type id
+ * @param[in] modifier The modifier unit type id
*
- * returns pointer to static string
+ * @returns a pointer to static string
*/
const char *
-ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type, uint8_t base, uint8_t modifier)
+ipmi_sdr_get_unit_string(bool pct, uint8_t relation,
+ uint8_t base, uint8_t modifier)
{
- static char unitstr[16];
+ /*
+ * Twice as long as the longest possible unit name, plus
+ * four characters for '%' and relation (either ' * ' or '/'),
+ * plus the terminating null-byte.
+ */
+ static char unitstr[2 * UNIT_TYPE_LONGEST_NAME + 4 + 1];
+
/*
* By default, if units are supposed to be percent, we will pre-pend
* the percent string to the textual representation of the units.
*/
- char *pctstr = pct ? "% " : "";
- memset(unitstr, 0, sizeof (unitstr));
- switch (type) {
- case 2:
- snprintf(unitstr, sizeof (unitstr), "%s%s * %s",
- pctstr, unit_desc[base], unit_desc[modifier]);
+ const char *pctstr = pct ? "% " : "";
+ const char *basestr;
+ const char *modstr;
+
+ if (base <= UNIT_TYPE_MAX) {
+ basestr = unit_desc[base];
+ }
+ else {
+ basestr = "invalid";
+ }
+
+ if (modifier <= UNIT_TYPE_MAX) {
+ modstr = unit_desc[modifier];
+ }
+ else {
+ modstr = "invalid";
+ }
+
+ switch (relation) {
+ case SDR_UNIT_MOD_MUL:
+ snprintf(unitstr, sizeof (unitstr), "%s%s * %s",
+ pctstr, basestr, modstr);
break;
- case 1:
+ case SDR_UNIT_MOD_DIV:
snprintf(unitstr, sizeof (unitstr), "%s%s/%s",
- pctstr, unit_desc[base], unit_desc[modifier]);
+ pctstr, basestr, modstr);
break;
- case 0:
+ case SDR_UNIT_MOD_NONE:
default:
/*
* Display the text "percent" only when the Base unit is
@@ -257,8 +285,8 @@ ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type, uint8_t base, uint8_t modifi
if (base == 0 && pct) {
snprintf(unitstr, sizeof(unitstr), "percent");
} else {
- snprintf(unitstr, sizeof (unitstr), "%s%s",
- pctstr, unit_desc[base]);
+ snprintf(unitstr, sizeof (unitstr), "%s%s",
+ pctstr, basestr);
}
break;
}
--
2.40.1

View File

@ -0,0 +1,326 @@
#!/bin/sh
#############################################################################
#
# exchange-bmc-os-info: Set OS and BMC (Baseboard Management Controller)
# parameters during system startup.
#
# version: 0.72
#
# Authors: Charles Rose <charles_rose@dell.com>
# Jordan Hargrave <jordan_hargrave@dell.com>
#
# Description: Script to set OS information in the BMC; fetch BMC IP/URL
# and set in the OS for use by other scripts/user.
#
# BMC IP and URL are made available in /var/run/bmc-info
#
# Example to launch BMC web-interface:
# # . /var/run/bmc-info
# # xdg-open $BMC_URL
#
# See here for details:
# https://fedoraproject.org/wiki/Features/AgentFreeManagement
#
# OEM Specific: OEM specific ipmi commands go in:
# 'oem_set_os_version' and 'oem_get_bmc_url'
#############################################################################
#
# chkconfig: 345 99 00
# description: Set OS name, hostname in BMC; make BMC IP/URL available in OS
# processname: exchange-bmc-os-info
# config: /etc/sysconfig/exchange-bmc-os-info
#
### BEGIN INIT INFO
# Provides: exchange-bmc-os-info
# Required-Start: ipmi
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
#############################################################################
# GLOBALS
#############################################################################
CONFIGFILE=/etc/sysconfig/exchange-bmc-os-info
IPMI_TOOL=/usr/bin/ipmitool
BMC_INFO=/var/run/bmc-info
# BMC Manufacturer ID used in 'oem_set_os_version' and 'oem_get_bmc_url'
DELL="674"
#OTHER_OEM="123"
# Defaults for ${CONFIGFILE}
SET_OS_INFO="yes"
RESET_OS_INFO="no"
SET_BMC_INFO="yes"
# getsysinfo and setsysinfo commands
IPMI_SET_SYSINFO="${IPMI_TOOL} mc setsysinfo"
IPMI_GET_SYSINFO="${IPMI_TOOL} mc getsysinfo"
#############################################################################
SCRIPT_NAME=$(basename $0)
# source config
[ -r ${CONFIGFILE} ] && . ${CONFIGFILE}
RETVAL=0
if [ -f /bin/gettext.sh ]; then
GETTEXT=1
. /bin/gettext.sh
OUTPUT="eval_gettext"
else
GETTEXT=0
OUTPUT="echo"
fi
#############################################################################
# Get Vendor ID of BMC for use in 'oem_set_os_version' and 'oem_get_bmc_url'
#
get_bmc_vendor_id()
{
BMC_VENDOR=$(${IPMI_TOOL} mc info 2>/dev/null | \
sed -n "s#^Manufacturer ID.*: ##p")
[ -z "${BMC_VENDOR}" ] && RETVAL=4
}
# set/getsysinfo support was added to ipmitool post v1.8.12 via this patch
# http://sourceforge.net/mailarchive/message.php?msg_id=29647222
check_ipmitool()
{
if [ -x ${IPMI_TOOL} ]; then
[ ! ${IPMI_GET_SYSINFO} >/dev/null 2>&1 ] && \
RETVAL=3
else
RETVAL=2
fi
}
bmc_exists()
{
check_ipmitool
[ $RETVAL -eq 0 ] && get_bmc_vendor_id
return $RETVAL
}
#############################################################################
get_os_info()
{
OS_HOSTNAME=$(hostname)
KERNEL_VERSION=$(uname -r -m)
if [ -e /etc/lsb-release ] ; then
. /etc/lsb-release
NAME=${DISTRIB_ID}
VERSION="${DISTRIB_RELEASE} ${DISTRIB_CODENAME}"
fi
# we prefer systemd's /etc/os-release over other sources
[ -e /etc/os-release ] && . /etc/os-release
OS_NAME=${NAME}
OS_VERSION="${VERSION} kernel ${KERNEL_VERSION}"
}
oem_set_os_version()
{
# OS Version setting is not standard yet
# we need per vendor oem commands
case "${BMC_VENDOR}" in
$DELL) ${IPMI_SET_SYSINFO} delloem_os_version \
"${OS_VERSION}" > /dev/null 2>&1
return $?
;;
# Add OEM specific commands.
# Example:
# $OTHER_OEM) ${IPMI_SET_SYSINFO} otheroem_os_version \
# "${OS_VERSION}" > /dev/null 2>&1
# return $?
# ;;
*) return 0
;;
esac
}
set_os_info()
{
# Set and reset OS info in the BMC
if [ "$1" = "reset" ]; then
OS_NAME=""
OS_HOSTNAME=""
OS_VERSION=""
fi
${IPMI_SET_SYSINFO} os_name "${OS_NAME}" >/dev/null 2>&1 \
|| RETVAL=6
${IPMI_SET_SYSINFO} primary_os_name "${OS_NAME}" >/dev/null 2>&1 \
|| RETVAL=6
${IPMI_SET_SYSINFO} system_name "${OS_HOSTNAME}" >/dev/null 2>&1 \
|| RETVAL=6
oem_set_os_version || RETVAL=6
}
#############################################################################
valid_url()
{
url="(https?|http)://[a-z0-9-]+(\.[a-z0-9-]+)+([/?].*)?"
printf -- "%s" "${TMP_URL}"| grep -Eq "^${url}"
return $?
}
oem_get_bmc_url()
{
# BMC URL is not standard yet
# we need per vendor oem commands
case "$BMC_VENDOR" in
$DELL) TMP_URL=$(${IPMI_GET_SYSINFO} delloem_url 2> /dev/null)
;;
# Add OEM specific commands
# Example:
# $OTHER_OEM)
# TMP_URL=$(${IPMI_GET_SYSINFO} otheroem_url 2> /dev/null)
# ;;
*) TMP_URL="" ;;
esac
valid_url && BMC_URL=${TMP_URL} || BMC_URL=""
}
valid_ip()
{
#Thanks to mkyong.com
octet="([01]?[[:digit:]][[:digit:]]?|2[0-4][[:digit:]]|25[0-5])"
printf -- "%s" "${TMP_IPv4}"| grep -Eq "^${octet}\\.${octet}\\.${octet}\\.${octet}$"
return $?
}
get_bmc_ip()
{
#Thanks to http://ingvar.blog.redpill-linpro.com
for CHANNEL in `seq 1 14`
do
[ $(${IPMI_TOOL} lan print ${CHANNEL} 2>/dev/null \
| grep -q "^Set") ] || break
done
# Get BMC_IPv4 and BMC_URL from BMC
TMP_IPv4=$(${IPMI_TOOL} lan print ${CHANNEL} 2>/dev/null \
| sed -n "s#^IP Address .*: ##p")
valid_ip && BMC_IPv4=${TMP_IPv4} || BMC_IPv4=""
}
get_bmc_info()
{
get_bmc_ip
if [ -z "${BMC_IPv4}" ] || [ "${BMC_IPv4}" = "0.0.0.0" ]; then
BMC_IPv4=""
RETVAL=5
else
# URL makes sense only if there is an IP
oem_get_bmc_url
fi
}
set_bmc_info()
{
if [ ! $(touch "${BMC_INFO}" && chmod 600 "${BMC_INFO}") ]; then
printf "BMC_IPv4=%s\n" "${BMC_IPv4}" > "${BMC_INFO}"
[ -n "${BMC_URL}" ] && \
printf "BMC_URL=%s\n" "${BMC_URL}" >> "${BMC_INFO}"
else
RETVAL=5
fi
}
unset_bmc_info()
{
[ -f ${BMC_INFO} ] && rm -f ${BMC_INFO} > /dev/null 2>&1
}
#############################################################################
start()
{
if bmc_exists; then
[ "${SET_OS_INFO}" = "yes" ] && \
get_os_info && set_os_info
if [ "${SET_BMC_INFO}" = "yes" ]; then
get_bmc_info
if [ ${RETVAL} -eq 0 ]; then
set_bmc_info
fi
fi
fi
}
#############################################################################
stop()
{
if bmc_exists; then
# reset OS info while system reboots
# aids with debugging OS boot-up issues
if [ "${RESET_OS_INFO}" = "yes" ]; then
set_os_info reset
fi
unset_bmc_info
fi
}
#############################################################################
restart()
{
stop
[ $RETVAL -eq 0 ] && start
}
#############################################################################
status()
{
[ -r ${BMC_INFO} ] && \
grep -q "BMC_IPv4" "${BMC_INFO}" >/dev/null 1>&2 && \
BMC_STATUS="ok" || BMC_STATUS="inactive"
${OUTPUT} "${SCRIPT_NAME}: ${BMC_STATUS}" 1>&2
[ ${GETTEXT} -eq 1 ] && echo
}
#############################################################################
usage()
{
${OUTPUT} "Usage: ${SCRIPT_NAME} {start|stop|restart|status}" 1>&2
[ ${GETTEXT} -eq 1 ] && echo
RETVAL=1
}
#############################################################################
# MAIN
#############################################################################
case "$1" in
start) start ;;
stop) stop ;;
restart) restart ;;
status) status ;;
*) usage ;;
esac
case "$RETVAL" in
0|1) ;;
2) ${OUTPUT} "${SCRIPT_NAME}: ipmitool(1) not found." 1>&2 ;;
3) ${OUTPUT} "${SCRIPT_NAME}: this version of ipmitool does not support getsysinfo." 1>&2 ;;
4) ${OUTPUT} "${SCRIPT_NAME}: failed to communicate with BMC." 1>&2 ;;
5) ${OUTPUT} "${SCRIPT_NAME}: failed to set OS information in BMC." 1>&2 ;;
6) ${OUTPUT} "${SCRIPT_NAME}: failed to get BMC information." 1>&2 ;;
*) ${OUTPUT} "${SCRIPT_NAME}: unexpected error." 1>&2 ;;
esac
if [ ${RETVAL} -gt 1 ]; then
${OUTPUT} " Return code: ${RETVAL}" 1>&2
[ ${GETTEXT} -eq 1 ] && echo
fi
exit ${RETVAL}
#############################################################################
# end of file
#############################################################################

View File

@ -0,0 +1,13 @@
[Unit]
Description=Exchange Information between BMC and OS
After=ipmi.service network.target
Requires=ipmi.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/exchange-bmc-os-info start
ExecStop=/usr/libexec/exchange-bmc-os-info stop
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,26 @@
# exchange-bmc-os-info
#
# Config file to control Exchange of information between
# the OS and Service Processor/Baseboard Management Controller (BMC)
#
# See here for details
# https://fedoraproject.org/wiki/Features/AgentFreeManagement
### Set OS Info in BMC/Service Processor ###
# Name: SET_OS_INFO
# Description: Set OS Name, Version and Hostname in the Service Processor (BMC)
# Default: yes
SET_OS_INFO="yes"
### Reset OS Info in BMC/Service Processor ###
# Name: RESET_OS_INFO
# Description: Reset OS Name, Version and Hostname in the Service Processor (BMC).
# Useful when the OS Name/Hostname should be empty on reboot
# Default: no
RESET_OS_INFO="no"
### Set BMC/Service Processor Info in OS ###
# Name; SET_BMC_INFO
# Description: Set IP Address and URL of Service Processor/BMC in /run/bmc-info
# Default: yes
SET_BMC_INFO="yes"

View File

@ -7,7 +7,7 @@ After=ipmi.service
EnvironmentFile=-/etc/sysconfig/ipmievd
ExecStart=/usr/sbin/ipmievd $IPMIEVD_OPTIONS
Type=forking
PIDFile=/run/ipmievd.pid
PIDFile=/var/run/ipmievd.pid
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1 @@
IPMIEVD_OPTIONS="sel daemon pidfile=/var/run/ipmievd.pid"

11
SOURCES/set-bmc-url.sh Normal file
View File

@ -0,0 +1,11 @@
# Export BMC URL
#
BMC_INFO="/var/run/bmc-info"
if [ "$(id -u)" = "0" ]; then
[ -f ${BMC_INFO} ] && . ${BMC_INFO} && \
export "${BMC_URL}" "${BMC_IPv4}" >/dev/null 2>&1
fi
unset BMC_INFO

View File

@ -1,37 +1,36 @@
%global gitname IPMITOOL
%global gitversion 1_8_19
Name: ipmitool
Summary: Utility for IPMI control
Version: 1.8.19
Release: 8%{?dist}
License: BSD-3-Clause-No-Nuclear-Warranty
Version: 1.8.18
Release: 19%{?dist}
License: BSD
URL: http://ipmitool.sourceforge.net/
Source0: https://github.com/%{name}/%{name}/archive/%{gitname}_%{gitversion}/%{name}-%{version}.tar.gz
Source0: http://downloads.sourceforge.net/project/%{name}/%{name}/%{version}/%{name}-%{version}.tar.bz2
Source1: openipmi-ipmievd.sysconf
Source2: ipmievd.service
Source3: exchange-bmc-os-info.service
Source4: exchange-bmc-os-info.sysconf
Source5: set-bmc-url.sh
Source6: exchange-bmc-os-info
# https://www.iana.org/assignments/enterprise-numbers.txt
Source7: enterprise-numbers
# https://github.com/ipmitool/ipmitool/issues/170
Patch3: ipmitool-1.8.19-set-kg-key.patch
Patch1: 0001-CVE-2011-4339-OpenIPMI.patch
# WARNING: THIS PATCH MUST BE USED FOR RAWHIDE (f26+) BRANCH
Patch2: 0002-openssl.patch
Patch3: 0003-ipmitool-1.8.11-set-kg-key.patch
Patch4: 0004-slowswid.patch
Patch5: 0005-sensor-id-length.patch
Patch6: 0006-enable-usb.patch
Patch7: 0007-check-input.patch
# https://github.com/ipmitool/ipmitool/issues/199
# https://github.com/ipmitool/ipmitool/pull/214 - approved but not merged
Patch14: 0014-lanplus-cipher-retry.patch
# Debian patches, never applied upstream
# https://bugs.launchpad.net/ubuntu/+source/ipmitool/+bug/633054
# https://sourceforge.net/p/ipmitool/mailman/message/24405281/
Patch100: 0100-fix_buf_overflow.patch
# https://sourceforge.net/p/ipmitool/bugs/490/
Patch105: 0105-sensor_reading.patch
Patch8: 0008-use-best-cipher.patch
Patch9: 0009-CVE-2020-5208.patch
Patch10: 0010-quanta-oem-support.patch
Patch11: 0011-pef-missing-newline.patch
Patch12: 0012-lanplus-cipher-retry.patch
Patch13: 0013-lanplus-Cleanup.-Refix-6dec83ff-fix-be2c0c4b.patch
Patch20: 0020-plugins-open-Fix-for-interrupted-select.patch
Patch21: 0021-open-checking-received-msg-id-against-expectation.patch
Patch22: 0022-nvidia-iana.patch
Patch23: 0023-move-static-objects-to-source-file.patch
Patch24: 0024-sdr-Fix-segfault-on-invalid-unit-types.patch
BuildRequires: openssl-devel readline-devel ncurses-devel
%{?systemd_requires}
@ -84,7 +83,6 @@ Requires: ipmitool
BuildArch: noarch
%{?systemd_requires}
BuildRequires: systemd
BuildRequires: make
Summary: Let OS and BMC exchange info
@ -95,7 +93,7 @@ for the host OS to use.
%prep
%autosetup -n %{name}-%{gitname}_%{gitversion} -p1
%autosetup -p1
for f in AUTHORS ChangeLog; do
iconv -f iso-8859-1 -t utf8 < ${f} > ${f}.utf8
@ -119,8 +117,9 @@ autoconf
automake --foreign
# end: release auto-tools
install -Dm 644 %{SOURCE7} .
%configure --disable-dependency-tracking --enable-file-security --disable-intf-free --enable-intf-usb
%configure \
CFLAGS="%{optflags} -fno-strict-aliasing" \
--disable-dependency-tracking --enable-file-security --disable-intf-free
make %{?_smp_mflags}
%install
@ -172,7 +171,6 @@ install -Dm 755 contrib/bmc-snmp-proxy %{buildroot}%{_libexecdir}/bmc-sn
%{_mandir}/man1/ipmitool.1*
%doc %{_datadir}/doc/ipmitool
%{_datadir}/ipmitool
%{_datadir}/misc/enterprise-numbers
%files -n ipmievd
%config(noreplace) %{_sysconfdir}/sysconfig/ipmievd
@ -192,89 +190,43 @@ install -Dm 755 contrib/bmc-snmp-proxy %{buildroot}%{_libexecdir}/bmc-sn
%{_libexecdir}/bmc-snmp-proxy
%changelog
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 1.8.19-8
- Bump release for June 2024 mass rebuild
* Mon Jul 31 2023 Pavel Cahyna <pcahyna@redhat.com> - 1.8.18-19
- Backport upstream PR 120 to fix segfault on invalid unit types
Resolves: rhbz#2224578
- Add vendor ID for NVIDIA BMCs
Resolves: rhbz#2218358
- Add upstream ipmievd patch to check received msg id against expectation
Fixes problem where SEL response is not recognized correctly
when SEL request times out
Resolves: rhbz#2224569
* Mon Feb 12 2024 Pavel Cahyna <pcahyna@redhat.com> - 1.8.19-7
- Update IANA numbers
- Apply patch from CentOS Stream, never applied upstream:
Disable retry of pre-session "Get cipher suites" command as some
* Mon Jul 19 2021 Pavel Cahyna <pcahyna@redhat.com> - 1.8.18-18
- Protect against negative values to memmove that caused
"ipmitool sol activate" to crash against an IBM DataPower appliance
(#1951480)
Cherry-picked from upstream PR#78.
* Wed Jun 03 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-17
- Disable retry of pre-session "Get cipher suites" command as some
BMCs are ignoring it (#1831158)
- Apply patches from Debian, never applied upstream:
- fix tsol buffer overflow,
https://sourceforge.net/p/ipmitool/mailman/message/24405281/
- fix non-analog sensor readings, https://sourceforge.net/p/ipmitool/bugs/490/
- Update /var/run to /run in ipmievd.service that systemd warns about (#2100475)
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.19-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Thu Apr 30 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-16
- Fix "ipmitool pef {status,info}" not printing final newline (#1840546)
* Sat Jan 20 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.19-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Thu Apr 30 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-15
- Backport OEM support for Quanta (#1811941)
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.19-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Fri Feb 07 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-14
- Fix memory leak (found by covscan)
* Wed Jul 12 2023 Josef Ridky <jridky@redhat.com> - 1.8.19-3
- Migrate to SPDX license
* Fri Feb 07 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-13
- Backport fix for CVE-2020-5208 (#1799039)
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.19-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Fri Nov 15 2019 Václav Doležal <vdolezal@redhat.com> - 1.8.18-12
- Disable -fstrict-aliasing (RPMDiff issue)
* Sun Sep 04 2022 Kevin Fenzi <kevin@scrye.com> - 1.8.19-1
- Update to 1.8.19. Fixes rhbz#2123819
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-26
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-25
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Tue Sep 14 2021 Sahana Prasad <sahana@redhat.com> - 1.8.18-24
- Rebuilt with OpenSSL 3.0.0
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-23
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 1.8.18-22
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-21
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-20
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Thu Feb 06 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-19
- Backport fix for CVE-2020-5208 (#1798722); for details see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp
* Mon Feb 03 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-18
- Backport patch to autoselect best cipher suite when working over lanplus backend
- Fixed 'ipmitool pef status/info' not printing final newline
- Expanded column for sensor name in 'ipmi sdr/sensor' output so longer names are aligned
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-17
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Jan 23 2020 Václav Doležal <vdolezal@redhat.com> - 1.8.18-16
- Fix FTBFS with GCC 10
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-15
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Sun Feb 17 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 1.8.18-14
- Rebuild for readline 8.0
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-13
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.8.18-12
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Tue Apr 10 2018 Josef Ridky <jridky@redhat.com> - 1.8.18-11
- Project moved to github
* Tue Oct 15 2019 Václav Doležal <vdolezal@redhat.com> - 1.8.18-11
- Choose the best cipher suite available when connecting over LAN (#1749360)
* Thu Feb 22 2018 Josef Ridky <jridky@redhat.com> - 1.8.18-10
- Spec clean up

File diff suppressed because it is too large Load Diff

View File

@ -1,239 +0,0 @@
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/doc/ipmitool.1.in ipmitool-IPMITOOL_1_8_19/doc/ipmitool.1.in
--- ipmitool-IPMITOOL_1_8_19.orig/doc/ipmitool.1.in 2023-01-02 11:41:51.179962218 -0800
+++ ipmitool-IPMITOOL_1_8_19/doc/ipmitool.1.in 2023-01-02 11:43:56.396850762 -0800
@@ -384,6 +384,20 @@
Displays the list of cipher suites supported for the given
application (ipmi or sol) on the given channel.
+.TP
+\fIsetkg\fP <\fIhex\fP|\fIplain\fP> <\fBkey\fP> [<\fBchannel\fR>]
+.br
+
+Sets K_g key to given value. Use \fIplain\fP to specify \fBkey\fR as simple ASCII string.
+Use \fIhex\fP to specify \fBkey\fR as sequence of hexadecimal codes of ASCII charactes.
+I.e. following two examples are equivalent:
+
+.RS
+ipmitool channel setkg plain PASSWORD
+
+ipmitool channel setkg hex 50415353574F5244
+.RE
+
.RE
.RE
.TP
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/helper.h ipmitool-IPMITOOL_1_8_19/include/ipmitool/helper.h
--- ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/helper.h 2022-09-01 11:42:31.000000000 -0700
+++ ipmitool-IPMITOOL_1_8_19/include/ipmitool/helper.h 2023-01-02 11:44:40.775811260 -0800
@@ -67,6 +67,8 @@
# define IPMI_UID_MAX 63
#endif
+#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
+
struct ipmi_intf;
struct valstr {
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/ipmi_channel.h ipmitool-IPMITOOL_1_8_19/include/ipmitool/ipmi_channel.h
--- ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/ipmi_channel.h 2022-09-01 11:42:31.000000000 -0700
+++ ipmitool-IPMITOOL_1_8_19/include/ipmitool/ipmi_channel.h 2023-01-02 11:46:39.321705721 -0800
@@ -49,6 +49,10 @@
#define IPMI_GET_USER_NAME 0x46
#define IPMI_SET_USER_PASSWORD 0x47
#define IPMI_GET_CHANNEL_CIPHER_SUITES 0x54
+#define IPMI_SET_CHANNEL_SECURITY_KEYS 0x56
+
+#define IPMI_KG_KEY_ID 1
+#define IPMI_SET_CHANNEL_SECURITY_KEYS_OP_SET 1
/* These are for channel_info_t.session_support */
#define IPMI_CHANNEL_SESSION_LESS 0x00
@@ -208,6 +212,39 @@
struct channel_access_t channel_access,
uint8_t access_option,
uint8_t privilege_option);
+struct set_channel_security_keys_req {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 :4;
+ uint8_t channel :4;
+
+ uint8_t __reserved2 :6;
+ uint8_t operation :2;
+
+ uint8_t key_id;
+ unsigned char key_value[IPMI_KG_BUFFER_SIZE-1]; /* we don't want space for '\0' at the end */
+#else
+ uint8_t channel :4;
+ uint8_t __reserved1 :4;
+
+ uint8_t operation :2;
+ uint8_t __reserved2 :6;
+
+ uint8_t key_id;
+ unsigned char key_value[IPMI_KG_BUFFER_SIZE-1]; /* we don't want space for '\0' at the end */
+#endif
+} __attribute__ ((packed));
+
+struct set_channel_security_keys_rsp {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 :6;
+ uint8_t lock_status :2;
+ unsigned char key_value; /* just the first character, use &key_value to explore the rest */
+#else
+ uint8_t lock_status :2;
+ uint8_t __reserved1 :6;
+ unsigned char key_value; /* just the first character, use &key_value to explore the rest */
+#endif
+} __attribute__ ((packed));
uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
void ipmi_current_channel_info(struct ipmi_intf *intf,
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/ipmi_intf.h ipmitool-IPMITOOL_1_8_19/include/ipmitool/ipmi_intf.h
--- ipmitool-IPMITOOL_1_8_19.orig/include/ipmitool/ipmi_intf.h 2022-09-01 11:42:31.000000000 -0700
+++ ipmitool-IPMITOOL_1_8_19/include/ipmitool/ipmi_intf.h 2023-01-02 11:47:15.995673068 -0800
@@ -59,7 +59,6 @@
#define IPMI_AUTHCODE_BUFFER_SIZE 20
#define IPMI_SIK_BUFFER_SIZE IPMI_MAX_MD_SIZE
-#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
enum cipher_suite_ids {
IPMI_LANPLUS_CIPHER_SUITE_0 = 0,
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/lib/ipmi_channel.c ipmitool-IPMITOOL_1_8_19/lib/ipmi_channel.c
--- ipmitool-IPMITOOL_1_8_19.orig/lib/ipmi_channel.c 2022-09-01 11:42:31.000000000 -0700
+++ ipmitool-IPMITOOL_1_8_19/lib/ipmi_channel.c 2023-01-02 11:51:08.420466223 -0800
@@ -901,6 +901,92 @@
return 0;
}
+int
+ipmi_set_channel_security_keys (struct ipmi_intf *intf, uint8_t channel, const char *method, const char *key)
+{
+ uint8_t kgkey[IPMI_KG_BUFFER_SIZE];
+ struct ipmi_rs *rsp;
+ struct ipmi_rq req;
+ struct set_channel_security_keys_req req_data;
+ int rc = -1;
+
+ /* convert provided key to array of bytes */
+ if (strcmp(method, "hex") == 0) {
+ if (strlen(key) > (IPMI_KG_BUFFER_SIZE-1)*2) {
+ lprintf(LOG_ERR, "Provided key is too long, max. length is %d bytes", (IPMI_KG_BUFFER_SIZE-1));
+ printf_channel_usage();
+ return -1;
+ }
+
+ rc = ipmi_parse_hex(key, kgkey, sizeof(kgkey)-1);
+ if (rc == -1) {
+ lprintf(LOG_ERR, "Number of Kg key characters is not even");
+ return rc;
+ } else if (rc == -3) {
+ lprintf(LOG_ERR, "Kg key is not hexadecimal number");
+ return rc;
+ } else if (rc > (IPMI_KG_BUFFER_SIZE-1)) {
+ lprintf(LOG_ERR, "Kg key is too long");
+ return rc;
+ }
+
+ } else if (strcmp(method, "plain") == 0) {
+ if (strlen(key) > IPMI_KG_BUFFER_SIZE-1) {
+ lprintf(LOG_ERR, "Provided key is too long, max. length is %d bytes", (IPMI_KG_BUFFER_SIZE -1));
+ printf_channel_usage();
+ return rc;
+ }
+
+ strncpy(kgkey, key, IPMI_KG_BUFFER_SIZE-1);
+ } else {
+ printf_channel_usage();
+ return rc;
+ }
+
+ /* assemble and send request to set kg key */
+ memset(&req_data, 0, sizeof(req_data));
+ req_data.channel = channel;
+ req_data.operation = IPMI_SET_CHANNEL_SECURITY_KEYS_OP_SET;
+ req_data.key_id = IPMI_KG_KEY_ID;
+ memcpy(req_data.key_value, kgkey, IPMI_KG_BUFFER_SIZE-1);
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = IPMI_SET_CHANNEL_SECURITY_KEYS;
+ req.msg.data = (uint8_t*) &req_data;
+ req.msg.data_len = sizeof(req_data);
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Set Channel Security Keys command failed");
+ return rc;
+ }
+ if (rsp->ccode > 0) {
+ const char *error = NULL;
+ switch (rsp->ccode) {
+ case 0x80:
+ error = "Key is locked";
+ break;
+ case 0x81:
+ error = "Insufficient key bytes";
+ break;
+ case 0x82:
+ error = "Too many key bytes";
+ break;
+ case 0x83:
+ error = "Key value does not meet criteria for K_g key";
+ break;
+ default:
+ error = val2str(rsp->ccode, completion_code_vals);
+ }
+ lprintf(LOG_ERR, "Error setting security key: %X (%s)", rsp->ccode, error);
+ return rc;
+ }
+
+ lprintf(LOG_NOTICE, "Set Channel Security Keys command succeeded");
+ return 0;
+}
+
int
ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv)
{
@@ -970,6 +1056,19 @@
retval = ipmi_print_channel_cipher_suites(intf,
argv[1], /* ipmi | sol */
channel);
+ } else if (strncmp(argv[0], "setkg", 5) == 0) {
+ if (argc < 3 || argc > 4)
+ printf_channel_usage();
+ else {
+ uint8_t ch = 0xe;
+ char *method = argv[1];
+ char *key = argv[2];
+ if (argc == 4) {
+ ch = (uint8_t)strtol(argv[3], NULL, 0);
+ }
+
+ retval = ipmi_set_channel_security_keys(intf, ch, method, key);
+ }
} else {
lprintf(LOG_ERR, "Invalid CHANNEL command: %s\n", argv[0]);
printf_channel_usage();
@@ -996,6 +1095,10 @@
lprintf(LOG_NOTICE,
"");
lprintf(LOG_NOTICE,
+" setkg hex|plain <key> [channel]");
+ lprintf(LOG_NOTICE,
+"");
+ lprintf(LOG_NOTICE,
"Possible privilege levels are:");
lprintf(LOG_NOTICE,
" 1 Callback level");
diff --color -Nur ipmitool-IPMITOOL_1_8_19.orig/src/plugins/ipmi_intf.c ipmitool-IPMITOOL_1_8_19/src/plugins/ipmi_intf.c
--- ipmitool-IPMITOOL_1_8_19.orig/src/plugins/ipmi_intf.c 2022-09-01 11:42:31.000000000 -0700
+++ ipmitool-IPMITOOL_1_8_19/src/plugins/ipmi_intf.c 2023-01-02 11:51:45.295433433 -0800
@@ -52,6 +52,7 @@
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/log.h>
+#include <ipmitool/helper.h>
#define IPMI_DEFAULT_PAYLOAD_SIZE 25

View File

@ -1 +0,0 @@
IPMIEVD_OPTIONS="sel daemon pidfile=/run/ipmievd.pid"

View File

@ -1,5 +0,0 @@
SHA512 (exchange-bmc-os-info) = 77aad6f132b0ab56dcf8f8a5d1efbba9196c2fbb5771e5106833455a071a5dc79109d945a7adc0022f9604cbfd4a01ea1ea54ce15a2409c85f5effbf6cfc4f09
SHA512 (exchange-bmc-os-info.service) = 4349e7be9879c55c64e6233f749db7d656a12b421ad53a41d612e8c891abbe108d0fabe57d5753b5c1367da4f34e2e3bb579ea4ba8bc39b81ec64b66d5f65f79
SHA512 (exchange-bmc-os-info.sysconf) = 475f5645eb6a7038efe5568950235fa43a081f26490b7e17de2279e022950144f197e1a545177447ce1ec345862e7fb8fb802eaa3728bc9e32868e34c081263a
SHA512 (set-bmc-url.sh) = 99bceee522b23e0c4bc55f9e4bdc08ece9ecbf8a50511fa8f8b90ecc94d8f9715e74bb15a5f1e7c2162e7ac2e1933aff0c78b464e1010f21c784d84c0b1bfe2a
SHA512 (ipmitool-1.8.19.tar.gz) = 2d91706e9feba4b2ce4808eca087b81b842c4292a5840830001919c06ec8babd8f8761b74bb9dcf8fbc7765f028a5b1a192a3c1b643f2adaa157fed6fb0d1ee3