codetwice / homebridge-http-securitysystem

Homebridge plugin that creates a SecuritySystem device which uses configurable HTTP calls to set and get its state.
BSD 2-Clause "Simplified" License
29 stars 17 forks source link

Insecure http parser issue with Abus Alarm #33

Closed Scream4Life closed 2 years ago

Scream4Life commented 2 years ago

I'm using this plugin to trigger my old Abus Secvest Alarm for years. This is my config so far

{
            "accessory": "Http-SecuritySystem",
            "name": "Secvest",
            "debug": false,
            "username": "xxxx",
            "password": "xxxx",
            "immediately": true,
            "polling": true,
            "pollInterval": 30000,
            "http_method": "GET",
            "urls": {
                "stay": {
                    "url": "http://IP:Port/setMode.cgi?Mode=Set&Source=Webpage",
                    "body": ""
                },
                "away": {
                    "url": "http://IP:Port/setMode.cgi?Mode=Set&Source=Webpage",
                    "body": ""
                },
                "night": {
                    "url": "http://IP:Port/setMode.cgi?Mode=Set&Source=Webpage",
                    "body": ""
                },
                "disarm": {
                    "url": "http://IP:Port/setMode.cgi?Mode=Unset&Source=Webpage",
                    "body": ""
                },
                "readCurrentState": {
                    "url": "http://IP:Port/getMode.cgi?Source=Webpage",
                    "body": ""
                },
                "readTargetState": {
                    "url": "http://IP:Port/getMode.cgi?Source=Webpage",
                    "body": ""
                }
            },
            "mappers": [
                {
                    "type": "static",
                    "parameters": {
                        "mapping": {
                            "Mode=Set\n": "2",
                            "Mode=Unset\n": "3"
                        }
                    }
                }
            ]
        }

For some reason - and I think is has to do with a newer nodejs version - the plugin does not work for me anymore and the log shows these errors

Jul 29 14:39:14 raspberrypi homebridge[444]: }
Jul 29 14:39:31 raspberrypi homebridge[444]: [29.7.2022, 14:39:31] [Secvest] getState function failed: Parse Error: Missing expected CR after header value
Jul 29 14:39:31 raspberrypi homebridge[444]: [29.7.2022, 14:39:31] [Secvest] Polling of current state failed, error was Error: Parse Error: Missing expected CR after header value
Jul 29 14:39:31 raspberrypi homebridge[444]:     at Socket.socketOnData (node:_http_client:494:22)
Jul 29 14:39:31 raspberrypi homebridge[444]:     at Socket.emit (node:events:527:28)
Jul 29 14:39:31 raspberrypi homebridge[444]:     at addChunk (node:internal/streams/readable:315:12)
Jul 29 14:39:31 raspberrypi homebridge[444]:     at readableAddChunk (node:internal/streams/readable:289:9)
Jul 29 14:39:31 raspberrypi homebridge[444]:     at Socket.Readable.push (node:internal/streams/readable:228:10)
Jul 29 14:39:31 raspberrypi homebridge[444]:     at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
Jul 29 14:39:31 raspberrypi homebridge[444]:   bytesParsed: 25,
Jul 29 14:39:31 raspberrypi homebridge[444]:   code: 'HPE_CR_EXPECTED',
Jul 29 14:39:31 raspberrypi homebridge[444]:   reason: 'Missing expected CR after header value',
Jul 29 14:39:31 raspberrypi homebridge[444]:   rawPacket: <Buffer 43 6f 6e 74 65 6e 74 2d 74 79 70 65 3a 20 74 65 78 74 2f 70 6c 61 69 6e 0a 0a 4d 6f 64 65 3d 55 6e 73 65 74 0a>

I found a similar issue here on the web but have no clue what to do now.

I'm running Raspbian GNU/Linux Stretch (9) with Nodejs v16.16.0. Homebridge on v1.5.0 and nom 8.11.0

codetwice commented 2 years ago

I have never seen this error, but it hints that your Abus Secvest system is returning slightly malformed HTTP responses, which new Node versions are apparently more sensitive to. The Github discussion you linked seems to come to the same conclusion and according to it one of the possible workarounds is to configure your HTTP client to also accept invalid HTTP responses.

I cannot test it myself, but you may recover the situation by adding this insecureHTTPParser to the params of the HTTP request. If you have latest version of my plugin, locate it in your node_modules folder, you will find an index.js inside.

Around line 200 there is a block like this:

        var params = {
        url: url,
        body: body,
        method: this.httpMethod,
        auth: {
            user: this.auth.username,
            pass: this.auth.password,
            sendImmediately: this.auth.immediately
        },
        headers: {}
    };

This is where that insecureHTTPParser belongs to, so change it to:

    var params = {
        url: url,
        body: body,
        method: this.httpMethod,
                insecureHTTPParser: true, 
        auth: {
            user: this.auth.username,
            pass: this.auth.password,
            sendImmediately: this.auth.immediately
        },
        headers: {}
    };

Once done, give it a try.

Scream4Life commented 2 years ago

Amazing! This helped. The error messages are gone and the accessory works properly again. Thanks you for your help!