int assemble_ipmi_ipmb_msg (fiid_obj_t obj_ipmb_msg_hdr, fiid_obj_t obj_cmd, fiid_obj_t obj_ipmb_msg, unsigned int flags) { uint8_t buf[IPMB_MAX_LEN+1]; unsigned int indx = 0; uint8_t *checksum_data_ptr = NULL; unsigned int checksum_data_count = 0; unsigned int required_len = 0; fiid_obj_t obj_ipmb_msg_trlr = NULL; uint8_t checksum; int len, rv = -1; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_ipmb_msg_hdr) || !fiid_obj_valid (obj_cmd) || !fiid_obj_valid (obj_ipmb_msg) || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg_hdr, tmpl_ipmb_msg_hdr_rq) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg, tmpl_ipmb_msg) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_ipmb_msg_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if ((len = fiid_template_len_bytes (tmpl_ipmb_msg_hdr_rq)) < 0) { ERRNO_TRACE (errno); return (-1); } required_len += len; if ((len = fiid_obj_len_bytes (obj_cmd)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } required_len += len; if ((len = fiid_template_len_bytes (tmpl_ipmb_msg_trlr)) < 0) { ERRNO_TRACE (errno); return (-1); } required_len += len; if (IPMB_MAX_LEN < required_len) { SET_ERRNO (EMSGSIZE); return (-1); } memset (buf, '\0', IPMB_MAX_LEN+1); if ((len = fiid_obj_get_block (obj_ipmb_msg_hdr, "rs_addr", "checksum1", buf + indx, IPMB_MAX_LEN - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr); goto cleanup; } indx += len; checksum_data_ptr = (buf + indx); if ((len = fiid_obj_get_block (obj_ipmb_msg_hdr, "rq_addr", "rq_seq", buf + indx, IPMB_MAX_LEN - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr); goto cleanup; } indx += len; checksum_data_count += len; if ((len = fiid_obj_get_all (obj_cmd, buf + indx, IPMB_MAX_LEN - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); goto cleanup; } indx += len; checksum_data_count += len; if (!(obj_ipmb_msg_trlr = fiid_obj_create (tmpl_ipmb_msg_trlr))) { ERRNO_TRACE (errno); goto cleanup; } checksum = ipmi_checksum (checksum_data_ptr, checksum_data_count); if (fiid_obj_set_all (obj_ipmb_msg_trlr, &checksum, sizeof (checksum)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr); goto cleanup; } if ((len = fiid_obj_get_all (obj_ipmb_msg_trlr, buf + indx, IPMB_MAX_LEN - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr); goto cleanup; } indx += len; if ((len = fiid_obj_set_all (obj_ipmb_msg, buf, indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg); goto cleanup; } rv = len; cleanup: fiid_obj_destroy (obj_ipmb_msg_trlr); return (rv); }
int unassemble_ipmi_ipmb_msg (fiid_obj_t obj_ipmb_msg, fiid_obj_t obj_ipmb_msg_hdr, fiid_obj_t obj_cmd, fiid_obj_t obj_ipmb_msg_trlr, unsigned int flags) { uint8_t buf[IPMB_MAX_LEN+1]; int buf_len, obj_ipmb_msg_trlr_len, len; unsigned int indx = 0; unsigned int ipmb_msg_len; unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK); if (!fiid_obj_valid (obj_ipmb_msg) || !fiid_obj_valid (obj_ipmb_msg_hdr) || !fiid_obj_valid (obj_cmd) || !fiid_obj_valid (obj_ipmb_msg_trlr) || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg_hdr, tmpl_ipmb_msg_hdr_rs) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_ipmb_msg_trlr, tmpl_ipmb_msg_trlr) < 0) { ERRNO_TRACE (errno); return (-1); } memset (buf, '\0', IPMB_MAX_LEN+1); if ((buf_len = fiid_obj_get_all (obj_ipmb_msg, buf, IPMB_MAX_LEN)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg); return (-1); } if (fiid_obj_clear (obj_ipmb_msg_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr); return (-1); } if (fiid_obj_clear (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if (fiid_obj_clear (obj_ipmb_msg_trlr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr); return (-1); } if ((len = fiid_obj_set_all (obj_ipmb_msg_hdr, buf + indx, buf_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_hdr); return (-1); } indx += len; if (buf_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((obj_ipmb_msg_trlr_len = fiid_template_len_bytes (tmpl_ipmb_msg_trlr)) < 0) { ERRNO_TRACE (errno); return (-1); } if ((buf_len - indx) <= obj_ipmb_msg_trlr_len) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } ipmb_msg_len = (buf_len - indx) - obj_ipmb_msg_trlr_len; if ((len = fiid_obj_set_all (obj_cmd, buf + indx, ipmb_msg_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } indx += len; if (buf_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((len = fiid_obj_set_all (obj_ipmb_msg_trlr, buf + indx, buf_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_ipmb_msg_trlr); return (-1); } indx += len; if (FIID_OBJ_PACKET_VALID (obj_ipmb_msg_hdr) == 1 && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1) && FIID_OBJ_PACKET_VALID (obj_ipmb_msg_trlr) == 1) return (1); return (0); }
int assemble_rmcp_pkt (fiid_obj_t obj_rmcp_hdr, fiid_obj_t obj_cmd, void *pkt, unsigned int pkt_len, unsigned int flags) { int obj_cmd_len, obj_rmcp_hdr_len; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_rmcp_hdr) || !fiid_obj_valid (obj_cmd) || !pkt || !pkt_len || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if ((obj_rmcp_hdr_len = fiid_obj_len_bytes (obj_rmcp_hdr)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_len_bytes (obj_cmd)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if (pkt_len < (obj_rmcp_hdr_len + obj_cmd_len)) { SET_ERRNO (EMSGSIZE); return (-1); } memset (pkt, '\0', pkt_len); if ((obj_rmcp_hdr_len = fiid_obj_get_all (obj_rmcp_hdr, pkt, pkt_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_get_all (obj_cmd, pkt + obj_rmcp_hdr_len, pkt_len - obj_rmcp_hdr_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } return (obj_rmcp_hdr_len + obj_cmd_len); }
int unassemble_rmcp_pkt (const void *pkt, unsigned int pkt_len, fiid_obj_t obj_rmcp_hdr, fiid_obj_t obj_cmd, unsigned int flags) { unsigned int indx = 0; int len; unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK); if (!pkt || !fiid_obj_valid (obj_rmcp_hdr) || !fiid_obj_valid (obj_cmd) || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (fiid_obj_clear (obj_rmcp_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if (fiid_obj_clear (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } indx += len; if (pkt_len <= indx) { /* trace, but don't error out, cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } indx += len; if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) == 1 && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1)) return (1); return (0); }
int unassemble_ipmi_lan_pkt (const void *pkt, unsigned int pkt_len, fiid_obj_t obj_rmcp_hdr, fiid_obj_t obj_lan_session_hdr, fiid_obj_t obj_lan_msg_hdr, fiid_obj_t obj_cmd, fiid_obj_t obj_lan_msg_trlr, unsigned int flags) { uint8_t authentication_type; unsigned int indx = 0; unsigned int obj_cmd_len; int obj_lan_msg_trlr_len, len; uint64_t val; unsigned int flags_mask = (IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK); if (!pkt || !fiid_obj_valid (obj_rmcp_hdr) || !fiid_obj_valid (obj_lan_session_hdr) || !fiid_obj_valid (obj_lan_msg_hdr) || !fiid_obj_valid (obj_cmd) || !fiid_obj_valid (obj_lan_msg_trlr) || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rs) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_trlr, tmpl_lan_msg_trlr) < 0) { ERRNO_TRACE (errno); return (-1); } indx = 0; if (fiid_obj_clear (obj_rmcp_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } if (fiid_obj_clear (obj_lan_session_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); return (-1); } if (fiid_obj_clear (obj_lan_msg_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); return (-1); } if (fiid_obj_clear (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if (fiid_obj_clear (obj_lan_msg_trlr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr); return (-1); } if ((len = fiid_obj_set_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } indx += len; if (pkt_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((len = fiid_obj_set_block (obj_lan_session_hdr, "authentication_type", "session_id", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); return (-1); } indx += len; if (FIID_OBJ_GET (obj_lan_session_hdr, "authentication_type", &val) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); return (-1); } authentication_type = val; if (!IPMI_1_5_AUTHENTICATION_TYPE_VALID (authentication_type)) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE) { if ((len = fiid_obj_set_data (obj_lan_session_hdr, "authentication_code", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); return (-1); } indx += len; if (pkt_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } } if ((len = fiid_obj_set_data (obj_lan_session_hdr, "ipmi_msg_len", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); return (-1); } indx += len; if (pkt_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((len = fiid_obj_set_all (obj_lan_msg_hdr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); return (-1); } indx += len; if (pkt_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((obj_lan_msg_trlr_len = fiid_template_len_bytes (tmpl_lan_msg_trlr)) < 0) { ERRNO_TRACE (errno); return (-1); } if ((pkt_len - indx) <= obj_lan_msg_trlr_len) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } obj_cmd_len = (pkt_len - indx) - obj_lan_msg_trlr_len; if ((len = fiid_obj_set_all (obj_cmd, pkt + indx, obj_cmd_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } indx += len; if (pkt_len <= indx) { /* cannot parse packet */ ERR_TRACE ("malformed packet", EINVAL); return (0); } if ((len = fiid_obj_set_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr); return (-1); } indx += len; if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) == 1 && FIID_OBJ_PACKET_VALID (obj_lan_session_hdr) == 1 && FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) == 1 && ((flags & IPMI_INTERFACE_FLAGS_NO_LEGAL_CHECK) || FIID_OBJ_PACKET_SUFFICIENT (obj_cmd) == 1) && FIID_OBJ_PACKET_VALID (obj_lan_msg_trlr) == 1) return (1); return (0); }
int assemble_ipmi_lan_pkt (fiid_obj_t obj_rmcp_hdr, fiid_obj_t obj_lan_session_hdr, fiid_obj_t obj_lan_msg_hdr, fiid_obj_t obj_cmd, const void *authentication_code_data, unsigned int authentication_code_data_len, void *pkt, unsigned int pkt_len, unsigned int flags) { uint8_t authentication_type; uint64_t val; unsigned int indx = 0; int required_len; void *authentication_code_field_ptr = NULL; void *checksum_data_ptr = NULL; void *msg_data_ptr = NULL; void *ipmi_msg_len_ptr = NULL; unsigned int msg_data_count = 0; unsigned int checksum_data_count = 0; uint8_t ipmi_msg_len; fiid_obj_t obj_lan_msg_trlr = NULL; uint8_t pwbuf[IPMI_1_5_MAX_PASSWORD_LENGTH]; uint8_t checksum; int len, rv = -1; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_rmcp_hdr) || !fiid_obj_valid (obj_lan_session_hdr) || !fiid_obj_valid (obj_lan_msg_hdr) || !fiid_obj_valid (obj_cmd) || (authentication_code_data && authentication_code_data_len > IPMI_1_5_MAX_PASSWORD_LENGTH) || !pkt || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rq) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } /* * ipmi_msg_len is calculated in this function, so we can't use * fiid_obj_packet_valid() on obj_lan_session_hdr b/c ipmi_msg_len * is probably not set yet. */ if (FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if (FIID_OBJ_GET (obj_lan_session_hdr, "authentication_type", &val) < 0) { ERRNO_TRACE (errno); return (-1); } authentication_type = val; if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE && authentication_type != IPMI_AUTHENTICATION_TYPE_MD2 && authentication_type != IPMI_AUTHENTICATION_TYPE_MD5 && authentication_type != IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY) { SET_ERRNO (EINVAL); return (-1); } /* no need for overflow checks, handled w/ _ipmi_lan_pkt_rq_min_size check */ required_len = _ipmi_lan_pkt_rq_min_size (authentication_type, obj_cmd); if (pkt_len < required_len) { SET_ERRNO (EMSGSIZE); return (-1); } memset (pkt, 0, pkt_len); if ((len = fiid_obj_get_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); goto cleanup; } indx += len; if ((len = fiid_obj_get_block (obj_lan_session_hdr, "authentication_type", "session_id", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } indx += len; /* authentication_code generated last. Save pointers for later calculation */ if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE) { authentication_code_field_ptr = (pkt + indx); indx += IPMI_1_5_MAX_PASSWORD_LENGTH; } ipmi_msg_len_ptr = (pkt + indx); if ((len = fiid_template_field_len_bytes (tmpl_lan_session_hdr, "ipmi_msg_len")) < 0) { ERRNO_TRACE (errno); goto cleanup; } if (len != 1) { SET_ERRNO (EINVAL); goto cleanup; } indx += len; msg_data_ptr = (pkt + indx); if ((len = fiid_obj_get_block (obj_lan_msg_hdr, "rs_addr", "checksum1", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); goto cleanup; } indx += len; msg_data_count += len; checksum_data_ptr = (pkt + indx); if ((len = fiid_obj_get_block (obj_lan_msg_hdr, "rq_addr", "rq_seq", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); goto cleanup; } indx += len; msg_data_count += len; checksum_data_count += len; if ((len = fiid_obj_get_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); goto cleanup; } indx += len; msg_data_count += len; checksum_data_count += len; if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr))) { ERRNO_TRACE (errno); goto cleanup; } checksum = ipmi_checksum (checksum_data_ptr, checksum_data_count); if (fiid_obj_set_all (obj_lan_msg_trlr, &checksum, sizeof (checksum)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr); goto cleanup; } if ((len = fiid_obj_get_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr); goto cleanup; } indx += len; msg_data_count += len; /* ipmi_msg_len done after message length is computed */ ipmi_msg_len = msg_data_count; memcpy (ipmi_msg_len_ptr, &ipmi_msg_len, sizeof (ipmi_msg_len)); /* Auth code must be done last, some authentication like md2 and md5 * require all fields, including checksums, to be calculated * beforehand */ if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE) { int authentication_len; memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH); if ((authentication_len = fiid_obj_field_len_bytes (obj_lan_session_hdr, "authentication_code")) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } if (authentication_len) { if (fiid_obj_get_data (obj_lan_session_hdr, "authentication_code", pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } memcpy (authentication_code_field_ptr, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); } else { if (authentication_code_data) memcpy (pwbuf, authentication_code_data, authentication_code_data_len); if (authentication_type == IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY) { memcpy (authentication_code_field_ptr, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); } else /* IPMI_AUTHENTICATION_TYPE_MD2 || IPMI_AUTHENTICATION_TYPE_MD5 */ { uint8_t session_id_buf[1024]; uint8_t session_sequence_number_buf[1024]; int session_id_len, session_sequence_number_len; if ((session_id_len = fiid_obj_get_data (obj_lan_session_hdr, "session_id", session_id_buf, 1024)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } if ((session_sequence_number_len = fiid_obj_get_data (obj_lan_session_hdr, "session_sequence_number", session_sequence_number_buf, 1024)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD2) { md2_t ctx; uint8_t digest[MD2_DIGEST_LENGTH]; assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD2_DIGEST_LENGTH); md2_init (&ctx); md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md2_update_data (&ctx, session_id_buf, session_id_len); md2_update_data (&ctx, msg_data_ptr, msg_data_count); md2_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len); md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md2_finish (&ctx, digest, MD2_DIGEST_LENGTH); md2_init (&ctx); memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH); secure_memset (digest, '\0', MD2_DIGEST_LENGTH); } else if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD5) { md5_t ctx; uint8_t digest[MD5_DIGEST_LENGTH]; assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD5_DIGEST_LENGTH); md5_init (&ctx); md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md5_update_data (&ctx, session_id_buf, session_id_len); md5_update_data (&ctx, msg_data_ptr, msg_data_count); md5_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len); md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md5_finish (&ctx, digest, MD5_DIGEST_LENGTH); md5_init (&ctx); memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH); secure_memset (digest, '\0', MD5_DIGEST_LENGTH); } } } } if (indx > INT_MAX) { SET_ERRNO (EMSGSIZE); goto cleanup; } rv = indx; cleanup: if (rv < 0) secure_memset (pkt, '\0', pkt_len); fiid_obj_destroy (obj_lan_msg_trlr); secure_memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH); return (rv); }
int assemble_ipmi_kcs_pkt (fiid_obj_t obj_kcs_hdr, fiid_obj_t obj_cmd, void *pkt, unsigned int pkt_len, unsigned int flags) { int obj_cmd_len, obj_kcs_hdr_len; unsigned int utmp; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_kcs_hdr) || !fiid_obj_valid (obj_cmd) || !pkt || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_kcs_hdr, tmpl_hdr_kcs) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_kcs_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if ((obj_kcs_hdr_len = fiid_obj_len_bytes (obj_kcs_hdr)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_len_bytes (obj_cmd)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } /* int overflow not possible here */ if (pkt_len < (obj_kcs_hdr_len + obj_cmd_len)) { SET_ERRNO (EMSGSIZE); return (-1); } memset (pkt, 0, pkt_len); if ((obj_kcs_hdr_len = fiid_obj_get_all (obj_kcs_hdr, pkt, pkt_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_kcs_hdr); return (-1); } if ((obj_cmd_len = fiid_obj_get_all (obj_cmd, pkt + obj_kcs_hdr_len, pkt_len - obj_kcs_hdr_len)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } utmp = obj_kcs_hdr_len + obj_cmd_len; if (utmp > INT_MAX) { SET_ERRNO (EMSGSIZE); return (-1); } return (obj_kcs_hdr_len + obj_cmd_len); }