summaryrefslogtreecommitdiff
path: root/src/plugins/lanplus/lanplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/lanplus/lanplus.c')
-rw-r--r--src/plugins/lanplus/lanplus.c360
1 files changed, 176 insertions, 184 deletions
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
index e72e235..ed41380 100644
--- a/src/plugins/lanplus/lanplus.c
+++ b/src/plugins/lanplus/lanplus.c
@@ -29,7 +29,6 @@
* 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 _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
@@ -103,15 +102,14 @@ static void getIpmiPayloadWireRep(
uint8_t rq_seq,
uint8_t curr_seq);
static void getSolPayloadWireRep(
- struct ipmi_intf * intf,
uint8_t * msg,
struct ipmi_v2_payload * payload);
static void read_open_session_response(struct ipmi_rs * rsp, int offset);
static void read_rakp2_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
static void read_rakp4_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
-static void read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
-static void read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
-static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static void read_session_data(struct ipmi_rs * rsp, int * offset);
+static void read_session_data_v15(struct ipmi_rs * rsp, int * offset);
+static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset);
static void read_ipmi_response(struct ipmi_rs * rsp, int * offset);
static void read_sol_packet(struct ipmi_rs * rsp, int * offset);
static struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf);
@@ -119,7 +117,6 @@ static struct ipmi_rs * ipmi_lanplus_send_sol(
struct ipmi_intf * intf,
struct ipmi_v2_payload * payload);
static int check_sol_packet_for_new_data(
- struct ipmi_intf * intf,
struct ipmi_rs *rsp);
static void ack_sol_packet(
struct ipmi_intf * intf,
@@ -164,141 +161,115 @@ extern int verbose;
* returns 0 on success
* 1 on failure
*/
-int lanplus_get_requested_ciphers(int cipher_suite_id,
- uint8_t * auth_alg,
- uint8_t * integrity_alg,
- uint8_t * crypt_alg)
+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;
}
-
-
-/*
- * Reverse the order of arbitrarily long strings of bytes
- */
-void lanplus_swap(
- uint8_t * buffer,
- int length)
-{
- int i;
- uint8_t temp;
-
- for (i =0; i < length/2; ++i)
- {
- temp = buffer[i];
- buffer[i] = buffer[length - 1 - i];
- buffer[length - 1 - i] = temp;
- }
-}
-
-
-
static const struct valstr plus_payload_types_vals[] = {
{ IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message
{ IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN)
@@ -320,7 +291,7 @@ ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_se
struct ipmi_rq_entry * e;
e = malloc(sizeof(struct ipmi_rq_entry));
- if (e == NULL) {
+ if (!e) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return NULL;
}
@@ -331,7 +302,7 @@ ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_se
e->intf = intf;
e->rq_seq = req_seq;
- if (ipmi_req_entries == NULL)
+ if (!ipmi_req_entries)
ipmi_req_entries = e;
else
ipmi_req_entries_tail->next = e;
@@ -523,7 +494,7 @@ ipmi_lan_recv_packet(struct ipmi_intf * intf)
* asf.data[f:a]= 0x000000000000
*/
static int
-ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
+ipmi_handle_pong(struct ipmi_rs *rsp)
{
struct rmcp_pong {
struct rmcp_hdr rmcp;
@@ -533,7 +504,7 @@ ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
uint8_t sup_entities;
uint8_t sup_interact;
uint8_t reserved[6];
- } * pong;
+ } *pong;
if (!rsp)
return -1;
@@ -595,7 +566,7 @@ ipmiv2_lan_ping(struct ipmi_intf * intf)
int rv;
data = malloc(len);
- if (data == NULL) {
+ if (!data) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return -1;
}
@@ -644,7 +615,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
rsp = ipmi_lan_recv_packet(intf);
/* check if no packet has come */
- if (rsp == NULL) {
+ if (!rsp) {
return NULL;
}
@@ -653,7 +624,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
if (rmcp_rsp->class == RMCP_CLASS_ASF) {
/* might be ping response packet */
- rv = ipmi_handle_pong(intf, rsp);
+ rv = ipmi_handle_pong(rsp);
return (rv <= 0) ? NULL : rsp;
}
@@ -683,7 +654,7 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
* -------------------------------------------------------------------
*/
- read_session_data(rsp, &offset, intf->session);
+ read_session_data(rsp, &offset);
/*
* Skip packets that are not intended for this session
@@ -764,14 +735,12 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
rsp->payload.ipmi_response.cmd);
- if (entry == NULL) {
+ if (!entry) {
lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
/* read one more packet */
return (struct ipmi_rs *)1;
};
- uint8_t target_cmd = entry->req.msg.target_cmd;
-
lprintf(LOG_DEBUG+2, "IPMI Request Match found");
if (entry->bridging_level) {
@@ -791,12 +760,6 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
printbuf(&rsp->data[offset], (rsp->data_len-offset-1),
"bridge command response");
/*
- * decrement payload size
- * (cks2 for outer Send Message)
- */
- payload_size--;
-
- /*
* need to make a loop for embedded bridged response
*/
loop++;
@@ -822,6 +785,9 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
+ offset = 0;
+ payload_start = 0;
+ payload_size = extra_data_length;
} else {
rsp->data_len = 0;
}
@@ -873,7 +839,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 > 0) {
+ if (extra_data_length > 0) {
rsp->data_len = extra_data_length;
memmove(rsp->data, rsp->data + offset, extra_data_length);
} else {
@@ -990,7 +956,7 @@ read_open_session_response(struct ipmi_rs * rsp, int offset)
*
* param rsp [in/out] reading from the data variable and writing to the rakp 2
* section
- * param offset [in] tells us where hte rakp2 payload starts
+ * param offset [in] tells us where the rakp2 payload starts
* param auth_alg [in] describes the authentication algorithm was agreed upon in
* the open session request/response phase. We need to know that here so
* that we know how many bytes (if any) to read fromt the packet.
@@ -1011,31 +977,19 @@ read_rakp2_message(
/* RAKP response code */
rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1];
- /* Console session ID */
- memcpy(&(rsp->payload.rakp2_message.console_id),
- rsp->data + offset + 4,
- 4);
- #if WORDS_BIGENDIAN
- rsp->payload.rakp2_message.console_id =
- BSWAP_32(rsp->payload.rakp2_message.console_id);
- #endif
+ /* Console session ID */
+ rsp->payload.rakp2_message.console_id = ipmi32toh(&rsp->data[offset + 4]);
- /* BMC random number */
- memcpy(&(rsp->payload.rakp2_message.bmc_rand),
- rsp->data + offset + 8,
- 16);
- #if WORDS_BIGENDIAN
- lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16);
- #endif
+ /* BMC random number */
+ memcpy(&(rsp->payload.rakp2_message.bmc_rand),
+ array_letoh(&rsp->data[offset + 8], 16),
+ 16);
+
+ /* BMC GUID */
+ memcpy(&(rsp->payload.rakp2_message.bmc_guid),
+ array_letoh(&rsp->data[offset + 24], 16),
+ 16);
- /* BMC GUID */
- memcpy(&(rsp->payload.rakp2_message.bmc_guid),
- rsp->data + offset + 24,
- 16);
- #if WORDS_BIGENDIAN
- lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16);
- #endif
-
/* Key exchange authentication code */
switch (auth_alg)
{
@@ -1089,7 +1043,7 @@ read_rakp2_message(
*
* param rsp [in/out] reading from the data variable and writing to the rakp
* 4 section
- * param offset [in] tells us where hte rakp4 payload starts
+ * param offset [in] tells us where the rakp4 payload starts
* param integrity_alg [in] describes the authentication algorithm was
* agreed upon in the open session request/response phase. We need
* to know that here so that we know how many bytes (if any) to read
@@ -1111,16 +1065,9 @@ read_rakp4_message(
/* RAKP response code */
rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1];
- /* Console session ID */
- memcpy(&(rsp->payload.rakp4_message.console_id),
- rsp->data + offset + 4,
- 4);
- #if WORDS_BIGENDIAN
- rsp->payload.rakp4_message.console_id =
- BSWAP_32(rsp->payload.rakp4_message.console_id);
- #endif
+ /* Console session ID */
+ rsp->payload.rakp4_message.console_id = ipmi32toh(&rsp->data[offset + 4]);
-
/* Integrity check value */
switch (auth_alg)
{
@@ -1178,21 +1125,19 @@ read_rakp4_message(
* param offset [in/out] should point to the beginning of the session when
* this function is called. The offset will be adjusted to
* point to the end of the session when this function exits.
- * param session holds our session state
*/
void
read_session_data(
struct ipmi_rs * rsp,
- int * offset,
- struct ipmi_session * s)
+ int * offset)
{
/* We expect to read different stuff depending on the authtype */
rsp->session.authtype = rsp->data[*offset];
if (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS)
- read_session_data_v2x(rsp, offset, s);
+ read_session_data_v2x(rsp, offset);
else
- read_session_data_v15(rsp, offset, s);
+ read_session_data_v15(rsp, offset);
}
@@ -1218,8 +1163,7 @@ read_session_data(
void
read_session_data_v2x(
struct ipmi_rs * rsp,
- int * offset,
- struct ipmi_session * s)
+ int * offset)
{
rsp->session.authtype = rsp->data[(*offset)++];
@@ -1231,25 +1175,15 @@ read_session_data_v2x(
rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F;
/* Session ID */
- memcpy(&rsp->session.id, rsp->data + *offset, 4);
+ rsp->session.id = ipmi32toh(&rsp->data[*offset]);
*offset += 4;
- #if WORDS_BIGENDIAN
- rsp->session.id = BSWAP_32(rsp->session.id);
- #endif
-
/* Ignored, so far */
- memcpy(&rsp->session.seq, rsp->data + *offset, 4);
+ rsp->session.seq = ipmi32toh(&rsp->data[*offset]);
*offset += 4;
- #if WORDS_BIGENDIAN
- rsp->session.seq = BSWAP_32(rsp->session.seq);
- #endif
- memcpy(&rsp->session.msglen, rsp->data + *offset, 2);
+ rsp->session.msglen = ipmi16toh(&rsp->data[*offset]);
*offset += 2;
- #if WORDS_BIGENDIAN
- rsp->session.msglen = BSWAP_16(rsp->session.msglen);
- #endif
}
@@ -1257,7 +1191,7 @@ read_session_data_v2x(
/*
* read_session_data_v15
*
- * Initialize the ipmi_rsp from the session header of the packet.
+ * Initialize the ipmi_rsp from the session header of the packet.
*
* The offset should point the first byte of the the IPMI session when this
* function is called. When this function exits, the offset will point to
@@ -1272,8 +1206,7 @@ read_session_data_v2x(
*/
void read_session_data_v15(
struct ipmi_rs * rsp,
- int * offset,
- struct ipmi_session * s)
+ int * offset)
{
/* All v15 messages are IPMI messages */
rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI;
@@ -1537,7 +1470,6 @@ void getIpmiPayloadWireRep(
* param payload [in] holds the v2 payload with our SOL data
*/
void getSolPayloadWireRep(
- struct ipmi_intf * intf, /* in out */
uint8_t * msg, /* output */
struct ipmi_v2_payload * payload) /* input */
{
@@ -1667,7 +1599,7 @@ ipmi_lanplus_build_v2x_msg(
msg = malloc(len);
- if (msg == NULL) {
+ if (!msg) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return;
}
@@ -1743,7 +1675,7 @@ ipmi_lanplus_build_v2x_msg(
break;
case IPMI_PAYLOAD_TYPE_SOL:
- getSolPayloadWireRep(intf,
+ getSolPayloadWireRep(
msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
payload);
@@ -1971,8 +1903,6 @@ ipmi_lanplus_build_v2x_ipmi_cmd(
entry = ipmi_req_add_entry(intf, req, curr_seq);
/* it's a bridge command */
} else {
- unsigned char backup_cmd;
-
/* Add entry for cmd */
entry = ipmi_req_add_entry(intf, req, curr_seq);
@@ -1988,7 +1918,7 @@ ipmi_lanplus_build_v2x_ipmi_cmd(
}
}
- if (entry == NULL)
+ if (!entry)
return NULL;
// Build our payload
@@ -2054,13 +1984,13 @@ ipmi_lanplus_build_v15_ipmi_cmd(
struct ipmi_rq_entry * entry;
entry = ipmi_req_add_entry(intf, req, 0);
- if (entry == NULL)
+ if (!entry)
return NULL;
len = req->msg.data_len + 21;
msg = malloc(len);
- if (msg == NULL) {
+ if (!msg) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return NULL;
}
@@ -2251,7 +2181,7 @@ ipmi_lanplus_send_payload(
entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request, isRetry);
}
- if (entry == NULL) {
+ if (!entry) {
lprintf(LOG_ERR, "Aborting send command, unable to build");
return NULL;
}
@@ -2397,7 +2327,7 @@ ipmi_lanplus_send_payload(
/* Duplicate Request ccode most likely indicates a response to
a previous retry. Ignore and keep polling. */
- while ((rsp != NULL) && (rsp->ccode == 0xcf))
+ while (rsp && rsp->ccode == 0xcf)
{
rsp = NULL;
rsp = ipmi_lan_poll_recv(intf);
@@ -2584,7 +2514,6 @@ ipmi_lanplus_send_sol(
*/
static int
check_sol_packet_for_new_data(
- struct ipmi_intf * intf,
struct ipmi_rs *rsp)
{
static uint8_t last_received_sequence_number = 0;
@@ -2623,7 +2552,7 @@ check_sol_packet_for_new_data(
/*
- *Rember the data for next round
+ * Remember the data for next round
*/
if (rsp->payload.sol_packet.packet_sequence_number)
{
@@ -2700,7 +2629,7 @@ ipmi_lanplus_recv_sol(struct ipmi_intf * intf)
* Remembers the data sent, and alters the data to just
* include the new stuff.
*/
- check_sol_packet_for_new_data(intf, rsp);
+ check_sol_packet_for_new_data(rsp);
}
return rsp;
}
@@ -2770,7 +2699,7 @@ ipmi_get_auth_capabilities_cmd(
rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL || rsp->ccode > 0) {
+ if (!rsp || rsp->ccode) {
/*
* It's very possible that this failed because we asked for IPMI
* v2 data. Ask again, without requesting IPMI v2 data.
@@ -2779,11 +2708,11 @@ ipmi_get_auth_capabilities_cmd(
rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
+ if (!rsp) {
lprintf(LOG_INFO, "Get Auth Capabilities error");
return 1;
}
- if (rsp->ccode > 0) {
+ if (rsp->ccode) {
lprintf(LOG_INFO, "Get Auth Capabilities error: %s",
val2str(rsp->ccode, completion_code_vals));
return 1;
@@ -2808,10 +2737,9 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[4];
- uint32_t bmc_session_lsbf;
uint8_t backupBridgePossible;
- if (intf->session == NULL
+ if (!intf->session
|| intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
return -1;
@@ -2820,12 +2748,7 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
intf->target_addr = IPMI_BMC_SLAVE_ADDR;
bridgePossible = 0;
- bmc_session_lsbf = intf->session->v2_data.bmc_id;
-#if WORDS_BIGENDIAN
- bmc_session_lsbf = BSWAP_32(bmc_session_lsbf);
-#endif
-
- memcpy(&msg_data, &bmc_session_lsbf, 4);
+ htoipmi32(intf->session->v2_data.bmc_id, msg_data);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
@@ -2834,7 +2757,7 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
+ if (!rsp) {
/* Looks like the session was closed */
lprintf(LOG_ERR, "Close Session command failed");
return -1;
@@ -2848,7 +2771,7 @@ ipmi_close_session_cmd(struct ipmi_intf * intf)
(long)intf->session->v2_data.bmc_id);
return -1;
}
- if (rsp->ccode > 0) {
+ if (rsp->ccode) {
lprintf(LOG_ERR, "Close Session command failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
@@ -2885,7 +2808,7 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf)
* Build an Open Session Request Payload
*/
msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE);
- if (msg == NULL) {
+ if (!msg) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -2966,7 +2889,7 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf)
free(msg);
msg = NULL;
- if (rsp == NULL ) {
+ if (!rsp ) {
lprintf(LOG_DEBUG, "Timeout in open session response message.");
return 2;
}
@@ -3071,7 +2994,7 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf)
* Build a RAKP 1 message
*/
msg = (uint8_t*)malloc(IPMI_RAKP1_MESSAGE_SIZE);
- if (msg == NULL) {
+ if (!msg) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -3102,9 +3025,7 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf)
return 1;
}
memcpy(msg + 8, session->v2_data.console_rand, 16);
- #if WORDS_BIGENDIAN
- lanplus_swap(msg + 8, 16);
- #endif
+ array_letoh(msg + 8, 16);
if (verbose > 1)
printbuf(session->v2_data.console_rand, 16,
@@ -3152,7 +3073,7 @@ ipmi_lanplus_rakp1(struct ipmi_intf * intf)
free(msg);
msg = NULL;
- if (rsp == NULL)
+ if (!rsp)
{
lprintf(LOG_WARNING, "> Error: no response from RAKP 1 message");
return 2;
@@ -3236,7 +3157,7 @@ ipmi_lanplus_rakp3(struct ipmi_intf * intf)
* Build a RAKP 3 message
*/
msg = (uint8_t*)malloc(IPMI_RAKP3_MESSAGE_MAX_SIZE);
- if (msg == NULL) {
+ if (!msg) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -3325,7 +3246,7 @@ ipmi_lanplus_rakp3(struct ipmi_intf * intf)
*/
return 1;
}
- else if (rsp == NULL)
+ else if (!rsp)
{
lprintf(LOG_WARNING, "> Error: no response from RAKP 3 message");
return 2;
@@ -3416,7 +3337,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
+ if (!rsp) {
lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
val2str(privlvl, ipmi_privlvl_vals));
bridgePossible = backupBridgePossible;
@@ -3425,7 +3346,7 @@ ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
if (verbose > 2)
printbuf(rsp->data, rsp->data_len, "set_session_privlvl");
- if (rsp->ccode > 0) {
+ if (rsp->ccode) {
lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
val2str(privlvl, ipmi_privlvl_vals),
val2str(rsp->ccode, completion_code_vals));
@@ -3441,6 +3362,62 @@ 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 - fall back to cipher suite 3 */
+ 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
*/
@@ -3470,7 +3447,7 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
if (!params->retry)
params->retry = IPMI_LAN_RETRY;
- if (params->hostname == NULL || strlen((const char *)params->hostname) == 0) {
+ if (!params->hostname || strlen((const char *)params->hostname) == 0) {
lprintf(LOG_ERR, "No hostname specified!");
return -1;
}
@@ -3491,7 +3468,9 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
/* Setup our lanplus session state */
memset(session, 0, sizeof(struct ipmi_session));
session->timeout = params->timeout;
- memcpy(&session->authcode, &params->authcode_set, sizeof(session->authcode));
+ memcpy(&session->authcode,
+ &params->authcode_set,
+ sizeof(session->authcode));
session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE;
session->v2_data.crypt_alg = IPMI_CRYPT_NONE;
session->sol_data.sequence_number = 1;
@@ -3510,15 +3489,30 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
goto fail;
}
- if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) {
+ if (!ipmi_oem_active(intf, "i82571spt") &&
+ !auth_cap.v20_data_available)
+ {
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
goto fail;
}
/*
- * If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence
- * needs to restart. The individual messages are not individually retryable,
- * as the session state is advancing.
+ * 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 needs to restart. The individual messages are not
+ * individually retryable, as the session state is advancing.
*/
for (retry = 0; retry < IPMI_LAN_RETRY; retry++) {
session->v2_data.session_state = LANPLUS_STATE_PRESESSION;
@@ -3687,21 +3681,19 @@ ipmi_lanplus_keepalive(struct ipmi_intf * intf)
return 0;
rsp = intf->sendrecv(intf, &req);
- while (rsp != NULL && is_sol_packet(rsp)) {
+ while (rsp && is_sol_packet(rsp)) {
/* rsp was SOL data instead of our answer */
/* since it didn't go through the sol recv, do sol recv stuff here */
ack_sol_packet(intf, rsp);
- check_sol_packet_for_new_data(intf, rsp);
+ check_sol_packet_for_new_data(rsp);
if (rsp->data_len)
intf->session->sol_data.sol_input_handler(rsp);
rsp = ipmi_lan_poll_recv(intf);
- if (rsp == NULL) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */
+ if (!rsp) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */
return 0; /* so get device id command never returned, the connection is still alive */
}
- if (rsp == NULL)
- return -1;
- if (rsp->ccode > 0)
+ if (!rsp || rsp->ccode)
return -1;
return 0;
@@ -3728,7 +3720,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 +3738,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
*/