1313 *)  
1414(*  Copyright (C) 2007 XenSource Inc *) 
1515
16+ module  D = Debug. Make (struct  let  name= " stunnel" end )
17+ open  D 
18+ 
1619open  Printf 
1720open  Pervasiveext 
1821open  Xstringext 
@@ -33,6 +36,11 @@ let stunnel_logger = ref ignore
3336
3437let  timeoutidle =  ref  None 
3538
39+ let  legacy_protocol_and_ciphersuites_allowed =  ref  true 
40+ 
41+ let  is_legacy_protocol_and_ciphersuites_allowed  ()  = 
42+ 	! legacy_protocol_and_ciphersuites_allowed
43+ 
3644let  init_stunnel_path  ()  = 
3745	try  cached_stunnel_path :=  Some  (Unix. getenv " XE_STUNNEL" 
3846	with  Not_found  -> 
@@ -116,50 +124,83 @@ type t = { mutable pid: pid; fd: Unix.file_descr; host: string; port: int;
116124	   unique_id : int  option ; 
117125	   mutable  logfile : string ; 
118126	   verified : bool ; 
127+ 	   legacy : bool ; 
119128	 }
120129
121- let  config_file  verify_cert  extended_diagnosis  host  port  =  
122- 	let  lines =  [" client=yes" " foreground=yes" " socket = r:TCP_NODELAY=1" " socket = r:SO_KEEPALIVE=1" " socket = a:SO_KEEPALIVE=1" 
123- 							 (match  ! timeoutidle with  None  ->  " " |  Some  x  ->  Printf. sprintf " TIMEOUTidle = %d" 
124- 							 Printf. sprintf " connect=%s:%d" @ 
125-     (if  extended_diagnosis then 
126-        [" debug=4" 
127-      else 
128-        [] ) @ 
129-     (if  verify_cert then 
130-        [" verify=2" 
131-         sprintf " CApath=%s" 
132-         sprintf " CRLpath=%s" 
133-      else 
134-        [] )
130+ let  config_file  verify_cert  extended_diagnosis  host  port  legacy  = 
131+ 
132+     let  good_ciphers =  " !EXPORT:TLSv1.2" in 
133+     let  back_compat_ciphers =  " RSA+AES256-SHA:RSA+AES128-SHA:RSA+RC4-SHA:RSA+RC4-MD5:RSA+DES-CBC3-SHA" in 
134+ 
135+ 	let  lines =  [
136+ 		" client=yes" " foreground=yes" " socket = r:TCP_NODELAY=1" " socket = r:SO_KEEPALIVE=1" " socket = a:SO_KEEPALIVE=1" 
137+ 		(match  ! timeoutidle with  None  ->  " " |  Some  x  ->  Printf. sprintf " TIMEOUTidle = %d" 
138+ 		Printf. sprintf " connect=%s:%d" 
139+ 		" fips = no" (*  stunnel fips-mode stops us using sslVersion other than TLSv1 which means 1.0 only. *) 
140+ 	] @ 	(if  extended_diagnosis then 
141+ 			[" debug=4" 
142+ 		else 
143+ 			[] 
144+ 	) @  (
145+ 		if  verify_cert then 
146+ 			[" verify=2" 
147+ 			sprintf " CApath=%s" 
148+ 			sprintf " CRLpath=%s" 
149+ 		else 
150+ 			[] 
151+ 	) @  (
152+ 		if  legacy then  [
153+ 			" sslVersion = all" 
154+ 			" options = NO_SSLv2" 
155+ 			" options = NO_SSLv3" 
156+ 			" ciphers = " ^  good_ciphers ^  " :" ^  back_compat_ciphers;
157+ 		] else  [
158+ 			" sslVersion = TLSv1.2" 
159+ 			" ciphers = " ^  good_ciphers;
160+ 		]
161+ 	)
135162  in 
136163    String. concat " " List. map (fun  x  -> x ^  " \n " 
137164
165+ let  set_legacy_protocol_and_ciphersuites_allowed  b  = 
166+ 	legacy_protocol_and_ciphersuites_allowed :=  b;
167+ 	info " legacy-config %B; example: %s" 
168+ 		(String. escaped (config_file false  false  " dummyhost" 443  b))
169+ 
138170let  ignore_exn  f  x  =  try  f x with  _  ->  () 
139171
140- let  rec  disconnect  ?(wait  = true )  ?(force  = false )  x  =   
172+ let  rec  disconnect  ?(wait  = true )  ?(force  = false )  x  = 
141173  List. iter (ignore_exn Unix. close) [ x.fd ];
142-   let  waiter, pid =  match  x.pid with 
143-     |  FEFork  pid  ->
144-         (fun  ()  -> 
145-            (if  wait then  Forkhelpers. waitpid 
146-             else  Forkhelpers. waitpid_nohang) pid),
147-         Forkhelpers. getpid pid
148-     |  StdFork  pid  -> 
149-         (fun  ()  -> 
150-            (if  wait then  Unix. waitpid []  
151-             else  Unix. waitpid [Unix. WNOHANG ]) pid),
152-         pid in 
153-   let  res =  
154-     try  waiter () 
155-     with  Unix. Unix_error  (Unix. ECHILD, _ , _ ) ->  pid, Unix. WEXITED  0  in 
156-   match  res with 
157-   |  0 , _  when  force ->
158-       (try  Unix. kill pid Sys. sigkill 
159-        with  Unix. Unix_error  (Unix. ESRCH, _ , _ ) -> () );
160-       disconnect ~wait: wait ~force: force x
161-   |  _  -> () 
162174
175+   let  do_disc  waiter  pid  = 
176+     let  res = 
177+       try  waiter () 
178+       with  Unix. Unix_error  (Unix. ECHILD, _ , _ ) ->  pid, Unix. WEXITED  0  in 
179+     match  res with 
180+     |  0 , _  when  force ->
181+         (try  Unix. kill pid Sys. sigkill 
182+          with  Unix. Unix_error  (Unix. ESRCH, _ , _ ) -> () );
183+         disconnect ~wait: wait ~force: force x
184+     |  _  -> () 
185+   in 
186+   let  verbose =  x.legacy &&  not  (! legacy_protocol_and_ciphersuites_allowed) in 
187+   match  x.pid with 
188+     |  FEFork  fpid  ->
189+         let  pid_int =  Forkhelpers. getpid fpid in 
190+         if  verbose then  info " Disconnecting FEFork %d" 
191+         do_disc
192+           (fun  ()  ->
193+              (if  wait then  Forkhelpers. waitpid 
194+               else  Forkhelpers. waitpid_nohang) fpid)
195+           pid_int
196+     |  StdFork  pid  ->
197+         if  verbose then  info " Disconnecting StdFork %d" 
198+         do_disc
199+           (fun  ()  ->
200+              (if  wait then  Unix. waitpid [] 
201+               else  Unix. waitpid [Unix. WNOHANG ]) pid)
202+           pid
203+     |  Nopid  -> if  verbose then  info " Disconnecting Nopid" 
163204
164205(*  With some probability, stunnel fails during its startup code before it reads
165206   the config data from us. Therefore we get a SIGPIPE writing the config data. 
@@ -189,10 +230,13 @@ let attempt_one_connect ?unique_id ?(use_fork_exec_helper = true)
189230      [" -fd" if  use_fork_exec_helper then  config_out_uuid else  config_out_fd] 
190231    end  in  
191232  let  data_out,data_in =  Unix. socketpair Unix. PF_UNIX  Unix. SOCK_STREAM  0  in  
233+   (*  Dereference just once to ensure we are consistent in t and config_file *)  
234+   let  legacy =  ! legacy_protocol_and_ciphersuites_allowed in  
192235  let  t =   
193236    { pid =  Nopid ; fd =  data_out; host =  host; port =  port;  
194237      connected_time =  Unix. gettimeofday () ; unique_id =  unique_id;  
195-       logfile =  " " =  verify_cert } in  
238+       logfile =  " " =  verify_cert; 
239+ 	  legacy =  legacy } in  
196240  let  result =  Forkhelpers. with_logfile_fd " stunnel"  
197241    ~delete: (not  extended_diagnosis) 
198242    (fun  logfd  -> 
@@ -218,7 +262,7 @@ let attempt_one_connect ?unique_id ?(use_fork_exec_helper = true)
218262	       (fun  ()  -> 
219263            match  config_in with  
220264            |  Some  fd  -> begin  
221- 	              let  config =  config_file verify_cert extended_diagnosis host port in  
265+ 	              let  config =  config_file verify_cert extended_diagnosis host port legacy  in  
222266	              (*  Catch the occasional initialisation failure of stunnel: *)  
223267	              try  
224268	                let  n =  Unix. write fd config 0  (String. length config) in  
0 commit comments