JCMais / node-libcurl

libcurl bindings for Node.js
https://npmjs.org/package/node-libcurl
MIT License
660 stars 117 forks source link

SFTP / SSH stuck on login when using Curl/Multi and password auth #403

Open deadbeef84 opened 8 months ago

deadbeef84 commented 8 months ago

Describe the bug

When connecting to an SFTP using Curl/Multi with a provided password, it appears to get stuck at login.

This only seems to apply to some SFTP servers, perhaps depending on supported auth types?

I managed to reproduce the same behavior when passing an incorrect password to another server.

To Reproduce

import { Curl } from 'node-libcurl'

const curl = new Curl()
curl.setOpt('URL', 'sftp://nxtest:foobar@10.0.1.209/')
curl.setOpt('SSL_VERIFYHOST', 0)
curl.setOpt('SSL_VERIFYPEER', 0)
curl.setOpt('VERBOSE', true)

// This should force it to only use provided password I think, but doesn't help
// curl.setOpt('SSH_AUTH_TYPES', 2)

// This will make the request timeout
// curl.setOpt('CONNECTTIMEOUT', 10)

// None of these trigger...
curl.on('data', (chunk) => {
  console.log('DATA', chunk.toString())
})
curl.on('header', (chunk) => {
  console.log('HEADER', chunk.toString())
})
curl.on('end', (statusCode, body, headers) => {
  console.info('Status Code: ', statusCode)
  console.info('Headers: ', headers)
  console.info('Body length: ', body.length)
  curl.close()
})
curl.on('error', (error, errorCode) => {
  console.error('Error: ', error, errorCode)
  curl.close()
})

curl.perform()

// necessary to keep process alive
setTimeout(() => console.log('done waiting'), 20e3)

The output:

*   Trying 10.0.1.209:22...
* Connected to 10.0.1.209 (10.0.1.209) port 22 (#0)
* User: nxtest
* Authentication using SSH public key file
done waiting

When using Easy it works correctly (just replaced Curl with Easy and removed event-listeners):

*   Trying 10.0.1.209:22...
* Connected to 10.0.1.209 (10.0.1.209) port 22 (#0)
* User: nxtest
* Authentication using SSH public key file
* Completed password authentication
* Authentication complete
* Connection #0 to host 10.0.1.209 left intact

Also when using curl cli:

$ curl -k -v sftp://nxtest:foobar@10.0.1.209/
*   Trying 10.0.1.209:22...
* Connected to 10.0.1.209 (10.0.1.209) port 22 (#0)
* User: nxtest
* Authentication using SSH public key file
* Completed password authentication
* Authentication complete
drwxr-xr-x    3 root     root         4096 May  3  2023 docker
drwxr-xr-x    7 root     root         4096 Nov 27 14:03 homes
drwxrwxrwx    4 root     root         4096 Dec 14 14:59 SMB-test
drwxrwxrwx    8 nxtest   users        4096 Apr 26  2023 home
* Connection #0 to host 10.0.1.209 left intact

I also tried a simple c application using multi, and it worked correctly:

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <curl/curl.h>

int main(void)
{
  CURL *handle;
  CURLM *multi_handle;

  int still_running = 1;
  int i;

  CURLMsg *msg;
  int msgs_left;

  handle = curl_easy_init();
  curl_easy_setopt(handle, CURLOPT_URL, "sftp://nxtest:foobar@10.0.1.209/");
  curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0);
  curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);
  curl_easy_setopt(handle, CURLOPT_SSH_AUTH_TYPES, 2);
  curl_easy_setopt(handle, CURLOPT_VERBOSE, 1);

  multi_handle = curl_multi_init();
  curl_multi_add_handle(multi_handle, handle);

  while(still_running) {
    CURLMcode mc = curl_multi_perform(multi_handle, &still_running);

    if(still_running)
      /* wait for activity, timeout or "nothing" */
      mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);

    if(mc)
      break;
  }

  while((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
    if(msg->msg == CURLMSG_DONE) {
      printf("transfer completed with status %d\n", msg->data.result);
    }
  }

  curl_multi_remove_handle(multi_handle, handle);
  curl_easy_cleanup(handle);
  curl_multi_cleanup(multi_handle);

  return 0;
}

Output:

*   Trying 10.0.1.209:22...
* Connected to 10.0.1.209 (10.0.1.209) port 22 (#0)
* User: nxtest
* Authentication using SSH public key file
* Completed password authentication
* Authentication complete
drwxr-xr-x    3 root     root         4096 May  3  2023 docker
drwxr-xr-x    7 root     root         4096 Nov 27 14:03 homes
drwxrwxrwx    4 root     root         4096 Dec 14 14:59 SMB-test
drwxrwxrwx    8 nxtest   users        4096 Apr 26  2023 home
* Connection #0 to host 10.0.1.209 left intact
transfer completed with status 0

Version information:

Version:

Version: libcurl/7.81.0 OpenSSL/3.0.10 zlib/1.2.13.1-motley brotli/1.0.9 zstd/1.4.8 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 OpenLDAP/2.5.16
Protocols: dict, file, ftp, ftps, gopher, gophers, http, https, imap, imaps, ldap, ldaps, mqtt, pop3, pop3s, rtmp, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
Features: AsynchDNS, IDN, IPv6, Largefile, GSS-API, Kerberos, SPNEGO, NTLM, NTLM_WB, SSL, libz, brotli, TLS-SRP, HTTP2, UnixSockets, HTTPS-proxy, PSL, alt-svc

OS: Ubuntu 22.04.3 LTS Node.js Version: v20.9.0

Additional context Add any other context about the problem here.

JCMais commented 7 months ago

Hi @deadbeef84 thanks for the report. I am not finding time right now to look into these, but as soon as go through my backlog on project I will try to reproduce your issue.

deadbeef84 commented 7 months ago

Thank you, let me know if there's anything I can do to help.