Mercurial > hg > orthanc
annotate OrthancFramework/Sources/DicomNetworking/Internals/DicomTls.cpp @ 5643:b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Fri, 31 May 2024 16:56:35 +0200 |
parents | f7adfb22e20e |
children | 343149762476 |
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 | |
5640
f7adfb22e20e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5632
diff
changeset
|
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
f7adfb22e20e
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5632
diff
changeset
|
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
5485
48b8dae6dc77
upgrade to year 2024
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5185
diff
changeset
|
7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
4432 | 8 * |
9 * This program is free software: you can redistribute it and/or | |
10 * modify it under the terms of the GNU Lesser General Public License | |
11 * as published by the Free Software Foundation, either version 3 of | |
12 * the License, or (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, but | |
15 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Lesser General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Lesser General Public | |
20 * License along with this program. If not, see | |
21 * <http://www.gnu.org/licenses/>. | |
22 **/ | |
23 | |
24 | |
25 #include "../../PrecompiledHeaders.h" | |
26 #include "DicomTls.h" | |
27 | |
28 #include "../../Logging.h" | |
29 #include "../../OrthancException.h" | |
30 #include "../../SystemToolbox.h" | |
5643
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
31 #include "../../Toolbox.h" |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
32 #include <openssl/ssl.h> |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
33 #include <openssl/err.h> |
4432 | 34 |
35 #if DCMTK_VERSION_NUMBER < 364 | |
36 # define DCF_Filetype_PEM SSL_FILETYPE_PEM | |
37 # if OPENSSL_VERSION_NUMBER >= 0x0090700fL | |
38 // This seems to correspond to TSP_Profile_AES: https://support.dcmtk.org/docs/tlsciphr_8h.html | |
39 static std::string opt_ciphersuites(TLS1_TXT_RSA_WITH_AES_128_SHA ":" SSL3_TXT_RSA_DES_192_CBC3_SHA); | |
40 # else | |
41 // This seems to correspond to TSP_Profile_Basic in DCMTK >= 3.6.4: https://support.dcmtk.org/docs/tlsciphr_8h.html | |
42 static std::string opt_ciphersuites(SSL3_TXT_RSA_DES_192_CBC3_SHA); | |
43 # endif | |
44 #endif | |
45 | |
46 | |
47 namespace Orthanc | |
48 { | |
49 namespace Internals | |
50 { | |
4997
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
51 #if DCMTK_VERSION_NUMBER >= 367 |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
52 static bool IsFailure(OFCondition cond) |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
53 { |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
54 return !cond.good(); |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
55 } |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
56 #else |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
57 static bool IsFailure(DcmTransportLayerStatus status) |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
58 { |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
59 return (status != TCS_ok); |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
60 } |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
61 #endif |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
62 |
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
63 |
4432 | 64 DcmTLSTransportLayer* InitializeDicomTls(T_ASC_Network *network, |
65 T_ASC_NetworkRole role, | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
66 const std::string& ownPrivateKeyPath, |
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
67 const std::string& ownCertificatePath, |
4656
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
68 const std::string& trustedCertificatesPath, |
5643
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
69 bool requireRemoteCertificate, |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
70 unsigned int minimalTlsVersion, |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
71 const std::set<std::string>& ciphers) |
4432 | 72 { |
73 if (network == NULL) | |
74 { | |
75 throw OrthancException(ErrorCode_NullPointer); | |
76 } | |
77 | |
78 if (role != NET_ACCEPTOR && | |
79 role != NET_REQUESTOR) | |
80 { | |
81 throw OrthancException(ErrorCode_ParameterOutOfRange, "Unknown role"); | |
82 } | |
83 | |
5598
317850cd46bc
fix DicomTlsTrustedCertificates configuration that should not be mandatory if DicomTlsRemoteCertificateRequired is false
Alain Mazy <am@orthanc.team>
parents:
5487
diff
changeset
|
84 if (requireRemoteCertificate && !SystemToolbox::IsRegularFile(trustedCertificatesPath)) |
4432 | 85 { |
86 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
|
87 trustedCertificatesPath); |
4432 | 88 } |
89 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
90 if (!SystemToolbox::IsRegularFile(ownPrivateKeyPath)) |
4432 | 91 { |
92 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
|
93 ownPrivateKeyPath); |
4432 | 94 } |
95 | |
4438
4a4e33c9082d
configuration options for DICOM TLS in Orthanc SCU
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
96 if (!SystemToolbox::IsRegularFile(ownCertificatePath)) |
4432 | 97 { |
98 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
|
99 ownCertificatePath); |
4432 | 100 } |
101 | |
102 CLOG(INFO, DICOM) << "Initializing DICOM TLS for Orthanc " | |
103 << (role == NET_ACCEPTOR ? "SCP" : "SCU"); | |
104 | |
105 #if DCMTK_VERSION_NUMBER >= 364 | |
106 const T_ASC_NetworkRole tmpRole = role; | |
107 #else | |
108 int tmpRole; | |
109 switch (role) | |
110 { | |
111 case NET_ACCEPTOR: | |
112 tmpRole = DICOM_APPLICATION_ACCEPTOR; | |
113 break; | |
114 | |
115 case NET_REQUESTOR: | |
116 tmpRole = DICOM_APPLICATION_REQUESTOR; | |
117 break; | |
118 | |
119 default: | |
120 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
121 } | |
122 #endif | |
123 | |
124 std::unique_ptr<DcmTLSTransportLayer> tls( | |
125 new DcmTLSTransportLayer(tmpRole /*opt_networkRole*/, NULL /*opt_readSeedFile*/, | |
126 OFFalse /*initializeOpenSSL, done by Orthanc::Toolbox::InitializeOpenSsl()*/)); | |
127 | |
5598
317850cd46bc
fix DicomTlsTrustedCertificates configuration that should not be mandatory if DicomTlsRemoteCertificateRequired is false
Alain Mazy <am@orthanc.team>
parents:
5487
diff
changeset
|
128 if (requireRemoteCertificate && IsFailure(tls->addTrustedCertificateFile(trustedCertificatesPath.c_str(), DCF_Filetype_PEM /*opt_keyFileFormat*/))) |
4432 | 129 { |
130 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
|
131 trustedCertificatesPath); |
4432 | 132 } |
133 | |
4997
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
134 if (IsFailure(tls->setPrivateKeyFile(ownPrivateKeyPath.c_str(), DCF_Filetype_PEM /*opt_keyFileFormat*/))) |
4432 | 135 { |
136 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
|
137 ownPrivateKeyPath); |
4432 | 138 } |
139 | |
5487
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
140 if (IsFailure(tls->setCertificateFile( |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
141 ownCertificatePath.c_str(), DCF_Filetype_PEM /*opt_keyFileFormat*/ |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
142 #if DCMTK_VERSION_NUMBER >= 368 |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
143 /** |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
144 * DICOM BCP 195 RFC 8996 TLS Profile, based on RFC 8996 and RFC 9325. |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
145 * This profile only negotiates TLS 1.2 or newer, and will not fall back to |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
146 * previous TLS versions. It provides the higher security level offered by the |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
147 * 2021 revised edition of BCP 195. |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
148 **/ |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
149 , TSP_Profile_BCP_195_RFC_8996 |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
150 #endif |
33f8e180edcf
upgraded static build to dcmtk 3.6.8
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5485
diff
changeset
|
151 ))) |
4432 | 152 { |
153 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
|
154 ownCertificatePath); |
4432 | 155 } |
156 | |
157 if (!tls->checkPrivateKeyMatchesCertificate()) | |
158 { | |
159 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
|
160 ownPrivateKeyPath + " vs. " + ownCertificatePath); |
4432 | 161 } |
162 | |
163 #if DCMTK_VERSION_NUMBER >= 364 | |
5643
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
164 if (minimalTlsVersion == 0) // use the default values (same behavior as before 1.12.4) |
4432 | 165 { |
5643
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
166 if (ciphers.size() > 0) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
167 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
168 throw OrthancException(ErrorCode_BadFileFormat, "The cipher suites can not be specified when using the default BCP profile"); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
169 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
170 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
171 if (IsFailure(tls->setTLSProfile(TSP_Profile_BCP195 /*opt_tlsProfile*/))) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
172 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
173 throw OrthancException(ErrorCode_InternalError, "Cannot set the DICOM TLS profile"); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
174 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
175 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
176 if (IsFailure(tls->activateCipherSuites())) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
177 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
178 throw OrthancException(ErrorCode_InternalError, "Cannot activate the cipher suites for DICOM TLS"); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
179 } |
4432 | 180 } |
5643
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
181 else |
4432 | 182 { |
5643
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
183 // Fine tune the SSL context |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
184 if (IsFailure(tls->setTLSProfile(TSP_Profile_None))) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
185 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
186 throw OrthancException(ErrorCode_InternalError, "Cannot set the DICOM TLS profile"); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
187 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
188 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
189 DcmTLSTransportLayer::native_handle_type sslNativeHandle = tls->getNativeHandle(); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
190 SSL_CTX_clear_options(sslNativeHandle, SSL_OP_NO_SSL_MASK); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
191 if (minimalTlsVersion > 1) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
192 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
193 SSL_CTX_set_options(sslNativeHandle, SSL_OP_NO_SSLv3); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
194 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
195 if (minimalTlsVersion > 2) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
196 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
197 SSL_CTX_set_options(sslNativeHandle, SSL_OP_NO_TLSv1); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
198 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
199 if (minimalTlsVersion > 3) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
200 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
201 SSL_CTX_set_options(sslNativeHandle, SSL_OP_NO_TLSv1_1); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
202 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
203 if (minimalTlsVersion > 4) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
204 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
205 SSL_CTX_set_options(sslNativeHandle, SSL_OP_NO_TLSv1_2); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
206 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
207 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
208 std::set<std::string> ciphersTls; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
209 std::set<std::string> ciphersTls13; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
210 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
211 // DCMTK 3.8 is missing a method to add TLS13 cipher suite in the DcmTLSTransportLayer interface. |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
212 // And, anyway, since we do not run dcmtkPrepare.cmake, DCMTK is not aware of TLS v1.3 cipher suite names. |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
213 for (std::set<std::string>::const_iterator it = ciphers.begin(); it != ciphers.end(); ++it) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
214 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
215 bool isValid = false; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
216 if (DcmTLSCiphersuiteHandler::lookupCiphersuiteByOpenSSLName(it->c_str()) != DcmTLSCiphersuiteHandler::unknownCipherSuiteIndex) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
217 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
218 ciphersTls.insert(it->c_str()); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
219 isValid = true; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
220 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
221 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
222 // list of TLS v1.3 ciphers according to https://www.openssl.org/docs/man3.3/man1/openssl-ciphers.html |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
223 if (strstr("TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256", it->c_str()) != NULL) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
224 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
225 ciphersTls13.insert(it->c_str()); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
226 isValid = true; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
227 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
228 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
229 if (!isValid) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
230 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
231 throw OrthancException(ErrorCode_BadFileFormat, "The cipher suite " + *it + " is not recognized as valid cipher suite by OpenSSL "); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
232 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
233 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
234 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
235 std::string joinedCiphersTls; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
236 std::string joinedCiphersTls13; |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
237 Toolbox::JoinStrings(joinedCiphersTls, ciphersTls, ":"); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
238 Toolbox::JoinStrings(joinedCiphersTls13, ciphersTls13, ":"); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
239 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
240 if (joinedCiphersTls.size() > 0 && SSL_CTX_set_cipher_list(sslNativeHandle, joinedCiphersTls.c_str()) != 1) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
241 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
242 OFCondition cond = DcmTLSTransportLayer::convertOpenSSLError(ERR_get_error(), OFTrue); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
243 throw OrthancException(ErrorCode_InternalError, "Unable to configure cipher suite. OpenSSL error: " + boost::lexical_cast<std::string>(cond.code()) + " - " + cond.text()); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
244 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
245 |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
246 if (joinedCiphersTls13.size() > 0 && SSL_CTX_set_ciphersuites(sslNativeHandle, joinedCiphersTls13.c_str()) != 1) |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
247 { |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
248 OFCondition cond = DcmTLSTransportLayer::convertOpenSSLError(ERR_get_error(), OFTrue); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
249 throw OrthancException(ErrorCode_InternalError, "Unable to configure cipher suite for TLS 1.3. OpenSSL error: " + boost::lexical_cast<std::string>(cond.code()) + " - " + cond.text()); |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
250 } |
b1a18218860c
2 new configurations: DicomTlsMinimumProtocolVersion + DicomTlsCiphersAccepted
Alain Mazy <am@orthanc.team>
parents:
5640
diff
changeset
|
251 |
4432 | 252 } |
253 #else | |
254 CLOG(INFO, DICOM) << "Using the following cipher suites for DICOM TLS: " << opt_ciphersuites; | |
4997
1f93dc290628
fix compatibility with dcmtk 3.6.7
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4870
diff
changeset
|
255 if (IsFailure(tls->setCipherSuites(opt_ciphersuites.c_str()))) |
4432 | 256 { |
257 throw OrthancException(ErrorCode_InternalError, "Unable to set cipher suites to: " + opt_ciphersuites); | |
258 } | |
259 #endif | |
260 | |
4656
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
261 if (requireRemoteCertificate) |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
262 { |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
263 // Check remote certificate, fail if no certificate is present |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
264 tls->setCertificateVerification(DCV_requireCertificate /*opt_certVerification*/); |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
265 } |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
266 else |
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
267 { |
5632
cfb67c7ccb4d
DicomTlsRemoteCertificateRequired=false is now equivalent to --ignore-peer-cert DCMTK option instead of --verify-peer-cert
Alain Mazy <am@orthanc.team>
parents:
5598
diff
changeset
|
268 // From 1.12.4, do not even request remote certificate (prior to 1.12.4, we were requesting a certificates, checking it if present and succeeding if not present) |
cfb67c7ccb4d
DicomTlsRemoteCertificateRequired=false is now equivalent to --ignore-peer-cert DCMTK option instead of --verify-peer-cert
Alain Mazy <am@orthanc.team>
parents:
5598
diff
changeset
|
269 tls->setCertificateVerification(DCV_ignoreCertificate /*opt_certVerification*/); |
4656
82a314325351
New configuration option: "DicomTlsRemoteCertificateRequired"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4438
diff
changeset
|
270 } |
4432 | 271 |
272 if (ASC_setTransportLayer(network, tls.get(), 0).bad()) | |
273 { | |
274 throw OrthancException(ErrorCode_InternalError, "Cannot enable DICOM TLS in the Orthanc " + | |
275 std::string(role == NET_ACCEPTOR ? "SCP" : "SCU")); | |
276 } | |
277 | |
278 return tls.release(); | |
279 } | |
280 } | |
281 } |