Skip to content

String reference not set to an instance of a String. Parameter name: s - version 2020.0.2 #1237

Closed

Description

@amitbarkai

Hi All

i am using version 2020.0.2 and getting the following exception while trying to connect to linux machine

System.ArgumentNullException: String reference not set to an instance of a String.

Parameter name: s

at Renci.SshNet.KeyboardInteractiveAuthenticationMethod.Authenticate(Session session)

at Renci.SshNet.ClientAuthentication.TryAuthenticate(ISession session, AuthenticationState authenticationState, String[] allowedAuthenticationMethods, SshAuthenticationException& authenticationException)

at Renci.SshNet.ClientAuthentication.Authenticate(IConnectionInfoInternal connectionInfo, ISession session)

at Renci.SshNet.ConnectionInfo.Authenticate(ISession session, IServiceFactory serviceFactory)

at Renci.SshNet.Session.Connect()

at Renci.SshNet.BaseClient.CreateAndConnectSession()

at Renci.SshNet.BaseClient.Connect()

when trying to connect vis Putty everything works just fine.

` var keyboardAuth = new KeyboardInteractiveAuthenticationMethod(username);
keyboardAuth.AuthenticationPrompt += keyboardAuthentication_AuthenticationPrompt;

            var passwordAuth = new Renci.SshNet.PasswordAuthenticationMethod(username, password.GetStringFromSecureString());

            var connectionInfo = new Renci.SshNet.ConnectionInfo(machine.Address, port, username, keyboardAuth, passwordAuth);
            connectionInfo.Timeout = connectionTimeout;

            _client = new Renci.SshNet.SshClient(connectionInfo);

_client.Connect()`

could you please explain what is happening here?

Activity

  1. amitbarkai commented on Nov 16, 2023

    @amitbarkai
    Author

    i think i've found the issue which might point to a BUG
    in my case the authentication method order was :

    • keyboard-interactive
    • username password

    code example :
    `
    // Create KeyboardInteractiveAuthenticationMethod
    var keyboardAuth = new KeyboardInteractiveAuthenticationMethod(username);
    keyboardAuth.AuthenticationPrompt += keyboardAuthentication_AuthenticationPrompt;

        // Create ConnectionInfo with both authentication methods
        var connectionInfo = new ConnectionInfo(host, port, username, keyboardAuth, passwordAuth);
    

    `

    when there is an issue / authentication method not defined
    "If there is no prompt defined on the server for keyboard-interactive authentication, it could potentially lead to authentication failures, but it's not the typical cause for a NullReferenceException within the SSH.NET"

    when i've change the order / removed the user interactive everything worked fine

  2. lifeincha0s commented on Nov 17, 2023

    @lifeincha0s

    I came across this same issue when I was implementing some of the more recent updates to the library. It has since been fixed in the latest builds. I started with a 2016.x.x version (in 2017) and I highly modified the library to meet my specific needs. The commit "Allow for easier troubleshooting of protocol version exchange." broke it. The issue stems from Session.Connect().

    Prior to 2020.x.x:

    // Set connection versions
    ConnectionInfo.ServerVersion = ServerVersion; // where ServerVersion is initialized in while loop prior
    ConnectionInfo.ClientVersion = ClientVersion;
    

    2020.x.x

    // Set connection versions
    ConnectionInfo.ServerVersion = serverIdentification.ToString();
    ConnectionInfo.ClientVersion = ClientVersion;
    

    Latest Build:

    // Set connection versions
    ServerVersion = ConnectionInfo.ServerVersion = serverIdentification.ToString();
    ConnectionInfo.ClientVersion = ClientVersion;
    

    Session.ClientVersion is initialized in Session.Session(), which, IMO, is a really bad place to put it. So, I changed it to a static readonly string, dropped it to ConnectionInfo (since it is technically connection information), and updated Session.ClientVersion to pull from there. However for 2020.x.x, the values are simply passed down to ConnectionInfo and Session.Serversion is never initialized, so the exception is thrown in CalculateHash() when passing Session.ServerVersion to ExchangeHashData. The latest version fixed that, but it seems a bit redundant since it can be fixed without modifying Session.Connect() by modifying the local properties:

    Session.ServerVersion
    {
    	get { return ConnectionInfo.ServerVersion; }
    }
    Session.ClientVersion
    {
    	get { return ConnectionInfo.ClientVersion; }
    }
    

    Cheers,

  3. amitbarkai commented on Nov 19, 2023

    @amitbarkai
    Author

    @lifeincha0s
    thanks for the replay
    since this issue happened for one of our customers , we are still trying to understand
    what is preventing the keyboard-interactive from working.

    having said that this is clearly a bug in the SSH.NET
    throwing this ArgumentNullException

  4. amitbarkai commented on Nov 19, 2023

    @amitbarkai
    Author

    continue to our conversation ..
    private void keyboardAuthentication_AuthenticationPrompt(object sender, Renci.SshNet.Common.AuthenticationPromptEventArgs e)
    {
    if (ConnectionInfo.AuthenticationMethod is PasswordAuthenticationMethod)
    {
    var passwordConnection = (PasswordAuthenticationMethod)ConnectionInfo.AuthenticationMethod;
    var passwordRegex = new Regex(IOC.Get.Service().LoginPasswordPrompt, RegexOptions.Multiline | RegexOptions.IgnoreCase);

            IOC.Get.Service<ILogService>().Write(LogMessages.DNAPR618I, LogTarget.Trace);
    
            foreach (var prompt in e.Prompts)
            {
               IOC.Get.Service<ILogService>().Write(LogMessages.DNAPR619I, LogTarget.Trace, prompt.Request);
               if (passwordRegex.IsMatch(prompt.Request))
               {
                  prompt.Response = passwordConnection.Password.GetStringFromSecureString();
               }
               else
               {
                  IOC.Get.Service<ILogService>().Write(LogMessages.DNAPR673E, LogTarget.Trace, prompt.Request);
               }
            }
         }
      }
    

    this is the AuthenticationPrompt implementation function
    and i would expect to see any of my logs , in case this issue is on our code.

    but for now it seems , at least for me , the issue is on the SSH.NET side no ?

  5. Rob-Hague commented on Nov 19, 2023

    @Rob-Hague
    Collaborator

    if (ConnectionInfo.AuthenticationMethod is PasswordAuthenticationMethod) looks suspicious to me. Can you try without it?

  6. amitbarkai commented on Nov 19, 2023

    @amitbarkai
    Author

    unfortunately , no , this is the first time this issue happens for us :)
    and we have more than 8K customers and much more traget machines.

    this issue happens only for this customer .
    not sure if it is related he has BeyhondTrust (PBrun) installed on this target machine

    NOTE : this issue happens for domain user only , for local user it works fine

  7. Rob-Hague commented on Nov 19, 2023

    @Rob-Hague
    Collaborator

    OK, understood. I'm sorry but I don't think any of that is related to SSH.NET and I can't help you on that.

    If you believe it is related, you can try troubleshooting using https://github.com/sshnet/SSH.NET/wiki/Troubleshooting-SSH.NET and report back. I hope you find a solution.

  8. amitbarkai commented on Nov 19, 2023

    @amitbarkai
    Author

    i have to admit it sounds like an adge case , when something is blocking the Keyboard-interactive
    in either domain / gpo level.

    we are still waiting to get more information about the customer environment , so we could understand what is the issue

  9. amitbarkai commented on Dec 4, 2023

    @amitbarkai
    Author

    would like to better understand what can / needs to be done
    this is our ssh client object creation - using two authentication methods ( with that order
    1.keyboard-interactive
    2.password authenticaiton

          public SshClient(IMachine machine, string username, SecureString password, int port, TimeSpan connectionTimeout)
          {
             try
             {
                ConnectionInfo = new PasswordConnectionInfo(machine.Address, username, password, port);
                var authenticationMethods = new List<Renci.SshNet.AuthenticationMethod>();
                var includeKeyboardInteractiveMethod = IOC.Get.Service<IConfig>().GetBool("IncludeKeyboardInteractiveMethod", true, false);
                var keyboardAuth = new KeyboardInteractiveAuthenticationMethod(username);
                keyboardAuth.AuthenticationPrompt += keyboardAuthentication_AuthenticationPrompt;
                IOC.Get.Service<ILogService>().Write($"IncludeKeyboardInteractiveMethod value is : {includeKeyboardInteractiveMethod}", LogTarget.Trace);
                if (includeKeyboardInteractiveMethod)
                {
                    authenticationMethods.Add(keyboardAuth);
                }
                authenticationMethods.Add(new Renci.SshNet.PasswordAuthenticationMethod(username, password.GetStringFromSecureString()));
    
                var connectionInfo = new Renci.SshNet.ConnectionInfo(machine.Address, port, username, authenticationMethods.ToArray());
                connectionInfo.Timeout = connectionTimeout;
    
                _client = new Renci.SshNet.SshClient(connectionInfo);
    
                setShellColumns(machine);
             }
             catch (Exception ex)
             {
                throw new Exception(string.Format(LogMessages.DNAPR209E, ex.Message), ex);
             }
          }

    the implementation for keyboardAuthentication_AuthenticationPrompt is

          private void keyboardAuthentication_AuthenticationPrompt(object sender, Renci.SshNet.Common.AuthenticationPromptEventArgs e)
          {
             if (ConnectionInfo.AuthenticationMethod is PasswordAuthenticationMethod)
             {
                var passwordConnection = (PasswordAuthenticationMethod)ConnectionInfo.AuthenticationMethod;
                var passwordRegex = new Regex(IOC.Get.Service<IUnixConfigReader>().LoginPasswordPrompt, RegexOptions.Multiline | RegexOptions.IgnoreCase);
    
    
                IOC.Get.Service<ILogService>().Write(LogMessages.DNAPR618I, LogTarget.Trace);
    
                foreach (var prompt in e.Prompts)
                {
                   IOC.Get.Service<ILogService>().Write(LogMessages.DNAPR619I, LogTarget.Trace, prompt.Request);
                   if (passwordRegex.IsMatch(prompt.Request))
                   {
                      prompt.Response = passwordConnection.Password.GetStringFromSecureString();
                   }
                   else
                   {
                      IOC.Get.Service<ILogService>().Write(LogMessages.DNAPR673E, LogTarget.Trace, prompt.Request);
                   }
                }
             }
          }

    ** this is the Login prompt regex - @"^Password: ?$|'+s password: ?$";
    the exception is thrown from the connect function showing the following logs

    11/9/2023 8:40:27 AM [5960][7] - Connect - DNAPR722E Failed to initialize SSH client to remote machine Machine-IP. Error: String reference not set to an instance of a String.
    Parameter name: s.
    11/9/2023 8:40:27 AM [5960][7] - ConnectClient - Connect Exception data: System.ArgumentNullException: String reference not set to an instance of a String.
    Parameter name: s
    at Renci.SshNet.KeyboardInteractiveAuthenticationMethod.Authenticate(Session session)
    at Renci.SshNet.ClientAuthentication.TryAuthenticate(ISession session, AuthenticationState authenticationState, String[] allowedAuthenticationMethods, SshAuthenticationException& authenticationException)
    at Renci.SshNet.ClientAuthentication.Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
    at Renci.SshNet.ConnectionInfo.Authenticate(ISession session, IServiceFactory serviceFactory)
    at Renci.SshNet.Session.Connect()
    at Renci.SshNet.BaseClient.CreateAndConnectSession()
    at Renci.SshNet.BaseClient.Connect()
    at Cyberark.DNA.Common.Communication.SSH.SshClient.Connect()

    as you could see the DNAPR618I is not show in the logs ( so something is clearly failing in an earlier stage)
    our customer was able to pin point the issue when
    his prompt was :
    Password for username@domain:
    which seems to affect to login process

    when the bold section was removed from the prompt everything worked fine.
    regardless of the above , i would expect when providing 2 authentication methods
    would this additional information help ?

    would you agree , that in case one , authentication throws an exception
    we should try and move to the next one ?

    thanks

  10. Rob-Hague commented on Dec 4, 2023

    @Rob-Hague
    Collaborator

    (FYI I edited your comment to format the code blocks: you need to surround with 3 ticks instead of 1 (```)

    I don't know what ConnectionInfo is in your code, but I'm guessing it is not Renci.SshNet.ConnectionInfo. Could the if (ConnectionInfo.AuthenticationMethod is PasswordAuthenticationMethod) be false which stops DNAPR618I? If it is true then I can't explain why the log does not show.

    Aside from that, your regex will indeed not match "Password for username@domain", so maybe the regex could be changed.

    As for whether the authentication process should continue on exception, it will already continue if for example, the wrong key or password is given as part of the normal procedure. But in an "exceptional" case like this one, which in fact indicates a problem in the code, I do not think the process should continue.

    What you could do is have an else in keyboardAuthentication_AuthenticationPrompt which just sets all the prompt.Response = "".

    Similarly we could null-coalesce the response to an empty string during serialisation, but (again) I think this is working around incorrect usage of the code. I don't have strong opinion here.

  11. amitbarkai commented on Dec 5, 2023

    @amitbarkai
    Author
  12. amitbarkai commented on Dec 5, 2023

    @amitbarkai
    Author
  13. added this to the 2023.0.1 milestone on Dec 20, 2023
  14. WojciechNagorski commented on Dec 29, 2023

    @WojciechNagorski
    Collaborator

    The 2023.0.1 version has been released to Nuget: https://www.nuget.org/packages/SSH.NET/2023.0.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions