/*
 * Return 0 on success
 * Return -1 on fatal error
 */
static int
_console_write (ipmiconsole_ctx_t c)
{
  char buffer[IPMICONSOLE_PACKET_BUFLEN];
  ssize_t len;
  int n;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);
  assert (!c->session.close_session_flag);

  /*
   * XXX: Shouldn't assume user will read data fast enough?  I could
   * overrun buffers?
   *
   * Deal with it later.
   */

  if ((n = scbuf_read (c->connection.console_bmc_to_remote_console, buffer, IPMICONSOLE_PACKET_BUFLEN)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_read: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if ((len = write (c->connection.ipmiconsole_fd,
                    buffer,
                    n)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("write: %s", strerror (errno)));

      if (errno == EPIPE)
        {
          /* This error is ok since the user is allowed to close the
           * session
           */
          ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SUCCESS);
        }
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }

  if (len != n)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("write: invalid bytes written; n=%d; len=%d", n, len));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  /* scbuf should be empty now */
  if (!scbuf_is_empty (c->connection.console_bmc_to_remote_console))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("console_bmc_to_remote_console not empty"));
      /* Note: Not a fatal error, just return*/
      return (0);
    }

  return (0);
}
示例#2
0
int
ipmiconsole_check_requester_sequence_number (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t req_seq, expected_req_seq;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    if (FIID_OBJ_GET (c->connection.obj_lan_msg_hdr_rs,
                      "rq_seq",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'rq_seq': %s",
                                   fiid_obj_errormsg (c->connection.obj_lan_msg_hdr_rs)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    req_seq = val;
    expected_req_seq = c->session.requester_sequence_number;

    if (req_seq != expected_req_seq)
        IPMICONSOLE_CTX_DEBUG (c, ("requester sequence number check failed; p = %d; req_seq = %Xh; expected_req_seq = %Xh", p, req_seq, expected_req_seq));

    return ((req_seq == expected_req_seq) ? 1 : 0);
}
示例#3
0
int
ipmiconsole_check_message_tag (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t message_tag, expected_message_tag;
    fiid_obj_t obj_cmd;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4);

    obj_cmd = ipmiconsole_packet_object (c, p);
    if (FIID_OBJ_GET (obj_cmd,
                      "message_tag",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'message_tag': %s",
                                   fiid_obj_errormsg (obj_cmd)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    message_tag = val;
    expected_message_tag = c->session.message_tag;

    if (message_tag != expected_message_tag)
        IPMICONSOLE_CTX_DEBUG (c, ("message tag check failed; p = %d", p));

    return ((message_tag == expected_message_tag) ? 1 : 0);
}
示例#4
0
int
ipmiconsole_check_rmcpplus_status_code (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t rmcpplus_status_code;
    uint64_t val;
    fiid_obj_t obj_cmd;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4);

    obj_cmd = ipmiconsole_packet_object (c, p);
    if (FIID_OBJ_GET (obj_cmd,
                      "rmcpplus_status_code",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'rmcpplus_status_code': %s",
                                   fiid_obj_errormsg (obj_cmd)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    rmcpplus_status_code = val;

    if (rmcpplus_status_code != RMCPPLUS_STATUS_NO_ERRORS)
        IPMICONSOLE_CTX_DEBUG (c, ("rmcpplus status code check failed; p = %d", p));

    return ((rmcpplus_status_code == RMCPPLUS_STATUS_NO_ERRORS) ? 1 : 0);
}
示例#5
0
int
ipmiconsole_check_network_function (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t netfn, expected_netfn;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    if (FIID_OBJ_GET (c->connection.obj_lan_msg_hdr_rs,
                      "net_fn",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'net_fn': %s",
                                   fiid_obj_errormsg (c->connection.obj_lan_msg_hdr_rs)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    netfn = val;
    expected_netfn = IPMI_NET_FN_APP_RS;

    if (netfn != expected_netfn)
        IPMICONSOLE_CTX_DEBUG (c, ("network function check failed; p = %d; netfn = %Xh; expected_netfn = %Xh", p, netfn, expected_netfn));

    return ((netfn == expected_netfn) ? 1 : 0);
}
示例#6
0
int
ipmiconsole_check_payload_pad (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    int rv;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    if ((rv = ipmi_rmcpplus_check_payload_pad (c->config.confidentiality_algorithm,
              c->connection.obj_rmcpplus_payload_rs)) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_check_payload_pad: p = %d; %s", p, strerror (errno)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }

    if (!rv)
        IPMICONSOLE_CTX_DEBUG (c, ("payload pad check failed; p = %d", p));

    return (rv);
}
/*
 * Return 0 on success
 * Return -1 on fatal error
 */
static int
_console_read (ipmiconsole_ctx_t c)
{
  char buffer[IPMICONSOLE_PACKET_BUFLEN];
  ssize_t len;
  int n, dropped = 0;
  int secure_malloc_flag;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);
  assert (!c->session.close_session_flag);

  secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0;

  if ((len = read (c->connection.ipmiconsole_fd,
                   buffer,
                   IPMICONSOLE_PACKET_BUFLEN)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("read: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }

  if (!len)
    {
      /* Returning -1 closes the session, but really this error is ok
       * since the user is allowed to close the session
       */
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SUCCESS);
      return (-1);
    }

  if ((n = scbuf_write (c->connection.console_remote_console_to_bmc, buffer, len, &dropped, secure_malloc_flag)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_write: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (n != len)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_write: invalid bytes written; n=%d; len=%d", n, len));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (dropped)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_write: dropped data: dropped=%d", dropped));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  return (0);
}
示例#8
0
int
ipmiconsole_check_payload_type (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t payload_type, expected_payload_type;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    if (FIID_OBJ_GET (c->connection.obj_rmcpplus_session_hdr_rs,
                      "payload_type",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'payload_type': %s",
                                   fiid_obj_errormsg (c->connection.obj_rmcpplus_session_hdr_rs)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    payload_type = val;

    if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE)
        expected_payload_type = IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE;
    else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2)
        expected_payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2;
    else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4)
        expected_payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4;
    else if (p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS)
        expected_payload_type = IPMI_PAYLOAD_TYPE_SOL;
    else
        expected_payload_type = IPMI_PAYLOAD_TYPE_IPMI;

    if (payload_type != expected_payload_type)
        IPMICONSOLE_CTX_DEBUG (c, ("payload type check failed; p = %d; payload_type = %Xh; expected_payload_type = %Xh", p, payload_type, expected_payload_type));

    return ((payload_type == expected_payload_type) ? 1 : 0);
}
示例#9
0
int
ipmiconsole_check_open_session_response_privilege (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    int rv;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE);

    /* IPMI Workaround
     *
     * Intel IPMI 2.0 implementations don't support the highest level privilege.
     */
    if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION)
    {
        uint8_t maximum_privilege_level;
        uint64_t val;

        if (FIID_OBJ_GET (c->connection.obj_open_session_response,
                          "maximum_privilege_level",
                          &val) < 0)
        {
            IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'maximum_privilege_level': %s",
                                       fiid_obj_errormsg (c->connection.obj_open_session_response)));
            ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
            return (-1);
        }
        maximum_privilege_level = val;

        rv = (maximum_privilege_level == c->config.privilege_level) ? 1 : 0;
    }
    else
    {
        if ((rv = ipmi_check_open_session_maximum_privilege (c->config.privilege_level,
                  c->connection.obj_open_session_response)) < 0)
        {
            IPMICONSOLE_CTX_DEBUG (c, ("ipmi_check_open_session_maximum_privilege: %s",
                                       strerror (errno)));
            ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
            return (-1);
        }
    }

    if (!rv)
        IPMICONSOLE_CTX_DEBUG (c, ("open session response privilege check failed; p = %d", p));

    return (rv);
}
示例#10
0
int
ipmiconsole_ctx_debug_setup (ipmiconsole_ctx_t c)
{
  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);

  if (c->config.debug_flags & IPMICONSOLE_DEBUG_FILE)
    {
      char filename[MAXPATHLEN];
      pid_t pid;

      pid = getpid();

      snprintf (filename,
                MAXPATHLEN,
                "%s.%s.%d",
                IPMICONSOLE_DEBUG_FILENAME,
                c->config.hostname,
		pid);

      if ((c->debug.debug_fd = open (filename,
                                     O_CREAT | O_APPEND | O_WRONLY | O_EXCL,
                                     0600)) < 0)
        {
          c->config.debug_flags &= ~IPMICONSOLE_DEBUG_FILE;
          IPMICONSOLE_CTX_DEBUG (c, ("open: %s", strerror (errno)));
          ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
          c->config.debug_flags = 0;
          return (-1);
        }
    }

  return (0);
}
示例#11
0
int
ipmiconsole_check_authentication_code (ipmiconsole_ctx_t c,
                                       ipmiconsole_packet_type_t p,
                                       void *buf,
                                       unsigned int buflen)
{
    char *password;
    int rv;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);
    assert (buf);
    assert (buflen);

    if (strlen (c->config.password))
        password = c->config.password;
    else
        password = NULL;

    if ((rv = ipmi_rmcpplus_check_packet_session_authentication_code (c->config.integrity_algorithm,
              buf,
              buflen,
              c->session.integrity_key_ptr,
              c->session.integrity_key_len,
              password,
              (password) ? strlen (password) : 0,
              c->connection.obj_rmcpplus_session_trlr_rs)) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_check_packet_session_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, ("authentication code check failed; p = %d", p));

    return (rv);
}
/*
 * Return 0 on success
 * Return -1 on fatal error
 */
static int
_asynccomm (ipmiconsole_ctx_t c)
{
  uint8_t tmpbyte;
  ssize_t len;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);

  if ((len = read (c->connection.asynccomm[0], (void *)&tmpbyte, 1)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("read: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }

  if (!len)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("asynccomm closed"));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  /* User may have requested several break conditions in a
   * row quickly.  We assume it means just one
   */
  if (tmpbyte == IPMICONSOLE_PIPE_GENERATE_BREAK_CODE)
    {
      if (!(c->session.break_requested))
        {
          int bytes_before_break;

          c->session.break_requested++;

          if ((bytes_before_break = scbuf_used (c->connection.console_remote_console_to_bmc)) < 0)
            {
              IPMICONSOLE_CTX_DEBUG (c, ("scbuf_used: %s", strerror (errno)));
              ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
              return (-1);
            }
          c->session.console_remote_console_to_bmc_bytes_before_break = bytes_before_break;
        }
    }

  return (0);
}
示例#13
0
int
ipmiconsole_check_outbound_sequence_number (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint32_t session_sequence_number;
    uint64_t val;
    int rv = 0;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    if (FIID_OBJ_GET (c->connection.obj_rmcpplus_session_hdr_rs,
                      "session_sequence_number",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'session_sequence_number': %s",
                                   fiid_obj_errormsg (c->connection.obj_rmcpplus_session_hdr_rs)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    session_sequence_number = val;

    if ((rv = ipmi_check_session_sequence_number_2_0 (session_sequence_number,
              &(c->session.highest_received_sequence_number),
              &(c->session.previously_received_list),
              0)) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("ipmi_check_session_sequence_number_2_0: 'session_sequence_number': %s",
                                   fiid_obj_errormsg (c->connection.obj_rmcpplus_session_hdr_rs)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }

    if (!rv)
        IPMICONSOLE_CTX_DEBUG (c, ("session sequence number check failed; p = %d; session_sequence_number = %u; highest_received_sequence_number = %u", p, session_sequence_number, c->session.highest_received_sequence_number));

    return (rv);
}
示例#14
0
int
ipmiconsole_check_checksum (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    fiid_obj_t obj_cmd;
    int rv;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    /* IPMI Workaround
     *
     * Discovered on Supermicro X9SCM-iiF, Supermicro X9DRi-F
     *
     * Checksums are computed incorrectly.
     */
    if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_NO_CHECKSUM_CHECK)
        return (1);

    obj_cmd = ipmiconsole_packet_object (c, p);
    if ((rv = ipmi_lan_check_checksum (c->connection.obj_lan_msg_hdr_rs,
                                       obj_cmd,
                                       c->connection.obj_lan_msg_trlr_rs)) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_check_checksum: p = %d; %s", p, strerror (errno)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }

    if (!rv)
        IPMICONSOLE_CTX_DEBUG (c, ("checksum check failed; p = %d", p));

    return (rv);
}
示例#15
0
int
ipmiconsole_check_packet (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    fiid_obj_t obj_cmd;
    int rv;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));

    obj_cmd = ipmiconsole_packet_object (c, p);
    if ((rv = fiid_obj_packet_valid (obj_cmd)) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_packet_valid: %s",
                                   fiid_obj_errormsg (obj_cmd)));
        return (-1);
    }

    if (!rv)
        IPMICONSOLE_CTX_DEBUG (c, ("invalid packet received; p = %d", p));

    return (rv);
}
示例#16
0
int
ipmiconsole_check_completion_code (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t comp_code;
    fiid_obj_t obj_cmd;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    obj_cmd = ipmiconsole_packet_object (c, p);
    if (FIID_OBJ_GET (obj_cmd,
                      "comp_code",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'comp_code': %s",
                                   fiid_obj_errormsg (obj_cmd)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    comp_code = val;

    if (comp_code != IPMI_COMP_CODE_COMMAND_SUCCESS)
        IPMICONSOLE_CTX_DEBUG (c, ("completion code check failed; p = %d; comp_code = %Xh", p, comp_code));

    return ((comp_code == IPMI_COMP_CODE_COMMAND_SUCCESS) ? 1 : 0);
}
示例#17
0
int
ipmiconsole_check_command (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint8_t cmd, expected_cmd;
    fiid_obj_t obj_cmd;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    obj_cmd = ipmiconsole_packet_object (c, p);
    if (FIID_OBJ_GET (obj_cmd,
                      "cmd",
                      &val) < 0)
    {
        IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'cmd': %s",
                                   fiid_obj_errormsg (obj_cmd)));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }
    cmd = val;

    switch (p)
    {
    case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
        expected_cmd = IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES;
        break;
    case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
        expected_cmd = IPMI_CMD_SET_SESSION_PRIVILEGE_LEVEL;
        break;
    case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
        expected_cmd = IPMI_CMD_GET_CHANNEL_PAYLOAD_SUPPORT;
        break;
    case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
        expected_cmd = IPMI_CMD_GET_PAYLOAD_ACTIVATION_STATUS;
        break;
    case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
        expected_cmd = IPMI_CMD_ACTIVATE_PAYLOAD;
        break;
    case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
        expected_cmd = IPMI_CMD_GET_CHANNEL_PAYLOAD_VERSION;
        break;
    case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
        expected_cmd = IPMI_CMD_DEACTIVATE_PAYLOAD;
        break;
    case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
        expected_cmd = IPMI_CMD_CLOSE_SESSION;
        break;
    default:
        IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: p = %d", p));
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
        return (-1);
    }

    if (cmd != expected_cmd)
        IPMICONSOLE_CTX_DEBUG (c, ("command check failed; p = %d; cmd = %Xh; expected_cmd = %Xh", p, cmd, expected_cmd));

    return ((cmd == expected_cmd) ? 1 : 0);
}
示例#18
0
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);
}
示例#19
0
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);
}
示例#20
0
static void
__ipmiconsole_ctx_connection_cleanup (ipmiconsole_ctx_t c, int session_submitted)
{
  int blocking_requested = 0;
  int status_initial = 0;
  int secure_malloc_flag;
  int perr;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);

  secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0;

  /* We have to cleanup, so in general continue on even if locking fails */

  if ((perr = pthread_mutex_lock (&(c->signal.status_mutex))) != 0)
    IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));

  /* Don't change status if it's already been set before */
  if (c->signal.status != IPMICONSOLE_CTX_STATUS_SOL_ESTABLISHED)
    {
      c->signal.status = IPMICONSOLE_CTX_STATUS_SOL_ERROR;
      status_initial++;
    }

  if ((perr = pthread_mutex_unlock (&(c->signal.status_mutex))) != 0)
    IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));

  if ((perr = pthread_mutex_lock (&(c->blocking.blocking_mutex))) != 0)
    IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));

  if (c->blocking.blocking_submit_requested
      && !c->blocking.sol_session_established)
    {
      uint8_t tmpbyte;

      blocking_requested++;

      if (c->config.behavior_flags & IPMICONSOLE_BEHAVIOR_DEACTIVATE_ONLY
          && c->session.deactivate_only_succeeded_flag)
        tmpbyte = IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_DEACTIVATED;
      else
        tmpbyte = IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_ERROR;

      if (write (c->blocking.blocking_notification[1], &tmpbyte, 1) < 0)
        IPMICONSOLE_CTX_DEBUG (c, ("write: %s", strerror (errno)));
    }

  if ((perr = pthread_mutex_unlock (&(c->blocking.blocking_mutex))) != 0)
    IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));

  /* only call the callback if it's an initial SOL error and blocking
   * was not requested and the session was submitted.  We do not want
   * to call the callback if an error happened in API land and we are
   * calling in via
   * ipmiconsole_ctx_connection_cleanup_session_not_submitted().
   */
  if (status_initial
      && !blocking_requested
      && session_submitted
      && c->non_blocking.callback)
    (*(c->non_blocking.callback))(c->non_blocking.callback_arg);

  /* Under default circumstances, close only the ipmiconsole_fd so
   * that an error will be detected by the user via a EOF on a read()
   * or EPIPE on a write() when reading/writing on their file
   * descriptor.
   *
   * On error situations (i.e. ipmiconsole_engine_submit() doesn't
   * return to the user w/ success), it is the responsibility of other
   * code to call _ipmiconsole_ctx_api_managed_session_data_cleanup().
   *
   * The exception to this is when the user specifies the
   * IPMICONSOLE_ENGINE_CLOSE_FD flag.  Then we close it here
   */
  if (c->config.engine_flags & IPMICONSOLE_ENGINE_CLOSE_FD)
    {
      /* ignore potential error, cleanup path */
      if (c->connection.user_fd >= 0)
        close (c->connection.user_fd);
    }
  /* ignore potential error, cleanup path */
  if (c->connection.ipmiconsole_fd >= 0)
    close (c->connection.ipmiconsole_fd);
  if (c->connection.console_remote_console_to_bmc)
    scbuf_destroy (c->connection.console_remote_console_to_bmc, secure_malloc_flag);
  if (c->connection.console_bmc_to_remote_console)
    scbuf_destroy (c->connection.console_bmc_to_remote_console, secure_malloc_flag);
  /* ignore potential error, cleanup path */
  if (c->connection.ipmi_fd >= 0)
    close (c->connection.ipmi_fd);
  if (c->connection.ipmi_from_bmc)
    scbuf_destroy (c->connection.ipmi_from_bmc, secure_malloc_flag);
  if (c->connection.ipmi_to_bmc)
    scbuf_destroy (c->connection.ipmi_to_bmc, secure_malloc_flag);
  /* Similarly to the user_fd above, it is the responsibility of other
   * code to close asynccomm[0] and asynccomm[1], which is replicated
   * in the context.
   */
  if (c->connection.obj_rmcp_hdr_rq)
    fiid_obj_destroy (c->connection.obj_rmcp_hdr_rq);
  if (c->connection.obj_rmcp_hdr_rs)
    fiid_obj_destroy (c->connection.obj_rmcp_hdr_rs);
  if (c->connection.obj_lan_session_hdr_rq)
    fiid_obj_destroy (c->connection.obj_lan_session_hdr_rq);
  if (c->connection.obj_lan_session_hdr_rs)
    fiid_obj_destroy (c->connection.obj_lan_session_hdr_rs);
  if (c->connection.obj_lan_msg_hdr_rq)
    fiid_obj_destroy (c->connection.obj_lan_msg_hdr_rq);
  if (c->connection.obj_lan_msg_hdr_rs)
    fiid_obj_destroy (c->connection.obj_lan_msg_hdr_rs);
  if (c->connection.obj_lan_msg_trlr_rs)
    fiid_obj_destroy (c->connection.obj_lan_msg_trlr_rs);
  if (c->connection.obj_rmcpplus_session_hdr_rq)
    fiid_obj_destroy (c->connection.obj_rmcpplus_session_hdr_rq);
  if (c->connection.obj_rmcpplus_session_hdr_rs)
    fiid_obj_destroy (c->connection.obj_rmcpplus_session_hdr_rs);
  if (c->connection.obj_rmcpplus_payload_rs)
    fiid_obj_destroy (c->connection.obj_rmcpplus_payload_rs);
  if (c->connection.obj_rmcpplus_session_trlr_rq)
    fiid_obj_destroy (c->connection.obj_rmcpplus_session_trlr_rq);
  if (c->connection.obj_rmcpplus_session_trlr_rs)
    fiid_obj_destroy (c->connection.obj_rmcpplus_session_trlr_rs);
  if (c->connection.obj_authentication_capabilities_rq)
    fiid_obj_destroy (c->connection.obj_authentication_capabilities_rq);
  if (c->connection.obj_authentication_capabilities_rs)
    fiid_obj_destroy (c->connection.obj_authentication_capabilities_rs);
  if (c->connection.obj_open_session_request)
    fiid_obj_destroy (c->connection.obj_open_session_request);
  if (c->connection.obj_open_session_response)
    fiid_obj_destroy (c->connection.obj_open_session_response);
  if (c->connection.obj_rakp_message_1)
    fiid_obj_destroy (c->connection.obj_rakp_message_1);
  if (c->connection.obj_rakp_message_2)
    fiid_obj_destroy (c->connection.obj_rakp_message_2);
  if (c->connection.obj_rakp_message_3)
    fiid_obj_destroy (c->connection.obj_rakp_message_3);
  if (c->connection.obj_rakp_message_4)
    fiid_obj_destroy (c->connection.obj_rakp_message_4);
  if (c->connection.obj_set_session_privilege_level_rq)
    fiid_obj_destroy (c->connection.obj_set_session_privilege_level_rq);
  if (c->connection.obj_set_session_privilege_level_rs)
    fiid_obj_destroy (c->connection.obj_set_session_privilege_level_rs);
  if (c->connection.obj_get_channel_payload_support_rq)
    fiid_obj_destroy (c->connection.obj_get_channel_payload_support_rq);
  if (c->connection.obj_get_channel_payload_support_rs)
    fiid_obj_destroy (c->connection.obj_get_channel_payload_support_rs);
  if (c->connection.obj_get_payload_activation_status_rq)
    fiid_obj_destroy (c->connection.obj_get_payload_activation_status_rq);
  if (c->connection.obj_get_payload_activation_status_rs)
    fiid_obj_destroy (c->connection.obj_get_payload_activation_status_rs);
  if (c->connection.obj_activate_payload_rq)
    fiid_obj_destroy (c->connection.obj_activate_payload_rq);
  if (c->connection.obj_activate_payload_rs)
    fiid_obj_destroy (c->connection.obj_activate_payload_rs);
  if (c->connection.obj_sol_payload_data_rq)
    fiid_obj_destroy (c->connection.obj_sol_payload_data_rq);
  if (c->connection.obj_sol_payload_data_rs)
    fiid_obj_destroy (c->connection.obj_sol_payload_data_rs);
  if (c->connection.obj_get_channel_payload_version_rq)
    fiid_obj_destroy (c->connection.obj_get_channel_payload_version_rq);
  if (c->connection.obj_get_channel_payload_version_rs)
    fiid_obj_destroy (c->connection.obj_get_channel_payload_version_rs);
  if (c->connection.obj_deactivate_payload_rq)
    fiid_obj_destroy (c->connection.obj_deactivate_payload_rq);
  if (c->connection.obj_deactivate_payload_rs)
    fiid_obj_destroy (c->connection.obj_deactivate_payload_rs);
  if (c->connection.obj_close_session_rq)
    fiid_obj_destroy (c->connection.obj_close_session_rq);
  if (c->connection.obj_close_session_rs)
    fiid_obj_destroy (c->connection.obj_close_session_rs);

  _ipmiconsole_ctx_connection_init (c);

  /* If the session was never submitted (i.e. error in API land), don't
   * move this around.
   */

  /* achu: See note in ipmiconsole_defs.h about the
   * c->session_submitted flag.  That flag is only used in API land
   * for the user to know if a session was submitted or not.  The
   * session_submitted flag passed into this function is the "real"
   * one that is known by the engine, and is not dependent on any race
   * conditions with the API level.
   */

  if (!session_submitted)
    return;

  /* Be careful, if the user requested to destroy the context, we can
   * destroy it here.  But if we destroy it, there is no mutex to
   * unlock.
   */

  /* Note: the code in __ipmiconsole_ctx_connection_cleanup() and
   * ipmiconsole_garbage_collector() may look like it may race and
   * could deadlock.  (ABBA and BAAB deadlock situation).  However,
   * the context mutex c->signal.destroyed_mutex is accessed in
   * __ipmiconsole_ctx_connection_cleanup() when trying to add this item
   * to the console_engine_ctxs_to_destroy list.  It is accessed in
   * ipmiconsole_garbage_collector() only on the items already in the
   * console_engine_ctxs_to_destroy list.  So the
   * c->signal.destroyed_mutex can never be raced against in these two
   * functions.
   */
  if ((perr = pthread_mutex_lock (&(c->signal.destroyed_mutex))) != 0)
    IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));

  if (c->signal.user_has_destroyed)
    {
      ipmiconsole_ctx_debug_cleanup (c);
      ipmiconsole_ctx_signal_cleanup (c);
      ipmiconsole_ctx_blocking_cleanup (c);
      ipmiconsole_ctx_cleanup (c);
    }
  else
    {
      if (!c->signal.moved_to_destroyed)
        {
          void *ptr;

          c->signal.moved_to_destroyed++;

          /* I suppose if we fail here, we mem-leak?? Log for now ... */

          if ((perr = pthread_mutex_lock (&(console_engine_ctxs_to_destroy_mutex))) != 0)
            IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));

          if (!(ptr = list_append (console_engine_ctxs_to_destroy, c)))
            IPMICONSOLE_DEBUG (("list_append: %s", strerror (errno)));

          if (ptr != (void *)c)
            IPMICONSOLE_DEBUG (("list_append: invalid pointer: ptr=%p; c=%p", ptr, c));

          if ((perr = pthread_mutex_unlock (&(console_engine_ctxs_to_destroy_mutex))) != 0)
            IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));
        }

      if ((perr = pthread_mutex_unlock (&(c->signal.destroyed_mutex))) != 0)
        IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));
    }
}
/*
 * Return 0 on success
 * Return -1 on fatal error
 */
static int
_ipmi_recvfrom (ipmiconsole_ctx_t c)
{
  char buffer[IPMICONSOLE_PACKET_BUFLEN];
  struct sockaddr_in from;
  unsigned int fromlen = sizeof (struct sockaddr_in);
  ssize_t len;
  int n, dropped = 0;
  int secure_malloc_flag;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);

  secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0;

  do
    {
      /* For receive side, ipmi_lan_recvfrom and
       * ipmi_rmcpplus_recvfrom are identical.  So we just use
       * ipmi_lan_recvfrom for both.
       *
       * In event of future change, should use util functions
       * ipmi_is_ipmi_1_5_packet or ipmi_is_ipmi_2_0_packet
       * appropriately.
       */
      len = ipmi_lan_recvfrom (c->connection.ipmi_fd,
                               buffer,
                               IPMICONSOLE_PACKET_BUFLEN,
                               0,
                               (struct sockaddr *)&from,
                               &fromlen);
    } while (len < 0 && errno == EINTR);

  /* achu & hliebig:
   *
   * Premise from ipmitool (http://ipmitool.sourceforge.net/)
   *
   * On some OSes (it seems Unixes), the behavior is to not return
   * port denied errors up to the client for UDP responses (i.e. you
   * need to timeout).  But on some OSes (it seems Windows), the
   * behavior is to return port denied errors up to the user for UDP
   * responses via ECONNRESET or ECONNREFUSED.
   *
   * If this were just the case, we could return or handle errors
   * properly and move on.  However, it's not the case.
   *
   * According to Ipmitool, on some motherboards, both the OS and the
   * BMC are capable of responding to an IPMI request.  That means you
   * can get an ECONNRESET or ECONNREFUSED, then later on, get your
   * real IPMI response.
   *
   * Our solution is copied from Ipmitool, we'll ignore some specific
   * errors and try to read again.
   *
   * If the ECONNREFUSED or ECONNRESET is from the OS, but we will get
   * an IPMI response later, the recvfrom later on gets the packet we
   * want.
   *
   * If the ECONNREFUSED or ECONNRESET is from the OS but there is no
   * BMC (or IPMI disabled, etc.), just do the recvfrom again to
   * eventually get a timeout, which is the behavior we'd like.
   */
  if (len < 0
      && (errno == ECONNRESET
          || errno == ECONNREFUSED))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_recvfrom: connection refused: %s", strerror (errno)));
      return (0);
    }

  if (len < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_recvfrom: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }

  if (!len)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_recvfrom: no data", strerror (errno)));
      /* Note: Not a fatal error, just return*/
      return (0);
    }

  /* Sanity Check */
  if (from.sin_family != AF_INET
      || from.sin_addr.s_addr != c->session.addr.sin_addr.s_addr)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("received from invalid address"));
      /* Note: Not a fatal error, just return */
      return (0);
    }

  /* Empty the scbuf if it's not empty */
  if (!scbuf_is_empty (c->connection.ipmi_from_bmc))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_from_bmc not empty, draining"));
      do {
        char tempbuf[IPMICONSOLE_PACKET_BUFLEN];
        if (scbuf_read (c->connection.ipmi_from_bmc, tempbuf, IPMICONSOLE_PACKET_BUFLEN) < 0)
          {
            IPMICONSOLE_CTX_DEBUG (c, ("scbuf_read: %s", strerror (errno)));
            break;
          }
      } while(!scbuf_is_empty (c->connection.ipmi_from_bmc));
    }

  if ((n = scbuf_write (c->connection.ipmi_from_bmc, buffer, len, &dropped, secure_malloc_flag)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_write: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (n != len)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_write: invalid bytes written; n=%d; len=%d", n, len));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (dropped)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_write: dropped data: dropped=%d", dropped));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  return (0);
}
/*
 * Return 0 on success
 * Return -1 on fatal error
 */
static int
_ipmi_sendto (ipmiconsole_ctx_t c)
{
  char buffer[IPMICONSOLE_PACKET_BUFLEN];
  ssize_t len;
  int n;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);

  if ((n = scbuf_read (c->connection.ipmi_to_bmc, buffer, IPMICONSOLE_PACKET_BUFLEN)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_read: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (ipmi_is_ipmi_1_5_packet (buffer, n))
    {
      do
	{
	  len = ipmi_lan_sendto (c->connection.ipmi_fd,
				 buffer,
				 n,
				 0,
				 (struct sockaddr *)&(c->session.addr),
				 sizeof (struct sockaddr_in));
	} while (len < 0 && errno == EINTR);
    }
  else
    {
      do
	{
	  len = ipmi_rmcpplus_sendto (c->connection.ipmi_fd,
				      buffer,
				      n,
				      0,
				      (struct sockaddr *)&(c->session.addr),
				      sizeof (struct sockaddr_in));
	} while (len < 0 && errno == EINTR);
    }

  if (len < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_sendto: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }

#if 0
  /* don't check, let bad packet timeout */
  if (len != n)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_sendto: invalid bytes written; n=%d; len=%d", n, len));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }
#endif

  /* scbuf should be empty now */
  if (!scbuf_is_empty (c->connection.ipmi_to_bmc))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_to_bmc not empty"));
      /* Note: Not a fatal error, just return*/
      return (0);
    }

  return (0);
}
static void *
_ipmiconsole_engine (void *arg)
{
  int perr, ctxs_count = 0;
  unsigned int index;
  unsigned int teardown_flag = 0;
  unsigned int teardown_initiated = 0;

  assert (arg);

  index = *((unsigned int *)arg);

  assert (index < IPMICONSOLE_THREAD_COUNT_MAX);

  free (arg);

  /* No need to exit on failure, probability is low we'll SIGPIPE anyways */
  if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
    IPMICONSOLE_DEBUG (("signal: %s", strerror (errno)));

  while (!teardown_flag || ctxs_count)
    {
      struct _ipmiconsole_poll_data poll_data;
      int count;
      unsigned int timeout_len;
      unsigned int i;
      int unlock_console_engine_ctxs_mutex_flag = 0;
      int spin_wait_flag = 0;
      char buf[IPMICONSOLE_PIPE_BUFLEN];

      memset (&poll_data, '\0', sizeof (struct _ipmiconsole_poll_data));

      if ((perr = pthread_mutex_lock (&console_engine_teardown_mutex)))
        {
          /* This is one of the only truly "fatal" conditions */
          IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));
          teardown_flag = 1;
        }

      if (console_engine_teardown_immediate)
        {
          if ((perr = pthread_mutex_unlock (&console_engine_teardown_mutex)))
            IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));
          break;
        }

      if (console_engine_teardown)
        teardown_flag = 1;

      if ((perr = pthread_mutex_unlock (&console_engine_teardown_mutex)))
        {
          /* This is one of the only truly "fatal" conditions */
          IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));
          teardown_flag = 1;
        }

      /* Notes:
       *
       * We must lock the list from here till all context data and pointers
       * are retrieved.
       */

      if ((perr = pthread_mutex_lock (&console_engine_ctxs_mutex[index])))
        {
          /* This is one of the only truly "fatal" conditions */
          IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));
          teardown_flag = 1;
        }

      /* Note: Set close_session_flag in the contexts before
       * ipmiconsole_process_ctxs(), so the initiation of the closing
       * down will begin now rather than the next iteration of the
       * loop.
       */
      if (teardown_flag && !teardown_initiated)
        {
          /* XXX: Umm, if this fails, we may not be able to teardown
           * cleanly.  Break out of the loop I guess.
           */
          if (list_for_each (console_engine_ctxs[index], _teardown_initiate, NULL) < 0)
            {
              IPMICONSOLE_DEBUG (("list_for_each: %s", strerror (errno)));
              break;
            }
          teardown_initiated++;
        }

      if ((ctxs_count = ipmiconsole_process_ctxs (console_engine_ctxs[index], &timeout_len)) < 0)
        goto continue_loop;

      if (!ctxs_count && teardown_flag)
        continue;

      if (!ctxs_count)
        {
          spin_wait_flag++;
          goto continue_loop;
        }
      poll_data.ctxs_len = ctxs_count;

      /* achu: I always wonder if this poll() loop could be done far
       * more elegantly and efficiently without all this crazy
       * indexing, perhaps through a callback/event mechanism.  It'd
       * probably be more efficient, since most callback/event based
       * models have min-heap like structures inside for determining
       * what things timed out. Overall though, I don't think the O(n)
       * (n being hosts/fds) processing is really that inefficient for
       * this particular application and is not worth going back and
       * changing.  By going to a callback/event mechanism, there will
       * still be some O(n) activities within the code, so I am only
       * going to create a more efficient O(n) poll loop.
       */

      /*
       * There are 3 pfds per ctx.  One for 'ipmi_fd', 'asynccomm[0]', and 'ipmiconsole_fd'.
       *
       * There is + 1 pfds for the "console_engine_ctxs_notifier".
       * This will be set up manually here, and not in _poll_setup().
       */
      if (!(poll_data.pfds = (struct pollfd *)malloc (((poll_data.ctxs_len * 3) + 1) * sizeof (struct pollfd))))
        {
          IPMICONSOLE_DEBUG (("malloc: %s", strerror (errno)));
          goto continue_loop;
        }

      if (!(poll_data.pfds_ctxs = (ipmiconsole_ctx_t *)malloc (poll_data.ctxs_len * sizeof (ipmiconsole_ctx_t))))
        {
          IPMICONSOLE_DEBUG (("malloc: %s", strerror (errno)));
          goto continue_loop;
        }

      if ((count = list_for_each (console_engine_ctxs[index], _poll_setup, &poll_data)) < 0)
        {
          IPMICONSOLE_DEBUG (("list_for_each: %s", strerror (errno)));
          goto continue_loop;
        }

      if ((perr = pthread_mutex_unlock (&console_engine_ctxs_mutex[index])))
        IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));
      unlock_console_engine_ctxs_mutex_flag++;

      /* Setup notifier pipe as last remaining poll data */
      poll_data.pfds[(poll_data.ctxs_len * 3)].fd = console_engine_ctxs_notifier[index][0];
      poll_data.pfds[(poll_data.ctxs_len * 3)].events = POLLIN;
      poll_data.pfds[(poll_data.ctxs_len * 3)].revents = 0;

      if (count != ctxs_count)
        {
          IPMICONSOLE_DEBUG (("list_for_each: invalid length returned: %d", count));
          goto continue_loop;
        }

      if (poll_data.pfds_index != ctxs_count)
        {
          IPMICONSOLE_DEBUG (("invalid index set on returned: %d", poll_data.pfds_index));
          goto continue_loop;
        }

      if (_ipmiconsole_poll (poll_data.pfds, (poll_data.ctxs_len * 3) + 1, timeout_len) < 0)
        {
          IPMICONSOLE_DEBUG (("poll: %s", strerror (errno)));
          goto continue_loop;
        }

      for (i = 0; i < poll_data.ctxs_len; i++)
        {
          if (poll_data.pfds[i*3].revents & POLLERR)
            {
              IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLERR"));
              /* See comments in _ipmi_recvfrom() regarding ECONNRESET/ECONNREFUSED */
              if (_ipmi_recvfrom (poll_data.pfds_ctxs[i]) < 0)
                {
                  ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_SYSTEM_ERROR);
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
            }
          if (!poll_data.pfds_ctxs[i]->session.close_session_flag)
            {
              if (poll_data.pfds[i*3+1].revents & POLLNVAL)
                {
                  /* This indicates the user closed the asynccomm file descriptors
                   * which is ok.
                   */
                  IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLNVAL"));
                  ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_SUCCESS);
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
              if (poll_data.pfds[i*3+2].revents & POLLHUP)
                {
                  /* This indicates the user closed the other end of
                   * the socketpair so it's ok.
                   */
                  IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLHUP"));
                  ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_SUCCESS);
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
              if (poll_data.pfds[i*3+1].revents & POLLERR)
                {
                  IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLERR"));
                  ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_INTERNAL_ERROR);
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
              if (poll_data.pfds[i*3+2].revents & POLLERR)
                {
                  IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLERR"));
                  ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_INTERNAL_ERROR);
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
            }
          if (poll_data.pfds[i*3].revents & POLLIN)
            {
              if (_ipmi_recvfrom (poll_data.pfds_ctxs[i]) < 0)
                {
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
            }
          if (poll_data.pfds[i*3].revents & POLLOUT)
            {
              if (_ipmi_sendto (poll_data.pfds_ctxs[i]) < 0)
                {
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
            }
          if (poll_data.pfds[i*3 + 1].revents & POLLIN)
            {
              if (_asynccomm (poll_data.pfds_ctxs[i]) < 0)
                {
                  poll_data.pfds_ctxs[i]->session.close_session_flag++;
                  continue;
                }
            }
          if (!poll_data.pfds_ctxs[i]->session.close_session_flag)
            {
              if (poll_data.pfds[i*3+2].revents & POLLIN)
                {
                  if (_console_read (poll_data.pfds_ctxs[i]) < 0)
                    {
                      poll_data.pfds_ctxs[i]->session.close_session_flag++;
                      continue;
                    }
                }
              if (poll_data.pfds[i*3+2].revents & POLLOUT)
                {
                  if (_console_write (poll_data.pfds_ctxs[i]) < 0)
                    {
                      poll_data.pfds_ctxs[i]->session.close_session_flag++;
                      continue;
                    }
                }
            }
        }

      /* We don't care what's read, just get it off the fd */
      if (poll_data.pfds[(poll_data.ctxs_len * 3)].revents & POLLIN)
        {
          if (read (console_engine_ctxs_notifier[index][0], buf, IPMICONSOLE_PIPE_BUFLEN) < 0)
            IPMICONSOLE_DEBUG (("read: %s", strerror (errno)));
        }

    continue_loop:
      if (!unlock_console_engine_ctxs_mutex_flag)
        {
          if ((perr = pthread_mutex_unlock (&console_engine_ctxs_mutex[index])))
            {
              /* This is one of the only truly "fatal" conditions */
              IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));
              teardown_flag = 1;
            }
        }
      if (spin_wait_flag)
        {
          /* No contexts stored, either because they all died or none
           * have been submitted yet.  Sleep a little bit to kill some
           * time and avoid spinning.
           */
          /* XXX: Is this portable? */
          usleep (IPMICONSOLE_SPIN_WAIT_TIME);
        }
      free (poll_data.pfds);
      free (poll_data.pfds_ctxs);
    }

  /* No way to return error, so just continue on even if there is a failure */
  if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex)))
    IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr)));

  console_engine_thread_count--;

  if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex)))
    IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr)));

  return (NULL);
}
示例#24
0
int
ipmiconsole_ctx_connection_setup (ipmiconsole_ctx_t c)
{
  struct sockaddr_in srcaddr;
  int sv[2];
  int secure_malloc_flag;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);
  assert (!(c->session_submitted));

  _ipmiconsole_ctx_connection_init (c);

  /* File Descriptor User Interface */

  if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
    {
      IPMICONSOLE_DEBUG (("socketpair: %s", strerror (errno)));
      if (errno == EMFILE)
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES);
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }
  c->connection.user_fd = sv[0];
  c->connection.ipmiconsole_fd = sv[1];

  if (ipmiconsole_set_closeonexec (c, c->connection.user_fd) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }
  if (ipmiconsole_set_closeonexec (c, c->connection.ipmiconsole_fd) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  /* Copy for API level */
  c->fds.user_fd = c->connection.user_fd;

  secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0;

  if (!(c->connection.console_remote_console_to_bmc = scbuf_create (CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MIN, CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  if (!(c->connection.console_bmc_to_remote_console = scbuf_create (CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MIN, CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  /* Connection Data */

  if ((c->connection.ipmi_fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    {
      IPMICONSOLE_DEBUG (("socket: %s", strerror (errno)));
      if (errno == EMFILE)
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES);
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  if (ipmiconsole_set_closeonexec (c, c->connection.ipmi_fd) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  memset (&srcaddr, '\0', sizeof (struct sockaddr_in));
  srcaddr.sin_family = AF_INET;
  srcaddr.sin_port = htons (0);
  srcaddr.sin_addr.s_addr = htonl (INADDR_ANY);

  if (bind (c->connection.ipmi_fd, (struct sockaddr *)&srcaddr, sizeof (struct sockaddr_in)) < 0)
    {
      IPMICONSOLE_DEBUG (("bind: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  if (!(c->connection.ipmi_from_bmc = scbuf_create (IPMI_FROM_BMC_BUF_MIN, IPMI_FROM_BMC_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  if (!(c->connection.ipmi_to_bmc = scbuf_create (IPMI_TO_BMC_BUF_MIN, IPMI_TO_BMC_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  /* Pipe for non-fd communication */
  if (pipe (c->connection.asynccomm) < 0)
    {
      IPMICONSOLE_DEBUG (("pipe: %s", strerror (errno)));
      if (errno == EMFILE)
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES);
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  if (ipmiconsole_set_closeonexec (c, c->connection.asynccomm[0]) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  if (ipmiconsole_set_closeonexec (c, c->connection.asynccomm[1]) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  /* Copy for API level */
  c->fds.asynccomm[0] = c->connection.asynccomm[0];
  c->fds.asynccomm[1] = c->connection.asynccomm[1];

  /* Fiid Objects */

  if (!(c->connection.obj_rmcp_hdr_rq = fiid_obj_create (tmpl_rmcp_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcp_hdr_rs = fiid_obj_create (tmpl_rmcp_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_session_hdr_rq = fiid_obj_create (tmpl_lan_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_session_hdr_rs = fiid_obj_create (tmpl_lan_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_msg_hdr_rq = fiid_obj_create (tmpl_lan_msg_hdr_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_msg_hdr_rs = fiid_obj_create (tmpl_lan_msg_hdr_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_msg_trlr_rs = fiid_obj_create (tmpl_lan_msg_trlr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_hdr_rq = fiid_obj_create (tmpl_rmcpplus_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_hdr_rs = fiid_obj_create (tmpl_rmcpplus_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_payload_rs = fiid_obj_create (tmpl_rmcpplus_payload)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_trlr_rq = fiid_obj_create (tmpl_rmcpplus_session_trlr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_trlr_rs = fiid_obj_create (tmpl_rmcpplus_session_trlr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_authentication_capabilities_rq = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_authentication_capabilities_rs = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_open_session_request = fiid_obj_create (tmpl_rmcpplus_open_session_request)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_open_session_response = fiid_obj_create (tmpl_rmcpplus_open_session_response)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_1 = fiid_obj_create (tmpl_rmcpplus_rakp_message_1)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_2 = fiid_obj_create (tmpl_rmcpplus_rakp_message_2)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_3 = fiid_obj_create (tmpl_rmcpplus_rakp_message_3)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_4 = fiid_obj_create (tmpl_rmcpplus_rakp_message_4)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_set_session_privilege_level_rq = fiid_obj_create (tmpl_cmd_set_session_privilege_level_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_set_session_privilege_level_rs = fiid_obj_create (tmpl_cmd_set_session_privilege_level_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_support_rq = fiid_obj_create (tmpl_cmd_get_channel_payload_support_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_support_rs = fiid_obj_create (tmpl_cmd_get_channel_payload_support_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_payload_activation_status_rq = fiid_obj_create (tmpl_cmd_get_payload_activation_status_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_payload_activation_status_rs = fiid_obj_create (tmpl_cmd_get_payload_activation_status_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_activate_payload_rq = fiid_obj_create (tmpl_cmd_activate_payload_sol_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_activate_payload_rs = fiid_obj_create (tmpl_cmd_activate_payload_sol_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_sol_payload_data_rq = fiid_obj_create (tmpl_sol_payload_data_remote_console_to_bmc)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_sol_payload_data_rs = fiid_obj_create (tmpl_sol_payload_data_bmc_to_remote_console)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_version_rq = fiid_obj_create (tmpl_cmd_get_channel_payload_version_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_version_rs = fiid_obj_create (tmpl_cmd_get_channel_payload_version_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_deactivate_payload_rq = fiid_obj_create (tmpl_cmd_deactivate_payload_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_deactivate_payload_rs = fiid_obj_create (tmpl_cmd_deactivate_payload_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_close_session_rq = fiid_obj_create (tmpl_cmd_close_session_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_close_session_rs = fiid_obj_create (tmpl_cmd_close_session_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  return (0);

 cleanup:
  /* Previously called here, but this is now supposed to be handled in API land */
  /* ipmiconsole_ctx_connection_cleanup(c) */
  /* _ipmiconsole_ctx_fds_cleanup(c); */
  /* _ipmiconsole_ctx_fds_setup(c); */
  return (-1);
}
示例#25
0
int
ipmiconsole_check_session_id (ipmiconsole_ctx_t c, ipmiconsole_packet_type_t p)
{
    uint32_t session_id, expected_session_id;
    uint64_t val;

    assert (c);
    assert (c->magic == IPMICONSOLE_CTX_MAGIC);
    assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
    assert (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4
            || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS
            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS
            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS
            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS
            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS);

    if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
            || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4)
    {
        fiid_obj_t obj_cmd;

        obj_cmd = ipmiconsole_packet_object (c, p);

        if (FIID_OBJ_GET (obj_cmd,
                          "remote_console_session_id",
                          &val) < 0)
        {
            IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'remote_console_session_id': %s",
                                       fiid_obj_errormsg (obj_cmd)));
            ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
            return (-1);
        }
        session_id = val;
        expected_session_id = c->session.remote_console_session_id;
    }
    else
    {
        if (FIID_OBJ_GET (c->connection.obj_rmcpplus_session_hdr_rs,
                          "session_id",
                          &val) < 0)
        {
            IPMICONSOLE_CTX_DEBUG (c, ("FIID_OBJ_GET: 'session_id': %s",
                                       fiid_obj_errormsg (c->connection.obj_rmcpplus_session_hdr_rs)));
            ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
            return (-1);
        }
        session_id = val;
        expected_session_id = c->session.remote_console_session_id;
    }

    if (session_id != expected_session_id)
        IPMICONSOLE_CTX_DEBUG (c, ("session id check failed; p = %d; session_id = %Xh; expected_session_id = %Xh", p, session_id, expected_session_id));

    return ((session_id == expected_session_id) ? 1 : 0);
}