changeset 1163:3db41779d8f9

abstraction to allow/prevent transfer syntaxes on AET basis
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 17 Sep 2014 17:23:08 +0200
parents 80671157d051
children 0a55d8eb194e
files OrthancServer/DicomProtocol/IApplicationEntityFilter.h OrthancServer/Internals/CommandDispatcher.cpp OrthancServer/ServerEnumerations.cpp OrthancServer/ServerEnumerations.h OrthancServer/main.cpp
diffstat 5 files changed, 182 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/DicomProtocol/IApplicationEntityFilter.h	Wed Sep 17 11:57:28 2014 +0200
+++ b/OrthancServer/DicomProtocol/IApplicationEntityFilter.h	Wed Sep 17 17:23:08 2014 +0200
@@ -51,5 +51,8 @@
     virtual bool IsAllowedRequest(const std::string& callingIp,
                                   const std::string& callingAet,
                                   DicomRequestType type) = 0;
+
+    virtual bool IsAllowedTransferSyntax(const std::string& callingAet,
+                                         TransferSyntax syntax) = 0;
   };
 }
--- a/OrthancServer/Internals/CommandDispatcher.cpp	Wed Sep 17 11:57:28 2014 +0200
+++ b/OrthancServer/Internals/CommandDispatcher.cpp	Wed Sep 17 17:23:08 2014 +0200
@@ -459,7 +459,38 @@
         return NULL;
       }
 
-      LOG(INFO) << "Association Received";
+      // Retrieve the AET and the IP address of the remote modality
+      std::string callingAet;
+      std::string callingIP;
+      std::string calledAet;
+  
+      {
+        DIC_AE callingAet_C;
+        DIC_AE calledAet_C;
+        DIC_AE callingIP_C;
+        DIC_AE calledIP_C;
+        if (ASC_getAPTitles(assoc->params, callingAet_C, calledAet_C, NULL).bad() ||
+            ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad())
+        {
+          T_ASC_RejectParameters rej =
+            {
+              ASC_RESULT_REJECTEDPERMANENT,
+              ASC_SOURCE_SERVICEUSER,
+              ASC_REASON_SU_NOREASON
+            };
+          ASC_rejectAssociation(assoc, &rej);
+          AssociationCleanup(assoc);
+          return NULL;
+        }
+
+        callingIP = std::string(/*OFSTRING_GUARD*/(callingIP_C));
+        callingAet = std::string(/*OFSTRING_GUARD*/(callingAet_C));
+        calledAet = (/*OFSTRING_GUARD*/(calledAet_C));
+      }
+
+      LOG(INFO) << "Association Received from AET " << callingAet 
+                << " on IP " << callingIP;
+
 
       std::vector<const char*> transferSyntaxes;
 
@@ -469,36 +500,72 @@
       transferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
 
       // New transfer syntaxes supported since Orthanc 0.7.2
-      transferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); 
-      transferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess3_5TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess6_8TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess7_9TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess10_12TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess11_13TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess14TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess15TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess16_18TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess17_19TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess20_22TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess21_23TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess24_26TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess25_27TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess28TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess29TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGProcess14SV1TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGLSLosslessTransferSyntax);
-      transferSyntaxes.push_back(UID_JPEGLSLossyTransferSyntax);
-      transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax);
-      transferSyntaxes.push_back(UID_JPEG2000TransferSyntax);
-      transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax);
-      transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax);
-      transferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax);
-      transferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax);
-      transferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax);
-      transferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax);
-      transferSyntaxes.push_back(UID_RLELosslessTransferSyntax);
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Deflated))
+      {
+        transferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); 
+      }
+
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpeg))
+      {
+        transferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess3_5TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess6_8TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess7_9TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess10_12TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess11_13TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess14TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess15TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess16_18TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess17_19TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess20_22TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess21_23TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess24_26TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess25_27TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess28TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess29TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGProcess14SV1TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGLSLosslessTransferSyntax);
+        transferSyntaxes.push_back(UID_JPEGLSLossyTransferSyntax);
+      }
+
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpeg2000))
+      {
+        transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax);
+        transferSyntaxes.push_back(UID_JPEG2000TransferSyntax);
+      }
+
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_JpegLossless))
+      {
+        transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax);
+        transferSyntaxes.push_back(UID_JPEG2000TransferSyntax);
+        transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax);
+        transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax);
+      }
+
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpip))
+      {
+        transferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax);
+        transferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax);
+      }
+
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Mpeg2))
+      {
+        transferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax);
+        transferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax);
+      }
+
+      if (!server.HasApplicationEntityFilter() ||
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Rle))
+      {
+        transferSyntaxes.push_back(UID_RLELosslessTransferSyntax);
+      }
 
       /* accept the Verification SOP Class if presented */
       cond = ASC_acceptContextsWithPreferredTransferSyntaxes(assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), &transferSyntaxes[0], transferSyntaxes.size());
@@ -555,62 +622,38 @@
         return NULL;
       }
 
-      std::string callingIP;
-      std::string callingTitle;
-  
       /* check the AETs */
+      if (!server.IsMyAETitle(calledAet))
       {
-        DIC_AE callingTitle_C;
-        DIC_AE calledTitle_C;
-        DIC_AE callingIP_C;
-        DIC_AE calledIP_C;
-        if (ASC_getAPTitles(assoc->params, callingTitle_C, calledTitle_C, NULL).bad() ||
-            ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad())
-        {
-          T_ASC_RejectParameters rej =
-            {
-              ASC_RESULT_REJECTEDPERMANENT,
-              ASC_SOURCE_SERVICEUSER,
-              ASC_REASON_SU_NOREASON
-            };
-          ASC_rejectAssociation(assoc, &rej);
-          AssociationCleanup(assoc);
-          return NULL;
-        }
-
-        callingIP = std::string(/*OFSTRING_GUARD*/(callingIP_C));
-        callingTitle = std::string(/*OFSTRING_GUARD*/(callingTitle_C));
-        std::string calledTitle(/*OFSTRING_GUARD*/(calledTitle_C));
-
-        if (!server.IsMyAETitle(calledTitle))
-        {
-          T_ASC_RejectParameters rej =
-            {
-              ASC_RESULT_REJECTEDPERMANENT,
-              ASC_SOURCE_SERVICEUSER,
-              ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED
-            };
-          ASC_rejectAssociation(assoc, &rej);
-          AssociationCleanup(assoc);
-          return NULL;
-        }
-
-        if (server.HasApplicationEntityFilter() &&
-            !server.GetApplicationEntityFilter().IsAllowedConnection(callingIP, callingTitle))
-        {
-          T_ASC_RejectParameters rej =
-            {
-              ASC_RESULT_REJECTEDPERMANENT,
-              ASC_SOURCE_SERVICEUSER,
-              ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED
-            };
-          ASC_rejectAssociation(assoc, &rej);
-          AssociationCleanup(assoc);
-          return NULL;
-        }
+        LOG(WARNING) << "Rejected association, because of a bad called AET in the request (" << calledAet << ")";
+        T_ASC_RejectParameters rej =
+          {
+            ASC_RESULT_REJECTEDPERMANENT,
+            ASC_SOURCE_SERVICEUSER,
+            ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED
+          };
+        ASC_rejectAssociation(assoc, &rej);
+        AssociationCleanup(assoc);
+        return NULL;
       }
 
-      if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0)
+      if (server.HasApplicationEntityFilter() &&
+          !server.GetApplicationEntityFilter().IsAllowedConnection(callingIP, callingAet))
+      {
+        LOG(WARNING) << "Rejected association for remote AET " << callingAet << " on IP " << callingIP;
+        T_ASC_RejectParameters rej =
+          {
+            ASC_RESULT_REJECTEDPERMANENT,
+            ASC_SOURCE_SERVICEUSER,
+            ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED
+          };
+        ASC_rejectAssociation(assoc, &rej);
+        AssociationCleanup(assoc);
+        return NULL;
+      }
+
+      if (opt_rejectWithoutImplementationUID && 
+          strlen(assoc->params->theirImplementationClassUID) == 0)
       {
         /* reject: the no implementation Class UID provided */
         T_ASC_RejectParameters rej =
@@ -644,7 +687,7 @@
       }
 
       IApplicationEntityFilter* filter = server.HasApplicationEntityFilter() ? &server.GetApplicationEntityFilter() : NULL;
-      return new CommandDispatcher(server, assoc, callingIP, callingTitle, filter);
+      return new CommandDispatcher(server, assoc, callingIP, callingAet, filter);
     }
 
     bool CommandDispatcher::Step()
--- a/OrthancServer/ServerEnumerations.cpp	Wed Sep 17 11:57:28 2014 +0200
+++ b/OrthancServer/ServerEnumerations.cpp	Wed Sep 17 17:23:08 2014 +0200
@@ -324,7 +324,6 @@
         return "Store";
         break;
 
-
       default: 
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
@@ -359,4 +358,36 @@
       throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
   }
+
+
+  const char* EnumerationToString(TransferSyntax syntax)
+  {
+    switch (syntax)
+    {
+      case TransferSyntax_Deflated:
+        return "Deflated";
+
+      case TransferSyntax_Jpeg:
+        return "JPEG";
+
+      case TransferSyntax_Jpeg2000:
+        return "JPEG2000";
+
+      case TransferSyntax_JpegLossless:
+        return "JPEG Lossless";
+
+      case TransferSyntax_Jpip:
+        return "JPIP";
+
+      case TransferSyntax_Mpeg2:
+        return "MPEG2";
+
+      case TransferSyntax_Rle:
+        return "RLE";
+
+      default: 
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
 }
--- a/OrthancServer/ServerEnumerations.h	Wed Sep 17 11:57:28 2014 +0200
+++ b/OrthancServer/ServerEnumerations.h	Wed Sep 17 17:23:08 2014 +0200
@@ -79,6 +79,17 @@
     DicomReplaceMode_IgnoreIfAbsent
   };
 
+  enum TransferSyntax
+  {
+    TransferSyntax_Deflated,
+    TransferSyntax_Jpeg,
+    TransferSyntax_Jpeg2000,
+    TransferSyntax_JpegLossless,
+    TransferSyntax_Jpip,
+    TransferSyntax_Mpeg2,
+    TransferSyntax_Rle
+  };
+
 
   /**
    * WARNING: Do not change the explicit values in the enumerations
@@ -157,6 +168,8 @@
 
   const char* EnumerationToString(DicomRequestType type);
 
+  const char* EnumerationToString(TransferSyntax syntax);
+
   ModalityManufacturer StringToModalityManufacturer(const std::string& manufacturer);
 
   ResourceType GetParentResourceType(ResourceType type);
--- a/OrthancServer/main.cpp	Wed Sep 17 11:57:28 2014 +0200
+++ b/OrthancServer/main.cpp	Wed Sep 17 17:23:08 2014 +0200
@@ -177,6 +177,13 @@
       return true;
     }
   }
+
+  virtual bool IsAllowedTransferSyntax(const std::string& callingAet,
+                                       TransferSyntax syntax)
+  {
+    // TODO - https://trello.com/c/8GxcTR0n
+    return true;
+  }
 };