?? auth.cc
字號:
// // XXX: if no valid keys, then don't use any authentication // if (_valid_key_chain.empty()) { return (_null_handler.effective_name()); } return auth_type_name();}const char*MD5AuthHandler::auth_type_name(){ return "md5";}voidMD5AuthHandler::reset(){ // // XXX: if no valid keys, then don't use any authentication // if (_valid_key_chain.empty()) { _null_handler.reset(); return; } reset_keys();}uint32_tMD5AuthHandler::head_entries() const{ // // XXX: if no valid keys, then don't use any authentication // if (_valid_key_chain.empty()) { return (_null_handler.head_entries()); } return 1;}uint32_tMD5AuthHandler::max_routing_entries() const{ // // XXX: if no valid keys, then don't use any authentication // if (_valid_key_chain.empty()) { return (_null_handler.max_routing_entries()); } return RIPv2_ROUTES_PER_PACKET - 1;}boolMD5AuthHandler::authenticate_inbound(const uint8_t* packet, size_t packet_bytes, const uint8_t*& entries_ptr, uint32_t& n_entries, const IPv4& src_addr, bool new_peer){ static_assert(MD5PacketTrailer::SIZE == 20); // // XXX: if no valid keys, then don't use any authentication // if (_valid_key_chain.empty()) { if (_null_handler.authenticate_inbound(packet, packet_bytes, entries_ptr, n_entries, src_addr, new_peer) != true) { set_error(_null_handler.error()); return (false); } reset_error(); return (true); } entries_ptr = NULL; n_entries = 0; if (packet_bytes > RIPv2_MAX_PACKET_BYTES + MD5PacketTrailer::size()) { set_error(c_format("packet too large (%u bytes)", XORP_UINT_CAST(packet_bytes))); return false; } if (packet_bytes < RIPv2_MIN_AUTH_PACKET_BYTES) { set_error(c_format("packet too small (%u bytes)", XORP_UINT_CAST(packet_bytes))); return false; } const MD5PacketRouteEntry4 mpr(packet + RipPacketHeader::size()); if (mpr.addr_family() != MD5PacketRouteEntry4::ADDR_FAMILY) { set_error("not an authenticated packet"); return false; } if (mpr.auth_type() != MD5PacketRouteEntry4::AUTH_TYPE) { set_error("not an MD5 authenticated packet"); return false; } if (mpr.auth_bytes() != MD5PacketTrailer::size()) { set_error(c_format("wrong number of auth bytes (%d != %u)", mpr.auth_bytes(), XORP_UINT_CAST(MD5PacketTrailer::size()))); return false; } if (uint32_t(mpr.auth_off() + mpr.auth_bytes()) != packet_bytes) { set_error(c_format("Size of packet does not correspond with " "authentication data offset and size " "(%d + %d != %u).", mpr.auth_off(), mpr.auth_bytes(), XORP_UINT_CAST(packet_bytes))); return false; } KeyChain::iterator k = find_if(_valid_key_chain.begin(), _valid_key_chain.end(), bind2nd(mem_fun_ref(&MD5Key::id_matches), mpr.key_id())); if (k == _valid_key_chain.end()) { set_error(c_format("packet with key ID %d for which no key is " "configured", mpr.key_id())); return false; } MD5Key* key = &(*k); if (new_peer) key->reset(src_addr); uint32_t last_seqno_recv = key->last_seqno_recv(src_addr); if (key->packets_received(src_addr) && !(new_peer && mpr.seqno() == 0) && (mpr.seqno() - last_seqno_recv >= 0x7fffffff)) { set_error(c_format("bad sequence number 0x%08x < 0x%08x", XORP_UINT_CAST(mpr.seqno()), XORP_UINT_CAST(last_seqno_recv))); return false; } const MD5PacketTrailer mpt(packet + mpr.auth_off()); if (mpt.valid() == false) { set_error("invalid authentication trailer"); return false; } MD5_CTX ctx; uint8_t digest[16]; MD5_Init(&ctx); MD5_Update(&ctx, packet, mpr.auth_off() + mpt.auth_data_offset()); MD5_Update(&ctx, key->key_data(), key->key_data_bytes()); MD5_Final(digest, &ctx); if (memcmp(digest, mpt.auth_data(), mpt.auth_data_bytes()) != 0) { set_error(c_format("authentication digest doesn't match local key " "(key ID = %d)", key->id()));// #define DUMP_BAD_MD5#ifdef DUMP_BAD_MD5 const char badmd5[] = "/tmp/rip_badmd5"; // If the file already exists don't dump anything. The file // should contain and only one packet. if (-1 == access(badmd5, R_OK)) { XLOG_INFO("Dumping bad MD5 to %s", badmd5); FILE *fp = fopen(badmd5, "w"); fwrite(packet, packet_bytes, 1 , fp); fclose(fp); }#endif return false; } // Update sequence number only after packet has passed digest check key->set_last_seqno_recv(src_addr, mpr.seqno()); reset_error(); n_entries = (mpr.auth_off() - RipPacketHeader::size()) / PacketRouteEntry<IPv4>::size() - 1; if (n_entries > 0) { entries_ptr = (packet + RipPacketHeader::size() + MD5PacketRouteEntry4::size()); } return true;}boolMD5AuthHandler::authenticate_outbound(RipPacket<IPv4>& packet, list<RipPacket<IPv4> *>& auth_packets, size_t& n_routes){ RipPacket<IPv4> first_packet(packet); vector<uint8_t> first_trailer; KeyChain::iterator iter; static_assert(MD5PacketTrailer::SIZE == 20); // // XXX: if no valid keys, then don't use any authentication // if (_valid_key_chain.empty()) { if (_null_handler.authenticate_outbound(packet, auth_packets, n_routes) != true) { set_error(_null_handler.error()); return (false); } reset_error(); return (true); } // // Create an authenticated copy of the packet for each valid key // for (iter = _valid_key_chain.begin(); iter != _valid_key_chain.end(); ++iter) { MD5Key& key = *iter; RipPacket<IPv4>* copy_packet = new RipPacket<IPv4>(packet); auth_packets.push_back(copy_packet); uint8_t* first_entry_ptr = NULL; if (head_entries() > 0) first_entry_ptr = copy_packet->route_entry_ptr(0); MD5PacketRouteEntry4Writer mpr(first_entry_ptr); mpr.initialize(copy_packet->data_bytes(), key.id(), MD5PacketTrailer::size(), key.next_seqno_out()); vector<uint8_t> trailer; trailer.resize(MD5PacketTrailer::size()); MD5PacketTrailerWriter mpt(&trailer[0]); mpt.initialize(); MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, copy_packet->data_ptr(), mpr.auth_off()); MD5_Update(&ctx, &trailer[0], mpt.auth_data_offset()); MD5_Update(&ctx, key.key_data(), key.key_data_bytes()); MD5_Final(mpt.auth_data(), &ctx); // // XXX: create a copy of the first packet without the trailer // and of the trailer itself. // if (iter == _valid_key_chain.begin()) { first_packet = *copy_packet; first_trailer = trailer; } copy_packet->append_data(trailer); } packet = first_packet; n_routes = packet.data_bytes() / MD5PacketRouteEntry4::size() - 1; packet.append_data(first_trailer); reset_error(); return (true);}boolMD5AuthHandler::add_key(uint8_t key_id, const string& key, const TimeVal& start_timeval, const TimeVal& end_timeval, string& error_msg){ TimeVal now; XorpTimer start_timer, end_timer; string dummy_error_msg; _eventloop.current_time(now); if (start_timeval > end_timeval) { error_msg = c_format("Start time is later than the end time"); return false; } if (end_timeval < now) { error_msg = c_format("End time is in the past"); return false; } if (start_timeval > now) { start_timer = _eventloop.new_oneoff_at( start_timeval, callback(this, &MD5AuthHandler::key_start_cb, key_id)); } if (end_timeval != TimeVal::MAXIMUM()) { end_timer = _eventloop.new_oneoff_at( end_timeval, callback(this, &MD5AuthHandler::key_stop_cb, key_id)); } // // XXX: If we are using the last authentication key that has expired, // move it to the list of invalid keys. // if (_valid_key_chain.size() == 1) { MD5Key& key = _valid_key_chain.front(); if (key.is_persistent()) { key.set_persistent(false); _invalid_key_chain.push_back(key); _valid_key_chain.pop_front(); } } // XXX: for simplicity just try to remove the key even if it doesn't exist remove_key(key_id, dummy_error_msg); // Add the new key to the appropriate chain MD5Key new_key = MD5Key(key_id, key, start_timeval, end_timeval, start_timer, end_timer); if (start_timer.scheduled()) _invalid_key_chain.push_back(new_key); else _valid_key_chain.push_back(new_key); return true;}boolMD5AuthHandler::remove_key(uint8_t key_id, string& error_msg){ KeyChain::iterator i; // Check among all valid keys i = find_if(_valid_key_chain.begin(), _valid_key_chain.end(), bind2nd(mem_fun_ref(&MD5Key::id_matches), key_id)); if (i != _valid_key_chain.end()) { _valid_key_chain.erase(i); return true; } // Check among all invalid keys i = find_if(_invalid_key_chain.begin(), _invalid_key_chain.end(), bind2nd(mem_fun_ref(&MD5Key::id_matches), key_id)); if (i != _invalid_key_chain.end()) { _invalid_key_chain.erase(i); return true; } error_msg = c_format("No such key"); return false;}voidMD5AuthHandler::key_start_cb(uint8_t key_id){ KeyChain::iterator i; // Find the key among all invalid keys and move it to the valid keys i = find_if(_invalid_key_chain.begin(), _invalid_key_chain.end(), bind2nd(mem_fun_ref(&MD5Key::id_matches), key_id)); if (i != _invalid_key_chain.end()) { MD5Key& key = *i; _valid_key_chain.push_back(key); _invalid_key_chain.erase(i); }}voidMD5AuthHandler::key_stop_cb(uint8_t key_id){ KeyChain::iterator i; // Find the key among all valid keys and move it to the invalid keys i = find_if(_valid_key_chain.begin(), _valid_key_chain.end(), bind2nd(mem_fun_ref(&MD5Key::id_matches), key_id)); if (i != _valid_key_chain.end()) { MD5Key& key = *i; // // XXX: If the last key expires then keep using it as per // RFC 2082 Section 4.3 until the lifetime is extended, the key // is deleted by network management, or a new key is configured. // if (_valid_key_chain.size() == 1) { XLOG_WARNING("Last authentication key (key ID = %u) has expired. " "Will keep using it until its lifetime is extended, " "the key is deleted, or a new key is configured.", key_id); key.set_persistent(true); return; } _invalid_key_chain.push_back(key); _valid_key_chain.erase(i); }}voidMD5AuthHandler::reset_keys(){ KeyChain::iterator iter; for (iter = _valid_key_chain.begin(); iter != _valid_key_chain.end(); ++iter) { iter->reset(); }}boolMD5AuthHandler::empty() const{ return (_valid_key_chain.empty() && _invalid_key_chain.empty());}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -