diff options
Diffstat (limited to 'src/plugins/lanplus/lanplus.c')
-rw-r--r-- | src/plugins/lanplus/lanplus.c | 360 |
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, ¶ms->authcode_set, sizeof(session->authcode)); + memcpy(&session->authcode, + ¶ms->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 */ |