Search code examples
node.jslinuxsoapopenssl

Allow Legacy Renegotiation for NodeJs


The best way to solve this would be to update the SSL endpoint I'm trying to connect to but I don't have the ability too.

I'm trying to reach a SOAP endpoint (it's painful) for an application that is barily being maintained and thus probably won't be able to get the proper SSL patch.

It's sitting behind a proxy that is doing active SSL rewrites and could also be to blame for the error:


var request = require("request")
var soap = require("soap")
const fs = require('fs')

var specialRequest = request.defaults({
  ca: fs.readFileSync("rewrite-example.pem")
})

var options = { request: specialRequest }

const WSDL = "https://SSL-rewrite.example?wsdl"

soap.createClient(WSDL, options, function(err, client) {
        if(err) throw Error(err)
})    

Error:

Uncaught TypeError: req.then is not a function
    at HttpClient.request (../node_modules/soap/lib/http.js:191:13)
    at Object.open_wsdl (../node_modules/soap/lib/wsdl/index.js:1271:20)
    at openWsdl (../node_modules/soap/lib/soap.js:70:16)
    at ../node_modules/soap/lib/soap.js:48:13
    at _requestWSDL (../node_modules/soap/lib/soap.js:76:9)
    at Object.createClient (../node_modules/soap/lib/soap.js:94:5)
> Uncaught: Error: write EPROTO C017726B8C7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:908

From what I found here, it's possible to create a custom OpenSSL config file allowing unsafe legacy renegotiation. And using Node's --openssl-config flag, it should be possible to "ignore" the renegotiation. I've tried writing a custom config file as written in the first link and passing it in but with no avail.

This question has been asked before, though reverting to an older verision of Node would not be ideal.

What might be some other wasys to resolve this?


Solution

  • As you already have found, this error is coming from CVE-2009-3555, this is IIS issue, so it even won't be ignored using node flags. Since node 17 or 18, they removed the OpenSSL option to accept legacy servers.

    I think a better solution in your case is passing httpsAgent with the option. soap.js uses Axios as of v0.40.0 according to the readme, so you should set the request param like this:

    const crypto = require('crypto')
    
    const options = {
      request: axios.create({
          // axios options
          httpsAgent: new https.Agent({
            // for self signed you could also add
            // rejectUnauthorized: false,
    
            // allow legacy server
            secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
          }),
        }),
      }
    

    https.Agent's secureOptions is a numeric bitmask of the SSL_OP_* options.