@@ -78,6 +78,23 @@ void *SvAdiosGet(void *svP)
7878 sessP->doAdiosGet ();
7979 return 0 ;
8080}
81+
82+ // Highest request wire-format version we accept (clients emit none yet, absent ==
83+ // 0). Policing it gives a future newer client a clear error, not a parse failure.
84+ constexpr uint32_t kMaxWireVersion = 0 ;
85+
86+ // Record a rejected request in the access log (the normal entry is logged only
87+ // after a successful read, which a rejection never reaches).
88+ void LogReject (const std::string &file, const char *reason, uint32_t batch)
89+ {
90+ if (!AccessLog::Instance ().Enabled ())
91+ return ;
92+ AccessLog::Record rec;
93+ rec.file = file.c_str ();
94+ rec.reject = reason;
95+ rec.batch = batch;
96+ AccessLog::Instance ().Log (rec);
97+ }
8198}
8299
83100/* *****************************************************************************/
@@ -499,6 +516,9 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
499516 std::string Filename;
500517 std::string EngineParams;
501518 bool ArrayOrder = true ;
519+ uint32_t RequestUUID = 0 ; // file id from client metadata; 0 = no check
520+ uint32_t WireVersion = 0 ; // request format version; absent/0 = original
521+ bool ClientBigEndian = false ; // client native byte order; absent = little
502522 size_t NVars = 0 ;
503523
504524 struct VarRequest
@@ -619,23 +639,68 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
619639 std::size_t pos = param.find (" =" ) + 1 ;
620640 EngineParams = UrlDecode (param.substr (pos));
621641 }
642+ else if (HasPrefix (param, " FileUUID=" ))
643+ {
644+ std::size_t pos = param.find (" =" ) + 1 ;
645+ std::stringstream sstream (param.substr (pos));
646+ sstream >> RequestUUID;
647+ }
648+ else if (HasPrefix (param, " WireVersion=" ))
649+ {
650+ std::size_t pos = param.find (" =" ) + 1 ;
651+ std::stringstream sstream (param.substr (pos));
652+ sstream >> WireVersion;
653+ }
654+ else if (HasPrefix (param, " ClientBigEndian=" ))
655+ {
656+ std::size_t pos = param.find (" =" ) + 1 ;
657+ std::stringstream sstream (param.substr (pos));
658+ int be = 0 ;
659+ sstream >> be;
660+ ClientBigEndian = (be != 0 );
661+ }
622662 }
623663 }
624664
625665 NVars = varRequests.size (); // trust actual count over NVars param
626666
627667 if (Filename.empty () || NVars == 0 )
628668 {
669+ LogReject (Filename, " badparams" , static_cast <uint32_t >(NVars));
629670 RespondErr (" batchget: invalid parameters" , EINVAL );
630671 return ;
631672 }
673+ if (WireVersion > kMaxWireVersion )
674+ {
675+ LogReject (Filename, " version" , static_cast <uint32_t >(NVars));
676+ std::string msg = " batchget: unsupported request protocol version " +
677+ std::to_string (WireVersion) + " ; this server supports up to " +
678+ std::to_string (kMaxWireVersion );
679+ RespondErr (msg.c_str (), EINVAL );
680+ return ;
681+ }
682+ if (ClientBigEndian != !adios2::helper::IsLittleEndian ())
683+ {
684+ LogReject (Filename, " byteorder" , static_cast <uint32_t >(NVars));
685+ RespondErr (" batchget: cross-endian remote reads not supported" , EINVAL );
686+ return ;
687+ }
632688
633689 try
634690 {
635691 auto poolEntry = m_FilePoolPtr->GetFree (Filename, ArrayOrder, EngineParams);
636692 auto engine = poolEntry.file ->m_engine ;
637693 auto io = poolEntry.file ->m_io ;
638694
695+ // Reject if the client's file id doesn't match the file we opened
696+ // (stale cached metadata); 0 = client has no id, no check.
697+ if (RequestUUID != 0 && engine.FileUUID () != RequestUUID)
698+ {
699+ LogReject (Filename, " identity" , static_cast <uint32_t >(NVars));
700+ RespondErr (" batchget: file identity mismatch; remote metadata is stale" , EINVAL );
701+ return ;
702+ }
703+
639704 // Compute sizes for each variable and total response size
640705 // Response format: [uint64_t NVars][uint64_t size_0]...[size_N-1][data_0]...[data_N-1]
641706 size_t headerSize = sizeof (uint64_t ) + NVars * sizeof (uint64_t );
@@ -648,6 +713,7 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
648713 adios2::DataType TypeOfVar = io.InquireVariableType (vr.VarName );
649714 if (TypeOfVar == adios2::DataType::None)
650715 {
716+ LogReject (Filename, " novar" , static_cast <uint32_t >(NVars));
651717 RespondErr (" batchget: unknown variable" , EINVAL );
652718 return ;
653719 }
@@ -678,6 +744,7 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
678744 m_responseBuffer = (char *)malloc (m_responseBufferSize);
679745 if (!m_responseBuffer)
680746 {
747+ LogReject (Filename, " alloc" , static_cast <uint32_t >(NVars));
681748 RespondErr (" batchget: allocation failed" , ENOMEM );
682749 return ;
683750 }
@@ -773,6 +840,7 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
773840 }
774841 catch (const std::exception &exc)
775842 {
843+ LogReject (Filename, " exception" , static_cast <uint32_t >(NVars));
776844 std::string msg = std::string (" batchget: exception during processing: " ) + exc.what ();
777845 RespondErr (msg.c_str (), EINVAL );
778846 }
@@ -787,6 +855,9 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
787855 size_t BlockID = (size_t )-1 , DimCount = 0 , StepStart = 0 ;
788856 size_t StepCount = 1 ;
789857 bool ArrayOrder = true ;
858+ uint32_t RequestUUID = 0 ; // file id from client metadata; 0 = no check
859+ uint32_t WireVersion = 0 ; // request format version; absent/0 = original
860+ bool ClientBigEndian = false ; // client native byte order; absent = little
790861 // Accuracy parameters
791862 double AccuracyError = 0.0 ;
792863 double AccuracyNorm = 0.0 ;
@@ -885,6 +956,41 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
885956 std::size_t pos = param.find (" =" ) + 1 ;
886957 EngineParams = UrlDecode (param.substr (pos));
887958 }
959+ else if (HasPrefix (param, " FileUUID=" ))
960+ {
961+ std::size_t pos = param.find (" =" ) + 1 ;
962+ std::stringstream sstream (param.substr (pos));
963+ sstream >> RequestUUID;
964+ }
965+ else if (HasPrefix (param, " WireVersion=" ))
966+ {
967+ std::size_t pos = param.find (" =" ) + 1 ;
968+ std::stringstream sstream (param.substr (pos));
969+ sstream >> WireVersion;
970+ }
971+ else if (HasPrefix (param, " ClientBigEndian=" ))
972+ {
973+ std::size_t pos = param.find (" =" ) + 1 ;
974+ std::stringstream sstream (param.substr (pos));
975+ int be = 0 ;
976+ sstream >> be;
977+ ClientBigEndian = (be != 0 );
978+ }
979+ }
980+ if (WireVersion > kMaxWireVersion )
981+ {
982+ LogReject (Filename, " version" , 1 );
983+ std::string msg = " get: unsupported request protocol version " +
984+ std::to_string (WireVersion) + " ; this server supports up to " +
985+ std::to_string (kMaxWireVersion );
986+ RespondErr (msg.c_str (), EINVAL );
987+ return ;
988+ }
989+ if (ClientBigEndian != !adios2::helper::IsLittleEndian ())
990+ {
991+ LogReject (Filename, " byteorder" , 1 );
992+ RespondErr (" get: cross-endian remote reads not supported" , EINVAL );
993+ return ;
888994 }
889995 // Get a "anonymous" engine with this file open with this array order.
890996 // (any other differentiating characteristics of an ADIOS Open should be included in these
@@ -901,10 +1007,19 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
9011007 auto poolEntry = m_FilePoolPtr->GetFree (Filename, ArrayOrder, EngineParams);
9021008 auto engine = poolEntry.file ->m_engine ;
9031009 auto io = poolEntry.file ->m_io ;
1010+
1011+ // Metadata-identity check (0 = client has no id, enforces nothing).
1012+ if (RequestUUID != 0 && engine.FileUUID () != RequestUUID)
1013+ {
1014+ LogReject (Filename, " identity" , 1 );
1015+ RespondErr (" get: file identity mismatch; remote metadata is stale" , EINVAL );
1016+ return ;
1017+ }
9041018 adios2::Box<adios2::Dims> varSel (Start, Count);
9051019 adios2::DataType TypeOfVar = io.InquireVariableType (VarName);
9061020 if (TypeOfVar == adios2::DataType::None)
9071021 {
1022+ LogReject (Filename, " novar" , 1 );
9081023 RespondErr (" get: unknown variable" , EINVAL );
9091024 return ;
9101025 }
@@ -975,6 +1090,7 @@ void XrdSsiSvService::ProcessRequest4Me(XrdSsiRequest *rqstP)
9751090 }
9761091 catch (const std::exception &exc)
9771092 {
1093+ LogReject (Filename, " exception" , 1 );
9781094 std::string errMsg = std::string (" Exception in Get: " ) + exc.what ();
9791095 RespondErr (errMsg.c_str (), EINVAL );
9801096 }
0 commit comments