init
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.ciphersFailure=Failed getting cipher list
|
||||
engine.emptyCipherSuite=Empty cipher suite
|
||||
engine.engineClosed=Engine is closed
|
||||
engine.failedCipherSuite=Failed to enable cipher suite [{0}]
|
||||
engine.inboundClose=Inbound closed before receiving peer's close_notify
|
||||
engine.invalidBufferArray=offset: [{0}], length: [{1}] (expected: offset <= offset + length <= srcs.length [{2}])
|
||||
engine.noSSLContext=No SSL context
|
||||
engine.noSession=SSL session ID not available
|
||||
engine.nullBuffer=Null buffer
|
||||
engine.nullBufferInArray=Null buffer in array
|
||||
engine.nullCipherSuite=Null cipher suite
|
||||
engine.nullName=Null value name
|
||||
engine.nullValue=Null value
|
||||
engine.openSSLError=OpenSSL error: [{0}] message: [{1}]
|
||||
engine.oversizedPacket=Encrypted packet is oversized
|
||||
engine.unsupportedCipher=Unsupported cipher suite: [{0}] [{1}]
|
||||
engine.unsupportedProtocol=Protocol [{0}] is not supported
|
||||
engine.unverifiedPeer=Peer unverified
|
||||
engine.writeToSSLFailed=Failed writing to SSL, returned: [{0}]
|
||||
|
||||
openssl.X509FactoryError=Error getting X509 factory instance
|
||||
openssl.addedClientCaCert=Added client CA cert: [{0}]
|
||||
openssl.applyConf=Applying OpenSSLConfCmd to SSL context
|
||||
openssl.certificateVerificationFailed=Certificate verification failed
|
||||
openssl.checkConf=Checking OpenSSLConf
|
||||
openssl.doubleInit=SSL context already initialized, ignoring
|
||||
openssl.errApplyConf=Could not apply OpenSSLConf to SSL context
|
||||
openssl.errCheckConf=Error during OpenSSLConf check
|
||||
openssl.errMakeConf=Could not create OpenSSLConf context
|
||||
openssl.errorSSLCtxInit=Error initializing SSL context
|
||||
openssl.keyManagerMissing=No key manager found
|
||||
openssl.makeConf=Creating OpenSSLConf context
|
||||
openssl.nonJsseCertficate=The certificate [{0}] or its private key [{1}] could not be processed using a JSSE key manager and will be given directly to OpenSSL
|
||||
openssl.nonJsseChain=The certificate chain [{0}] was not specified or was not valid and JSSE requires a valid certificate chain so attempting to use OpenSSL directly
|
||||
openssl.trustManagerMissing=No trust manager found
|
||||
|
||||
opensslconf.applyCommand=OpenSSLConf applying command (name [{0}], value [{1}])
|
||||
opensslconf.applyFailed=Failure while applying OpenSSLConf to SSL context
|
||||
opensslconf.checkCommand=OpenSSLConf checking command (name [{0}], value [{1}])
|
||||
opensslconf.checkFailed=Failure while checking OpenSSLConf
|
||||
opensslconf.failedCommand=OpenSSLConf failed command (name [{0}], value [{1}]) with result [{2}] - will be ignored
|
||||
opensslconf.finishFailed=OpenSSLConf finish failed with result [{0}]
|
||||
opensslconf.noCommandName=OpenSSLConf no command name - will be ignored (command value [{0}])
|
||||
opensslconf.resultCommand=OpenSSLConf command (name [{0}], value [{1}]) returned [{2}]
|
||||
|
||||
sessionContext.nullTicketKeys=Null keys
|
||||
@@ -0,0 +1,33 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.ciphersFailure=Fehler beim abfragen der Cipher Liste
|
||||
engine.emptyCipherSuite=leere Cipher-Suite
|
||||
engine.inboundClose=Die eingehende Verbindung wurde vor einer close_notify Nachricht der Gegenstelle geschlossen
|
||||
engine.noSession=SSL Session-ID nicht vorhanden
|
||||
engine.openSSLError=OpenSSL Fehler: [{0}] Nachricht: [{1}]
|
||||
engine.unsupportedProtocol=Protokoll [{0}] ist nicht unterstützt
|
||||
|
||||
openssl.addedClientCaCert=Client CA Zertifikat hinzugefügt: [{0}]
|
||||
openssl.certificateVerificationFailed=Zertifikatsprüfung fehlgeschlagen
|
||||
openssl.errApplyConf=Die OpenSSLConf konnte nicht auf den SSL Context angewandt werden
|
||||
openssl.errCheckConf=Fehler beim Prüfen der OpenSSLConf
|
||||
openssl.errMakeConf=Der OpenSSLConf Context konnte nicht erzeugt werden
|
||||
openssl.errorSSLCtxInit=Fehler beim initialisieren des SSL Contexts
|
||||
openssl.keyManagerMissing=Kein Key-Manager gefunden
|
||||
openssl.trustManagerMissing=Kein Trust-Manager gefunden
|
||||
|
||||
opensslconf.applyFailed=Fehler bei der Anwendung der OpenSSLConf auf den SSL Context
|
||||
opensslconf.checkFailed=Fehler beim Prüfen der OpenSSLConf
|
||||
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.emptyCipherSuite=Suite de cifrado vacía
|
||||
engine.engineClosed=El notor esta cerrado
|
||||
engine.noSession=El identificador de la sesión SSL no está disponible
|
||||
engine.openSSLError=Error de OpenSSL: [{0}] mensage: [{1}]\n
|
||||
engine.writeToSSLFailed=Fallo al escribir hacia SSL, resultado: [{0}]
|
||||
|
||||
openssl.addedClientCaCert=Ceritifcado CA de cliente adicionado: [{0}]
|
||||
openssl.trustManagerMissing=No se encontró un manejador confiable
|
||||
|
||||
opensslconf.checkFailed=Fallo mientras se chequeaba OpenSSLConf\n
|
||||
@@ -0,0 +1,61 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.ciphersFailure=Echec en essayant d'obtenir la liste des chiffres
|
||||
engine.emptyCipherSuite=La suite de chiffrement (cipher suite) est vide
|
||||
engine.engineClosed=Le moteur a déjà été fermé
|
||||
engine.failedCipherSuite=Impossible d''activer la suite de chiffres [{0}]
|
||||
engine.inboundClose=L'entrée a été fermée avant d'avoir reçu le close_notify du pair
|
||||
engine.invalidBufferArray=offset: [{0}], length: [{1}] (attendu: offset <= offset + length <= srcs.length [{2}])
|
||||
engine.noSSLContext=Pas de contexte SSL
|
||||
engine.noSession=Identificateur de session SSL non disponible
|
||||
engine.nullBuffer=Tampon null
|
||||
engine.nullBufferInArray=Tampon null dans le tableau
|
||||
engine.nullCipherSuite=Suite de chiffres nulle
|
||||
engine.nullName=La valeur du nom est null
|
||||
engine.nullValue=La valeur est null
|
||||
engine.openSSLError=Erreur OpenSSL : [{0}] message : [{1}]
|
||||
engine.oversizedPacket=Le paquet crypté est trop gros
|
||||
engine.unsupportedCipher=Suite de chiffres non supportée: [{0}] [{1}]
|
||||
engine.unsupportedProtocol=Le protocole [{0}] n''est pas supporté
|
||||
engine.unverifiedPeer=Le pair n'est pas vérifié
|
||||
engine.writeToSSLFailed=Echec d''écriture vers SSL, code de retour: [{0}]
|
||||
|
||||
openssl.X509FactoryError=Impossible d'obtenir l'instance de la fabrique X509
|
||||
openssl.addedClientCaCert=Ajout du certificat CA du client: [{0}]
|
||||
openssl.applyConf=Application de OpenSSLConfCmd au contexte SSL
|
||||
openssl.certificateVerificationFailed=La vérification du certificat a échoué
|
||||
openssl.checkConf=Vérification de OpenSSLConf en cours
|
||||
openssl.doubleInit=Le contexte SSL a déjà été initialisé, ignoré
|
||||
openssl.errApplyConf=Impossible d'appliquer la OpenSSLConf au contexte SSL
|
||||
openssl.errCheckConf=Erreur pendant la vérification de OpenSSLConf
|
||||
openssl.errMakeConf=Impossible de créer le contexte de OpenSSLConf
|
||||
openssl.errorSSLCtxInit=Erreur d'initialisation du contexte SSL
|
||||
openssl.keyManagerMissing=Aucun gestionnaire de clés trouvé
|
||||
openssl.makeConf=Création du contexte de OpenSSLConf
|
||||
openssl.nonJsseCertficate=Le certificat [{0}] ou sa clé privée [{1}] n''a pas pu être traité en utilisant un gestionnaire de clé de JSSE, et sera directement passée à OpenSSL
|
||||
openssl.nonJsseChain=La chaîne de certificat [{0}] n''a pas été spécifiée ou est invalide et JSSE requiert une chaîne de certificats valide, donc OpenSSL sera utilisé directement
|
||||
openssl.trustManagerMissing=Gestionnaire de confiance non trouvé
|
||||
|
||||
opensslconf.applyCommand=Application de la commande OpenSSLConf (nom [{0}] valeur [{1}])
|
||||
opensslconf.applyFailed=Erreur en appliquant OpenSSLConf au contexte SSL
|
||||
opensslconf.checkCommand=Vérification de la commande OpenSSLConf (nom [{0}] valeur [{1}])
|
||||
opensslconf.checkFailed=Echec de la vérification de OpenSSLConf
|
||||
opensslconf.failedCommand=La commande OpenSSLConf (nom [{0}] valeur [{1}]) a échoué avec le résultat [{2}] qui sera ignoré
|
||||
opensslconf.finishFailed=OpenSSLConf s''est terminé en échec avec le résultat [{0}]
|
||||
opensslconf.noCommandName=Pas de nom de commande OpenSSLConf (valeur [{0}]), cela sera ignoré
|
||||
opensslconf.resultCommand=La commande OpenSSLConf (nom [{0}] valeur [{1}]) a retourné [{2}]
|
||||
|
||||
sessionContext.nullTicketKeys=Clés nulles
|
||||
@@ -0,0 +1,59 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.ciphersFailure=暗号リストを取得できません。
|
||||
engine.emptyCipherSuite=暗号スイートがありません。
|
||||
engine.engineClosed=エンジンが閉じられています
|
||||
engine.failedCipherSuite=暗号スイート[{0}]を有効にできませんでした。
|
||||
engine.inboundClose=ピアのclose_notifyを受信する前のインバウンドクローズ
|
||||
engine.invalidBufferArray=オフセット: [{0}], 長さ: [{1}] (期待値: offset <= offset + length <= srcs.length [{2}])
|
||||
engine.noSSLContext=SSLコンテキストがありません
|
||||
engine.noSession=SSLセッションIDが利用可能ではありません
|
||||
engine.nullBuffer=Null バッファ
|
||||
engine.nullBufferInArray=配列内のNull バッファ
|
||||
engine.nullCipherSuite=Null 暗号スイート
|
||||
engine.nullName=Null値名
|
||||
engine.nullValue=Null値
|
||||
engine.openSSLError=OpenSSLエラー:[{0}] メッセージ:[{1}]
|
||||
engine.oversizedPacket=暗号化パケットのサイズが超過しています。
|
||||
engine.unsupportedCipher=サポートされていない暗号スイート:[{0}] [{1}]
|
||||
engine.unsupportedProtocol=プロトコル [{0}] には対応していません。
|
||||
engine.unverifiedPeer=未確認のピア
|
||||
engine.writeToSSLFailed=SSLへの書き込みに失敗しました。返却値:[{0}]
|
||||
|
||||
openssl.X509FactoryError=X509ファクトリインスタンスの取得エラー
|
||||
openssl.addedClientCaCert=クライアント CA 証明書を登録しました: [{0}]
|
||||
openssl.applyConf=OpenSSLConfCmdをSSLコンテキストに適用します。
|
||||
openssl.certificateVerificationFailed=証明書確認に失敗しました
|
||||
openssl.checkConf=OpenSSLConfの確認
|
||||
openssl.doubleInit=SSLコンテキストが既に初期化されています。無視します。
|
||||
openssl.errApplyConf=OpenSSLConfをSSLコンテキストに適用できませんでした。
|
||||
openssl.errCheckConf=OpenSSLConfチェック中のエラー
|
||||
openssl.errMakeConf=OpenSSLConfコンテキストを作成できませんでした。
|
||||
openssl.errorSSLCtxInit=SSL コンテキストの初期化中にエラーが発生しました。
|
||||
openssl.keyManagerMissing=キーマネージャーが見つかりません。
|
||||
openssl.makeConf=OpenSSLConfコンテキストの作成
|
||||
openssl.trustManagerMissing=トラストマネージャが見つかりません
|
||||
|
||||
opensslconf.applyCommand=OpenSSLConfはコマンド(名前[{0}]、値[{1}])を適用しています。
|
||||
opensslconf.applyFailed=OpenSSLConfをSSLコンテキストに適用する際の失敗
|
||||
opensslconf.checkCommand=OpenSSLConfチェックコマンド(名前[{0}]、値[{1}])
|
||||
opensslconf.checkFailed=OpenSSLConf のチェックが失敗しました。
|
||||
opensslconf.failedCommand=結果[{2}]でOpenSSLConfがコマンド(名前[{0}]、値[{1}])に失敗しました。無視されます。
|
||||
opensslconf.finishFailed=結果[{0}]でOpenSSLConfのfinish処理が失敗しました
|
||||
opensslconf.noCommandName=OpenSSLConfコマンド名なし - 無視されます(コマンド値[{0}])
|
||||
opensslconf.resultCommand=OpenSSLConfコマンド(名前[{0}]、値[{1}])が[{2}]を返しました。
|
||||
|
||||
sessionContext.nullTicketKeys=Null キー
|
||||
@@ -0,0 +1,61 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.ciphersFailure=Cipher들의 목록을 얻지 못했습니다.
|
||||
engine.emptyCipherSuite=CipherSuite 이름이 존재하지 않습니다.
|
||||
engine.engineClosed=엔진이 닫혀 있습니다.
|
||||
engine.failedCipherSuite=Cipher suite [{0}]을(를) 사용가능 상태로 설정하지 못했습니다.
|
||||
engine.inboundClose=Peer의 close_notify를 받기 전에, Inbound가 닫혔습니다.
|
||||
engine.invalidBufferArray=offset: [{0}], 길이: [{1}] (요구사항: offset <= offset + length <= srcs.length [{2}])
|
||||
engine.noSSLContext=SSL 컨텍스트가 없음.
|
||||
engine.noSession=SSL 세션 ID가 존재하지 않습니다.
|
||||
engine.nullBuffer=널 버퍼
|
||||
engine.nullBufferInArray=배열 내에 널 버퍼임
|
||||
engine.nullCipherSuite=널 cipher suite
|
||||
engine.nullName=name이 널입니다.
|
||||
engine.nullValue=널 값
|
||||
engine.openSSLError=OpenSSL 오류: [{0}], 메시지: [{1}]
|
||||
engine.oversizedPacket=암호화된 패킷이 너무 큽니다.
|
||||
engine.unsupportedCipher=지원되지 않는 cipher suite: [{0}] [{1}]
|
||||
engine.unsupportedProtocol=프로토콜 [{0}]은(는) 지원되지 않습니다.
|
||||
engine.unverifiedPeer=검증되지 않은 Peer
|
||||
engine.writeToSSLFailed=SSL에 쓰기 실패, 반환 값: [{0}]
|
||||
|
||||
openssl.X509FactoryError=X509 팩토리 인스턴스를 얻는 중 오류 발생
|
||||
openssl.addedClientCaCert=클라이언트 CA 인증서를 추가했습니다: [{0}]
|
||||
openssl.applyConf=OpenSSLConfCmd를 SSL 컨텍스트에 적용합니다.
|
||||
openssl.certificateVerificationFailed=인증서 검증에 실패했습니다.
|
||||
openssl.checkConf=OpenSSLConf를 점검합니다.
|
||||
openssl.doubleInit=SSL 컨텍스트가 이미 초기화되어 있으므로, 초기화 호출을 무시합니다.
|
||||
openssl.errApplyConf=SSL 컨텍스트에 OpenSSLConf를 적용할 수 없었습니다.
|
||||
openssl.errCheckConf=OpenSSLConf 점검 중 오류 발생
|
||||
openssl.errMakeConf=OpenSSLConf 컨텍스트를 생성할 수 없었습니다.
|
||||
openssl.errorSSLCtxInit=SSL 컨텍스트를 초기화 하는 중 오류 발생
|
||||
openssl.keyManagerMissing=키 매니저를 찾을 수 없습니다.
|
||||
openssl.makeConf=OpenSSLConf 컨텍스트를 생성합니다.
|
||||
openssl.nonJsseCertficate=인증서 [{0}] 또는 그것의 개인 키 [{1}]이(가) JSSE 키 매니저를 사용하여 처리되지 못하였으므로, OpenSSL에 직접 전달할 것입니다.
|
||||
openssl.nonJsseChain=해당 인증서 체인 [{0}]이(가) 지정되지 않았거나 유효하지 않으며, JSSE는 유효한 인증서 체인을 요구하므로, OpenSSL을 직접 사용하려 시도합니다.
|
||||
openssl.trustManagerMissing=Trust 매니저를 찾을 수 없습니다.
|
||||
|
||||
opensslconf.applyCommand=OpenSSLConf이 명령을 적용합니다 (이름 [{0}], 값 [{1}]).
|
||||
opensslconf.applyFailed=OpenSSLConf를 SSL 컨텍스트에 적용하는 중 실패
|
||||
opensslconf.checkCommand=OpenSSLConf 점검 명령 (이름 [{0}], 값 [{1}])
|
||||
opensslconf.checkFailed=OpenSSLConf 점검 실패
|
||||
opensslconf.failedCommand=OpenSSLConf가 명령(이름: [{0}], 값: [{1}])을 처리하지 못했습니다 (결과: [{2}]). 이는 무시될 것입니다.
|
||||
opensslconf.finishFailed=OpenSSLConf의 완료가 실패했습니다 (결과 값: [{0}]).
|
||||
opensslconf.noCommandName=OpenSSLConf: 명령 이름이 없습니다 - 무시될 것입니다. (명령 값 [{0}])
|
||||
opensslconf.resultCommand=OpenSSLConf 명령(이름: [{0}], 값: [{1}])이 [{2}]을(를) 반환했습니다.
|
||||
|
||||
sessionContext.nullTicketKeys=널 키들
|
||||
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.noSession=Идентификатор SSL сессии недоступен
|
||||
@@ -0,0 +1,35 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
engine.ciphersFailure=获取密码列表失败
|
||||
engine.emptyCipherSuite=空密码套件
|
||||
engine.engineClosed=引擎已经关闭
|
||||
engine.noSession=SSL会话ID不可用
|
||||
engine.nullCipherSuite=无加密套件
|
||||
engine.openSSLError=OpenSSL 错误:[{0}] 信息: [{1}]
|
||||
engine.unsupportedProtocol=不支持协议 [{0}]
|
||||
engine.writeToSSLFailed=写入SSL失败,返回:[{0}]
|
||||
|
||||
openssl.X509FactoryError=获取X509工厂实例时出错
|
||||
openssl.addedClientCaCert=添加了客户端 CA 证书:[{0}]
|
||||
openssl.errApplyConf=无法将OpenSSLConf 应用于SSL 上下文
|
||||
openssl.errMakeConf=无法创建OpenSSLConf上下文
|
||||
openssl.keyManagerMissing=key管理器未找到
|
||||
openssl.trustManagerMissing=没有找到.信任管理者
|
||||
|
||||
opensslconf.checkFailed=检查OpenSSLConf时失败。
|
||||
opensslconf.finishFailed=OpenSSLConf 配置失败结果为 [{0}]
|
||||
|
||||
sessionContext.nullTicketKeys=Null keys
|
||||
128
java/org/apache/tomcat/util/net/openssl/OpenSSLConf.java
Normal file
128
java/org/apache/tomcat/util/net/openssl/OpenSSLConf.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.jni.SSLConf;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class OpenSSLConf implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Log log = LogFactory.getLog(OpenSSLConf.class);
|
||||
private static final StringManager sm = StringManager.getManager(OpenSSLConf.class);
|
||||
|
||||
private final List<OpenSSLConfCmd> commands = new ArrayList<>();
|
||||
|
||||
public void addCmd(OpenSSLConfCmd cmd) {
|
||||
commands.add(cmd);
|
||||
}
|
||||
|
||||
public List<OpenSSLConfCmd> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public boolean check(long cctx) throws Exception {
|
||||
boolean result = true;
|
||||
OpenSSLConfCmd cmd;
|
||||
String name;
|
||||
String value;
|
||||
int rc;
|
||||
for (int i = 0; i < commands.size(); i++) {
|
||||
cmd = commands.get(i);
|
||||
name = cmd.getName();
|
||||
value = cmd.getValue();
|
||||
if (name == null) {
|
||||
log.error(sm.getString("opensslconf.noCommandName", value));
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("opensslconf.checkCommand", name, value));
|
||||
}
|
||||
try {
|
||||
rc = SSLConf.check(cctx, name, value);
|
||||
} catch (Exception e) {
|
||||
log.error(sm.getString("opensslconf.checkFailed"));
|
||||
return false;
|
||||
}
|
||||
if (rc <= 0) {
|
||||
log.error(sm.getString("opensslconf.failedCommand", name, value,
|
||||
Integer.toString(rc)));
|
||||
result = false;
|
||||
} else if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("opensslconf.resultCommand", name, value,
|
||||
Integer.toString(rc)));
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
log.error(sm.getString("opensslconf.checkFailed"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean apply(long cctx, long ctx) throws Exception {
|
||||
boolean result = true;
|
||||
SSLConf.assign(cctx, ctx);
|
||||
OpenSSLConfCmd cmd;
|
||||
String name;
|
||||
String value;
|
||||
int rc;
|
||||
for (int i = 0; i < commands.size(); i++) {
|
||||
cmd = commands.get(i);
|
||||
name = cmd.getName();
|
||||
value = cmd.getValue();
|
||||
if (name == null) {
|
||||
log.error(sm.getString("opensslconf.noCommandName", value));
|
||||
result = false;
|
||||
continue;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("opensslconf.applyCommand", name, value));
|
||||
}
|
||||
try {
|
||||
rc = SSLConf.apply(cctx, name, value);
|
||||
} catch (Exception e) {
|
||||
log.error(sm.getString("opensslconf.applyFailed"));
|
||||
return false;
|
||||
}
|
||||
if (rc <= 0) {
|
||||
log.error(sm.getString("opensslconf.failedCommand", name, value,
|
||||
Integer.toString(rc)));
|
||||
result = false;
|
||||
} else if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("opensslconf.resultCommand", name, value,
|
||||
Integer.toString(rc)));
|
||||
}
|
||||
}
|
||||
rc = SSLConf.finish(cctx);
|
||||
if (rc <= 0) {
|
||||
log.error(sm.getString("opensslconf.finishFailed", Integer.toString(rc)));
|
||||
result = false;
|
||||
}
|
||||
if (!result) {
|
||||
log.error(sm.getString("opensslconf.applyFailed"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
43
java/org/apache/tomcat/util/net/openssl/OpenSSLConfCmd.java
Normal file
43
java/org/apache/tomcat/util/net/openssl/OpenSSLConfCmd.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class OpenSSLConfCmd implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String name = null;
|
||||
private String value = null;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
563
java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
Normal file
563
java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
Normal file
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.jni.CertificateVerifier;
|
||||
import org.apache.tomcat.jni.Pool;
|
||||
import org.apache.tomcat.jni.SSL;
|
||||
import org.apache.tomcat.jni.SSLConf;
|
||||
import org.apache.tomcat.jni.SSLContext;
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint;
|
||||
import org.apache.tomcat.util.net.Constants;
|
||||
import org.apache.tomcat.util.net.SSLHostConfig;
|
||||
import org.apache.tomcat.util.net.SSLHostConfig.CertificateVerification;
|
||||
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
|
||||
import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
|
||||
|
||||
private static final Base64 BASE64_ENCODER = new Base64(64, new byte[] {'\n'});
|
||||
|
||||
private static final Log log = LogFactory.getLog(OpenSSLContext.class);
|
||||
|
||||
// Note: this uses the main "net" package strings as many are common with APR
|
||||
private static final StringManager netSm = StringManager.getManager(AbstractEndpoint.class);
|
||||
private static final StringManager sm = StringManager.getManager(OpenSSLContext.class);
|
||||
|
||||
private static final String defaultProtocol = "TLS";
|
||||
|
||||
private final SSLHostConfig sslHostConfig;
|
||||
private final SSLHostConfigCertificate certificate;
|
||||
private OpenSSLSessionContext sessionContext;
|
||||
private X509TrustManager x509TrustManager;
|
||||
|
||||
private final List<String> negotiableProtocols;
|
||||
|
||||
private String enabledProtocol;
|
||||
|
||||
public String getEnabledProtocol() {
|
||||
return enabledProtocol;
|
||||
}
|
||||
|
||||
public void setEnabledProtocol(String protocol) {
|
||||
enabledProtocol = (protocol == null) ? defaultProtocol : protocol;
|
||||
}
|
||||
|
||||
private final long aprPool;
|
||||
private final AtomicInteger aprPoolDestroyed = new AtomicInteger(0);
|
||||
|
||||
// OpenSSLConfCmd context
|
||||
protected final long cctx;
|
||||
// SSL context
|
||||
protected final long ctx;
|
||||
|
||||
static final CertificateFactory X509_CERT_FACTORY;
|
||||
|
||||
private static final String BEGIN_KEY = "-----BEGIN PRIVATE KEY-----\n";
|
||||
|
||||
private static final Object END_KEY = "\n-----END PRIVATE KEY-----";
|
||||
private boolean initialized = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
X509_CERT_FACTORY = CertificateFactory.getInstance("X.509");
|
||||
} catch (CertificateException e) {
|
||||
throw new IllegalStateException(sm.getString("openssl.X509FactoryError"), e);
|
||||
}
|
||||
}
|
||||
|
||||
public OpenSSLContext(SSLHostConfigCertificate certificate, List<String> negotiableProtocols)
|
||||
throws SSLException {
|
||||
this.sslHostConfig = certificate.getSSLHostConfig();
|
||||
this.certificate = certificate;
|
||||
aprPool = Pool.create(0);
|
||||
boolean success = false;
|
||||
try {
|
||||
// Create OpenSSLConfCmd context if used
|
||||
OpenSSLConf openSslConf = sslHostConfig.getOpenSslConf();
|
||||
if (openSslConf != null) {
|
||||
try {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(sm.getString("openssl.makeConf"));
|
||||
cctx = SSLConf.make(aprPool,
|
||||
SSL.SSL_CONF_FLAG_FILE |
|
||||
SSL.SSL_CONF_FLAG_SERVER |
|
||||
SSL.SSL_CONF_FLAG_CERTIFICATE |
|
||||
SSL.SSL_CONF_FLAG_SHOW_ERRORS);
|
||||
} catch (Exception e) {
|
||||
throw new SSLException(sm.getString("openssl.errMakeConf"), e);
|
||||
}
|
||||
} else {
|
||||
cctx = 0;
|
||||
}
|
||||
sslHostConfig.setOpenSslConfContext(Long.valueOf(cctx));
|
||||
|
||||
// SSL protocol
|
||||
int value = SSL.SSL_PROTOCOL_NONE;
|
||||
for (String protocol : sslHostConfig.getEnabledProtocols()) {
|
||||
if (Constants.SSL_PROTO_SSLv2Hello.equalsIgnoreCase(protocol)) {
|
||||
// NO-OP. OpenSSL always supports SSLv2Hello
|
||||
} else if (Constants.SSL_PROTO_SSLv2.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_SSLV2;
|
||||
} else if (Constants.SSL_PROTO_SSLv3.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_SSLV3;
|
||||
} else if (Constants.SSL_PROTO_TLSv1.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_TLSV1;
|
||||
} else if (Constants.SSL_PROTO_TLSv1_1.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_TLSV1_1;
|
||||
} else if (Constants.SSL_PROTO_TLSv1_2.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_TLSV1_2;
|
||||
} else if (Constants.SSL_PROTO_TLSv1_3.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_TLSV1_3;
|
||||
} else if (Constants.SSL_PROTO_ALL.equalsIgnoreCase(protocol)) {
|
||||
value |= SSL.SSL_PROTOCOL_ALL;
|
||||
} else {
|
||||
// Should not happen since filtering to build
|
||||
// enabled protocols removes invalid values.
|
||||
throw new Exception(netSm.getString(
|
||||
"endpoint.apr.invalidSslProtocol", protocol));
|
||||
}
|
||||
}
|
||||
|
||||
// Create SSL Context
|
||||
try {
|
||||
ctx = SSLContext.make(aprPool, value, SSL.SSL_MODE_SERVER);
|
||||
} catch (Exception e) {
|
||||
// If the sslEngine is disabled on the AprLifecycleListener
|
||||
// there will be an Exception here but there is no way to check
|
||||
// the AprLifecycleListener settings from here
|
||||
throw new Exception(
|
||||
netSm.getString("endpoint.apr.failSslContextMake"), e);
|
||||
}
|
||||
|
||||
this.negotiableProtocols = negotiableProtocols;
|
||||
|
||||
success = true;
|
||||
} catch(Exception e) {
|
||||
throw new SSLException(sm.getString("openssl.errorSSLCtxInit"), e);
|
||||
} finally {
|
||||
if (!success) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void destroy() {
|
||||
// Guard against multiple destroyPools() calls triggered by construction exception and finalize() later
|
||||
if (aprPoolDestroyed.compareAndSet(0, 1)) {
|
||||
if (ctx != 0) {
|
||||
SSLContext.free(ctx);
|
||||
}
|
||||
if (cctx != 0) {
|
||||
SSLConf.free(cctx);
|
||||
}
|
||||
if (aprPool != 0) {
|
||||
Pool.destroy(aprPool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the SSL_CTX.
|
||||
*
|
||||
* @param kms Must contain a KeyManager of the type
|
||||
* {@code OpenSSLKeyManager}
|
||||
* @param tms Must contain a TrustManager of the type
|
||||
* {@code X509TrustManager}
|
||||
* @param sr Is not used for this implementation.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) {
|
||||
if (initialized) {
|
||||
log.warn(sm.getString("openssl.doubleInit"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (sslHostConfig.getInsecureRenegotiation()) {
|
||||
SSLContext.setOptions(ctx, SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
|
||||
} else {
|
||||
SSLContext.clearOptions(ctx, SSL.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
|
||||
}
|
||||
|
||||
// Use server's preference order for ciphers (rather than
|
||||
// client's)
|
||||
String honorCipherOrderStr = sslHostConfig.getHonorCipherOrder();
|
||||
if (honorCipherOrderStr != null) {
|
||||
if (Boolean.parseBoolean(honorCipherOrderStr)) {
|
||||
SSLContext.setOptions(ctx, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
} else {
|
||||
SSLContext.clearOptions(ctx, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable compression if requested
|
||||
if (sslHostConfig.getDisableCompression()) {
|
||||
SSLContext.setOptions(ctx, SSL.SSL_OP_NO_COMPRESSION);
|
||||
} else {
|
||||
SSLContext.clearOptions(ctx, SSL.SSL_OP_NO_COMPRESSION);
|
||||
}
|
||||
|
||||
// Disable TLS Session Tickets (RFC4507) to protect perfect forward secrecy
|
||||
if (sslHostConfig.getDisableSessionTickets()) {
|
||||
SSLContext.setOptions(ctx, SSL.SSL_OP_NO_TICKET);
|
||||
} else {
|
||||
SSLContext.clearOptions(ctx, SSL.SSL_OP_NO_TICKET);
|
||||
}
|
||||
|
||||
// List the ciphers that the client is permitted to negotiate
|
||||
SSLContext.setCipherSuite(ctx, sslHostConfig.getCiphers());
|
||||
|
||||
if (certificate.getCertificateFile() == null) {
|
||||
certificate.setCertificateKeyManager(OpenSSLUtil.chooseKeyManager(kms));
|
||||
}
|
||||
|
||||
addCertificate(certificate);
|
||||
|
||||
// Client certificate verification
|
||||
int value = 0;
|
||||
switch (sslHostConfig.getCertificateVerification()) {
|
||||
case NONE:
|
||||
value = SSL.SSL_CVERIFY_NONE;
|
||||
break;
|
||||
case OPTIONAL:
|
||||
value = SSL.SSL_CVERIFY_OPTIONAL;
|
||||
break;
|
||||
case OPTIONAL_NO_CA:
|
||||
value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA;
|
||||
break;
|
||||
case REQUIRED:
|
||||
value = SSL.SSL_CVERIFY_REQUIRE;
|
||||
break;
|
||||
}
|
||||
SSLContext.setVerify(ctx, value, sslHostConfig.getCertificateVerificationDepth());
|
||||
|
||||
if (tms != null) {
|
||||
// Client certificate verification based on custom trust managers
|
||||
x509TrustManager = chooseTrustManager(tms);
|
||||
SSLContext.setCertVerifyCallback(ctx, new CertificateVerifier() {
|
||||
@Override
|
||||
public boolean verify(long ssl, byte[][] chain, String auth) {
|
||||
X509Certificate[] peerCerts = certificates(chain);
|
||||
try {
|
||||
x509TrustManager.checkClientTrusted(peerCerts, auth);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.debug(sm.getString("openssl.certificateVerificationFailed"), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// Pass along the DER encoded certificates of the accepted client
|
||||
// certificate issuers, so that their subjects can be presented
|
||||
// by the server during the handshake to allow the client choosing
|
||||
// an acceptable certificate
|
||||
for (X509Certificate caCert : x509TrustManager.getAcceptedIssuers()) {
|
||||
SSLContext.addClientCACertificateRaw(ctx, caCert.getEncoded());
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(sm.getString("openssl.addedClientCaCert", caCert.toString()));
|
||||
}
|
||||
} else {
|
||||
// Client certificate verification based on trusted CA files and dirs
|
||||
SSLContext.setCACertificate(ctx,
|
||||
SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()),
|
||||
SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath()));
|
||||
}
|
||||
|
||||
if (negotiableProtocols != null && negotiableProtocols.size() > 0) {
|
||||
List<String> protocols = new ArrayList<>();
|
||||
protocols.addAll(negotiableProtocols);
|
||||
protocols.add("http/1.1");
|
||||
String[] protocolsArray = protocols.toArray(new String[0]);
|
||||
SSLContext.setAlpnProtos(ctx, protocolsArray, SSL.SSL_SELECTOR_FAILURE_NO_ADVERTISE);
|
||||
SSLContext.setNpnProtos(ctx, protocolsArray, SSL.SSL_SELECTOR_FAILURE_NO_ADVERTISE);
|
||||
}
|
||||
|
||||
// Apply OpenSSLConfCmd if used
|
||||
OpenSSLConf openSslConf = sslHostConfig.getOpenSslConf();
|
||||
if (openSslConf != null && cctx != 0) {
|
||||
// Check OpenSSLConfCmd if used
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(sm.getString("openssl.checkConf"));
|
||||
try {
|
||||
if (!openSslConf.check(cctx)) {
|
||||
log.error(sm.getString("openssl.errCheckConf"));
|
||||
throw new Exception(sm.getString("openssl.errCheckConf"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception(sm.getString("openssl.errCheckConf"), e);
|
||||
}
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(sm.getString("openssl.applyConf"));
|
||||
try {
|
||||
if (!openSslConf.apply(cctx, ctx)) {
|
||||
log.error(sm.getString("openssl.errApplyConf"));
|
||||
throw new SSLException(sm.getString("openssl.errApplyConf"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SSLException(sm.getString("openssl.errApplyConf"), e);
|
||||
}
|
||||
// Reconfigure the enabled protocols
|
||||
int opts = SSLContext.getOptions(ctx);
|
||||
List<String> enabled = new ArrayList<>();
|
||||
// Seems like there is no way to explicitly disable SSLv2Hello
|
||||
// in OpenSSL so it is always enabled
|
||||
enabled.add(Constants.SSL_PROTO_SSLv2Hello);
|
||||
if ((opts & SSL.SSL_OP_NO_TLSv1) == 0) {
|
||||
enabled.add(Constants.SSL_PROTO_TLSv1);
|
||||
}
|
||||
if ((opts & SSL.SSL_OP_NO_TLSv1_1) == 0) {
|
||||
enabled.add(Constants.SSL_PROTO_TLSv1_1);
|
||||
}
|
||||
if ((opts & SSL.SSL_OP_NO_TLSv1_2) == 0) {
|
||||
enabled.add(Constants.SSL_PROTO_TLSv1_2);
|
||||
}
|
||||
if ((opts & SSL.SSL_OP_NO_SSLv2) == 0) {
|
||||
enabled.add(Constants.SSL_PROTO_SSLv2);
|
||||
}
|
||||
if ((opts & SSL.SSL_OP_NO_SSLv3) == 0) {
|
||||
enabled.add(Constants.SSL_PROTO_SSLv3);
|
||||
}
|
||||
sslHostConfig.setEnabledProtocols(
|
||||
enabled.toArray(new String[enabled.size()]));
|
||||
// Reconfigure the enabled ciphers
|
||||
sslHostConfig.setEnabledCiphers(SSLContext.getCiphers(ctx));
|
||||
}
|
||||
|
||||
sessionContext = new OpenSSLSessionContext(this);
|
||||
// If client authentication is being used, OpenSSL requires that
|
||||
// this is set so always set it in case an app is configured to
|
||||
// require it
|
||||
sessionContext.setSessionIdContext(SSLContext.DEFAULT_SESSION_ID_CONTEXT);
|
||||
sslHostConfig.setOpenSslContext(Long.valueOf(ctx));
|
||||
initialized = true;
|
||||
} catch (Exception e) {
|
||||
log.warn(sm.getString("openssl.errorSSLCtxInit"), e);
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addCertificate(SSLHostConfigCertificate certificate) throws Exception {
|
||||
// Load Server key and certificate
|
||||
if (certificate.getCertificateFile() != null) {
|
||||
// Set certificate
|
||||
SSLContext.setCertificate(ctx,
|
||||
SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()),
|
||||
SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyFile()),
|
||||
certificate.getCertificateKeyPassword(), getCertificateIndex(certificate));
|
||||
// Set certificate chain file
|
||||
SSLContext.setCertificateChainFile(ctx,
|
||||
SSLHostConfig.adjustRelativePath(certificate.getCertificateChainFile()), false);
|
||||
// Set revocation
|
||||
SSLContext.setCARevocation(ctx,
|
||||
SSLHostConfig.adjustRelativePath(
|
||||
sslHostConfig.getCertificateRevocationListFile()),
|
||||
SSLHostConfig.adjustRelativePath(
|
||||
sslHostConfig.getCertificateRevocationListPath()));
|
||||
} else {
|
||||
String alias = certificate.getCertificateKeyAlias();
|
||||
X509KeyManager x509KeyManager = certificate.getCertificateKeyManager();
|
||||
if (alias == null) {
|
||||
alias = "tomcat";
|
||||
}
|
||||
X509Certificate[] chain = x509KeyManager.getCertificateChain(alias);
|
||||
if (chain == null) {
|
||||
alias = findAlias(x509KeyManager, certificate);
|
||||
chain = x509KeyManager.getCertificateChain(alias);
|
||||
}
|
||||
PrivateKey key = x509KeyManager.getPrivateKey(alias);
|
||||
StringBuilder sb = new StringBuilder(BEGIN_KEY);
|
||||
String encoded = BASE64_ENCODER.encodeToString(key.getEncoded());
|
||||
if (encoded.endsWith("\n")) {
|
||||
encoded = encoded.substring(0, encoded.length() - 1);
|
||||
}
|
||||
sb.append(encoded);
|
||||
sb.append(END_KEY);
|
||||
SSLContext.setCertificateRaw(ctx, chain[0].getEncoded(),
|
||||
sb.toString().getBytes(StandardCharsets.US_ASCII),
|
||||
getCertificateIndex(certificate));
|
||||
for (int i = 1; i < chain.length; i++) {
|
||||
SSLContext.addChainCertificateRaw(ctx, chain[i].getEncoded());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getCertificateIndex(SSLHostConfigCertificate certificate) {
|
||||
int result;
|
||||
// If the type is undefined there will only be one certificate (enforced
|
||||
// in SSLHostConfig) so use the RSA slot.
|
||||
if (certificate.getType() == Type.RSA || certificate.getType() == Type.UNDEFINED) {
|
||||
result = SSL.SSL_AIDX_RSA;
|
||||
} else if (certificate.getType() == Type.EC) {
|
||||
result = SSL.SSL_AIDX_ECC;
|
||||
} else if (certificate.getType() == Type.DSA) {
|
||||
result = SSL.SSL_AIDX_DSA;
|
||||
} else {
|
||||
result = SSL.SSL_AIDX_MAX;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a valid alias when none was specified in the config.
|
||||
*/
|
||||
private static String findAlias(X509KeyManager keyManager,
|
||||
SSLHostConfigCertificate certificate) {
|
||||
|
||||
Type type = certificate.getType();
|
||||
String result = null;
|
||||
|
||||
List<Type> candidateTypes = new ArrayList<>();
|
||||
if (Type.UNDEFINED.equals(type)) {
|
||||
// Try all types to find an suitable alias
|
||||
candidateTypes.addAll(Arrays.asList(Type.values()));
|
||||
candidateTypes.remove(Type.UNDEFINED);
|
||||
} else {
|
||||
// Look for the specific type to find a suitable alias
|
||||
candidateTypes.add(type);
|
||||
}
|
||||
|
||||
Iterator<Type> iter = candidateTypes.iterator();
|
||||
while (result == null && iter.hasNext()) {
|
||||
result = keyManager.chooseServerAlias(iter.next().toString(), null, null);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static X509TrustManager chooseTrustManager(TrustManager[] managers) {
|
||||
for (TrustManager m : managers) {
|
||||
if (m instanceof X509TrustManager) {
|
||||
return (X509TrustManager) m;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException(sm.getString("openssl.trustManagerMissing"));
|
||||
}
|
||||
|
||||
private static X509Certificate[] certificates(byte[][] chain) {
|
||||
X509Certificate[] peerCerts = new X509Certificate[chain.length];
|
||||
for (int i = 0; i < peerCerts.length; i++) {
|
||||
peerCerts[i] = new OpenSSLX509Certificate(chain[i]);
|
||||
}
|
||||
return peerCerts;
|
||||
}
|
||||
|
||||
|
||||
long getSSLContextID() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SSLSessionContext getServerSessionContext() {
|
||||
return sessionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLEngine createSSLEngine() {
|
||||
return new OpenSSLEngine(ctx, defaultProtocol, false, sessionContext,
|
||||
(negotiableProtocols != null && negotiableProtocols.size() > 0), initialized,
|
||||
sslHostConfig.getCertificateVerificationDepth(),
|
||||
sslHostConfig.getCertificateVerification() == CertificateVerification.OPTIONAL_NO_CA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLServerSocketFactory getServerSocketFactory() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLParameters getSupportedSSLParameters() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain(String alias) {
|
||||
X509Certificate[] chain = null;
|
||||
X509KeyManager x509KeyManager = certificate.getCertificateKeyManager();
|
||||
if (x509KeyManager != null) {
|
||||
if (alias == null) {
|
||||
alias = "tomcat";
|
||||
}
|
||||
chain = x509KeyManager.getCertificateChain(alias);
|
||||
if (chain == null) {
|
||||
alias = findAlias(x509KeyManager, certificate);
|
||||
chain = x509KeyManager.getCertificateChain(alias);
|
||||
}
|
||||
}
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
X509Certificate[] acceptedCerts = null;
|
||||
if (x509TrustManager != null) {
|
||||
acceptedCerts = x509TrustManager.getAcceptedIssuers();
|
||||
}
|
||||
return acceptedCerts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
/*
|
||||
* When an SSLHostConfig is replaced at runtime, it is not possible to
|
||||
* call destroy() on the associated OpenSSLContext since it is likely
|
||||
* that there will be in-progress connections using the OpenSSLContext.
|
||||
* A reference chain has been deliberately established (see
|
||||
* OpenSSLSessionContext) to ensure that the OpenSSLContext remains
|
||||
* ineligible for GC while those connections are alive. Once those
|
||||
* connections complete, the OpenSSLContext will become eligible for GC
|
||||
* and this method will ensure that the associated native resources are
|
||||
* cleaned up.
|
||||
*/
|
||||
try {
|
||||
destroy();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
1433
java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
Normal file
1433
java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
|
||||
import org.apache.tomcat.util.net.SSLImplementation;
|
||||
import org.apache.tomcat.util.net.SSLSupport;
|
||||
import org.apache.tomcat.util.net.SSLUtil;
|
||||
import org.apache.tomcat.util.net.jsse.JSSESupport;
|
||||
|
||||
public class OpenSSLImplementation extends SSLImplementation {
|
||||
|
||||
@Override
|
||||
public SSLSupport getSSLSupport(SSLSession session) {
|
||||
return new JSSESupport(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLUtil getSSLUtil(SSLHostConfigCertificate certificate) {
|
||||
return new OpenSSLUtil(certificate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlpnSupported() {
|
||||
// OpenSSL supported ALPN
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
|
||||
import org.apache.tomcat.jni.SSL;
|
||||
import org.apache.tomcat.jni.SSLContext;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* OpenSSL specific {@link SSLSessionContext} implementation.
|
||||
*/
|
||||
public class OpenSSLSessionContext implements SSLSessionContext {
|
||||
private static final StringManager sm = StringManager.getManager(OpenSSLSessionContext.class);
|
||||
private static final Enumeration<byte[]> EMPTY = new EmptyEnumeration();
|
||||
|
||||
private final OpenSSLSessionStats stats;
|
||||
// This is deliberately unused. The reference is retained so that a
|
||||
// reference chain is established and maintained to the OpenSSLContext while
|
||||
// there is a connection that is using the OpenSSLContext. Therefore, the
|
||||
// OpenSSLContext can not be eligible for GC while it is in use.
|
||||
@SuppressWarnings("unused")
|
||||
private final OpenSSLContext context;
|
||||
private final long contextID;
|
||||
|
||||
OpenSSLSessionContext(OpenSSLContext context) {
|
||||
this.context = context;
|
||||
this.contextID = context.getSSLContextID();
|
||||
stats = new OpenSSLSessionStats(contextID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLSession getSession(byte[] bytes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<byte[]> getIds() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SSL session ticket keys of this context.
|
||||
*
|
||||
* @param keys The session ticket keys
|
||||
*/
|
||||
public void setTicketKeys(byte[] keys) {
|
||||
if (keys == null) {
|
||||
throw new IllegalArgumentException(sm.getString("sessionContext.nullTicketKeys"));
|
||||
}
|
||||
SSLContext.setSessionTicketKeys(contextID, keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable caching of SSL sessions.
|
||||
*
|
||||
* @param enabled {@code true} to enable caching, {@code false} to disable
|
||||
*/
|
||||
public void setSessionCacheEnabled(boolean enabled) {
|
||||
long mode = enabled ? SSL.SSL_SESS_CACHE_SERVER : SSL.SSL_SESS_CACHE_OFF;
|
||||
SSLContext.setSessionCacheMode(contextID, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if caching of SSL sessions is enabled, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isSessionCacheEnabled() {
|
||||
return SSLContext.getSessionCacheMode(contextID) == SSL.SSL_SESS_CACHE_SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The statistics for this context.
|
||||
*/
|
||||
public OpenSSLSessionStats stats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionTimeout(int seconds) {
|
||||
if (seconds < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
SSLContext.setSessionCacheTimeout(contextID, seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSessionTimeout() {
|
||||
return (int) SSLContext.getSessionCacheTimeout(contextID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionCacheSize(int size) {
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
SSLContext.setSessionCacheSize(contextID, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSessionCacheSize() {
|
||||
return (int) SSLContext.getSessionCacheSize(contextID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context within which session be reused (server side only)
|
||||
* See <a href="http://www.openssl.org/docs/ssl/SSL_CTX_set_session_id_context.html">
|
||||
* man SSL_CTX_set_session_id_context</a>
|
||||
*
|
||||
* @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name
|
||||
* of the application and/or the hostname and/or service name
|
||||
* @return {@code true} if success, {@code false} otherwise.
|
||||
*/
|
||||
public boolean setSessionIdContext(byte[] sidCtx) {
|
||||
return SSLContext.setSessionIdContext(contextID, sidCtx);
|
||||
}
|
||||
|
||||
private static final class EmptyEnumeration implements Enumeration<byte[]> {
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] nextElement() {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
}
|
||||
126
java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java
Normal file
126
java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import org.apache.tomcat.jni.SSLContext;
|
||||
|
||||
/**
|
||||
* Stats exposed by an OpenSSL session context.
|
||||
*
|
||||
* @see <a href="https://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html"><code>SSL_CTX_sess_number</code></a>
|
||||
*/
|
||||
public final class OpenSSLSessionStats {
|
||||
|
||||
private final long context;
|
||||
|
||||
OpenSSLSessionStats(long context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current number of sessions in the internal session cache.
|
||||
*/
|
||||
public long number() {
|
||||
return SSLContext.sessionNumber(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of started SSL/TLS handshakes in client mode.
|
||||
*/
|
||||
public long connect() {
|
||||
return SSLContext.sessionConnect(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of successfully established SSL/TLS sessions in client mode.
|
||||
*/
|
||||
public long connectGood() {
|
||||
return SSLContext.sessionConnectGood(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of start renegotiations in client mode.
|
||||
*/
|
||||
public long connectRenegotiate() {
|
||||
return SSLContext.sessionConnectRenegotiate(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of started SSL/TLS handshakes in server mode.
|
||||
*/
|
||||
public long accept() {
|
||||
return SSLContext.sessionAccept(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of successfully established SSL/TLS sessions in server mode.
|
||||
*/
|
||||
public long acceptGood() {
|
||||
return SSLContext.sessionAcceptGood(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of start renegotiations in server mode.
|
||||
*/
|
||||
public long acceptRenegotiate() {
|
||||
return SSLContext.sessionAcceptRenegotiate(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of successfully reused sessions. In client mode, a
|
||||
* session set with {@code SSL_set_session} successfully reused is
|
||||
* counted as a hit. In server mode, a session successfully
|
||||
* retrieved from internal or external cache is counted as a hit.
|
||||
*/
|
||||
public long hits() {
|
||||
return SSLContext.sessionHits(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of successfully retrieved sessions from the external
|
||||
* session cache in server mode.
|
||||
*/
|
||||
public long cbHits() {
|
||||
return SSLContext.sessionCbHits(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of sessions proposed by clients that were not found in
|
||||
* the internal session cache in server mode.
|
||||
*/
|
||||
public long misses() {
|
||||
return SSLContext.sessionMisses(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of sessions proposed by clients and either found in
|
||||
* the internal or external session cache in server mode, but that
|
||||
* were invalid due to timeout. These sessions are not included in
|
||||
* the {@link #hits()} count.
|
||||
*/
|
||||
public long timeouts() {
|
||||
return SSLContext.sessionTimeouts(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of sessions that were removed because the maximum
|
||||
* session cache size was exceeded.
|
||||
*/
|
||||
public long cacheFull() {
|
||||
return SSLContext.sessionCacheFull(context);
|
||||
}
|
||||
}
|
||||
128
java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
Normal file
128
java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.SSLContext;
|
||||
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
|
||||
import org.apache.tomcat.util.net.SSLUtilBase;
|
||||
import org.apache.tomcat.util.net.jsse.JSSEKeyManager;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class OpenSSLUtil extends SSLUtilBase {
|
||||
|
||||
private static final Log log = LogFactory.getLog(OpenSSLUtil.class);
|
||||
private static final StringManager sm = StringManager.getManager(OpenSSLContext.class);
|
||||
|
||||
|
||||
public OpenSSLUtil(SSLHostConfigCertificate certificate) {
|
||||
super(certificate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() {
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Set<String> getImplementedProtocols() {
|
||||
return OpenSSLEngine.IMPLEMENTED_PROTOCOLS_SET;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Set<String> getImplementedCiphers() {
|
||||
return OpenSSLEngine.AVAILABLE_CIPHER_SUITES;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean isTls13RenegAuthAvailable() {
|
||||
// OpenSSL does support authentication after the initial handshake
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SSLContext createSSLContextInternal(List<String> negotiableProtocols) throws Exception {
|
||||
return new OpenSSLContext(certificate, negotiableProtocols);
|
||||
}
|
||||
|
||||
|
||||
public static X509KeyManager chooseKeyManager(KeyManager[] managers) throws Exception {
|
||||
if (managers == null) {
|
||||
return null;
|
||||
}
|
||||
for (KeyManager manager : managers) {
|
||||
if (manager instanceof JSSEKeyManager) {
|
||||
return (JSSEKeyManager) manager;
|
||||
}
|
||||
}
|
||||
for (KeyManager manager : managers) {
|
||||
if (manager instanceof X509KeyManager) {
|
||||
return (X509KeyManager) manager;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException(sm.getString("openssl.keyManagerMissing"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public KeyManager[] getKeyManagers() throws Exception {
|
||||
try {
|
||||
return super.getKeyManagers();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// No (or invalid?) certificate chain was provided for the cert
|
||||
String msg = sm.getString("openssl.nonJsseChain", certificate.getCertificateChainFile());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info(msg, e);
|
||||
} else {
|
||||
log.info(msg);
|
||||
}
|
||||
return null;
|
||||
} catch (KeyStoreException | IOException e) {
|
||||
// Depending on what is presented, JSSE may also throw
|
||||
// KeyStoreException or IOException if it doesn't understand the
|
||||
// provided file.
|
||||
if (certificate.getCertificateFile() != null) {
|
||||
String msg = sm.getString("openssl.nonJsseCertficate",
|
||||
certificate.getCertificateFile(), certificate.getCertificateKeyFile());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info(msg, e);
|
||||
} else {
|
||||
log.info(msg);
|
||||
}
|
||||
// Assume JSSE processing of the certificate failed, try again with OpenSSL
|
||||
// without a key manager
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Principal;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
final class OpenSSLX509Certificate extends X509Certificate {
|
||||
|
||||
private final byte[] bytes;
|
||||
private X509Certificate wrapped;
|
||||
|
||||
public OpenSSLX509Certificate(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException {
|
||||
unwrap().checkValidity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException {
|
||||
unwrap().checkValidity(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return unwrap().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSerialNumber() {
|
||||
return unwrap().getSerialNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getIssuerDN() {
|
||||
return unwrap().getIssuerDN();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getSubjectDN() {
|
||||
return unwrap().getSubjectDN();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getNotBefore() {
|
||||
return unwrap().getNotBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getNotAfter() {
|
||||
return unwrap().getNotAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getTBSCertificate() throws CertificateEncodingException {
|
||||
return unwrap().getTBSCertificate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getSignature() {
|
||||
return unwrap().getSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSigAlgName() {
|
||||
return unwrap().getSigAlgName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSigAlgOID() {
|
||||
return unwrap().getSigAlgOID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getSigAlgParams() {
|
||||
return unwrap().getSigAlgParams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getIssuerUniqueID() {
|
||||
return unwrap().getIssuerUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getSubjectUniqueID() {
|
||||
return unwrap().getSubjectUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getKeyUsage() {
|
||||
return unwrap().getKeyUsage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBasicConstraints() {
|
||||
return unwrap().getBasicConstraints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return bytes.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(PublicKey key)
|
||||
throws CertificateException, NoSuchAlgorithmException,
|
||||
InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
unwrap().verify(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(PublicKey key, String sigProvider)
|
||||
throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
unwrap().verify(key, sigProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return unwrap().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicKey getPublicKey() {
|
||||
return unwrap().getPublicKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasUnsupportedCriticalExtension() {
|
||||
return unwrap().hasUnsupportedCriticalExtension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCriticalExtensionOIDs() {
|
||||
return unwrap().getCriticalExtensionOIDs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getNonCriticalExtensionOIDs() {
|
||||
return unwrap().getNonCriticalExtensionOIDs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getExtensionValue(String oid) {
|
||||
return unwrap().getExtensionValue(oid);
|
||||
}
|
||||
|
||||
private X509Certificate unwrap() {
|
||||
X509Certificate wrapped = this.wrapped;
|
||||
if (wrapped == null) {
|
||||
try {
|
||||
wrapped = this.wrapped = (X509Certificate) OpenSSLContext.X509_CERT_FACTORY.generateCertificate(
|
||||
new ByteArrayInputStream(bytes));
|
||||
} catch (CertificateException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
public enum Authentication {
|
||||
RSA /* RSA auth */,
|
||||
DSS /* DSS auth */,
|
||||
aNULL /* no auth (i.e. use ADH or AECDH) */,
|
||||
DH /* Fixed DH auth (kDHd or kDHr) */,
|
||||
ECDH /* Fixed ECDH auth (kECDHe or kECDHr) */,
|
||||
KRB5 /* KRB5 auth */,
|
||||
ECDSA /* ECDSA auth*/,
|
||||
PSK /* PSK auth */,
|
||||
GOST94 /* GOST R 34.10-94 signature auth */,
|
||||
GOST01 /* GOST R 34.10-2001 */,
|
||||
FZA /* Fortezza */,
|
||||
SRP,
|
||||
ANY /* TLS 1.3 */
|
||||
}
|
||||
5119
java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java
Normal file
5119
java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
enum Encryption {
|
||||
AES128,
|
||||
AES128CCM,
|
||||
AES128CCM8,
|
||||
AES128GCM,
|
||||
AES256,
|
||||
AES256CCM,
|
||||
AES256CCM8,
|
||||
AES256GCM,
|
||||
ARIA128GCM,
|
||||
ARIA256GCM,
|
||||
CAMELLIA256,
|
||||
CAMELLIA128,
|
||||
CHACHA20POLY1305,
|
||||
TRIPLE_DES,
|
||||
DES,
|
||||
IDEA,
|
||||
eGOST2814789CNT,
|
||||
SEED,
|
||||
FZA,
|
||||
RC4,
|
||||
RC2,
|
||||
eNULL
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
enum EncryptionLevel {
|
||||
STRONG_NONE,
|
||||
EXP40,
|
||||
EXP56,
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
FIPS
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
enum KeyExchange {
|
||||
EECDH /* SSL_kEECDH - ephemeral ECDH */,
|
||||
RSA /* SSL_kRSA - RSA key exchange */,
|
||||
DHr /* SSL_kDHr - DH cert, RSA CA cert */ /* no such ciphersuites supported! */,
|
||||
DHd /* SSL_kDHd - DH cert, DSA CA cert */ /* no such ciphersuite supported! */,
|
||||
EDH /* SSL_kDHE - tmp DH key no DH cert */,
|
||||
PSK /* SSK_kPSK - PSK */,
|
||||
FZA /* SSL_kFZA - Fortezza */ /* no such ciphersuite supported! */,
|
||||
KRB5 /* SSL_kKRB5 - Kerberos 5 key exchange */,
|
||||
ECDHr /* SSL_kECDHr - ECDH cert, RSA CA cert */,
|
||||
ECDHe /* SSL_kECDHe - ECDH cert, ECDSA CA cert */,
|
||||
GOST /* SSL_kGOST - GOST key exchange */,
|
||||
SRP /* SSL_kSRP - SRP */,
|
||||
RSAPSK,
|
||||
ECDHEPSK,
|
||||
DHEPSK,
|
||||
ANY /* TLS 1.3 */
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
converter.mapping=Cipher suite mapping: [{0}] => [{1}]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
converter.mapping=Association de la suite de chiffres: [{0}] => [{1}]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
converter.mapping=暗号スイートの対応付け: [{0}] => [{1}]
|
||||
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
converter.mapping=Cipher suite 매핑: [{0}] => [{1}]
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
enum MessageDigest {
|
||||
MD5,
|
||||
SHA1,
|
||||
GOST94,
|
||||
GOST89MAC,
|
||||
SHA256,
|
||||
SHA384,
|
||||
AEAD
|
||||
}
|
||||
@@ -0,0 +1,915 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.Constants;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* Class in charge with parsing openSSL expressions to define a list of ciphers.
|
||||
*/
|
||||
public class OpenSSLCipherConfigurationParser {
|
||||
|
||||
private static final Log log = LogFactory.getLog(OpenSSLCipherConfigurationParser.class);
|
||||
private static final StringManager sm =
|
||||
StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
|
||||
|
||||
private static boolean initialized = false;
|
||||
|
||||
private static final String SEPARATOR = ":|,| ";
|
||||
/**
|
||||
* If ! is used then the ciphers are permanently deleted from the list. The ciphers deleted can never reappear in the list
|
||||
* even if they are explicitly stated.
|
||||
*/
|
||||
private static final String EXCLUDE = "!";
|
||||
/**
|
||||
* If - is used then the ciphers are deleted from the list, but some or all of the ciphers can be added again by later
|
||||
* options.
|
||||
*/
|
||||
private static final String DELETE = "-";
|
||||
/**
|
||||
* If + is used then the ciphers are moved to the end of the list. This option doesn't add any new ciphers it just moves
|
||||
* matching existing ones.
|
||||
*/
|
||||
private static final String TO_END = "+";
|
||||
/**
|
||||
* Lists of cipher suites can be combined in a single cipher string using the + character.
|
||||
* This is used as a logical and operation.
|
||||
* For example SHA1+DES represents all cipher suites containing the SHA1 and the DES algorithms.
|
||||
*/
|
||||
private static final String AND = "+";
|
||||
/**
|
||||
* All ciphers by their openssl alias name.
|
||||
*/
|
||||
private static final Map<String, List<Cipher>> aliases = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* the 'NULL' ciphers that is those offering no encryption. Because these offer no encryption at all and are a security risk
|
||||
* they are disabled unless explicitly included.
|
||||
*/
|
||||
private static final String eNULL = "eNULL";
|
||||
/**
|
||||
* The cipher suites offering no authentication. This is currently the anonymous DH algorithms. T These cipher suites are
|
||||
* vulnerable to a 'man in the middle' attack and so their use is normally discouraged.
|
||||
*/
|
||||
private static final String aNULL = "aNULL";
|
||||
|
||||
/**
|
||||
* 'high' encryption cipher suites. This currently means those with key lengths larger than 128 bits, and some cipher suites
|
||||
* with 128-bit keys.
|
||||
*/
|
||||
private static final String HIGH = "HIGH";
|
||||
/**
|
||||
* 'medium' encryption cipher suites, currently some of those using 128 bit encryption.
|
||||
*/
|
||||
private static final String MEDIUM = "MEDIUM";
|
||||
/**
|
||||
* 'low' encryption cipher suites, currently those using 64 or 56 bit encryption algorithms but excluding export cipher
|
||||
* suites.
|
||||
*/
|
||||
private static final String LOW = "LOW";
|
||||
/**
|
||||
* Export encryption algorithms. Including 40 and 56 bits algorithms.
|
||||
*/
|
||||
private static final String EXPORT = "EXPORT";
|
||||
/**
|
||||
* 40 bit export encryption algorithms.
|
||||
*/
|
||||
private static final String EXPORT40 = "EXPORT40";
|
||||
/**
|
||||
* 56 bit export encryption algorithms.
|
||||
*/
|
||||
private static final String EXPORT56 = "EXPORT56";
|
||||
/**
|
||||
* Cipher suites using RSA key exchange.
|
||||
*/
|
||||
private static final String kRSA = "kRSA";
|
||||
/**
|
||||
* Cipher suites using RSA authentication.
|
||||
*/
|
||||
private static final String aRSA = "aRSA";
|
||||
/**
|
||||
* Cipher suites using RSA for key exchange
|
||||
* Despite what the docs say, RSA is equivalent to kRSA.
|
||||
*/
|
||||
private static final String RSA = "RSA";
|
||||
/**
|
||||
* Cipher suites using ephemeral DH key agreement.
|
||||
*/
|
||||
private static final String kEDH = "kEDH";
|
||||
/**
|
||||
* Cipher suites using ephemeral DH key agreement.
|
||||
*/
|
||||
private static final String kDHE = "kDHE";
|
||||
/**
|
||||
* Cipher suites using ephemeral DH key agreement. equivalent to kEDH:-ADH
|
||||
*/
|
||||
private static final String EDH = "EDH";
|
||||
/**
|
||||
* Cipher suites using ephemeral DH key agreement. equivalent to kEDH:-ADH
|
||||
*/
|
||||
private static final String DHE = "DHE";
|
||||
/**
|
||||
* Cipher suites using DH key agreement and DH certificates signed by CAs with RSA keys.
|
||||
*/
|
||||
private static final String kDHr = "kDHr";
|
||||
/**
|
||||
* Cipher suites using DH key agreement and DH certificates signed by CAs with DSS keys.
|
||||
*/
|
||||
private static final String kDHd = "kDHd";
|
||||
/**
|
||||
* Cipher suites using DH key agreement and DH certificates signed by CAs with RSA or DSS keys.
|
||||
*/
|
||||
private static final String kDH = "kDH";
|
||||
/**
|
||||
* Cipher suites using fixed ECDH key agreement signed by CAs with RSA keys.
|
||||
*/
|
||||
private static final String kECDHr = "kECDHr";
|
||||
/**
|
||||
* Cipher suites using fixed ECDH key agreement signed by CAs with ECDSA keys.
|
||||
*/
|
||||
private static final String kECDHe = "kECDHe";
|
||||
/**
|
||||
* Cipher suites using fixed ECDH key agreement signed by CAs with RSA and ECDSA keys or either respectively.
|
||||
*/
|
||||
private static final String kECDH = "kECDH";
|
||||
/**
|
||||
* Cipher suites using ephemeral ECDH key agreement, including anonymous cipher suites.
|
||||
*/
|
||||
private static final String kEECDH = "kEECDH";
|
||||
/**
|
||||
* Cipher suites using ephemeral ECDH key agreement, excluding anonymous cipher suites.
|
||||
* Same as "kEECDH:-AECDH"
|
||||
*/
|
||||
private static final String EECDH = "EECDH";
|
||||
/**
|
||||
* Cipher suitesusing ECDH key exchange, including anonymous, ephemeral and fixed ECDH.
|
||||
*/
|
||||
private static final String ECDH = "ECDH";
|
||||
/**
|
||||
* Cipher suites using ephemeral ECDH key agreement, including anonymous cipher suites.
|
||||
*/
|
||||
private static final String kECDHE = "kECDHE";
|
||||
/**
|
||||
* Cipher suites using authenticated ephemeral ECDH key agreement
|
||||
*/
|
||||
private static final String ECDHE = "ECDHE";
|
||||
/**
|
||||
* Cipher suites using authenticated ephemeral ECDH key agreement
|
||||
*/
|
||||
private static final String EECDHE = "EECDHE";
|
||||
/**
|
||||
* Anonymous Elliptic Curve Diffie Hellman cipher suites.
|
||||
*/
|
||||
private static final String AECDH = "AECDH";
|
||||
/**
|
||||
* Cipher suites using DSS for key exchange
|
||||
*/
|
||||
private static final String DSS = "DSS";
|
||||
/**
|
||||
* Cipher suites using DSS authentication, i.e. the certificates carry DSS keys.
|
||||
*/
|
||||
private static final String aDSS = "aDSS";
|
||||
/**
|
||||
* Cipher suites effectively using DH authentication, i.e. the certificates carry DH keys.
|
||||
*/
|
||||
private static final String aDH = "aDH";
|
||||
/**
|
||||
* Cipher suites effectively using ECDH authentication, i.e. the certificates carry ECDH keys.
|
||||
*/
|
||||
private static final String aECDH = "aECDH";
|
||||
/**
|
||||
* Cipher suites effectively using ECDSA authentication, i.e. the certificates carry ECDSA keys.
|
||||
*/
|
||||
private static final String aECDSA = "aECDSA";
|
||||
/**
|
||||
* Cipher suites effectively using ECDSA authentication, i.e. the certificates carry ECDSA keys.
|
||||
*/
|
||||
private static final String ECDSA = "ECDSA";
|
||||
/**
|
||||
* Ciphers suites using FORTEZZA key exchange algorithms.
|
||||
*/
|
||||
private static final String kFZA = "kFZA";
|
||||
/**
|
||||
* Ciphers suites using FORTEZZA authentication algorithms.
|
||||
*/
|
||||
private static final String aFZA = "aFZA";
|
||||
/**
|
||||
* Ciphers suites using FORTEZZA encryption algorithms.
|
||||
*/
|
||||
private static final String eFZA = "eFZA";
|
||||
/**
|
||||
* Ciphers suites using all FORTEZZA algorithms.
|
||||
*/
|
||||
private static final String FZA = "FZA";
|
||||
/**
|
||||
* Cipher suites using DH, including anonymous DH, ephemeral DH and fixed DH.
|
||||
*/
|
||||
private static final String DH = "DH";
|
||||
/**
|
||||
* Anonymous DH cipher suites.
|
||||
*/
|
||||
private static final String ADH = "ADH";
|
||||
/**
|
||||
* Cipher suites using 128 bit AES.
|
||||
*/
|
||||
private static final String AES128 = "AES128";
|
||||
/**
|
||||
* Cipher suites using 256 bit AES.
|
||||
*/
|
||||
private static final String AES256 = "AES256";
|
||||
/**
|
||||
* Cipher suites using either 128 or 256 bit AES.
|
||||
*/
|
||||
private static final String AES = "AES";
|
||||
/**
|
||||
* AES in Galois Counter Mode (GCM): these cipher suites are only supported in TLS v1.2.
|
||||
*/
|
||||
private static final String AESGCM = "AESGCM";
|
||||
/**
|
||||
* AES in Counter with CBC-MAC Mode (CCM).
|
||||
*/
|
||||
private static final String AESCCM = "AESCCM";
|
||||
/**
|
||||
* AES in Counter with CBC-MAC Mode and 8-byte authentication (CCM8).
|
||||
*/
|
||||
private static final String AESCCM8 = "AESCCM8";
|
||||
/**
|
||||
* Cipher suites using either 128 bit ARIA.
|
||||
*/
|
||||
private static final String ARIA128 = "ARIA128";
|
||||
/**
|
||||
* Cipher suites using either 256 bit ARIA.
|
||||
*/
|
||||
private static final String ARIA256 = "ARIA256";
|
||||
/**
|
||||
* Cipher suites using either 128 or 256 bit ARIA.
|
||||
*/
|
||||
private static final String ARIA = "ARIA";
|
||||
/**
|
||||
* Cipher suites using 128 bit CAMELLIA.
|
||||
*/
|
||||
private static final String CAMELLIA128 = "CAMELLIA128";
|
||||
/**
|
||||
* Cipher suites using 256 bit CAMELLIA.
|
||||
*/
|
||||
private static final String CAMELLIA256 = "CAMELLIA256";
|
||||
/**
|
||||
* Cipher suites using either 128 or 256 bit CAMELLIA.
|
||||
*/
|
||||
private static final String CAMELLIA = "CAMELLIA";
|
||||
/**
|
||||
* Cipher suites using CHACHA20.
|
||||
*/
|
||||
private static final String CHACHA20 = "CHACHA20";
|
||||
/**
|
||||
* Cipher suites using triple DES.
|
||||
*/
|
||||
private static final String TRIPLE_DES = "3DES";
|
||||
/**
|
||||
* Cipher suites using DES (not triple DES).
|
||||
*/
|
||||
private static final String DES = "DES";
|
||||
/**
|
||||
* Cipher suites using RC4.
|
||||
*/
|
||||
private static final String RC4 = "RC4";
|
||||
/**
|
||||
* Cipher suites using RC2.
|
||||
*/
|
||||
private static final String RC2 = "RC2";
|
||||
/**
|
||||
* Cipher suites using IDEA.
|
||||
*/
|
||||
private static final String IDEA = "IDEA";
|
||||
/**
|
||||
* Cipher suites using SEED.
|
||||
*/
|
||||
private static final String SEED = "SEED";
|
||||
/**
|
||||
* Cipher suites using MD5.
|
||||
*/
|
||||
private static final String MD5 = "MD5";
|
||||
/**
|
||||
* Cipher suites using SHA1.
|
||||
*/
|
||||
private static final String SHA1 = "SHA1";
|
||||
/**
|
||||
* Cipher suites using SHA1.
|
||||
*/
|
||||
private static final String SHA = "SHA";
|
||||
/**
|
||||
* Cipher suites using SHA256.
|
||||
*/
|
||||
private static final String SHA256 = "SHA256";
|
||||
/**
|
||||
* Cipher suites using SHA384.
|
||||
*/
|
||||
private static final String SHA384 = "SHA384";
|
||||
/**
|
||||
* Cipher suites using KRB5.
|
||||
*/
|
||||
private static final String KRB5 = "KRB5";
|
||||
/**
|
||||
* Cipher suites using GOST R 34.10 (either 2001 or 94) for authentication.
|
||||
*/
|
||||
private static final String aGOST = "aGOST";
|
||||
/**
|
||||
* Cipher suites using GOST R 34.10-2001 for authentication.
|
||||
*/
|
||||
private static final String aGOST01 = "aGOST01";
|
||||
/**
|
||||
* Cipher suites using GOST R 34.10-94 authentication (note that R 34.10-94 standard has been expired so use GOST R
|
||||
* 34.10-2001)
|
||||
*/
|
||||
private static final String aGOST94 = "aGOST94";
|
||||
/**
|
||||
* Cipher suites using using VKO 34.10 key exchange, specified in the RFC 4357.
|
||||
*/
|
||||
private static final String kGOST = "kGOST";
|
||||
/**
|
||||
* Cipher suites, using HMAC based on GOST R 34.11-94.
|
||||
*/
|
||||
private static final String GOST94 = "GOST94";
|
||||
/**
|
||||
* Cipher suites using GOST 28147-89 MAC instead of HMAC.
|
||||
*/
|
||||
private static final String GOST89MAC = "GOST89MAC";
|
||||
/**
|
||||
* Cipher suites using SRP authentication, specified in the RFC 5054.
|
||||
*/
|
||||
private static final String aSRP = "aSRP";
|
||||
/**
|
||||
* Cipher suites using SRP key exchange, specified in the RFC 5054.
|
||||
*/
|
||||
private static final String kSRP = "kSRP";
|
||||
/**
|
||||
* Same as kSRP
|
||||
*/
|
||||
private static final String SRP = "SRP";
|
||||
/**
|
||||
* Cipher suites using pre-shared keys (PSK).
|
||||
*/
|
||||
private static final String PSK = "PSK";
|
||||
/**
|
||||
* Cipher suites using PSK authentication.
|
||||
*/
|
||||
private static final String aPSK = "aPSK";
|
||||
/**
|
||||
* Cipher suites using PSK key 'exchange'.
|
||||
*/
|
||||
private static final String kPSK = "kPSK";
|
||||
private static final String kRSAPSK = "kRSAPSK";
|
||||
private static final String kECDHEPSK = "kECDHEPSK";
|
||||
private static final String kDHEPSK = "kDHEPSK";
|
||||
|
||||
private static final String DEFAULT = "DEFAULT";
|
||||
private static final String COMPLEMENTOFDEFAULT = "COMPLEMENTOFDEFAULT";
|
||||
|
||||
private static final String ALL = "ALL";
|
||||
private static final String COMPLEMENTOFALL = "COMPLEMENTOFALL";
|
||||
|
||||
private static final Map<String,String> jsseToOpenSSL = new HashMap<>();
|
||||
|
||||
private static final void init() {
|
||||
|
||||
for (Cipher cipher : Cipher.values()) {
|
||||
String alias = cipher.getOpenSSLAlias();
|
||||
if (aliases.containsKey(alias)) {
|
||||
aliases.get(alias).add(cipher);
|
||||
} else {
|
||||
List<Cipher> list = new ArrayList<>();
|
||||
list.add(cipher);
|
||||
aliases.put(alias, list);
|
||||
}
|
||||
aliases.put(cipher.name(), Collections.singletonList(cipher));
|
||||
|
||||
for (String openSSlAltName : cipher.getOpenSSLAltNames()) {
|
||||
if (aliases.containsKey(openSSlAltName)) {
|
||||
aliases.get(openSSlAltName).add(cipher);
|
||||
} else {
|
||||
List<Cipher> list = new ArrayList<>();
|
||||
list.add(cipher);
|
||||
aliases.put(openSSlAltName, list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
jsseToOpenSSL.put(cipher.name(), cipher.getOpenSSLAlias());
|
||||
Set<String> jsseNames = cipher.getJsseNames();
|
||||
for (String jsseName : jsseNames) {
|
||||
jsseToOpenSSL.put(jsseName, cipher.getOpenSSLAlias());
|
||||
}
|
||||
}
|
||||
List<Cipher> allCiphersList = Arrays.asList(Cipher.values());
|
||||
Collections.reverse(allCiphersList);
|
||||
LinkedHashSet<Cipher> allCiphers = defaultSort(new LinkedHashSet<>(allCiphersList));
|
||||
addListAlias(eNULL, filterByEncryption(allCiphers, Collections.singleton(Encryption.eNULL)));
|
||||
LinkedHashSet<Cipher> all = new LinkedHashSet<>(allCiphers);
|
||||
remove(all, eNULL);
|
||||
addListAlias(ALL, all);
|
||||
addListAlias(HIGH, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.HIGH)));
|
||||
addListAlias(MEDIUM, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.MEDIUM)));
|
||||
addListAlias(LOW, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.LOW)));
|
||||
addListAlias(EXPORT, filterByEncryptionLevel(allCiphers, new HashSet<>(Arrays.asList(EncryptionLevel.EXP40, EncryptionLevel.EXP56))));
|
||||
aliases.put("EXP", aliases.get(EXPORT));
|
||||
addListAlias(EXPORT40, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.EXP40)));
|
||||
addListAlias(EXPORT56, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.EXP56)));
|
||||
aliases.put("NULL", aliases.get(eNULL));
|
||||
aliases.put(COMPLEMENTOFALL, aliases.get(eNULL));
|
||||
addListAlias(aNULL, filterByAuthentication(allCiphers, Collections.singleton(Authentication.aNULL)));
|
||||
addListAlias(kRSA, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.RSA)));
|
||||
addListAlias(aRSA, filterByAuthentication(allCiphers, Collections.singleton(Authentication.RSA)));
|
||||
// Despite what the docs say, RSA is equivalent to kRSA
|
||||
aliases.put(RSA, aliases.get(kRSA));
|
||||
addListAlias(kEDH, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EDH)));
|
||||
addListAlias(kDHE, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EDH)));
|
||||
Set<Cipher> edh = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EDH));
|
||||
edh.removeAll(filterByAuthentication(allCiphers, Collections.singleton(Authentication.aNULL)));
|
||||
addListAlias(EDH, edh);
|
||||
addListAlias(DHE, edh);
|
||||
addListAlias(kDHr, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.DHr)));
|
||||
addListAlias(kDHd, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.DHd)));
|
||||
addListAlias(kDH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.DHr, KeyExchange.DHd))));
|
||||
|
||||
addListAlias(kECDHr, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.ECDHr)));
|
||||
addListAlias(kECDHe, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.ECDHe)));
|
||||
addListAlias(kECDH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.ECDHe, KeyExchange.ECDHr))));
|
||||
addListAlias(ECDH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.ECDHe, KeyExchange.ECDHr, KeyExchange.EECDH))));
|
||||
addListAlias(kECDHE, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH)));
|
||||
|
||||
Set<Cipher> ecdhe = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH));
|
||||
remove(ecdhe, aNULL);
|
||||
addListAlias(ECDHE, ecdhe);
|
||||
|
||||
addListAlias(kEECDH, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH)));
|
||||
aliases.put(EECDHE, aliases.get(kEECDH));
|
||||
Set<Cipher> eecdh = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH));
|
||||
eecdh.removeAll(filterByAuthentication(allCiphers, Collections.singleton(Authentication.aNULL)));
|
||||
addListAlias(EECDH, eecdh);
|
||||
addListAlias(aDSS, filterByAuthentication(allCiphers, Collections.singleton(Authentication.DSS)));
|
||||
aliases.put(DSS, aliases.get(aDSS));
|
||||
addListAlias(aDH, filterByAuthentication(allCiphers, Collections.singleton(Authentication.DH)));
|
||||
Set<Cipher> aecdh = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH));
|
||||
addListAlias(AECDH, filterByAuthentication(aecdh, Collections.singleton(Authentication.aNULL)));
|
||||
addListAlias(aECDH, filterByAuthentication(allCiphers, Collections.singleton(Authentication.ECDH)));
|
||||
addListAlias(ECDSA, filterByAuthentication(allCiphers, Collections.singleton(Authentication.ECDSA)));
|
||||
aliases.put(aECDSA, aliases.get(ECDSA));
|
||||
addListAlias(kFZA, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.FZA)));
|
||||
addListAlias(aFZA, filterByAuthentication(allCiphers, Collections.singleton(Authentication.FZA)));
|
||||
addListAlias(eFZA, filterByEncryption(allCiphers, Collections.singleton(Encryption.FZA)));
|
||||
addListAlias(FZA, filter(allCiphers, null, Collections.singleton(KeyExchange.FZA), Collections.singleton(Authentication.FZA), Collections.singleton(Encryption.FZA), null, null));
|
||||
addListAlias(Constants.SSL_PROTO_TLSv1_2, filterByProtocol(allCiphers, Collections.singleton(Protocol.TLSv1_2)));
|
||||
addListAlias(Constants.SSL_PROTO_TLSv1_0, filterByProtocol(allCiphers, Collections.singleton(Protocol.TLSv1)));
|
||||
addListAlias(Constants.SSL_PROTO_SSLv3, filterByProtocol(allCiphers, Collections.singleton(Protocol.SSLv3)));
|
||||
aliases.put(Constants.SSL_PROTO_TLSv1, aliases.get(Constants.SSL_PROTO_TLSv1_0));
|
||||
addListAlias(Constants.SSL_PROTO_SSLv2, filterByProtocol(allCiphers, Collections.singleton(Protocol.SSLv2)));
|
||||
addListAlias(DH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.DHr, KeyExchange.DHd, KeyExchange.EDH))));
|
||||
Set<Cipher> adh = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EDH));
|
||||
adh.retainAll(filterByAuthentication(allCiphers, Collections.singleton(Authentication.aNULL)));
|
||||
addListAlias(ADH, adh);
|
||||
addListAlias(AES128, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES128GCM))));
|
||||
addListAlias(AES256, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM))));
|
||||
addListAlias(AES, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES128GCM, Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM))));
|
||||
addListAlias(ARIA128, filterByEncryption(allCiphers, Collections.singleton(Encryption.ARIA128GCM)));
|
||||
addListAlias(ARIA256, filterByEncryption(allCiphers, Collections.singleton(Encryption.ARIA256GCM)));
|
||||
addListAlias(ARIA, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.ARIA128GCM, Encryption.ARIA256GCM))));
|
||||
addListAlias(AESGCM, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128GCM, Encryption.AES256GCM))));
|
||||
addListAlias(AESCCM, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES256CCM, Encryption.AES256CCM8))));
|
||||
addListAlias(AESCCM8, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128CCM8, Encryption.AES256CCM8))));
|
||||
addListAlias(CAMELLIA, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.CAMELLIA128, Encryption.CAMELLIA256))));
|
||||
addListAlias(CAMELLIA128, filterByEncryption(allCiphers, Collections.singleton(Encryption.CAMELLIA128)));
|
||||
addListAlias(CAMELLIA256, filterByEncryption(allCiphers, Collections.singleton(Encryption.CAMELLIA256)));
|
||||
addListAlias(CHACHA20, filterByEncryption(allCiphers, Collections.singleton(Encryption.CHACHA20POLY1305)));
|
||||
addListAlias(TRIPLE_DES, filterByEncryption(allCiphers, Collections.singleton(Encryption.TRIPLE_DES)));
|
||||
addListAlias(DES, filterByEncryption(allCiphers, Collections.singleton(Encryption.DES)));
|
||||
addListAlias(RC4, filterByEncryption(allCiphers, Collections.singleton(Encryption.RC4)));
|
||||
addListAlias(RC2, filterByEncryption(allCiphers, Collections.singleton(Encryption.RC2)));
|
||||
addListAlias(IDEA, filterByEncryption(allCiphers, Collections.singleton(Encryption.IDEA)));
|
||||
addListAlias(SEED, filterByEncryption(allCiphers, Collections.singleton(Encryption.SEED)));
|
||||
addListAlias(MD5, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.MD5)));
|
||||
addListAlias(SHA1, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.SHA1)));
|
||||
aliases.put(SHA, aliases.get(SHA1));
|
||||
addListAlias(SHA256, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.SHA256)));
|
||||
addListAlias(SHA384, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.SHA384)));
|
||||
addListAlias(aGOST, filterByAuthentication(allCiphers, new HashSet<>(Arrays.asList(Authentication.GOST01, Authentication.GOST94))));
|
||||
addListAlias(aGOST01, filterByAuthentication(allCiphers, Collections.singleton(Authentication.GOST01)));
|
||||
addListAlias(aGOST94, filterByAuthentication(allCiphers, Collections.singleton(Authentication.GOST94)));
|
||||
addListAlias(kGOST, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.GOST)));
|
||||
addListAlias(GOST94, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.GOST94)));
|
||||
addListAlias(GOST89MAC, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.GOST89MAC)));
|
||||
addListAlias(PSK, filter(allCiphers, null, new HashSet<>(Arrays.asList(KeyExchange.PSK, KeyExchange.RSAPSK, KeyExchange.DHEPSK, KeyExchange.ECDHEPSK)), Collections.singleton(Authentication.PSK), null, null, null));
|
||||
addListAlias(aPSK, filterByAuthentication(allCiphers, Collections.singleton(Authentication.PSK)));
|
||||
addListAlias(kPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.PSK)));
|
||||
addListAlias(kRSAPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.RSAPSK)));
|
||||
addListAlias(kECDHEPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.ECDHEPSK)));
|
||||
addListAlias(kDHEPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.DHEPSK)));
|
||||
addListAlias(KRB5, filter(allCiphers, null, Collections.singleton(KeyExchange.KRB5), Collections.singleton(Authentication.KRB5), null, null, null));
|
||||
addListAlias(aSRP, filterByAuthentication(allCiphers, Collections.singleton(Authentication.SRP)));
|
||||
addListAlias(kSRP, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.SRP)));
|
||||
addListAlias(SRP, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.SRP)));
|
||||
initialized = true;
|
||||
// Despite what the OpenSSL docs say, DEFAULT also excludes SSLv2
|
||||
addListAlias(DEFAULT, parse("ALL:!EXPORT:!eNULL:!aNULL:!SSLv2:!DES:!RC2:!RC4:!DSS:!SEED:!IDEA:!CAMELLIA:!AESCCM:!3DES:!ARIA"));
|
||||
// COMPLEMENTOFDEFAULT is also not exactly as defined by the docs
|
||||
LinkedHashSet<Cipher> complementOfDefault = filterByKeyExchange(all, new HashSet<>(Arrays.asList(KeyExchange.EDH,KeyExchange.EECDH)));
|
||||
complementOfDefault = filterByAuthentication(complementOfDefault, Collections.singleton(Authentication.aNULL));
|
||||
complementOfDefault.removeAll(aliases.get(eNULL));
|
||||
complementOfDefault.addAll(aliases.get(Constants.SSL_PROTO_SSLv2));
|
||||
complementOfDefault.addAll(aliases.get(EXPORT));
|
||||
complementOfDefault.addAll(aliases.get(DES));
|
||||
complementOfDefault.addAll(aliases.get(TRIPLE_DES));
|
||||
complementOfDefault.addAll(aliases.get(RC2));
|
||||
complementOfDefault.addAll(aliases.get(RC4));
|
||||
complementOfDefault.addAll(aliases.get(aDSS));
|
||||
complementOfDefault.addAll(aliases.get(SEED));
|
||||
complementOfDefault.addAll(aliases.get(IDEA));
|
||||
complementOfDefault.addAll(aliases.get(CAMELLIA));
|
||||
complementOfDefault.addAll(aliases.get(AESCCM));
|
||||
complementOfDefault.addAll(aliases.get(ARIA));
|
||||
defaultSort(complementOfDefault);
|
||||
addListAlias(COMPLEMENTOFDEFAULT, complementOfDefault);
|
||||
}
|
||||
|
||||
static void addListAlias(String alias, Set<Cipher> ciphers) {
|
||||
aliases.put(alias, new ArrayList<>(ciphers));
|
||||
}
|
||||
|
||||
static void moveToEnd(final LinkedHashSet<Cipher> ciphers, final String alias) {
|
||||
moveToEnd(ciphers, aliases.get(alias));
|
||||
}
|
||||
|
||||
static void moveToEnd(final LinkedHashSet<Cipher> ciphers, final Collection<Cipher> toBeMovedCiphers) {
|
||||
List<Cipher> movedCiphers = new ArrayList<>(toBeMovedCiphers);
|
||||
movedCiphers.retainAll(ciphers);
|
||||
ciphers.removeAll(movedCiphers);
|
||||
ciphers.addAll(movedCiphers);
|
||||
}
|
||||
|
||||
static void moveToStart(final LinkedHashSet<Cipher> ciphers, final Collection<Cipher> toBeMovedCiphers) {
|
||||
List<Cipher> movedCiphers = new ArrayList<>(toBeMovedCiphers);
|
||||
List<Cipher> originalCiphers = new ArrayList<>(ciphers);
|
||||
movedCiphers.retainAll(ciphers);
|
||||
ciphers.clear();
|
||||
ciphers.addAll(movedCiphers);
|
||||
ciphers.addAll(originalCiphers);
|
||||
}
|
||||
|
||||
static void add(final LinkedHashSet<Cipher> ciphers, final String alias) {
|
||||
ciphers.addAll(aliases.get(alias));
|
||||
}
|
||||
|
||||
static void remove(final Set<Cipher> ciphers, final String alias) {
|
||||
ciphers.removeAll(aliases.get(alias));
|
||||
}
|
||||
|
||||
static LinkedHashSet<Cipher> strengthSort(final LinkedHashSet<Cipher> ciphers) {
|
||||
/*
|
||||
* This routine sorts the ciphers with descending strength. The sorting
|
||||
* must keep the pre-sorted sequence, so we apply the normal sorting
|
||||
* routine as '+' movement to the end of the list.
|
||||
*/
|
||||
Set<Integer> keySizes = new HashSet<>();
|
||||
for (Cipher cipher : ciphers) {
|
||||
keySizes.add(Integer.valueOf(cipher.getStrength_bits()));
|
||||
}
|
||||
List<Integer> strength_bits = new ArrayList<>(keySizes);
|
||||
Collections.sort(strength_bits);
|
||||
Collections.reverse(strength_bits);
|
||||
final LinkedHashSet<Cipher> result = new LinkedHashSet<>(ciphers);
|
||||
for (int strength : strength_bits) {
|
||||
moveToEnd(result, filterByStrengthBits(ciphers, strength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* See
|
||||
* https://github.com/openssl/openssl/blob/7c96dbcdab959fef74c4caae63cdebaa354ab252/ssl/ssl_ciph.c#L1371
|
||||
*/
|
||||
static LinkedHashSet<Cipher> defaultSort(final LinkedHashSet<Cipher> ciphers) {
|
||||
final LinkedHashSet<Cipher> result = new LinkedHashSet<>(ciphers.size());
|
||||
final LinkedHashSet<Cipher> ecdh = new LinkedHashSet<>(ciphers.size());
|
||||
|
||||
/* Everything else being equal, prefer ephemeral ECDH over other key exchange mechanisms */
|
||||
ecdh.addAll(filterByKeyExchange(ciphers, Collections.singleton(KeyExchange.EECDH)));
|
||||
|
||||
/* AES is our preferred symmetric cipher */
|
||||
Set<Encryption> aes = new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM,
|
||||
Encryption.AES128CCM8, Encryption.AES128GCM, Encryption.AES256,
|
||||
Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM));
|
||||
|
||||
/* Now arrange all ciphers by preference: */
|
||||
result.addAll(filterByEncryption(ecdh, aes));
|
||||
result.addAll(filterByEncryption(ciphers, aes));
|
||||
|
||||
/* Add everything else */
|
||||
result.addAll(ecdh);
|
||||
result.addAll(ciphers);
|
||||
|
||||
/* Low priority for MD5 */
|
||||
moveToEnd(result, filterByMessageDigest(result, Collections.singleton(MessageDigest.MD5)));
|
||||
|
||||
/* Move anonymous ciphers to the end. Usually, these will remain disabled.
|
||||
* (For applications that allow them, they aren't too bad, but we prefer
|
||||
* authenticated ciphers.) */
|
||||
moveToEnd(result, filterByAuthentication(result, Collections.singleton(Authentication.aNULL)));
|
||||
|
||||
/* Move ciphers without forward secrecy to the end */
|
||||
moveToEnd(result, filterByAuthentication(result, Collections.singleton(Authentication.ECDH)));
|
||||
moveToEnd(result, filterByKeyExchange(result, Collections.singleton(KeyExchange.RSA)));
|
||||
moveToEnd(result, filterByKeyExchange(result, Collections.singleton(KeyExchange.PSK)));
|
||||
|
||||
/* RC4 is sort-of broken -- move the the end */
|
||||
moveToEnd(result, filterByEncryption(result, Collections.singleton(Encryption.RC4)));
|
||||
return strengthSort(result);
|
||||
}
|
||||
|
||||
static Set<Cipher> filterByStrengthBits(Set<Cipher> ciphers, int strength_bits) {
|
||||
Set<Cipher> result = new LinkedHashSet<>(ciphers.size());
|
||||
for (Cipher cipher : ciphers) {
|
||||
if (cipher.getStrength_bits() == strength_bits) {
|
||||
result.add(cipher);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Set<Cipher> filterByProtocol(Set<Cipher> ciphers, Set<Protocol> protocol) {
|
||||
return filter(ciphers, protocol, null, null, null, null, null);
|
||||
}
|
||||
|
||||
static LinkedHashSet<Cipher> filterByKeyExchange(Set<Cipher> ciphers, Set<KeyExchange> kx) {
|
||||
return filter(ciphers, null, kx, null, null, null, null);
|
||||
}
|
||||
|
||||
static LinkedHashSet<Cipher> filterByAuthentication(Set<Cipher> ciphers, Set<Authentication> au) {
|
||||
return filter(ciphers, null, null, au, null, null, null);
|
||||
}
|
||||
|
||||
static Set<Cipher> filterByEncryption(Set<Cipher> ciphers, Set<Encryption> enc) {
|
||||
return filter(ciphers, null, null, null, enc, null, null);
|
||||
}
|
||||
|
||||
static Set<Cipher> filterByEncryptionLevel(Set<Cipher> ciphers, Set<EncryptionLevel> level) {
|
||||
return filter(ciphers, null, null, null, null, level, null);
|
||||
}
|
||||
|
||||
static Set<Cipher> filterByMessageDigest(Set<Cipher> ciphers, Set<MessageDigest> mac) {
|
||||
return filter(ciphers, null, null, null, null, null, mac);
|
||||
}
|
||||
|
||||
static LinkedHashSet<Cipher> filter(Set<Cipher> ciphers, Set<Protocol> protocol, Set<KeyExchange> kx,
|
||||
Set<Authentication> au, Set<Encryption> enc, Set<EncryptionLevel> level, Set<MessageDigest> mac) {
|
||||
LinkedHashSet<Cipher> result = new LinkedHashSet<>(ciphers.size());
|
||||
for (Cipher cipher : ciphers) {
|
||||
if (protocol != null && protocol.contains(cipher.getProtocol())) {
|
||||
result.add(cipher);
|
||||
}
|
||||
if (kx != null && kx.contains(cipher.getKx())) {
|
||||
result.add(cipher);
|
||||
}
|
||||
if (au != null && au.contains(cipher.getAu())) {
|
||||
result.add(cipher);
|
||||
}
|
||||
if (enc != null && enc.contains(cipher.getEnc())) {
|
||||
result.add(cipher);
|
||||
}
|
||||
if (level != null && level.contains(cipher.getLevel())) {
|
||||
result.add(cipher);
|
||||
}
|
||||
if (mac != null && mac.contains(cipher.getMac())) {
|
||||
result.add(cipher);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static LinkedHashSet<Cipher> parse(String expression) {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
String[] elements = expression.split(SEPARATOR);
|
||||
LinkedHashSet<Cipher> ciphers = new LinkedHashSet<>();
|
||||
Set<Cipher> removedCiphers = new HashSet<>();
|
||||
for (String element : elements) {
|
||||
if (element.startsWith(DELETE)) {
|
||||
String alias = element.substring(1);
|
||||
if (aliases.containsKey(alias)) {
|
||||
remove(ciphers, alias);
|
||||
}
|
||||
} else if (element.startsWith(EXCLUDE)) {
|
||||
String alias = element.substring(1);
|
||||
if (aliases.containsKey(alias)) {
|
||||
removedCiphers.addAll(aliases.get(alias));
|
||||
} else {
|
||||
log.warn(sm.getString("jsse.openssl.unknownElement", alias));
|
||||
}
|
||||
} else if (element.startsWith(TO_END)) {
|
||||
String alias = element.substring(1);
|
||||
if (aliases.containsKey(alias)) {
|
||||
moveToEnd(ciphers, alias);
|
||||
}
|
||||
} else if ("@STRENGTH".equals(element)) {
|
||||
strengthSort(ciphers);
|
||||
break;
|
||||
} else if (aliases.containsKey(element)) {
|
||||
add(ciphers, element);
|
||||
} else if (element.contains(AND)) {
|
||||
String[] intersections = element.split("\\" + AND);
|
||||
if(intersections.length > 0 && aliases.containsKey(intersections[0])) {
|
||||
List<Cipher> result = new ArrayList<>(aliases.get(intersections[0]));
|
||||
for(int i = 1; i < intersections.length; i++) {
|
||||
if(aliases.containsKey(intersections[i])) {
|
||||
result.retainAll(aliases.get(intersections[i]));
|
||||
}
|
||||
}
|
||||
ciphers.addAll(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
ciphers.removeAll(removedCiphers);
|
||||
return ciphers;
|
||||
}
|
||||
|
||||
public static List<String> convertForJSSE(Collection<Cipher> ciphers) {
|
||||
List<String> result = new ArrayList<>(ciphers.size());
|
||||
for (Cipher cipher : ciphers) {
|
||||
result.addAll(cipher.getJsseNames());
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("jsse.openssl.effectiveCiphers", displayResult(ciphers, true, ",")));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified expression according to the OpenSSL syntax and
|
||||
* returns a list of standard JSSE cipher names.
|
||||
*
|
||||
* @param expression the openssl expression to define a list of cipher.
|
||||
* @return the corresponding list of ciphers.
|
||||
*/
|
||||
public static List<String> parseExpression(String expression) {
|
||||
return convertForJSSE(parse(expression));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a JSSE cipher name to an OpenSSL cipher name.
|
||||
*
|
||||
* @param jsseCipherName The JSSE name for a cipher
|
||||
*
|
||||
* @return The OpenSSL name for the specified JSSE cipher
|
||||
*/
|
||||
public static String jsseToOpenSSL(String jsseCipherName) {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
return jsseToOpenSSL.get(jsseCipherName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts an OpenSSL cipher name to a JSSE cipher name.
|
||||
*
|
||||
* @param opensslCipherName The OpenSSL name for a cipher
|
||||
*
|
||||
* @return The JSSE name for the specified OpenSSL cipher. If none is known,
|
||||
* the IANA standard name will be returned instead
|
||||
*/
|
||||
public static String openSSLToJsse(String opensslCipherName) {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
List<Cipher> ciphers = aliases.get(opensslCipherName);
|
||||
if (ciphers == null || ciphers.size() != 1) {
|
||||
// Not an OpenSSL cipher name
|
||||
return null;
|
||||
}
|
||||
Cipher cipher = ciphers.get(0);
|
||||
// Each Cipher always has at least one JSSE name
|
||||
return cipher.getJsseNames().iterator().next();
|
||||
}
|
||||
|
||||
|
||||
static String displayResult(Collection<Cipher> ciphers, boolean useJSSEFormat, String separator) {
|
||||
if (ciphers.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder builder = new StringBuilder(ciphers.size() * 16);
|
||||
for (Cipher cipher : ciphers) {
|
||||
if (useJSSEFormat) {
|
||||
for (String name : cipher.getJsseNames()) {
|
||||
builder.append(name);
|
||||
builder.append(separator);
|
||||
}
|
||||
} else {
|
||||
builder.append(cipher.getOpenSSLAlias());
|
||||
}
|
||||
builder.append(separator);
|
||||
}
|
||||
return builder.toString().substring(0, builder.length() - 1);
|
||||
}
|
||||
|
||||
public static void usage() {
|
||||
System.out.println("Usage: java " + OpenSSLCipherConfigurationParser.class.getName() + " [options] cipherspec");
|
||||
System.out.println();
|
||||
System.out.println("Displays the TLS cipher suites matching the cipherspec.");
|
||||
System.out.println();
|
||||
System.out.println(" --help,");
|
||||
System.out.println(" -h Print this help message");
|
||||
System.out.println(" --openssl Show OpenSSL cipher suite names instead of IANA cipher suite names.");
|
||||
System.out.println(" --verbose,");
|
||||
System.out.println(" -v Provide detailed cipher listing");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
boolean verbose = false;
|
||||
boolean useOpenSSLNames = false;
|
||||
int argindex;
|
||||
for(argindex = 0; argindex < args.length; ++argindex)
|
||||
{
|
||||
String arg = args[argindex];
|
||||
if("--verbose".equals(arg) || "-v".equals(arg))
|
||||
verbose = true;
|
||||
else if("--openssl".equals(arg))
|
||||
useOpenSSLNames = true;
|
||||
else if("--help".equals(arg) || "-h".equals(arg)) {
|
||||
usage();
|
||||
System.exit(0);
|
||||
}
|
||||
else if("--".equals(arg)) {
|
||||
++argindex;
|
||||
break;
|
||||
} else if(arg.startsWith("-")) {
|
||||
System.out.println("Unknown option: " + arg);
|
||||
usage();
|
||||
System.exit(1);
|
||||
} else {
|
||||
// Non-switch argument... probably the cipher spec
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String cipherSpec;
|
||||
if(argindex < args.length) {
|
||||
cipherSpec = args[argindex];
|
||||
} else {
|
||||
cipherSpec = "DEFAULT";
|
||||
}
|
||||
Set<Cipher> ciphers = parse(cipherSpec);
|
||||
boolean first = true;
|
||||
if(null != ciphers && 0 < ciphers.size()) {
|
||||
for(Cipher cipher : ciphers)
|
||||
{
|
||||
if(first) {
|
||||
first = false;
|
||||
} else {
|
||||
if(!verbose)
|
||||
System.out.print(',');
|
||||
}
|
||||
if(useOpenSSLNames)
|
||||
System.out.print(cipher.getOpenSSLAlias());
|
||||
else
|
||||
System.out.print(cipher.name());
|
||||
if(verbose) {
|
||||
System.out.println("\t" + cipher.getProtocol() + "\tKx=" + cipher.getKx() + "\tAu=" + cipher.getAu() + "\tEnc=" + cipher.getEnc() + "\tMac=" + cipher.getMac());
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
} else {
|
||||
System.out.println("No ciphers match '" + cipherSpec + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
import org.apache.tomcat.util.net.Constants;
|
||||
|
||||
enum Protocol {
|
||||
|
||||
SSLv3(Constants.SSL_PROTO_SSLv3),
|
||||
SSLv2(Constants.SSL_PROTO_SSLv2),
|
||||
TLSv1(Constants.SSL_PROTO_TLSv1),
|
||||
TLSv1_2(Constants.SSL_PROTO_TLSv1_2),
|
||||
TLSv1_3(Constants.SSL_PROTO_TLSv1_3);
|
||||
|
||||
private final String openSSLName;
|
||||
|
||||
private Protocol(String openSSLName) {
|
||||
this.openSSLName = openSSLName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name returned by OpenSSL in the protocol column when using
|
||||
* <code>openssl ciphers -v</code>. This is currently only used by the unit
|
||||
* tests hence it is package private.
|
||||
*/
|
||||
String getOpenSSLName() {
|
||||
return openSSLName;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user