@@ -481,86 +481,83 @@ void Cookie::initialize(std::chrono::steady_clock::time_point now,
481481 start = now;
482482}
483483
484- cb::mcbp::Status Cookie::validate () {
485- using cb::mcbp::Status;
484+ cb::mcbp::Status Cookie::validateServerRequest (
485+ const cb::mcbp::Request& request) {
486+ using namespace cb ::mcbp;
487+ // We should not be receiving a server command.
488+ auto opcode = request.getServerOpcode ();
489+ if (is_valid_opcode (opcode)) {
490+ // Ideally we should have validated its content, but given that
491+ // we don't support any server commands we can just return not supported
492+ // instead
493+ return Status::NotSupported;
494+ }
486495
496+ audit_invalid_packet (connection, getPacket ());
497+ return Status::UnknownCommand;
498+ }
499+
500+ cb::mcbp::Status Cookie::validateClientRequest (
501+ const cb::mcbp::Request& request) {
502+ using namespace cb ::mcbp;
487503 static McbpValidator packetValidator;
488504
489505 // Note: validate is called after the connection fetched the frame
490506 // off the network, and in order to know when the frame ends
491507 // it needed to validate the frame layout (known magic and
492508 // all the length fields inside the raw header adds up so
493509 // that the bodylen() contains the entire data).
494- const auto & header = getHeader ();
495- if (header.isResponse ()) {
496- // We don't have packet validators for responses (yet)
497- validated = true ;
498- return cb::mcbp::Status::Success;
499- }
500-
501- const auto & request = header.getRequest ();
502- if (cb::mcbp::is_server_magic ((request.getMagic ()))) {
503- // We should not be receiving a server command.
504- auto opcode = request.getServerOpcode ();
505- if (!cb::mcbp::is_valid_opcode (opcode)) {
506- return cb::mcbp::Status::UnknownCommand;
507- }
508-
509- audit_invalid_packet (connection, getPacket ());
510- return cb::mcbp::Status::NotSupported;
511- }
512-
513- auto opcode = request.getClientOpcode ();
510+ const auto opcode = request.getClientOpcode ();
514511
515512 if (!connection.isAuthenticated ()) {
516513 // We're not authenticated. To reduce the attack vector we'll only
517514 // allow certain commands to be executed
518- constexpr std::array<cb::mcbp:: ClientOpcode, 5 > allowed{
519- {cb::mcbp:: ClientOpcode::Hello,
520- cb::mcbp:: ClientOpcode::SaslListMechs,
521- cb::mcbp:: ClientOpcode::SaslAuth,
522- cb::mcbp:: ClientOpcode::SaslStep,
523- cb::mcbp:: ClientOpcode::GetErrorMap}};
515+ constexpr std::array<ClientOpcode, 5 > allowed{
516+ {ClientOpcode::Hello,
517+ ClientOpcode::SaslListMechs,
518+ ClientOpcode::SaslAuth,
519+ ClientOpcode::SaslStep,
520+ ClientOpcode::GetErrorMap}};
524521 if (std::ranges::find (allowed, opcode) == allowed.end ()) {
525522#if CB_DEVELOPMENT_ASSERTS
526- if (cb::mcbp:: is_valid_opcode (opcode)) {
523+ if (is_valid_opcode (opcode)) {
527524 LOG_WARNING_CTX (
528525 " Trying to execute before authentication. Returning "
529526 " eaccess" ,
530527 {" conn_id" , getConnectionId ()},
531528 {" opcode" , opcode});
532529 }
533530#endif
534- return cb::mcbp:: Status::Eaccess;
531+ return Status::Eaccess;
535532 }
536533 }
537534
538- if (!cb::mcbp:: is_valid_opcode (opcode)) {
535+ if (!is_valid_opcode (opcode)) {
539536 // We don't know about this command. Stop processing
540537 // It is legal to send unknown commands, so we don't log or audit this
541- return cb::mcbp:: Status::UnknownCommand;
538+ return Status::UnknownCommand;
542539 }
543540
544541 // A cluster-only bucket don't have an associated engine parameter
545542 // so we don't even want to try to validate the packet unless it is
546543 // one of the few commands allowed to be executed in such a bucket
547544 // (to avoid a potential call throug a nil pointer)
548545 if (connection.getBucket ().type == BucketType::ClusterConfigOnly) {
549- constexpr std::array<cb::mcbp:: ClientOpcode, 4 > allowed{
550- {cb::mcbp:: ClientOpcode::Hello,
551- cb::mcbp:: ClientOpcode::GetErrorMap,
552- cb::mcbp:: ClientOpcode::GetClusterConfig,
553- cb::mcbp:: ClientOpcode::SelectBucket}};
546+ constexpr std::array<ClientOpcode, 4 > allowed{
547+ {ClientOpcode::Hello,
548+ ClientOpcode::GetErrorMap,
549+ ClientOpcode::GetClusterConfig,
550+ ClientOpcode::SelectBucket}};
554551 if (std::ranges::find (allowed, opcode) == allowed.end ()) {
555552 if (connection.isXerrorSupport ()) {
556- return cb::mcbp:: Status::EConfigOnly;
553+ return Status::EConfigOnly;
557554 }
558- return cb::mcbp:: Status::NotSupported;
555+ return Status::NotSupported;
559556 }
560557 }
561558
562- auto result = packetValidator.validate (opcode, *this );
563- if (!cb::mcbp:: isStatusSuccess (result)) {
559+ const auto result = packetValidator.validate (opcode, *this );
560+ if (!isStatusSuccess (result)) {
564561 if (result != Status::UnknownCollection &&
565562 result != Status::NotMyVbucket &&
566563 result != Status::BucketSizeLimitExceeded &&
@@ -596,6 +593,26 @@ cb::mcbp::Status Cookie::validate() {
596593 return Status::Success;
597594}
598595
596+ cb::mcbp::Status Cookie::validate () {
597+ using namespace cb ::mcbp;
598+ const auto & header = getHeader ();
599+ if (header.isRequest ()) [[likely]] {
600+ const auto & request = header.getRequest ();
601+ if (is_server_magic (request.getMagic ())) [[unlikely]] {
602+ return validateServerRequest (request);
603+ }
604+ return validateClientRequest (request);
605+ }
606+
607+ // We can't really validate a response packets in this context as we would
608+ // break the protocol if we tried to send a response to a response packet
609+ // Instead we'll let each handler validate the response packet before they
610+ // use it and optionally just disconnect the client if they think it is
611+ // the right thing to do.
612+ validated = true ;
613+ return Status::Success;
614+ }
615+
599616Cookie::~Cookie () {
600617 if (isEwouldblock ()) {
601618 LOG_CRITICAL_CTX (
0 commit comments