向tcp数据包添加身份验证会导致校验和失败

时间:2015-04-28 10:21:28

标签: c++ boost boost-asio

我有一段代码将数据包发送到TCP网络。我所做的是将两个新字段username_和password_添加到Packet对象。这是用于服务器端的身份验证。 问题是新数据包与新字段的校验和比较失败。我已经确保新字段到char *的String转换正确完成,但问题尚未解决。

这是数据包对象:

const static uint32_t        TAG_START         = 0xAA5AAAAAU;  //  0x35F4BE07
const  std::string           USERNAME          = "ARG-CO";
const  std::string           PASSWORD          = "FUCK-YOU!";
const static uint32_t        TAG_END           = 0x555555A5U;  // 0xB7DF087A
const static uint16_t        VERSION           = 0U;           // starting version
const static uint16_t        CURRENT_VERSION   = 1U;           // increment, when protocol changes
const static uint32_t        CRC_INIT          = 0xAFCE9265U;  // initial checksum (crc) value
const static unsigned int    USERNAME_SIZE  = 7;
const static unsigned int    PASSWORD_SIZE = 10;
const static unsigned int    MAX_DATA_SIZE     = 4096; //4113 // packet data size limit in bytes, to limit necessary buffers, for now this is sizeof(car_multi_record)
const static unsigned int    PACKET_SIZE       = 52 + USERNAME_SIZE + PASSWORD_SIZE;           // empty packet size in bytes when serialized, sizeof(header)
const static unsigned int    MAX_PACKET_SIZE   = PACKET_SIZE + MAX_DATA_SIZE;

并且主要数据包创建在此成员函数内完成:

    static Packet::ptr create(RTCINET_COMMANDS cmd, RTCINET_COMMANDS subcmd, Packet::ptr_bytea ba)
// TODO: unsigned short command_seq, data_seq, length
{
    //Add user authentication fields, username n password here

    std::cout << "creating packet..";
    Packet::ptr pack(new Packet());

    pack->command_ = cmd;
    pack->subcommand_ = subcmd;
    pack->data_length_ = ba->size();
    pack->data_ = ba;
    pack->make_checksum();
    //assert(pack->check_checksum());


    std::cout << "\n########### creating packet ###########";
    std::cout << "\ntag_start_: "        << pack->tag_start_ << std::endl;
    std::cout << "username_: "           << pack->username_ << std::endl;
    std::cout << "password_: "           << pack->password_ << std::endl;
    std::cout << "version_: "            << pack->version_ << std::endl;
    std::cout << "checksum_: "           << pack->checksum_ << std::endl;
    std::cout << "connection_id_: "      << pack->connection_id_ << std::endl;
    std::cout << "timestamp_sec_: "      << pack->timestamp_sec_ << std::endl;
    std::cout << "timestamp_microsec_: " << pack->timestamp_microsec_ << std::endl;
    std::cout << "command_: "            << pack->command_ << std::endl;
    std::cout << "command_seq_: "        << pack->command_seq_ << std::endl;
    std::cout << "subcommand: "          << pack->subcommand_ << std::endl;
    std::cout << "data_seq: "            << pack->data_seq_ << std::endl;
    std::cout << "data_length: "         << pack->data_length_ << std::endl;
    std::cout << "data_: "               << pack->data_ << std::endl;
    std::cout << "tag_end_: "            << pack->tag_end_ << std::endl;

    assert(pack->is_valid());

    return pack;
}

请注意,主要问题是断言程序的断言功能:

assert(pack->is_valid());

但是,我确保在create_packet函数中创建的数据包与is_valid函数中的数据包具有完全相同的值:

   bool Packet::is_valid() const
{
    /*
    std::cout << "TAG_START: "       << Packet::TAG_START       << "=="  << this->tag_start_   << std::endl;
    std::cout << "TAG_END: "         << Packet::TAG_END         << "=="  << this->tag_end_     << std::endl;
    std::cout << "VERSION: "         << Packet::VERSION         << "<"  << this->version_     << std::endl;
    std::cout << "CURRENT_VERSION: " << Packet::CURRENT_VERSION << ">=" << this->version_     << std::endl;
    std::cout << "DATA SIZE: "       << this->data_->size()     << "==" << this->data_length_ << std::endl;
    std::cout << "MAX_DATA_SIZE: "   << Packet::MAX_DATA_SIZE   << ">="  << this->data_length_ << std::endl;
    std::cout << "MAX_PACKET_SIZE: " << Packet::MAX_PACKET_SIZE << ">="  << this->size()       << std::endl;
    std::cout << "check_checksum: "  << check_checksum();
*/
    std::cout << "\n########### validating . ###########";
    std::cout << "\ntag_start_: "        << this->tag_start_ << std::endl;
    std::cout << "username_: "           << this->username_ << std::endl;
    std::cout << "password_: "           << this->password_ << std::endl;
    std::cout << "version_: "            << this->version_ << std::endl;
    std::cout << "checksum_: "           << this->checksum_ << std::endl;
    std::cout << "connection_id_: "      << this->connection_id_ << std::endl;
    std::cout << "timestamp_sec_: "      << this->timestamp_sec_ << std::endl;
    std::cout << "timestamp_microsec_: " << this->timestamp_microsec_ << std::endl;
    std::cout << "command_: "            << this->command_ << std::endl;
    std::cout << "command_seq_: "        << this->command_seq_ << std::endl;
    std::cout << "subcommand: "          << this->subcommand_ << std::endl;
    std::cout << "data_seq: "            << this->data_seq_ << std::endl;
    std::cout << "data_length: "         << this->data_length_ << std::endl;
    std::cout << "data_: "               << this->data_ << std::endl;
    std::cout << "tag_end_: "            << this->tag_end_ << std::endl;


    std::cout << "############## determine sizes #############\n"
              << "username: "   << this->username_.size()
              << "\npassword: " << this->password_.size();

    std::cout << "\n########### checking checksum ############" << std::endl;
    std::cout << check_checksum() << std::endl;

    return
            (Packet::TAG_START              == this->tag_start_)
            and (Packet::TAG_END            == this->tag_end_)
            and (Packet::VERSION            <  this->version_)
            and (Packet::CURRENT_VERSION    >= this->version_)
            // TODO: and check command and subcommand fields to exist in commands list
            and (this->data_->size()        == this->data_length_)
            and (Packet::MAX_DATA_SIZE      >= this->data_length_)
            and (Packet::MAX_PACKET_SIZE    >= this->size())
            and check_checksum();
}

我怀疑的是

的实施
 boost::crc_32_type crc;

与check_checksum functions()中一样:

    unsigned int Packet::get_checksum() const
{
    //boost::crc_basic<16>  crc_ccitt1(0x1021, 0xFFFF, 0, false, false);
    //crc_ccitt1.process_bytes(data, data_len);
    //assert(crc_ccitt1.checksum() == expected);

    // Repeat with the optimal version (assuming a 16-bit type exists)
    //boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false>  crc_ccitt2;
    //crc_ccitt2 = std::for_each(data, data + data_len, crc_ccitt2);

    boost::crc_32_type crc;  // predefined CRC class template using 32 bits, used in PKZip, AUTODIN II, Ethernet, FDDI
    ptr_bytea ba = get_bin();


    for (bytea::const_iterator iter = ba->begin(); iter != ba->end(); iter++)
    {
        crc.process_byte(*iter);
    }

    std::cout << "###### get_checksum ######## " << crc.checksum();

    return crc();  // or crc.checksum();
}

void Packet::make_checksum()
{
    checksum_ = CRC_INIT;
    checksum_ = get_checksum();
}

bool Packet::check_checksum() const
{
    //unsigned int cs = checksum_;
    //checksum_ = CRC_INIT;
    //bool check = (get_checksum() == cs);
    //checksum_ = cs;
    //return check;

    // to be able to add const qualifier to method, make a copy of this object, and operate on it.

    Packet pack(*this);

    pack.checksum_ = CRC_INIT;

    return (pack.get_checksum() == this->checksum_);
}

Packet::ptr_bytea Packet::get_bin() const
{
    std::stringstream ss(std::ios_base::out | std::ios_base::in | std::ios_base::binary | std::ios_base::trunc);
    byte b = 0U;

    ss.write((char *) & this->tag_start_,             sizeof(Packet::tag_start_));

    ss.write(this->username_.c_str(),                 Packet::username_.size());
    ss.write(this->password_.c_str(),                 Packet::password_.size());

    ss.write((char *) & this->version_,               sizeof(Packet::version_));
    ss.write((char *) & this->checksum_,              sizeof(Packet::checksum_));
    ss.write((char *) & this->connection_id_,         sizeof(Packet::connection_id_));
    ss.write((char *) & this->packet_seq_,            sizeof(Packet::packet_seq_));
    ss.write((char *)   this->guid_,                  sizeof(Packet::guid_));
    ss.write((char *) & this->timestamp_sec_,         sizeof(Packet::timestamp_sec_));
    ss.write((char *) & this->timestamp_microsec_,    sizeof(Packet::timestamp_microsec_));
    ss.write((char *) & this->command_,               sizeof(Packet::command_));
    ss.write((char *) & this->command_seq_,           sizeof(Packet::command_seq_));
    ss.write((char *) & this->subcommand_,            sizeof(Packet::subcommand_));
    ss.write((char *) & this->data_seq_,              sizeof(Packet::data_seq_));
    ss.write((char *) & this->data_length_,           sizeof(Packet::data_length_));

    for (bytea::const_iterator iter = this->data_->begin(); iter != this->data_->end(); iter++) {
        b = *iter;
        ss.write((char *) & b, sizeof(b));
    }

    ss.write((char *) & this->tag_end_, sizeof(Packet::tag_end_));

    ss.flush();

    while (ss.read((char *) & b, sizeof(b))) {
        //ba->push_back(b);
        std::cout << std::hex << b;
    }

    if (not ss)
        std::cerr << "failed to serialize the packet to binary data" << std::endl;
    //else
    //std::cerr << ss.rdbuf().str();
    //std::cerr << *this << std::endl;

    Packet::ptr_bytea ba(new bytea);
    while (ss.read((char *) & b, sizeof(b))) {
        ba->push_back(b);
    }

    //return ss.rdbuf();  // internal stringbuf object maintained by stringstream
    return ba;
}

任何人都可以帮助我阻止两个校验和相等的错误吗?

0 个答案:

没有答案