void Fiid_obj_clear_field(fiid_obj_t obj, char *field) { int8_t rv; assert(fiid_obj_valid(obj) && field); if ((rv = fiid_obj_clear_field(obj, field)) < 0) ierr_exit("Fiid_obj_clear_field: %s", strerror(errno)); }
int ipmiconsole_check_rakp_4_integrity_check_value (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p) { uint8_t managed_system_guid[IPMI_MANAGED_SYSTEM_GUID_LENGTH]; int managed_system_guid_len; uint32_t managed_system_session_id; uint8_t authentication_algorithm = 0; uint64_t val; int rv; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); assert (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4); /* IPMI Workaround * * Intel IPMI 2.0 implementations respond with the integrity check * value based on the integrity algorithm rather than the * authentication algorithm. */ if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION) { if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE) authentication_algorithm = IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE; else if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96) authentication_algorithm = IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1; else if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128) authentication_algorithm = IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5; else if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_MD5_128) { /* achu: I have thus far been unable to reverse engineer this * corner case. Since we cannot provide a reasonable two * part authentication, we're going to error out. */ IPMICONSOLE_CTX_DEBUG (c, ("Intel Non-Compliance: Cannot Reverse Engineer")); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_BMC_ERROR); return (0); } } else authentication_algorithm = c->config.authentication_algorithm; if (FIID_OBJ_GET (c->connection.obj_open_session_response, "managed_system_session_id", &val) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'managed_system_session_id': %s", fiid_obj_errormsg (c->connection.obj_open_session_response))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } managed_system_session_id = val; if ((managed_system_guid_len = fiid_obj_get_data (c->connection.obj_rakp_message_2, "managed_system_guid", managed_system_guid, IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'managed_system_guid': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (managed_system_guid_len != IPMI_MANAGED_SYSTEM_GUID_LENGTH) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: invalid managed system guid length: %d", managed_system_guid_len)); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } /* IPMI Workaround (achu) * * Discovered on Supermicro X8DTG, Supermicro X8DTU, Intel * S5500WBV/Penguin Relion 700 * * For whatever reason, with cipher suite 0, the RAKP 4 response * returns with an Integrity Check Value when it should be empty. */ if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_NON_EMPTY_INTEGRITY_CHECK_VALUE && !c->config.cipher_suite_id) { if (fiid_obj_clear_field (c->connection.obj_rakp_message_4, "integrity_check_value") < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_clear_field: 'integrity_check_value': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_4))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } } if ((rv = ipmi_rmcpplus_check_rakp_4_integrity_check_value (authentication_algorithm, c->session.sik_key_ptr, c->session.sik_key_len, c->session.remote_console_random_number, IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH, managed_system_session_id, managed_system_guid, managed_system_guid_len, c->connection.obj_rakp_message_4)) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_check_rakp_4_integrity_check_value: p = %d; %s", p, strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (!rv) IPMICONSOLE_CTX_DEBUG (c, ("rakp 4 integrity check value check failed; p = %d", p)); return (rv); }
int ipmiconsole_check_rakp_2_key_exchange_authentication_code (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p) { uint8_t managed_system_random_number[IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH]; int managed_system_random_number_len; uint8_t managed_system_guid[IPMI_MANAGED_SYSTEM_GUID_LENGTH]; int managed_system_guid_len; char username_buf[IPMI_MAX_USER_NAME_LENGTH+1]; char *username; unsigned int username_len; char *password; unsigned int password_len; uint32_t managed_system_session_id; uint64_t val; int rv; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); assert (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2); /* IPMI Workaround * * Intel IPMI 2.0 implementations pad their usernames. */ if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION) { memset (username_buf, '\0', IPMI_MAX_USER_NAME_LENGTH+1); if (strlen (c->config.username)) strcpy (username_buf, c->config.username); username = username_buf; username_len = IPMI_MAX_USER_NAME_LENGTH; } else { if (strlen (c->config.username)) username = c->config.username; else username = NULL; username_len = (username) ? strlen (username) : 0; } /* IPMI Workaround * * Supermicro IPMI 2.0 implementations may have invalid payload lengths * on the RAKP response packet. */ if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_SUPERMICRO_2_0_SESSION) { uint8_t keybuf[IPMICONSOLE_PACKET_BUFLEN]; int keybuf_len; if ((keybuf_len = fiid_obj_get_data (c->connection.obj_rakp_message_2, "key_exchange_authentication_code", keybuf, IPMICONSOLE_PACKET_BUFLEN)) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE && keybuf_len == 1) { if (fiid_obj_clear_field (c->connection.obj_rakp_message_2, "key_exchange_authentication_code") < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_clear_field: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } } else if (c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1 && keybuf_len == (IPMI_HMAC_SHA1_DIGEST_LENGTH + 1)) { if (fiid_obj_set_data (c->connection.obj_rakp_message_2, "key_exchange_authentication_code", keybuf, IPMI_HMAC_SHA1_DIGEST_LENGTH) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_set_data: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } } else if (c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5 && keybuf_len == (IPMI_HMAC_MD5_DIGEST_LENGTH + 1)) { if (fiid_obj_set_data (c->connection.obj_rakp_message_2, "key_exchange_authentication_code", keybuf, IPMI_HMAC_MD5_DIGEST_LENGTH) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_set_data: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } } } if (strlen (c->config.password)) password = c->config.password; else password = NULL; password_len = (password) ? strlen (password) : 0; /* IPMI Workaround * * Intel IPMI 2.0 implementations improperly calculate HMAC-MD5-128 hashes * when the passwords are > 16 bytes long. The BMCs probably assume * all keys are <= 16 bytes in length. So we have to adjust. */ if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION && c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5 && password_len > IPMI_1_5_MAX_PASSWORD_LENGTH) password_len = IPMI_1_5_MAX_PASSWORD_LENGTH; /* IPMI Workaround * * Discovered on Sun Fire 4100. * * The key exchange authentication code is the wrong length. We * need to shorten it. */ if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_SUN_2_0_SESSION && c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1) { uint8_t buf[IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH]; int buf_len; /* trace, but do not return potential error */ if ((buf_len = fiid_obj_get_data (c->connection.obj_rakp_message_2, "key_exchange_authentication_code", buf, IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH)) < 0) IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); if (buf_len == (IPMI_HMAC_SHA1_DIGEST_LENGTH + 1)) { /* trace, but do not return potential error */ if (fiid_obj_clear_field (c->connection.obj_rakp_message_2, "key_exchange_authentication_code") < 0) IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_clear_field: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); if (fiid_obj_set_data (c->connection.obj_rakp_message_2, "key_exchange_authentication_code", buf, IPMI_HMAC_SHA1_DIGEST_LENGTH) < 0) IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_set_data: 'key_exchange_authentication_code': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); } } if (FIID_OBJ_GET (c->connection.obj_open_session_response, "managed_system_session_id", &val) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'managed_system_session_id': %s", fiid_obj_errormsg (c->connection.obj_open_session_response))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } managed_system_session_id = val; if ((managed_system_random_number_len = fiid_obj_get_data (c->connection.obj_rakp_message_2, "managed_system_random_number", managed_system_random_number, IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'managed_system_random_number': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (managed_system_random_number_len != IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: invalid managed system random number length: %d", managed_system_random_number_len)); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if ((managed_system_guid_len = fiid_obj_get_data (c->connection.obj_rakp_message_2, "managed_system_guid", managed_system_guid, IPMI_MANAGED_SYSTEM_GUID_LENGTH)) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'managed_system_guid': %s", fiid_obj_errormsg (c->connection.obj_rakp_message_2))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (managed_system_guid_len != IPMI_MANAGED_SYSTEM_GUID_LENGTH) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: invalid managed system guid length: %d", managed_system_guid_len)); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if ((rv = ipmi_rmcpplus_check_rakp_2_key_exchange_authentication_code (c->config.authentication_algorithm, password, password_len, c->session.remote_console_session_id, managed_system_session_id, c->session.remote_console_random_number, IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH, managed_system_random_number, managed_system_random_number_len, managed_system_guid, managed_system_guid_len, c->session.name_only_lookup, c->config.privilege_level, username, username_len, c->connection.obj_rakp_message_2)) < 0) { IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_check_rakp_2_key_exchange_authentication_code: p = %d; %s", p, strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (!rv) IPMICONSOLE_CTX_DEBUG (c, ("rakp 2 key exchanged authentication code check failed; p = %d", p)); return (rv); }