@ FFDCIgnore ( { IOException . class } ) private boolean acceptAndExecuteCommand ( ) { boolean socketValid = false ; try { //exceptions thrown by accept are assumed to mean the channel is no longer usable. SocketChannel sc = serverSocketChannel . accept ( ) ; socketValid = true ; if ( sc != null ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "accepted socket" , sc ) ; } try { String uuidAndCommand = read ( sc ) ; ServerCommandID commandID = new ServerCommandID ( uuidAndCommand ) ; String command = commandID . getOperation ( ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { // Don't trace uuidAndCommand to avoid putting it in logs // (not as secure as the workarea). Tr . debug ( tc , "read UUID and command" , command ) ; } // As a first level of security, require that the user has read access to the .sCommand file. if ( ! commandID . validate ( ) ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "invalid UUID" , uuidAndCommand ) ; } } else { // As a second level of security, ensure that the client has write access to the workarea. We do // this because by default, many umasks create world-readable files, which means everyone on a // system can read the .sCommand file. // // Generate a unique filename in .sCommandAuth and request that the client create the named file. String authID ; File authFile ; do { authID = Integer . toString ( nextCommandAuthID ++ ) ; authFile = new File ( commandAuthDir , authID ) ; } while ( authFile . exists ( ) ) ; // The server is going to create the file (to ensure server ownership bits are preserved), authFile . createNewFile ( ) ; // write the authId: the client will delete the file to prove write-access write ( sc , authID ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "wrote authorization challenge" , authID , authFile ) ; } // Read the response: the caller should have deleted the file. String authIDResponse = read ( sc ) ; if ( ! authIDResponse . equals ( authID ) || authFile . exists ( ) ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "authorization failed" ) ; } } else { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "authorization succeeded" ) ; } sc = executeCommand ( sc , command ) ; } } } finally { // Close the socket: one command per connection. Utils . tryToClose ( sc ) ; } } } catch ( IOException ex ) { // FFDCIgnore of IOExceptions: some expected due to async close } catch ( Throwable t ) { // Don't allow an exception from a single command to // break the entire command listener. } return socketValid ; }
Read and execute a command from the server socket