diff --git a/.github/workflows/CI-jython.yml b/.github/workflows/CI-jython.yml index 463b7a176..b04f021b8 100644 --- a/.github/workflows/CI-jython.yml +++ b/.github/workflows/CI-jython.yml @@ -48,6 +48,9 @@ jobs: echo $'Host test_hostname\n Hostname localhost\n User test\n Port 22\n' >> ~/.ssh/config echo $'Host testkey_hostname\n Hostname localhost\n User testkey\n Port 22\n IdentityFile atest/testdata/keyfiles/id_rsa\n' >> ~/.ssh/config echo $'Host test_proxy_hostname\n Hostname localhost\n User test\n Port 22\n ProxyCommand ssh -W %h:%p testkey_hostname\n' >> ~/.ssh/config + sudo useradd test-nopasswd -m -s /bin/bash + sudo passwd --delete test-nopasswd + sudo bash -c "echo 'PermitEmptyPasswords yes' >> /etc/ssh/sshd_config" sudo service ssh restart eval "$(ssh-agent -s)" ssh-add atest/testdata/keyfiles/id_rsa diff --git a/.github/workflows/CI-python.yml b/.github/workflows/CI-python.yml index cc1937558..d39452bd2 100644 --- a/.github/workflows/CI-python.yml +++ b/.github/workflows/CI-python.yml @@ -46,6 +46,9 @@ jobs: echo $'Host test_hostname\n Hostname localhost\n User test\n Port 22\n' >> ~/.ssh/config echo $'Host testkey_hostname\n Hostname localhost\n User testkey\n Port 22\n IdentityFile atest/testdata/keyfiles/id_rsa\n' >> ~/.ssh/config echo $'Host test_proxy_hostname\n Hostname localhost\n User test\n Port 22\n ProxyCommand ssh -W %h:%p testkey_hostname\n' >> ~/.ssh/config + sudo useradd test-nopasswd -m -s /bin/bash + sudo passwd --delete test-nopasswd + sudo bash -c "echo 'PermitEmptyPasswords yes' >> /etc/ssh/sshd_config" sudo service ssh restart eval "$(ssh-agent -s)" ssh-add atest/testdata/keyfiles/id_rsa diff --git a/atest/README.rst b/atest/README.rst index 2f68359b4..15725393d 100644 --- a/atest/README.rst +++ b/atest/README.rst @@ -47,6 +47,18 @@ Setup on Linux - exit +- Create a new user ``test-nopasswd``: + +:: + + sudo useradd --create-home --shell /bin/bash test-nopasswd + +- Delete it's password + +:: + + sudo passwd --delete test-nopasswd + - Create a new user ``testkey``: :: @@ -106,7 +118,7 @@ Additional OpenSSH configuration - Add/edit the following lines: :: - + PermitEmptyPasswords yes Banner /etc/ssh/sshd-banner # for testing pre-login banner Subsystem subsys echo "Subsystem invoked." # for testing invoke_subsystem diff --git a/atest/docker/Dockerfile b/atest/docker/Dockerfile index 9ae1d028f..203a995a6 100644 --- a/atest/docker/Dockerfile +++ b/atest/docker/Dockerfile @@ -9,11 +9,15 @@ RUN python3.7 -m pip install --upgrade pip RUN python3.7 -m pip install --upgrade robotframework-sshlibrary robotbackgroundlogger robotstatuschecker ARG repository RUN apt-get install -y openssh-server sudo git -RUN useradd test -m -s /bin/bash +RUN useradd --create-home --shell /bin/bash test-nopasswd +RUN passwd --delete test-nopasswd +RUN echo "PermitEmptyPasswords yes" >> /etc/ssh/sshd_config +RUN systemctl restart sshd +RUN useradd test --create-home --shell /bin/bash test RUN (echo 'test'; echo 'test') | passwd test RUN echo -e "test\n test" | adduser test sudo RUN sh -c "echo 'test ALL=(ALL:ALL) PASSWD:ALL' > /etc/sudoers.d/passworded" -RUN useradd -m testkey -s /bin/bash +RUN useradd -m testkey -s /bin/bash RUN sudo -E su test -c echo "$'export PS1='\u@\h \W \$ '' >> /home/test/.bashrc" RUN sudo -E su testkey -c echo "$'export PS1='\u@\h \W \$ '' >> /home/testkey/.bashrc" RUN sudo -E su testkey -c "mkdir -p /home/testkey/.ssh" @@ -28,6 +32,6 @@ RUN echo 'Subsystem subsys echo "Subsystem invoked."' >> /etc/ssh/sshd_config RUN sudo mkdir -p ~/.ssh RUN echo 'Host test_hostname\n Hostname localhost\n' >> ~/.ssh/config RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 diff --git a/atest/login.robot b/atest/login.robot index 6d3becd9e..aa3b5e1ee 100644 --- a/atest/login.robot +++ b/atest/login.robot @@ -61,9 +61,21 @@ Login With Public Key Using Config File [Setup] Open Connection ${TESTKEY_HOSTNAME} prompt=${PROMPT} Login With Public Key read_config=True +Login With No Password + [Setup] Open Connection ${HOST} prompt=${PROMPT} + Login ${USERNAME_NOPASSWD} + +Login With Explicit No Password + [Setup] Open Connection ${HOST} prompt=${PROMPT} + Login ${USERNAME_NOPASSWD} ${EMPTY_STRING} + +Login With Empty Quotes No Password + [Setup] Open Connection ${HOST} prompt=${PROMPT} + Login ${USERNAME_NOPASSWD} "" + #Login Using Config File Proxy Command # TODO fix failing with Travis-CI # [Tags] pybot # [Setup] Open Connection ${TEST_PROXY_HOSTNAME} prompt=${PROMPT} # ${output}= Login password=test read_config=True -# Should Contain ${output} test@ \ No newline at end of file +# Should Contain ${output} test@ diff --git a/atest/resources/common.robot b/atest/resources/common.robot index b5717b75e..ee51c1ff4 100644 --- a/atest/resources/common.robot +++ b/atest/resources/common.robot @@ -3,6 +3,7 @@ Library SSHLibrary WITH NAME SSH *** Variables *** ${USERNAME} test +${USERNAME_NOPASSWD} test-nopasswd ${PASSWORD} test ${HOST} localhost ${PROMPT} $ @@ -10,12 +11,13 @@ ${REMOTE TEST ROOT NAME} robot-testdir ${REMOTE HOME TEST} /home/test ${REMOTE TEST ROOT} ${REMOTE HOME TEST}/${REMOTE TEST ROOT NAME} ${LOCAL TESTDATA} ${CURDIR}${/}..${/}testdata -${KEY DIR} ${LOCAL TESTDATA}${/}keyfiles -${KEY USERNAME} testkey -${KEY} ${KEY DIR}${/}id_rsa -${TEST_HOSTNAME} test_hostname -${TESTKEY_HOSTNAME} testkey_hostname -${TEST_PROXY_HOSTNAME} test_proxy_hostname +${KEY DIR} ${LOCAL TESTDATA}${/}keyfiles +${KEY USERNAME} testkey +${KEY} ${KEY DIR}${/}id_rsa +${TEST_HOSTNAME} test_hostname +${TESTKEY_HOSTNAME} testkey_hostname +${TEST_PROXY_HOSTNAME} test_proxy_hostname +${EMPTY_STRING} \ *** Keywords *** Login As Valid User diff --git a/src/SSHLibrary/abstractclient.py b/src/SSHLibrary/abstractclient.py index 422fbd151..9fa28362f 100644 --- a/src/SSHLibrary/abstractclient.py +++ b/src/SSHLibrary/abstractclient.py @@ -202,7 +202,9 @@ def login(self, username=None, password=None, allow_agent=False, look_for_keys=F """ keep_alive_interval = int(TimeEntry(keep_alive_interval).value) username = self._encode(username) - if not password and not allow_agent: + if not password or password == '""': + password = None + if password and not allow_agent: password = self._encode(password) try: self._login(username, password, allow_agent, look_for_keys, proxy_cmd, read_config, diff --git a/src/SSHLibrary/javaclient.py b/src/SSHLibrary/javaclient.py index aded5ce03..6622aaf40 100644 --- a/src/SSHLibrary/javaclient.py +++ b/src/SSHLibrary/javaclient.py @@ -66,7 +66,10 @@ def _login(self, username, password, allow_agent='ignored', look_for_keys='ignor raise JavaSSHClientException("Arguments 'allow_agent', 'look_for_keys', " "`jumphost_index_or_alias` and `keep_alive_interval`" " do not work with Jython.") - if not self.client.authenticateWithPassword(username, password): + + auth = self.client.authenticateWithPassword(username, password) if password \ + else self.client.authenticateWithNone(username) + if not auth: raise SSHClientException def _login_with_public_key(self, username, key_file, password,