示例#1
0
文件: rakp.c 项目: wrouesnel/openipmi
static int
rakp_hmac_c4(rakp_info_t   *info,
             unsigned char *data,
             unsigned int  data_len)
{
    unsigned char       idata[36];
    unsigned int        ilen;
    unsigned char       integ_data[20];
    rakp_hmac_key_t     *rinfo = info->key_data;
    const unsigned char *p;
    unsigned int        plen;

    if (data_len < 8+rinfo->integ_len)
        return E2BIG;

    p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
    memcpy(idata+0, p, 16);
    ipmi_set_uint32(idata+16, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));
    p = ipmi_rmcpp_auth_get_mgsys_guid(info->ainfo, &plen);
    if (plen < 16)
        return EINVAL;
    memcpy(idata+20, p, 16);

    p = ipmi_rmcpp_auth_get_sik(info->ainfo, &plen);
    HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 36, integ_data, &ilen);
    if (memcmp(data+8, integ_data, rinfo->integ_len) != 0)
        return EINVAL;

    return 0;
}
示例#2
0
static void
handle_picmg_cmd_get_shelf_manager_ip_addresses(lmc_data_t    *mc,
						msg_t         *msg,
						unsigned char *rdata,
						unsigned int  *rdata_len,
						void          *cb_data)
{
    emu_data_t   *emu = mc->emu;
    unsigned int addr;
    unsigned int count;
    emu_addr_t   *ap = NULL;
    int          i;

    if (check_msg_length(msg, 2, rdata, rdata_len))
	return;

    addr = msg->data[1];
    
    for (count=0, i=0; i<MAX_EMU_ADDR; i++) {
	if (emu->addr[i].valid) {
	    if (count == addr)
		ap = &(emu->addr[i]);
	    count++;
	}
    }

    if (addr >= count) {
	rdata[0] = IPMI_PARAMETER_OUT_OF_RANGE_CC;
	*rdata_len = 1;
	return;
    }

    rdata[0] = 0;
    ipmi_set_uint32(rdata+1, emu->last_addr_change_time.tv_sec);
    rdata[5] = count;
    rdata[6] = 0x03;
    rdata[7] = addr - 1;
    rdata[8] = 20;

    rdata[9] = ap->addr_type;
    if (addr == 0)
	rdata[9] |= 0x80;
    memcpy(rdata+10, ap->addr_data, ap->addr_len);
    *rdata_len = 10 + ap->addr_len;
}
示例#3
0
文件: rakp.c 项目: wrouesnel/openipmi
static int
send_rakp3(ipmi_con_t *ipmi, rakp_info_t *info,
           ipmi_msgi_t *rspi, int addr_num, int err)
{
    int                 rv;
    unsigned char       data[64];
    ipmi_msg_t          msg;
    ipmi_rmcpp_addr_t   addr;

    memset(data, 0, sizeof(data));
    data[0] = info->msg_tag;
    data[1] = err;
    ipmi_set_uint32(data+4, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));

    msg.netfn = IPMI_RMCPP_DUMMY_NETFN;
    msg.cmd = 0;
    msg.data = data;
    msg.data_len = 8;
    addr.addr_type = IPMI_RMCPP_ADDR_START + IPMI_RMCPP_PAYLOAD_TYPE_RAKP_3;
    rspi->data1 = info;

    if (info->set3) {
        unsigned int len;
        len = msg.data_len;
        rv = info->set3(info, data, &len, sizeof(data));
        if (rv)
            return rv;
        msg.data_len = len;
    }

    if (err)
        /* Don't handle the responst (if one comes back) on an error. */
        rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
                                           (ipmi_addr_t *) &addr, sizeof(addr),
                                           &msg, NULL, rspi);
    else
        rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
                                           (ipmi_addr_t *) &addr, sizeof(addr),
                                           &msg, handle_rakp4, rspi);
    return rv;
}
示例#4
0
文件: rakp.c 项目: wrouesnel/openipmi
static int
send_rakp1(ipmi_con_t *ipmi, rakp_info_t *info,
           ipmi_msgi_t *rspi, int addr_num)
{
    int                 rv;
    unsigned char       data[44];
    ipmi_msg_t          msg;
    ipmi_rmcpp_addr_t   addr;
    const unsigned char *p;
    unsigned int        plen;

    memset(data, 0, sizeof(data));
    data[0] = info->msg_tag;
    ipmi_set_uint32(data+4, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));

    p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
    if (plen < 16)
        return EINVAL;
    memcpy(data+8, p, 16);

    data[24] = ipmi_rmcpp_auth_get_role(info->ainfo);
    data[27] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
    p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
    if (plen < 16)
        return EINVAL;
    memcpy(data+28, p, data[27]);

    msg.netfn = IPMI_RMCPP_DUMMY_NETFN;
    msg.cmd = 0;
    msg.data = data;
    msg.data_len = 28 + data[27];
    addr.addr_type = IPMI_RMCPP_ADDR_START + IPMI_RMCPP_PAYLOAD_TYPE_RAKP_1;
    rspi->data1 = info;

    rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
                                       (ipmi_addr_t *) &addr, sizeof(addr),
                                       &msg, handle_rakp2, rspi);
    return rv;
}
示例#5
0
文件: rakp.c 项目: wrouesnel/openipmi
static int
rakp_hmac_s3(rakp_info_t   *info,
             unsigned char *data,
             unsigned int  *data_len,
             unsigned int  total_len)
{
    unsigned char       idata[38];
    unsigned int        ilen;
    rakp_hmac_key_t     *rinfo = info->key_data;
    const unsigned char *p;
    unsigned int        plen;

    if (((*data_len)+rinfo->key_len) > total_len)
        return E2BIG;

    p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
    memcpy(idata+0, p, 16);
    ipmi_set_uint32(idata+16, ipmi_rmcpp_auth_get_my_session_id(info->ainfo));
    idata[20] = ipmi_rmcpp_auth_get_role(info->ainfo);
    if (info->hacks & IPMI_CONN_HACK_RAKP3_WRONG_ROLEM)
        /* For the RAKP3 message, the Intel BMC only uses the bottom 4
           nibbles. */
        idata[20] &= 0xf;
    idata[21] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
    if (idata[21] > 16)
        return EINVAL;
    p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
    memcpy(idata+22, p, idata[21]);

    p = ipmi_rmcpp_auth_get_password(info->ainfo, &plen);
    if (plen < rinfo->key_len)
        return EINVAL;

    HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 22+idata[21],
         data+*data_len, &ilen);
    *data_len += rinfo->key_len;
    return 0;
}
示例#6
0
文件: sol.c 项目: turtle-fly/openipmi
void
ipmi_sol_activate(lmc_data_t    *mc,
		  channel_t     *channel,
		  msg_t         *msg,
		  unsigned char *rdata,
		  unsigned int  *rdata_len)
{
    ipmi_sol_t *sol = ipmi_mc_get_sol(mc);
    soldata_t *sd = sol->soldata;
    uint16_t port;
    int rv;
    msg_t *dmsg;
    unsigned int instance;

    if (!sol->solparm.enabled) {
	rdata[0] = 0x81; /* Payload is disabled. */
	*rdata_len = 1;
	return;
    }

    /*
     * FIXME - we are currently ignoring all the payload encryption and
     * authentication bits in the message.
     */

    instance = msg->data[1] & 0xf;
    if (instance == 1) {
	if (sol->active) {
	    *rdata = 0x80; /* Payload already active */
	    *rdata_len = 1;
	    return;
	}
	dmsg = &sd->dummy_send_msg;
    } else if (instance == 2 && sol->history_size) {
	if (sol->history_active) {
	    *rdata = 0x80; /* Payload already active */
	    *rdata_len = 1;
	    return;
	}
	dmsg = &sd->history_dummy_send_msg;
    } else {
	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
	*rdata_len = 1;
	return;
    }

    dmsg->src_addr = sd->sys->alloc(sd->sys, msg->src_len);
    if (!dmsg->src_addr) {
	rdata[0] = IPMI_OUT_OF_SPACE_CC;
	*rdata_len = 1;
	return;
    }
    memcpy(dmsg->src_addr, msg->src_addr, msg->src_len);
    dmsg->src_len = msg->src_len;
    dmsg->rmcpp.payload = IPMI_RMCPP_PAYLOAD_TYPE_SOL;

    rv = channel->set_associated_mc(channel, msg->sid, msg->data[0] & 0xf, mc,
				    &port, sol_session_closed, sol);
    if (rv == EBUSY) {
	sd->sys->free(sd->sys, dmsg->src_addr);
	dmsg->src_addr = NULL;
	rdata[0] = IPMI_NODE_BUSY_CC;
	*rdata_len = 1;
	return;
    } else if (rv) {
	sd->sys->free(sd->sys, dmsg->src_addr);
	dmsg->src_addr = NULL;
	rdata[0] = IPMI_UNKNOWN_ERR_CC;
	*rdata_len = 1;
	return;
    }

    dmsg->sid = msg->sid;

    if (instance == 1) {
	rv = sd->activate(sol, msg);
	if (rv) {
	    sd->sys->free(sd->sys, dmsg->src_addr);
	    dmsg->src_addr = NULL;
	    rdata[0] = IPMI_UNKNOWN_ERR_CC;
	    *rdata_len = 1;
	    return;
	}

	sol->active = 1;
	sol->session_id = msg->sid;
	sd->channel = channel;
	sd->outlen = 0;
	ipmi_set_uint16(rdata + 5, sizeof(sd->inbuf));
	ipmi_set_uint16(rdata + 7, sizeof(sd->outbuf));
    } else if (instance == 2 && sol->history_size) {
	struct timeval tv;

	sd->history_copy = copy_history_buffer(sol, &sd->history_copy_size);
	if (!sd->history_copy) {
	    rdata[0] = IPMI_OUT_OF_SPACE_CC;
	    *rdata_len = 1;
	    return;
	}
	sd->history_pos = 0;
	sol->history_active = 1;
	sol->history_session_id = msg->sid;
	sd->history_channel = channel;
	ipmi_set_uint16(rdata + 5, MAX_HISTORY_SEND);
	ipmi_set_uint16(rdata + 7, MAX_HISTORY_SEND);
	tv.tv_sec = 0;
	tv.tv_usec = 0; /* Send immediately */
	sd->history_num_sends = 0;
	sd->sys->start_timer(sd->history_timer, &tv);
    }

    rdata[0] = 0;
    ipmi_set_uint32(rdata + 1, 0);
    ipmi_set_uint16(rdata + 9, port);
    ipmi_set_uint16(rdata + 11, 0xffff);
    *rdata_len = 13;
}
示例#7
0
static void
handle_picmg_cmd_fru_inventory_device_lock_control(lmc_data_t    *mc,
						   msg_t         *msg,
						   unsigned char *rdata,
						   unsigned int  *rdata_len,
						   void          *cb_data)
{
    emu_data_t *emu = mc->emu;
    uint16_t   lock_id;
    fru_data_t *fru;

    if (mc->ipmb != 0x20) {
	handle_invalid_cmd(mc, rdata, rdata_len);
	return;
    }

    if (check_msg_length(msg, 5, rdata, rdata_len))
	return;

    if (msg->data[1] != 254) {
	rdata[0] = IPMI_DESTINATION_UNAVAILABLE_CC;
	*rdata_len = 1;
	return;
    }

    rdata[0] = 0;
    rdata[1] = IPMI_PICMG_GRP_EXT;

    switch (msg->data[2]) {
    case 0:
	rdata[2] = 0;
	rdata[3] = 0;
	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
	*rdata_len = 8;
	break;

    case 1:
	if (emu->atca_fru_inv_locked) {
	    rdata[0] = 0x81;
	    *rdata_len = 1;
	    break;
	}
	fru = find_fru(mc, 254);
	if (!fru || fru->length == 0) {
	    rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC;
	    *rdata_len = 1;
	    break;
	}
	emu->temp_fru_inv_data = malloc(fru->length);
	if (!emu->temp_fru_inv_data) {
	    rdata[0] = IPMI_OUT_OF_SPACE_CC;
	    *rdata_len = 1;
	    break;
	}
	emu->temp_fru_inv_data_len = fru->length;
	memcpy(emu->temp_fru_inv_data, fru->data, 
	       emu->temp_fru_inv_data_len);

	emu->atca_fru_inv_locked = 1;
	emu->atca_fru_inv_curr_lock_id++;
	ipmi_set_uint16(rdata+2, emu->atca_fru_inv_curr_lock_id);
	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
	*rdata_len = 8;
	emu->atca_fru_inv_lock_timeout = 20;
	break;

    case 2:
	lock_id = ipmi_get_uint16(msg->data+3);
	if (!emu->atca_fru_inv_locked
	    || (lock_id != emu->atca_fru_inv_curr_lock_id))
	{
	    rdata[0] = 0x81;
	    *rdata_len = 1;
	    break;
	}
	emu->atca_fru_inv_locked = 0;
	rdata[2] = 0;
	rdata[3] = 0;
	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
	*rdata_len = 8;
	free(emu->temp_fru_inv_data);
	emu->temp_fru_inv_data = NULL;
	break;

    case 3:
	lock_id = ipmi_get_uint16(msg->data+3);
	if (!emu->atca_fru_inv_locked
	    || (lock_id != emu->atca_fru_inv_curr_lock_id))
	{
	    rdata[0] = 0x81;
	    *rdata_len = 1;
	    break;
	}
	emu->atca_fru_inv_locked = 0;
	rdata[2] = 0;
	rdata[3] = 0;
	ipmi_set_uint32(rdata+4, emu->atca_fru_inv_curr_timestamp);
	*rdata_len = 8;
	emu->atca_fru_inv_curr_timestamp++;
	/* FIXME - validate data. */
	fru = find_fru(mc, 254);
	if (!fru || fru->length == 0) {
	    rdata[0] = IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC;
	    *rdata_len = 1;
	    break;
	}
	memcpy(fru->data, emu->temp_fru_inv_data,
	       emu->temp_fru_inv_data_len);
	free(emu->temp_fru_inv_data);
	emu->temp_fru_inv_data = NULL;
	break;

    default:
	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
	*rdata_len = 1;
	break;
    }
}
示例#8
0
文件: rakp.c 项目: wrouesnel/openipmi
static int
rakp_hmac_c2(rakp_info_t   *info,
             unsigned char *data,
             unsigned int  data_len)
{
    unsigned char       idata[74];
    unsigned int        ilen;
    unsigned char       integ_data[20];
    rakp_hmac_key_t     *rinfo = info->key_data;
    const unsigned char *p;
    unsigned char       *s;
    unsigned char       *k;
    unsigned int        plen;

    if (data_len < 40+rinfo->key_len)
        return E2BIG;

    ipmi_set_uint32(idata+0, ipmi_rmcpp_auth_get_my_session_id(info->ainfo));
    ipmi_set_uint32(idata+4, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));
    p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
    memcpy(idata+8, p, 16);
    p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
    memcpy(idata+24, p, 16);
    p = ipmi_rmcpp_auth_get_mgsys_guid(info->ainfo, &plen);
    memcpy(idata+40, p, 16);
    idata[56] = ipmi_rmcpp_auth_get_role(info->ainfo);
    idata[57] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
    if (idata[57] > 16)
        return EINVAL;
    p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
    memcpy(idata+58, p, idata[57]);

    p = ipmi_rmcpp_auth_get_password(info->ainfo, &plen);
    if (plen < rinfo->key_len)
        return EINVAL;
    HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 58+idata[57], integ_data, &ilen);
    if (memcmp(data+40, integ_data, rinfo->key_len) != 0)
        return EINVAL;

    /* Now generate the SIK */
    p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
    memcpy(idata+0, p, 16);
    p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
    memcpy(idata+16, p, 16);
    idata[32] = ipmi_rmcpp_auth_get_role(info->ainfo);
    idata[33] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
    p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
    memcpy(idata+34, p, idata[33]);
    p = ipmi_rmcpp_auth_get_bmc_key(info->ainfo, &plen);
    if (plen < rinfo->key_len)
        return EINVAL;
    s = ipmi_rmcpp_auth_get_sik(info->ainfo, &plen);
    if (plen < rinfo->key_len)
        return EINVAL;
    HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 34+idata[33], s, &ilen);
    ipmi_rmcpp_auth_set_sik_len(info->ainfo, rinfo->key_len);

    /* Now generate k1 and k2. */
    k = ipmi_rmcpp_auth_get_k1(info->ainfo, &plen);
    if (plen < rinfo->key_len)
        return EINVAL;
    memset(idata, 1, rinfo->key_len);
    HMAC(rinfo->evp_md, s, rinfo->key_len, idata, rinfo->key_len, k, &ilen);
    ipmi_rmcpp_auth_set_k2_len(info->ainfo, rinfo->key_len);
    k = ipmi_rmcpp_auth_get_k2(info->ainfo, &plen);
    if (plen < rinfo->key_len)
        return EINVAL;
    memset(idata, 2, rinfo->key_len);
    HMAC(rinfo->evp_md, s, rinfo->key_len, idata, rinfo->key_len, k, &ilen);
    ipmi_rmcpp_auth_set_k2_len(info->ainfo, rinfo->key_len);

    return 0;
}