55
66use std:: collections:: HashMap ;
77use std:: convert:: Infallible ;
8+ use std:: fs;
9+ use std:: io:: { Read , Write } ;
810use std:: net:: { IpAddr , Ipv4Addr , SocketAddr } ;
911use std:: path:: { Path , PathBuf } ;
1012use std:: sync:: { Arc , Mutex } ;
@@ -13,7 +15,6 @@ use std::time::{Duration, Instant};
1315use const_format:: concatcp;
1416use hyper:: service:: { make_service_fn, service_fn} ;
1517use hyper:: { Body , Request , Response , Server } ;
16- use tempfile:: { tempdir, TempDir } ;
1718use tokio:: io:: { AsyncBufReadExt , BufReader } ;
1819use tokio:: pin;
1920
@@ -77,21 +78,15 @@ pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result<i3
7778 legal:: require_consent ( & ctx. paths , args. accept_server_license_terms ) ?;
7879
7980 let platform: crate :: update_service:: Platform = PreReqChecker :: new ( ) . verify ( ) . await ?;
80- let token_file = if !args. without_connection_token {
81+ if !args. without_connection_token {
8182 // Ensure there's a defined connection token, since if multiple server versions
8283 // are excuted, they will need to have a single shared token.
83- let connection_token = args
84- . connection_token
85- . clone ( )
86- . unwrap_or_else ( || uuid:: Uuid :: new_v4 ( ) . to_string ( ) ) ;
87- let tf = ConnectionTokenFile :: new ( & connection_token)
84+ let token_path = ctx. paths . root ( ) . join ( "serve-web-token" ) ;
85+ let token = mint_connection_token ( & token_path, args. connection_token . clone ( ) )
8886 . map_err ( CodeError :: CouldNotCreateConnectionTokenFile ) ?;
89- args. connection_token = Some ( connection_token) ;
90- args. connection_token_file = Some ( tf. path ( ) . to_string_lossy ( ) . to_string ( ) ) ;
91- Some ( tf)
92- } else {
93- None
94- } ;
87+ args. connection_token = Some ( token) ;
88+ args. connection_token_file = Some ( token_path. to_string_lossy ( ) . to_string ( ) ) ;
89+ }
9590
9691 let cm = ConnectionManager :: new ( & ctx, platform, args. clone ( ) ) ;
9792 let key = get_server_key_half ( & ctx. paths ) ;
@@ -143,7 +138,6 @@ pub async fn serve_web(ctx: CommandContext, mut args: ServeWebArgs) -> Result<i3
143138 } ;
144139
145140 r. map_err ( CodeError :: CouldNotListenOnInterface ) ?;
146- drop ( token_file) ; // ensure it lives long enough
147141
148142 Ok ( 0 )
149143}
@@ -789,20 +783,29 @@ struct StartArgs {
789783 opener : BarrierOpener < Result < StartData , String > > ,
790784}
791785
792- struct ConnectionTokenFile {
793- path : PathBuf ,
794- _dir : TempDir , // implements Drop to delete the dir
795- }
796-
797- impl ConnectionTokenFile {
798- fn new ( connection_token : & str ) -> std:: io:: Result < Self > {
799- let d = tempdir ( ) ?;
800- let path = d. path ( ) . join ( "connection-token" ) ;
801- std:: fs:: write ( & path, connection_token) ?;
802- Ok ( ConnectionTokenFile { path, _dir : d } )
786+ fn mint_connection_token ( path : & Path , prefer_token : Option < String > ) -> std:: io:: Result < String > {
787+ #[ cfg( not( windows) ) ]
788+ use std:: os:: unix:: fs:: OpenOptionsExt ;
789+
790+ let mut f = fs:: OpenOptions :: new ( ) ;
791+ f. create ( true ) ;
792+ f. write ( true ) ;
793+ f. read ( true ) ;
794+ #[ cfg( not( windows) ) ]
795+ f. mode ( 0o600 ) ;
796+ let mut f = f. open ( path) ?;
797+
798+ if prefer_token. is_none ( ) {
799+ let mut t = String :: new ( ) ;
800+ f. read_to_string ( & mut t) ?;
801+ let t = t. trim ( ) ;
802+ if !t. is_empty ( ) {
803+ return Ok ( t. to_string ( ) ) ;
804+ }
803805 }
804806
805- fn path ( & self ) -> & Path {
806- & self . path
807- }
807+ f. set_len ( 0 ) ?;
808+ let prefer_token = prefer_token. unwrap_or_else ( || uuid:: Uuid :: new_v4 ( ) . to_string ( ) ) ;
809+ f. write_all ( prefer_token. as_bytes ( ) ) ?;
810+ Ok ( prefer_token)
808811}
0 commit comments