Class SessionHelper

    • Field Detail

      • sessionLock

        protected final java.lang.Object sessionLock
        Session level lock for regulating access to sensitive data
      • authStart

        protected java.time.Instant authStart
      • idleStart

        protected java.time.Instant idleStart
      • serverSession

        private final boolean serverSession
        Client or server side
      • ioSession

        private final IoSession ioSession
        The underlying network session
      • properties

        private final java.util.Map<java.lang.String,​java.lang.Object> properties
        The session specific properties
      • timeoutStatus

        private final java.util.concurrent.atomic.AtomicReference<TimeoutIndicator> timeoutStatus
      • username

        private volatile java.lang.String username
        The name of the authenticated user
      • authed

        private volatile boolean authed
        Boolean indicating if this session has been authenticated or not
    • Constructor Detail

      • SessionHelper

        protected SessionHelper​(boolean serverSession,
                                FactoryManager factoryManager,
                                IoSession ioSession)
        Create a new session.
        Parameters:
        serverSession - true if this is a server session, false if client one
        factoryManager - the factory manager
        ioSession - the underlying I/O session
    • Method Detail

      • isServerSession

        public boolean isServerSession()
        Description copied from interface: SessionContext
        Quick indication if this is a server or client session (instead of having to ask instanceof).
        Specified by:
        isServerSession in interface SessionContext
        Returns:
        true if this is a server session
      • getProperties

        public java.util.Map<java.lang.String,​java.lang.Object> getProperties()
        Description copied from interface: PropertyResolver

        A map of properties that can be used to configure the SSH server or client. This map will never be changed by either the server or client and is not supposed to be changed at runtime (changes are not bound to have any effect on a running client or server), though it may affect the creation of sessions later as these values are usually not cached.

        Note: the type of the mapped property should match the expected configuration value type - Long, Integer, Boolean, String, etc.... If it doesn't, the toString() result of the mapped value is used to convert it to the required type. E.g., if the mapped value is the string "1234" and the expected value is a long then it will be parsed into one. Also, if the mapped value is an Integer but a long is expected, then it will be converted into one.

        Specified by:
        getProperties in interface PropertyResolver
        Returns:
        a valid Map containing configuration values, never null. Note: may be immutable.
      • getAttributesCount

        public int getAttributesCount()
        Specified by:
        getAttributesCount in interface AttributeRepository
        Returns:
        Current number of user-defined attributes stored in the repository
      • getAttribute

        public <T> T getAttribute​(AttributeRepository.AttributeKey<T> key)
        Description copied from interface: AttributeRepository
        Returns the value of the user-defined attribute.
        Specified by:
        getAttribute in interface AttributeRepository
        Type Parameters:
        T - The generic attribute type
        Parameters:
        key - The key of the attribute; must not be null.
        Returns:
        null if there is no value associated with the specified key
      • computeAttributeIfAbsent

        public <T> T computeAttributeIfAbsent​(AttributeRepository.AttributeKey<T> key,
                                              java.util.function.Function<? super AttributeRepository.AttributeKey<T>,​? extends T> resolver)
        Description copied from interface: AttributeStore
        If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
        Specified by:
        computeAttributeIfAbsent in interface AttributeStore
        Type Parameters:
        T - The generic attribute type
        Parameters:
        key - The key of the attribute; must not be null.
        resolver - The (never null) mapping function to use if value not already mapped. If returns null then value is not mapped to the provided key.
        Returns:
        The resolved value - null if value not mapped and resolver did not return a non-null value for it
      • setAttribute

        public <T> T setAttribute​(AttributeRepository.AttributeKey<T> key,
                                  T value)
        Description copied from interface: AttributeStore
        Sets a user-defined attribute.
        Specified by:
        setAttribute in interface AttributeStore
        Type Parameters:
        T - The generic attribute type
        Parameters:
        key - The key of the attribute; must not be null.
        value - The value of the attribute; must not be null.
        Returns:
        The old value of the attribute; null if it is new.
      • removeAttribute

        public <T> T removeAttribute​(AttributeRepository.AttributeKey<T> key)
        Description copied from interface: AttributeStore
        Removes the user-defined attribute
        Specified by:
        removeAttribute in interface AttributeStore
        Type Parameters:
        T - The generic attribute type
        Parameters:
        key - The key of the attribute; must not be null.
        Returns:
        The removed value; null if no previous value
      • getUsername

        public java.lang.String getUsername()
        Specified by:
        getUsername in interface UsernameHolder
        Returns:
        The attached username - may be null/empty if holder not yet initialized
      • isAuthenticated

        public boolean isAuthenticated()
        Specified by:
        isAuthenticated in interface SessionContext
        Returns:
        true if session has successfully completed the authentication phase
      • setAuthenticated

        public void setAuthenticated()
                              throws java.io.IOException
        Specified by:
        setAuthenticated in interface Session
        Throws:
        java.io.IOException
      • getAuthTimeoutStart

        public java.time.Instant getAuthTimeoutStart()
        Specified by:
        getAuthTimeoutStart in interface Session
        Returns:
        The timestamp value (milliseconds since EPOCH) when timer was started
      • resetAuthTimeout

        public java.time.Instant resetAuthTimeout()
        Description copied from interface: Session
        Re-start the authentication timeout timer
        Specified by:
        resetAuthTimeout in interface Session
        Returns:
        The timestamp value (milliseconds since EPOCH) when timer was started
        See Also:
        Session.getAuthTimeoutStart()
      • checkAuthenticationTimeout

        protected TimeoutIndicator checkAuthenticationTimeout​(java.time.Instant now,
                                                              java.time.Duration authTimeout)
        Checks if authentication timeout expired
        Parameters:
        now - The current time in millis
        authTimeout - The configured timeout - if non-positive then no timeout
        Returns:
        A TimeoutIndicator specifying the timeout status and disconnect reason message if timeout expired, null or NoTimeout if no timeout occurred
        See Also:
        getAuthTimeout()
      • getIdleTimeoutStart

        public java.time.Instant getIdleTimeoutStart()
        Specified by:
        getIdleTimeoutStart in interface Session
        Returns:
        The timestamp value (milliseconds since EPOCH) when timer was started
      • checkIdleTimeout

        protected TimeoutIndicator checkIdleTimeout​(java.time.Instant now,
                                                    java.time.Duration idleTimeout)
        Checks if idle timeout expired
        Parameters:
        now - The current time in millis
        idleTimeout - The configured timeout - if non-positive then no timeout
        Returns:
        A TimeoutIndicator specifying the timeout status and disconnect reason message if timeout expired, null or NoTimeout if no timeout occurred
        See Also:
        getIdleTimeout()
      • resetIdleTimeout

        public java.time.Instant resetIdleTimeout()
        Description copied from interface: Session
        Re-start idle timeout timer
        Specified by:
        resetIdleTimeout in interface Session
        Returns:
        The timestamp value (milliseconds since EPOCH) when timer was started
        See Also:
        Session.getIdleTimeoutStart()
      • getTimeoutStatus

        public TimeoutIndicator getTimeoutStatus()
        Description copied from interface: Session
        Check if timeout has occurred.
        Specified by:
        getTimeoutStatus in interface Session
        Returns:
        the timeout status - never null
      • handleIgnore

        protected void handleIgnore​(Buffer buffer)
                             throws java.lang.Exception
        Throws:
        java.lang.Exception
      • doInvokeIgnoreMessageHandler

        protected void doInvokeIgnoreMessageHandler​(Buffer buffer)
                                             throws java.lang.Exception
        Invoked by handleDebug(Buffer) after validating that the buffer structure seems well-formed and also resetting the idle timeout. By default, retrieves the ReservedSessionMessagesHandler and invokes its handleIgnoreMessage method.
        Parameters:
        buffer - The input Buffer
        Throws:
        java.lang.Exception - if failed to handle the message
      • sendNotImplemented

        protected IoWriteFuture sendNotImplemented​(long seqNoValue)
                                            throws java.io.IOException
        Sends a SSH_MSG_UNIMPLEMENTED message
        Parameters:
        seqNoValue - The referenced sequence number
        Returns:
        An IoWriteFuture that can be used to wait for packet write completion
        Throws:
        java.io.IOException - if an error occurred sending the packet
      • handleUnimplemented

        protected void handleUnimplemented​(Buffer buffer)
                                    throws java.lang.Exception
        Throws:
        java.lang.Exception
      • doInvokeUnimplementedMessageHandler

        protected boolean doInvokeUnimplementedMessageHandler​(int cmd,
                                                              Buffer buffer)
                                                       throws java.lang.Exception
        Parameters:
        cmd - The unimplemented command
        buffer - The input Buffer
        Returns:
        Result of invoking handleUnimplementedMessage
        Throws:
        java.lang.Exception - if failed to handle the message
      • sendDebugMessage

        public IoWriteFuture sendDebugMessage​(boolean display,
                                              java.lang.Object msg,
                                              java.lang.String lang)
                                       throws java.io.IOException
        Description copied from interface: Session
        Sends an SSH_MSG_DEBUG to the peer session
        Specified by:
        sendDebugMessage in interface Session
        Parameters:
        display - true if OK to display the message at the peer as-is
        msg - The message object whose toString() value to be used - if null then the "null" string is sent
        lang - The language - null/empty if some pre-agreed default is used
        Returns:
        An IoWriteFuture that can be used to check when the packet has actually been sent
        Throws:
        java.io.IOException - if an error occurred when encoding or sending the packet
        See Also:
        RFC 4253 - section 11.3
      • handleDebug

        protected void handleDebug​(Buffer buffer)
                            throws java.lang.Exception
        Throws:
        java.lang.Exception
      • doInvokeDebugMessageHandler

        protected void doInvokeDebugMessageHandler​(Buffer buffer)
                                            throws java.lang.Exception
        Invoked by handleDebug(Buffer) after validating that the buffer structure seems well-formed and also resetting the idle timeout. By default, retrieves the ReservedSessionMessagesHandler and invokes its handleDebugMessage method.
        Parameters:
        buffer - The input Buffer
        Throws:
        java.lang.Exception - if failed to handle the message
      • sendIgnoreMessage

        public IoWriteFuture sendIgnoreMessage​(byte... data)
                                        throws java.io.IOException
        Description copied from interface: Session
        Sends an SSH_MSG_IGNORE to the peer session
        Specified by:
        sendIgnoreMessage in interface Session
        Parameters:
        data - The message data
        Returns:
        An IoWriteFuture that can be used to check when the packet has actually been sent
        Throws:
        java.io.IOException - if an error occurred when encoding or sending the packet
        See Also:
        RFC 4253 - section 11.2
      • writePacket

        public IoWriteFuture writePacket​(Buffer buffer,
                                         long timeout,
                                         java.util.concurrent.TimeUnit unit)
                                  throws java.io.IOException
        Description copied from interface: Session
        Encode and send the given buffer with the specified timeout. If the buffer could not be written before the timeout elapses, the returned IoWriteFuture will be set with a TimeoutException exception to indicate a timeout.
        Specified by:
        writePacket in interface Session
        Parameters:
        buffer - the buffer to encode and spend
        timeout - the timeout
        unit - the time unit of the timeout parameter
        Returns:
        a future that can be used to check when the packet has actually been sent
        Throws:
        java.io.IOException - if an error occurred when encoding or sending the packet
      • signalSessionEstablished

        protected void signalSessionEstablished​(IoSession ioSession)
                                         throws java.lang.Exception
        Throws:
        java.lang.Exception
      • signalSessionEstablished

        protected void signalSessionEstablished​(SessionListener listener)
      • signalSessionCreated

        protected void signalSessionCreated​(IoSession ioSession)
                                     throws java.lang.Exception
        Throws:
        java.lang.Exception
      • signalSessionCreated

        protected void signalSessionCreated​(SessionListener listener)
      • signalSendIdentification

        protected void signalSendIdentification​(java.lang.String version,
                                                java.util.List<java.lang.String> extraLines)
                                         throws java.lang.Exception
        Throws:
        java.lang.Exception
      • signalSendIdentification

        protected void signalSendIdentification​(SessionListener listener,
                                                java.lang.String version,
                                                java.util.List<java.lang.String> extraLines)
      • signalReadPeerIdentificationLine

        protected void signalReadPeerIdentificationLine​(java.lang.String line,
                                                        java.util.List<java.lang.String> extraLines)
                                                 throws java.lang.Exception
        Throws:
        java.lang.Exception
      • signalReadPeerIdentificationLine

        protected void signalReadPeerIdentificationLine​(SessionListener listener,
                                                        java.lang.String version,
                                                        java.util.List<java.lang.String> extraLines)
      • signalPeerIdentificationReceived

        protected void signalPeerIdentificationReceived​(java.lang.String version,
                                                        java.util.List<java.lang.String> extraLines)
                                                 throws java.lang.Exception
        Throws:
        java.lang.Exception
      • signalPeerIdentificationReceived

        protected void signalPeerIdentificationReceived​(SessionListener listener,
                                                        java.lang.String version,
                                                        java.util.List<java.lang.String> extraLines)
      • signalSessionEvent

        protected void signalSessionEvent​(SessionListener.Event event)
                                   throws java.lang.Exception
        Sends a session event to all currently registered session listeners
        Parameters:
        event - The event to send
        Throws:
        java.lang.Exception - If any of the registered listeners threw an exception.
      • invokeSessionSignaller

        protected void invokeSessionSignaller​(Invoker<SessionListener,​java.lang.Void> invoker)
                                       throws java.lang.Throwable
        Throws:
        java.lang.Throwable
      • resizeKey

        protected byte[] resizeKey​(byte[] e,
                                   int kdfSize,
                                   Digest hash,
                                   byte[] k,
                                   byte[] h)
                            throws java.lang.Exception
        Method used while putting new keys into use that will resize the key used to initialize the cipher to the needed length.
        Parameters:
        e - the key to resize
        kdfSize - the cipher key-derivation-factor (in bytes)
        hash - the hash algorithm
        k - the key exchange k parameter
        h - the key exchange h parameter
        Returns:
        the resized key
        Throws:
        java.lang.Exception - if a problem occur while resizing the key
      • resolvePeerAddress

        protected java.net.SocketAddress resolvePeerAddress​(java.net.SocketAddress knownAddress)
        Parameters:
        knownAddress - Any externally set peer address - e.g., due to some proxy mechanism meta-data
        Returns:
        The external address if not null otherwise, the IoSession peer address
      • calculateNextIgnorePacketCount

        protected long calculateNextIgnorePacketCount​(Random r,
                                                      long freq,
                                                      int variance)
      • resolveIdentificationString

        protected java.lang.String resolveIdentificationString​(java.lang.String configPropName)
        Resolves the identification to send to the peer session by consulting the associated FactoryManager. If a value is set, then it is appended to the standard SessionContext.DEFAULT_SSH_VERSION_PREFIX. Otherwise a default value is returned consisting of the prefix and the core artifact name + version in uppercase - e.g.,' "SSH-2.0-APACHE-SSHD-1.2.3.4"
        Parameters:
        configPropName - The property used to query the factory manager
        Returns:
        The resolved identification value
      • sendIdentification

        protected IoWriteFuture sendIdentification​(java.lang.String version,
                                                   java.util.List<java.lang.String> extraLines)
                                            throws java.lang.Exception
        Send our identification.
        Parameters:
        version - our identification to send
        extraLines - Extra lines to send - used only by server sessions
        Returns:
        IoWriteFuture that can be used to wait for notification that identification has been send
        Throws:
        java.lang.Exception - If failed to send the packet
      • doReadIdentification

        protected java.util.List<java.lang.String> doReadIdentification​(Buffer buffer,
                                                                        boolean server)
                                                                 throws java.lang.Exception
        Read the remote identification from this buffer. If more data is needed, the buffer will be reset to its original state and a null value will be returned. Else the identification string will be returned and the data read will be consumed from the buffer.
        Parameters:
        buffer - the buffer containing the identification string
        server - true if it is called by the server session, false if by the client session
        Returns:
        A List of all received remote identification lines until the version line was read or null if more data is needed. The identification line is the last one in the list
        Throws:
        java.lang.Exception - if malformed identification found
      • resolveSessionKexProposal

        protected java.lang.String resolveSessionKexProposal​(java.lang.String hostKeyTypes)
                                                      throws java.io.IOException
        Throws:
        java.io.IOException
      • createProposal

        protected java.util.Map<KexProposalOption,​java.lang.String> createProposal​(java.lang.String hostKeyTypes)
                                                                                  throws java.io.IOException
        Create our proposal for SSH negotiation
        Parameters:
        hostKeyTypes - The comma-separated list of supported host key types
        Returns:
        The proposal Map
        Throws:
        java.io.IOException - If internal problem - e.g., KEX extensions negotiation issue
      • signalNegotiationOptionsCreated

        protected void signalNegotiationOptionsCreated​(java.util.Map<KexProposalOption,​java.lang.String> proposal)
      • signalNegotiationOptionsCreated

        protected void signalNegotiationOptionsCreated​(SessionListener listener,
                                                       java.util.Map<KexProposalOption,​java.lang.String> proposal)
      • signalNegotiationStart

        protected void signalNegotiationStart​(java.util.Map<KexProposalOption,​java.lang.String> c2sOptions,
                                              java.util.Map<KexProposalOption,​java.lang.String> s2cOptions)
      • signalNegotiationEnd

        protected void signalNegotiationEnd​(java.util.Map<KexProposalOption,​java.lang.String> c2sOptions,
                                            java.util.Map<KexProposalOption,​java.lang.String> s2cOptions,
                                            java.util.Map<KexProposalOption,​java.lang.String> negotiatedGuess,
                                            java.lang.Throwable reason)
      • preProcessEncodeBuffer

        protected Buffer preProcessEncodeBuffer​(int cmd,
                                                Buffer buffer)
                                         throws java.io.IOException
        Invoked by the session before encoding the buffer in order to make sure that it is at least of size SSH_PACKET_HEADER_LEN. This is required in order to efficiently handle the encoding. If necessary, it re-allocates a new buffer and returns it instead.
        Parameters:
        cmd - The command stored in the buffer
        buffer - The original Buffer - assumed to be properly formatted and be of at least the required minimum length.
        Returns:
        The adjusted Buffer. Note: users may use this method to totally alter the contents of the buffer being sent but it is highly discouraged as it may have unexpected results.
        Throws:
        java.io.IOException - If failed to process the buffer
      • disconnect

        public void disconnect​(int reason,
                               java.lang.String msg)
                        throws java.io.IOException
        Description copied from interface: Session
        Send a disconnect packet with the given reason and message. Once the packet has been sent, the session will be closed asynchronously.
        Specified by:
        disconnect in interface Session
        Parameters:
        reason - the reason code for this disconnect
        msg - the text message
        Throws:
        java.io.IOException - if an error occurred sending the packet
      • handleDisconnect

        protected void handleDisconnect​(Buffer buffer)
                                 throws java.lang.Exception
        Throws:
        java.lang.Exception
      • handleDisconnect

        protected void handleDisconnect​(int code,
                                        java.lang.String msg,
                                        java.lang.String lang,
                                        Buffer buffer)
                                 throws java.lang.Exception
        Throws:
        java.lang.Exception
      • signalDisconnect

        protected void signalDisconnect​(int code,
                                        java.lang.String msg,
                                        java.lang.String lang,
                                        boolean initiator)
      • signalDisconnect

        protected void signalDisconnect​(SessionListener listener,
                                        int code,
                                        java.lang.String msg,
                                        java.lang.String lang,
                                        boolean initiator)
      • exceptionCaught

        public void exceptionCaught​(java.lang.Throwable t)
        Handle any exceptions that occurred on this session. The session will be closed and a disconnect packet will be sent before if the given exception is an SshException.
        Specified by:
        exceptionCaught in interface Session
        Parameters:
        t - the exception to process
      • signalExceptionCaught

        protected void signalExceptionCaught​(java.lang.Throwable t)
      • signalExceptionCaught

        protected void signalExceptionCaught​(SessionListener listener,
                                             java.lang.Throwable t)
      • signalSessionClosed

        protected void signalSessionClosed()
      • signalSessionClosed

        protected void signalSessionClosed​(SessionListener listener)
      • getForwarder

        protected Forwarder getForwarder()
      • getAuthTimeout

        public java.time.Duration getAuthTimeout()
        Specified by:
        getAuthTimeout in interface Session
        Returns:
        Timeout value in milliseconds for authentication stage
      • getIdleTimeout

        public java.time.Duration getIdleTimeout()
        Specified by:
        getIdleTimeout in interface Session
        Returns:
        Timeout value in milliseconds for communication
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object