2019-06-30 16:07:58 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Copyright 2015 Matthew Holt and The Caddy Authors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Licensed 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. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								package  caddytls 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"crypto/tls" 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"crypto/x509" 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"encoding/base64" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"encoding/json" 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 01:17:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"os" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"path/filepath" 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-02 12:37:06 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/caddyserver/caddy/v2" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 15:18:14 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/mholt/acmez" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"go.uber.org/zap" 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  init ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									caddy . RegisterModule ( LeafCertClientAuth { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 15:18:14 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ConnectionPolicies govern the establishment of TLS connections. It is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// an ordered group of connection policies; the first matching policy will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// be used to configure TLS connections at handshake-time. 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								type  ConnectionPolicies  [ ] * ConnectionPolicy 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Provision sets up each connection policy. It should be called 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// during the Validate() phase, after the TLS app (if any) is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// already set up. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( cp  ConnectionPolicies )  Provision ( ctx  caddy . Context )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									for  i ,  pol  :=  range  cp  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-27 11:31:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// matchers 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-10 13:36:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										mods ,  err  :=  ctx . LoadModule ( pol ,  "MatchersRaw" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  fmt . Errorf ( "loading handshake matchers: %v" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-10 13:36:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 16:39:09 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  modIface  :=  range  mods . ( map [ string ] any )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-10 13:36:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											cp [ i ] . matchers  =  append ( cp [ i ] . matchers ,  modIface . ( ConnectionMatcher ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-27 11:31:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 19:14:49 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// enable HTTP/2 by default 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  len ( pol . ALPN )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											pol . ALPN  =  append ( pol . ALPN ,  defaultALPN ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// pre-build standard TLS config so we don't have to at handshake-time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  =  pol . buildStandardTLSConfig ( ctx ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  fmt . Errorf ( "connection policy %d: building standard TLS config: %s" ,  i ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  pol . ClientAuthentication  !=  nil  &&  len ( pol . ClientAuthentication . VerifiersRaw )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											clientCertValidations ,  err  :=  ctx . LoadModule ( pol . ClientAuthentication ,  "VerifiersRaw" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  fmt . Errorf ( "loading client cert verifiers: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 16:39:09 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											for  _ ,  validator  :=  range  clientCertValidations . ( [ ] any )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												cp [ i ] . ClientAuthentication . verifiers  =  append ( cp [ i ] . ClientAuthentication . verifiers ,  validator . ( ClientCertificateVerifier ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// TLSConfig returns a standard-lib-compatible TLS configuration which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// selects the first matching policy based on the ClientHello. 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( cp  ConnectionPolicies )  TLSConfig ( _  caddy . Context )  * tls . Config  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// using ServerName to match policies is extremely common, especially in configs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// with lots and lots of different policies; we can fast-track those by indexing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// them by SNI, so we don't have to iterate potentially thousands of policies 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-02 13:27:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// (TODO: this map does not account for wildcards, see if this is a problem in practice? look for reports of high connection latency with wildcard certs but low latency for non-wildcards in multi-thousand-cert deployments) 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									indexedBySNI  :=  make ( map [ string ] ConnectionPolicies ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( cp )  >  30  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  _ ,  p  :=  range  cp  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											for  _ ,  m  :=  range  p . matchers  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  sni ,  ok  :=  m . ( MatchServerName ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													for  _ ,  sniName  :=  range  sni  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														indexedBySNI [ sniName ]  =  append ( indexedBySNI [ sniName ] ,  p ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									return  & tls . Config { 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-22 16:50:29 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										MinVersion :  tls . VersionTLS12 , 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										GetConfigForClient :  func ( hello  * tls . ClientHelloInfo )  ( * tls . Config ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// filter policies by SNI first, if possible, to speed things up 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// when there may be lots of policies 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											possiblePolicies  :=  cp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  indexedPolicies ,  ok  :=  indexedBySNI [ hello . ServerName ] ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												possiblePolicies  =  indexedPolicies 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										policyLoop : 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											for  _ ,  pol  :=  range  possiblePolicies  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												for  _ ,  matcher  :=  range  pol . matchers  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
													if  ! matcher . Match ( hello )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														continue  policyLoop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-15 12:01:58 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												return  pol . TLSConfig ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-20 20:36:29 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
											return  nil ,  fmt . Errorf ( "no server TLS configuration available for ClientHello: %+v" ,  hello ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} , 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ConnectionPolicy specifies the logic for handling a TLS handshake. 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-28 23:56:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// An empty policy is valid; safe and sensible defaults will be used. 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								type  ConnectionPolicy  struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-10 13:36:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// How to match this policy with a TLS ClientHello. If 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// this policy is the first to match, it will be used. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									MatchersRaw  caddy . ModuleMap  ` json:"match,omitempty" caddy:"namespace=tls.handshake_match" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// How to choose a certificate if more than one matched 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// the given ServerName (SNI) value. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												caddytls: Refactor certificate selection policies (close #1575)
Certificate selection used to be a module, but this seems unnecessary,
especially since the built-in CustomSelectionPolicy allows quite complex
selection logic on a number of fields in certs. If we need to extend
that logic, we can, but I don't think there are SO many possibilities
that we need modules.
This update also allows certificate selection to choose between multiple
matching certs based on client compatibility and makes a number of other
improvements in the default cert selection logic, both here and in the
latest CertMagic.
The hardest part of this was the conn policy consolidation logic
(Caddyfile only, of course). We have to merge connection policies that
we can easily combine, because if two certs are manually loaded in a
Caddyfile site block, that produces two connection policies, and each
cert is tagged with a different tag, meaning only the first would ever
be selected. So given the same matchers, we can merge the two, but this
required improving the Tag selection logic to support multiple tags to
choose from, hence "tags" changed to "any_tag" or "all_tags" (but we
use any_tag in our Caddyfile logic).
Combining conn policies with conflicting settings is impossible, so
that should return an error if two policies with the exact same matchers
have non-empty settings that are not the same (the one exception being
any_tag which we can merge because the logic for them is to OR them).
It was a bit complicated. It seems to work in numerous tests I've
conducted, but we'll see how it pans out in the release candidates.
											 
										 
										
											2020-04-01 20:49:35 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									CertSelection  * CustomCertSelectionPolicy  ` json:"certificate_selection,omitempty" ` 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-10 13:36:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// The list of cipher suites to support. Caddy's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// defaults are modern and secure. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									CipherSuites  [ ] string  ` json:"cipher_suites,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// The list of elliptic curves to support. Caddy's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// defaults are modern and secure. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Curves  [ ] string  ` json:"curves,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Protocols to use for Application-Layer Protocol 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Negotiation (ALPN) during the handshake. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ALPN  [ ] string  ` json:"alpn,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Minimum TLS protocol version to allow. Default: `tls1.2` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ProtocolMin  string  ` json:"protocol_min,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Maximum TLS protocol version to allow. Default: `tls1.3` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ProtocolMax  string  ` json:"protocol_max,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Enables and configures TLS client authentication. 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ClientAuthentication  * ClientAuthentication  ` json:"client_authentication,omitempty" ` 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// DefaultSNI becomes the ServerName in a ClientHello if there 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// is no policy configured for the empty SNI value. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									DefaultSNI  string  ` json:"default_sni,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Also known as "SSLKEYLOGFILE", TLS secrets will be written to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// this file in NSS key log format which can then be parsed by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Wireshark and other tools. This is INSECURE as it allows other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// programs or tools to decrypt TLS connections. However, this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// capability can be useful for debugging and troubleshooting. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// **ENABLING THIS LOG COMPROMISES SECURITY!** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// This feature is EXPERIMENTAL and subject to change or removal. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									InsecureSecretsLog  string  ` json:"insecure_secrets_log,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-15 12:01:58 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TLSConfig is the fully-formed, standard lib TLS config 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// used to serve TLS connections. Provision all 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// ConnectionPolicies to populate this. It is exported only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// so it can be minimally adjusted after provisioning 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// if necessary (like to adjust NextProtos to disable HTTP/2), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// and may be unexported in the future. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									TLSConfig  * tls . Config  ` json:"-" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									matchers  [ ] ConnectionMatcher 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-06-14 11:58:28 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( p  * ConnectionPolicy )  buildStandardTLSConfig ( ctx  caddy . Context )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-16 16:05:38 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									tlsAppIface ,  err  :=  ctx . App ( "tls" ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-29 09:22:00 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "getting tls app: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									tlsApp  :=  tlsAppIface . ( * TLS ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-01 11:47:46 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// fill in some "easy" default values, but for other values 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// (such as slices), we should ensure that they start empty 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// so the user-provided config can fill them in; then we will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// fill in a default config at the end if they are still unset 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									cfg  :=  & tls . Config { 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 14:50:51 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										NextProtos :  p . ALPN , 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										GetCertificate :  func ( hello  * tls . ClientHelloInfo )  ( * tls . Certificate ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// TODO: I don't love how this works: we pre-build certmagic configs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// so that handshakes are faster. Unfortunately, certmagic configs are 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// comprised of settings from both a TLS connection policy and a TLS 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-17 21:00:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// automation policy. The only two fields (as of March 2020; v2 beta 17) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// of a certmagic config that come from the TLS connection policy are 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// CertSelection and DefaultServerName, so an automation policy is what 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// builds the base certmagic config. Since the pre-built config is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// shared, I don't think we can change any of its fields per-handshake, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// hence the awkward shallow copy (dereference) here and the subsequent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// changing of some of its fields. I'm worried this dereference allocates 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// more at handshake-time, but I don't know how to practically pre-build 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// a certmagic config for each combination of conn policy + automation policy... 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg  :=  * tlsApp . getConfigForName ( hello . ServerName ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-01 21:07:38 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  p . CertSelection  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// you would think we could just set this whether or not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// p.CertSelection is nil, but that leads to panics if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// it is, because cfg.CertSelection is an interface, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// so it will have a non-nil value even if the actual 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// value underlying it is nil (sigh) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												cfg . CertSelection  =  p . CertSelection 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 23:15:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											cfg . DefaultServerName  =  p . DefaultSNI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  cfg . GetCertificate ( hello ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										MinVersion :  tls . VersionTLS12 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										MaxVersion :  tls . VersionTLS13 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-29 23:11:46 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// session tickets support 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-30 09:07:43 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  tlsApp . SessionTickets  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . SessionTicketsDisabled  =  tlsApp . SessionTickets . Disabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// session ticket key rotation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										tlsApp . SessionTickets . register ( cfg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ctx . OnCancel ( func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-03 21:33:22 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// do cleanup when the context is canceled because, 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-30 09:07:43 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// though unlikely, it is possible that a context 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// needing a TLS server config could exist for less 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// than the lifetime of the whole app 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											tlsApp . SessionTickets . unregister ( cfg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-29 23:11:46 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TODO: Clean up session ticket active locks in storage if app (or process) is being closed! 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-20 20:36:29 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									// add all the cipher suites in order, without duplicates 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									cipherSuitesAdded  :=  make ( map [ uint16 ] struct { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  csName  :=  range  p . CipherSuites  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-01 14:09:29 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										csID  :=  CipherSuiteID ( csName ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  csID  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  fmt . Errorf ( "unsupported cipher suite: %s" ,  csName ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										if  _ ,  ok  :=  cipherSuitesAdded [ csID ] ;  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cipherSuitesAdded [ csID ]  =  struct { } { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . CipherSuites  =  append ( cfg . CipherSuites ,  csID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// add all the curve preferences in order, without duplicates 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									curvesAdded  :=  make ( map [ tls . CurveID ] struct { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  curveName  :=  range  p . Curves  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-09 12:05:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										curveID  :=  SupportedCurves [ curveName ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										if  _ ,  ok  :=  curvesAdded [ curveID ] ;  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											curvesAdded [ curveID ]  =  struct { } { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . CurvePreferences  =  append ( cfg . CurvePreferences ,  curveID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// ensure ALPN includes the ACME TLS-ALPN protocol 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  alpnFound  bool 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  a  :=  range  p . ALPN  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 15:18:14 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  a  ==  acmez . ACMETLS1Protocol  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
											alpnFound  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! alpnFound  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 15:18:14 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cfg . NextProtos  =  append ( cfg . NextProtos ,  acmez . ACMETLS1Protocol ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// min and max protocol versions 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 19:25:32 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ( p . ProtocolMin  !=  ""  &&  p . ProtocolMax  !=  "" )  &&  p . ProtocolMin  >  p . ProtocolMax  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "protocol min (%x) cannot be greater than protocol max (%x)" ,  p . ProtocolMin ,  p . ProtocolMax ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  p . ProtocolMin  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-09 12:05:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cfg . MinVersion  =  SupportedProtocols [ p . ProtocolMin ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  p . ProtocolMax  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-09 12:05:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cfg . MaxVersion  =  SupportedProtocols [ p . ProtocolMax ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// client authentication 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  p . ClientAuthentication  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  :=  p . ClientAuthentication . ConfigureTLSConfig ( cfg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  fmt . Errorf ( "configuring TLS client authentication: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  p . InsecureSecretsLog  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										filename ,  err  :=  caddy . NewReplacer ( ) . ReplaceOrErr ( p . InsecureSecretsLog ,  true ,  true ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										filename ,  err  =  filepath . Abs ( filename ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										logFile ,  _ ,  err  :=  secretsLogPool . LoadOrNew ( filename ,  func ( )  ( caddy . Destructor ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											w ,  err  :=  os . OpenFile ( filename ,  os . O_WRONLY | os . O_CREATE | os . O_APPEND ,  0600 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  destructableWriter { w } ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ctx . OnCancel ( func ( )  {  _ ,  _  =  secretsLogPool . Delete ( filename )  } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . KeyLogWriter  =  logFile . ( io . Writer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										tlsApp . logger . Warn ( "TLS SECURITY COMPROMISED: secrets logging is enabled!" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											zap . String ( "log_filename" ,  filename ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-01 11:47:46 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									setDefaultTLSParams ( cfg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-15 12:01:58 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									p . TLSConfig  =  cfg 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-05 12:37:52 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SettingsEmpty returns true if p's settings (fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// except the matchers) are all empty/unset. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( p  ConnectionPolicy )  SettingsEmpty ( )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  p . CertSelection  ==  nil  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . CipherSuites  ==  nil  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . Curves  ==  nil  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . ALPN  ==  nil  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . ProtocolMin  ==  ""  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . ProtocolMax  ==  ""  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . ClientAuthentication  ==  nil  && 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										p . DefaultSNI  ==  ""  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										p . InsecureSecretsLog  ==  "" 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-05 12:37:52 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ClientAuthentication configures TLS client auth. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  ClientAuthentication  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// A list of base64 DER-encoded CA certificates 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// against which to validate client certificates. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Client certs which are not signed by any of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// these CAs will be rejected. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									TrustedCACerts  [ ] string  ` json:"trusted_ca_certs,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TrustedCACertPEMFiles is a list of PEM file names 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// from which to load certificates of trusted CAs. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Client certificates which are not signed by any of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// these CA certificates will be rejected. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									TrustedCACertPEMFiles  [ ] string  ` json:"trusted_ca_certs_pem_files,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// DEPRECATED: This field is deprecated and will be removed in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// a future version. Please use the `validators` field instead 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// with the tls.client_auth.leaf module instead. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// A list of base64 DER-encoded client leaf certs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// to accept. If this list is not empty, client certs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// which are not in this list will be rejected. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									TrustedLeafCerts  [ ] string  ` json:"trusted_leaf_certs,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Client certificate verification modules. These can perform 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// custom client authentication checks, such as ensuring the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// certificate is not revoked. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									VerifiersRaw  [ ] json . RawMessage  ` json:"verifiers,omitempty" caddy:"namespace=tls.client_auth inline_key=verifier" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									verifiers  [ ] ClientCertificateVerifier 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-08 16:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// The mode for authenticating the client. Allowed values are: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Mode | Description 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// -----|--------------- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// `request` | Ask clients for a certificate, but allow even if there isn't one; do not verify it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// `require` | Require clients to present a certificate, but do not verify it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// `verify_if_given` | Ask clients for a certificate; allow even if there isn't one, but verify it if there is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// `require_and_verify` | Require clients to present a valid certificate that is verified 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// The default mode is `require_and_verify` if any 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TrustedCACerts or TrustedCACertPEMFiles or TrustedLeafCerts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// are provided; otherwise, the default mode is `require`. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-08 16:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									Mode  string  ` json:"mode,omitempty" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									existingVerifyPeerCert  func ( [ ] [ ] byte ,  [ ] [ ] * x509 . Certificate )  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Active returns true if clientauth has an actionable configuration. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( clientauth  ClientAuthentication )  Active ( )  bool  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  len ( clientauth . TrustedCACerts )  >  0  || 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										len ( clientauth . TrustedCACertPEMFiles )  >  0  || 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										len ( clientauth . TrustedLeafCerts )  >  0  ||  // TODO: DEPRECATED 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										len ( clientauth . VerifiersRaw )  >  0  || 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										len ( clientauth . Mode )  >  0 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ConfigureTLSConfig sets up cfg to enforce clientauth's configuration. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( clientauth  * ClientAuthentication )  ConfigureTLSConfig ( cfg  * tls . Config )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// if there's no actionable client auth, simply disable it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! clientauth . Active ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . ClientAuth  =  tls . NoClientCert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-08 16:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// enforce desired mode of client authentication 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( clientauth . Mode )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										switch  clientauth . Mode  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  "request" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . ClientAuth  =  tls . RequestClientCert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  "require" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . ClientAuth  =  tls . RequireAnyClientCert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  "verify_if_given" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . ClientAuth  =  tls . VerifyClientCertIfGiven 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  "require_and_verify" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . ClientAuth  =  tls . RequireAndVerifyClientCert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										default : 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-05 20:19:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  fmt . Errorf ( "client auth mode not recognized: %s" ,  clientauth . Mode ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-08 16:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// otherwise, set a safe default mode 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  len ( clientauth . TrustedCACerts )  >  0  || 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											len ( clientauth . TrustedCACertPEMFiles )  >  0  || 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											len ( clientauth . TrustedLeafCerts )  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-08 16:48:25 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											cfg . ClientAuth  =  tls . RequireAndVerifyClientCert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											cfg . ClientAuth  =  tls . RequireAnyClientCert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// enforce CA verification by adding CA certs to the ClientCAs pool 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  len ( clientauth . TrustedCACerts )  >  0  ||  len ( clientauth . TrustedCACertPEMFiles )  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										caPool  :=  x509 . NewCertPool ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  _ ,  clientCAString  :=  range  clientauth . TrustedCACerts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											clientCA ,  err  :=  decodeBase64DERCert ( clientCAString ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  fmt . Errorf ( "parsing certificate: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											caPool . AddCert ( clientCA ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  pemFile  :=  range  clientauth . TrustedCACertPEMFiles  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 01:17:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											pemContents ,  err  :=  os . ReadFile ( pemFile ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-11-25 10:53:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  fmt . Errorf ( "reading %s: %v" ,  pemFile ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											caPool . AppendCertsFromPEM ( pemContents ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cfg . ClientCAs  =  caPool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TODO: DEPRECATED: Only here for backwards compatibility. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// If leaf cert is specified, enforce by adding a client auth module 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  len ( clientauth . TrustedLeafCerts )  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										caddy . Log ( ) . Named ( "tls.connection_policy" ) . Warn ( "trusted_leaf_certs is deprecated; use leaf verifier module instead" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  trustedLeafCerts  [ ] * x509 . Certificate 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  clientCertString  :=  range  clientauth . TrustedLeafCerts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											clientCert ,  err  :=  decodeBase64DERCert ( clientCertString ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  fmt . Errorf ( "parsing certificate: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											trustedLeafCerts  =  append ( trustedLeafCerts ,  clientCert ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										clientauth . verifiers  =  append ( clientauth . verifiers ,  LeafCertClientAuth { TrustedLeafCerts :  trustedLeafCerts } ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// if a custom verification function already exists, wrap it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									clientauth . existingVerifyPeerCert  =  cfg . VerifyPeerCertificate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									cfg . VerifyPeerCertificate  =  clientauth . verifyPeerCertificate 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// verifyPeerCertificate is for use as a tls.Config.VerifyPeerCertificate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// callback to do custom client certificate verification. It is intended 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// for installation only by clientauth.ConfigureTLSConfig(). 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( clientauth  * ClientAuthentication )  verifyPeerCertificate ( rawCerts  [ ] [ ] byte ,  verifiedChains  [ ] [ ] * x509 . Certificate )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// first use any pre-existing custom verification function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  clientauth . existingVerifyPeerCert  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  :=  clientauth . existingVerifyPeerCert ( rawCerts ,  verifiedChains ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  verifier  :=  range  clientauth . verifiers  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  :=  verifier . VerifyClientCertificate ( rawCerts ,  verifiedChains ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-03 17:35:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// decodeBase64DERCert base64-decodes, then DER-decodes, certStr. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  decodeBase64DERCert ( certStr  string )  ( * x509 . Certificate ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									derBytes ,  err  :=  base64 . StdEncoding . DecodeString ( certStr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  x509 . ParseCertificate ( derBytes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-01 11:47:46 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// setDefaultTLSParams sets the default TLS cipher suites, protocol versions, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// and server preferences of cfg if they are not already set; it does not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// overwrite values, only fills in missing values. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  setDefaultTLSParams ( cfg  * tls . Config )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( cfg . CipherSuites )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . CipherSuites  =  getOptimalDefaultCipherSuites ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Not a cipher suite, but still important for mitigating protocol downgrade attacks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// (prepend since having it at end breaks http2 due to non-h2-approved suites before it) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									cfg . CipherSuites  =  append ( [ ] uint16 { tls . TLS_FALLBACK_SCSV } ,  cfg . CipherSuites ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( cfg . CurvePreferences )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . CurvePreferences  =  defaultCurves 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  cfg . MinVersion  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . MinVersion  =  tls . VersionTLS12 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  cfg . MaxVersion  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cfg . MaxVersion  =  tls . VersionTLS13 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// LeafCertClientAuth verifies the client's leaf certificate. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  LeafCertClientAuth  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									TrustedLeafCerts  [ ] * x509 . Certificate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// CaddyModule returns the Caddy module information. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( LeafCertClientAuth )  CaddyModule ( )  caddy . ModuleInfo  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  caddy . ModuleInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ID :   "tls.client_auth.leaf" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										New :  func ( )  caddy . Module  {  return  new ( LeafCertClientAuth )  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( l  LeafCertClientAuth )  VerifyClientCertificate ( rawCerts  [ ] [ ] byte ,  _  [ ] [ ] * x509 . Certificate )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( rawCerts )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "no client certificate provided" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									remoteLeafCert ,  err  :=  x509 . ParseCertificate ( rawCerts [ 0 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "can't parse the given certificate: %s" ,  err . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  trustedLeafCert  :=  range  l . TrustedLeafCerts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  remoteLeafCert . Equal ( trustedLeafCert )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  fmt . Errorf ( "client leaf certificate failed validation" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-27 11:31:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// PublicKeyAlgorithm is a JSON-unmarshalable wrapper type. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  PublicKeyAlgorithm  x509 . PublicKeyAlgorithm 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// UnmarshalJSON satisfies json.Unmarshaler. 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-27 11:31:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( a  * PublicKeyAlgorithm )  UnmarshalJSON ( b  [ ] byte )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									algoStr  :=  strings . ToLower ( strings . Trim ( string ( b ) ,  ` " ` ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									algo ,  ok  :=  publicKeyAlgorithms [ algoStr ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "unrecognized public key algorithm: %s (expected one of %v)" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											algoStr ,  publicKeyAlgorithms ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-27 11:31:47 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									* a  =  PublicKeyAlgorithm ( algo ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-24 13:18:45 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-25 13:54:48 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								// ConnectionMatcher is a type which matches TLS handshakes. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  ConnectionMatcher  interface  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Match ( * tls . ClientHelloInfo )  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 19:14:49 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-02 22:25:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ClientCertificateVerifier is a type which verifies client certificates. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// It is called during verifyPeerCertificate in the TLS handshake. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  ClientCertificateVerifier  interface  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									VerifyClientCertificate ( rawCerts  [ ] [ ] byte ,  verifiedChains  [ ] [ ] * x509 . Certificate )  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 19:14:49 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  defaultALPN  =  [ ] string { "h2" ,  "http/1.1" } 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 16:05:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  destructableWriter  struct {  * os . File  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( d  destructableWriter )  Destruct ( )  error  {  return  d . Close ( )  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								var  secretsLogPool  =  caddy . NewUsagePool ( )