Mercurial > hg > orthanc
annotate OrthancFramework/Sources/DicomNetworking/Internals/DicomTls.cpp @ 4870:43e613a7756b
upgrade to year 2022
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 Jan 2022 11:15:42 +0100 |
parents | 7053502fbf97 |
children | 1f93dc290628 |
rev | line source |
---|---|
4432 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
4870
43e613a7756b
upgrade to year 2022
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4831
diff
changeset
|
5 * Copyright (C) 2017-2022 Osimis S.A., Belgium |
43e613a7756b
upgrade to year 2022
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4831
diff
changeset
|
6 * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
4432 | 7 * |
8 * This program is free software: you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public License | |
10 * as published by the Free Software Foundation, either version 3 of | |
11 * the License, or (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, but | |
14 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with this program. If not, see | |
20 * <http://www.gnu.org/licenses/>. | |
21 **/ | |
22 | |
23 | |
24 #include "../../PrecompiledHeaders.h" | |
25 #include "DicomTls.h" | |
26 | |
27 #include "../../Logging.h" | |
28 #include "../../OrthancException.h" | |
29 #include "../../SystemToolbox.h" | |
30 | |
31 | |
32 #if DCMTK_VERSION_NUMBER < 364 | |
33 # define DCF_Filetype_PEM SSL_FILETYPE_PEM | |
34 # if OPENSSL_VERSION_NUMBER >= 0x0090700fL | |
35 // This seems to correspond to TSP_Profile_AES: https://support.dcmtk.org/docs/tlsciphr_8h.html | |
36 static std::string opt_ciphersuites(TLS1_TXT_RSA_WITH_AES_128_SHA ":" SSL3_TXT_RSA_DES_192_CBC3_SHA); | |
37 # else | |
38 // This seems to correspond to TSP_Profile_Basic in DCMTK >= 3.6.4: https://support.dcmtk.org/docs/tlsciphr_8h.html | |
39 static std::string opt_ciphersuites(SSL3_TXT_RSA_DES_192_CBC3_SHA); | |
40 # endif | |
41 #endif | |
42 | |
43 | |
44 namespace Orthanc | |
45 { | |
46 namespace Internals | |
47 { | |
48 DcmTLSTransportLayer* InitializeDicomTls(T_ASC_Network *network, | |
49 T_ASC_NetworkRole role, | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
50 const std::string& ownPrivateKeyPath, |
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
51 const std::string& ownCertificatePath, |
4656
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
52 const std::string& trustedCertificatesPath, |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
53 bool requireRemoteCertificate) |
4432 | 54 { |
55 if (network == NULL) | |
56 { | |
57 throw OrthancException(ErrorCode_NullPointer); | |
58 } | |
59 | |
60 if (role != NET_ACCEPTOR && | |
61 role != NET_REQUESTOR) | |
62 { | |
63 throw OrthancException(ErrorCode_ParameterOutOfRange, "Unknown role"); | |
64 } | |
65 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
66 if (!SystemToolbox::IsRegularFile(trustedCertificatesPath)) |
4432 | 67 { |
68 throw OrthancException(ErrorCode_InexistentFile, "Cannot read file with trusted certificates for DICOM TLS: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
69 trustedCertificatesPath); |
4432 | 70 } |
71 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
72 if (!SystemToolbox::IsRegularFile(ownPrivateKeyPath)) |
4432 | 73 { |
74 throw OrthancException(ErrorCode_InexistentFile, "Cannot read file with own private key for DICOM TLS: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
75 ownPrivateKeyPath); |
4432 | 76 } |
77 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
78 if (!SystemToolbox::IsRegularFile(ownCertificatePath)) |
4432 | 79 { |
80 throw OrthancException(ErrorCode_InexistentFile, "Cannot read file with own certificate for DICOM TLS: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
81 ownCertificatePath); |
4432 | 82 } |
83 | |
84 CLOG(INFO, DICOM) << "Initializing DICOM TLS for Orthanc " | |
85 << (role == NET_ACCEPTOR ? "SCP" : "SCU"); | |
86 | |
87 #if DCMTK_VERSION_NUMBER >= 364 | |
88 const T_ASC_NetworkRole tmpRole = role; | |
89 #else | |
90 int tmpRole; | |
91 switch (role) | |
92 { | |
93 case NET_ACCEPTOR: | |
94 tmpRole = DICOM_APPLICATION_ACCEPTOR; | |
95 break; | |
96 | |
97 case NET_REQUESTOR: | |
98 tmpRole = DICOM_APPLICATION_REQUESTOR; | |
99 break; | |
100 | |
101 default: | |
102 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
103 } | |
104 #endif | |
105 | |
106 std::unique_ptr<DcmTLSTransportLayer> tls( | |
107 new DcmTLSTransportLayer(tmpRole /*opt_networkRole*/, NULL /*opt_readSeedFile*/, | |
108 OFFalse /*initializeOpenSSL, done by Orthanc::Toolbox::InitializeOpenSsl()*/)); | |
109 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
110 if (tls->addTrustedCertificateFile(trustedCertificatesPath.c_str(), DCF_Filetype_PEM /*opt_keyFileFormat*/) != TCS_ok) |
4432 | 111 { |
112 throw OrthancException(ErrorCode_BadFileFormat, "Cannot parse PEM file with trusted certificates for DICOM TLS: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
113 trustedCertificatesPath); |
4432 | 114 } |
115 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
116 if (tls->setPrivateKeyFile(ownPrivateKeyPath.c_str(), DCF_Filetype_PEM /*opt_keyFileFormat*/) != TCS_ok) |
4432 | 117 { |
118 throw OrthancException(ErrorCode_BadFileFormat, "Cannot parse PEM file with private key for DICOM TLS: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
119 ownPrivateKeyPath); |
4432 | 120 } |
121 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
122 if (tls->setCertificateFile(ownCertificatePath.c_str(), DCF_Filetype_PEM /*opt_keyFileFormat*/) != TCS_ok) |
4432 | 123 { |
124 throw OrthancException(ErrorCode_BadFileFormat, "Cannot parse PEM file with own certificate for DICOM TLS: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
125 ownCertificatePath); |
4432 | 126 } |
127 | |
128 if (!tls->checkPrivateKeyMatchesCertificate()) | |
129 { | |
130 throw OrthancException(ErrorCode_BadFileFormat, "The private key doesn't match the own certificate: " + | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
131 ownPrivateKeyPath + " vs. " + ownCertificatePath); |
4432 | 132 } |
133 | |
134 #if DCMTK_VERSION_NUMBER >= 364 | |
135 if (tls->setTLSProfile(TSP_Profile_BCP195 /*opt_tlsProfile*/) != TCS_ok) | |
136 { | |
137 throw OrthancException(ErrorCode_InternalError, "Cannot set the DICOM TLS profile"); | |
138 } | |
139 | |
140 if (tls->activateCipherSuites()) | |
141 { | |
142 throw OrthancException(ErrorCode_InternalError, "Cannot activate the cipher suites for DICOM TLS"); | |
143 } | |
144 #else | |
145 CLOG(INFO, DICOM) << "Using the following cipher suites for DICOM TLS: " << opt_ciphersuites; | |
146 if (tls->setCipherSuites(opt_ciphersuites.c_str()) != TCS_ok) | |
147 { | |
148 throw OrthancException(ErrorCode_InternalError, "Unable to set cipher suites to: " + opt_ciphersuites); | |
149 } | |
150 #endif | |
151 | |
4656
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
152 if (requireRemoteCertificate) |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
153 { |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
154 // Check remote certificate, fail if no certificate is present |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
155 tls->setCertificateVerification(DCV_requireCertificate /*opt_certVerification*/); |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
156 } |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
157 else |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
158 { |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
159 // Check remote certificate if present, succeed if no certificate is present |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
160 tls->setCertificateVerification(DCV_checkCertificate /*opt_certVerification*/); |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
161 } |
4432 | 162 |
163 if (ASC_setTransportLayer(network, tls.get(), 0).bad()) | |
164 { | |
165 throw OrthancException(ErrorCode_InternalError, "Cannot enable DICOM TLS in the Orthanc " + | |
166 std::string(role == NET_ACCEPTOR ? "SCP" : "SCU")); | |
167 } | |
168 | |
169 return tls.release(); | |
170 } | |
171 } | |
172 } |