Commit 8fa54098 authored by Kamil Dudka's avatar Kamil Dudka
Browse files

nss: make FTPS work with --proxytunnel

If the NSS code was in the middle of a non-blocking handshake and it
was asked to finish the handshake in blocking mode, it unexpectedly
continued in the non-blocking mode, which caused a FTPS connection
over CONNECT to fail with "(81) Socket not ready for send/recv".

Bug: https://bugzilla.redhat.com/1420327
parent bef0d001
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ This release includes the following bugfixes:
 o telnet: Fix typos [45]
 o transfer: only retry nobody-requests for HTTP [46]
 o http2: reset push header counter fixes crash [47]
 o nss: make FTPS work with --proxytunnel [48]

This release includes the following known bugs:

@@ -157,3 +158,4 @@ References to bug reports and discussions on issues:
 [45] = https://curl.haxx.se/bug/?i=1245
 [46] = https://curl.haxx.se/bug/?i=1243
 [47] = https://curl.haxx.se/bug/?i=1249
 [48] = https://bugzilla.redhat.com/1420327
+11 −12
Original line number Diff line number Diff line
@@ -1612,13 +1612,14 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
  return curlerr;
}

/* Switch the SSL socket into non-blocking mode. */
static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
                                 struct Curl_easy *data)
/* Switch the SSL socket into blocking or non-blocking mode. */
static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
                                 struct Curl_easy *data,
                                 bool blocking)
{
  static PRSocketOptionData sock_opt;
  sock_opt.option = PR_SockOpt_Nonblocking;
  sock_opt.value.non_blocking = PR_TRUE;
  sock_opt.value.non_blocking = !blocking;

  if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
    return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
@@ -2007,16 +2008,14 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
      /* we do not expect CURLE_AGAIN from nss_setup_connect() */
      return result;

    if(!blocking) {
      /* in non-blocking mode, set NSS non-blocking mode before handshake */
      result = nss_set_nonblock(connssl, data);
      if(result)
        return result;
    }

    connssl->connecting_state = ssl_connect_2;
  }

  /* enable/disable blocking mode before handshake */
  result = nss_set_blocking(connssl, data, blocking);
  if(result)
    return result;

  result = nss_do_connect(conn, sockindex);
  switch(result) {
  case CURLE_OK:
@@ -2032,7 +2031,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,

  if(blocking) {
    /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
    result = nss_set_nonblock(connssl, data);
    result = nss_set_blocking(connssl, data, /* blocking */ FALSE);
    if(result)
      return result;
  }