Unable to authenticate through EXT


I’m trying to configure GenieACS in a way that every CPE has its own username and password calculated on the serial number. I’m working with GenieACS v1.2.9 on Debian 11. I have GENIEACS_EXT_DIR=/opt/genieacs/ext in my environment file. I created /opt/genieacs/ext/authenticate.js as follows

"use strict";

function getPassword(args, callback) {
	callback(null, crypto.createHash('sha256').update('secret'+args[0]).digest('hex'));

exports.getPassword = getPassword;

and set cwmp.auth to AUTH(DeviceID.SerialNumber, EXT("authenticate", "getPassword", DeviceID.SerialNumber)) but, at least for the moment, I only get Authentication failure.

Any clue?

you don’t need auth, what you really need is to place your acs on a vlan

Delete all of that stuff and just use the built-in inform provision. It sets all of this up for you.

Unfortunately is not something I can do in the current deployment setup, not due to technical reasons.

I should set - what - through the inform provision?
To be precise: I want any CPE to have a separate username and password.

To authenticate itself to the ACS? Or for the ACS to authenticate itself to the CPE?

Here is the default inform provision. It sets the username/password for ACS to CPE authentication.

// Device ID as user name
const username = declare("DeviceID.ID", {value: 1}).value[0]

// Password will be fixed for a given device because Math.random() is seeded with device ID by default.
const password = Math.trunc(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);

const informInterval = 300;

// Refresh values daily
const daily = Date.now(86400000);

// Unique inform offset per device for better load distribution
const informTime = daily % 86400000;

declare("InternetGatewayDevice.ManagementServer.ConnectionRequestUsername", {value: daily}, {value: username});
declare("InternetGatewayDevice.ManagementServer.ConnectionRequestPassword", {value: daily}, {value: password});
declare("InternetGatewayDevice.ManagementServer.PeriodicInformEnable", {value: daily}, {value: true});
declare("InternetGatewayDevice.ManagementServer.PeriodicInformInterval", {value: daily}, {value: informInterval});
declare("InternetGatewayDevice.ManagementServer.PeriodicInformTime", {value: daily}, {value: informTime});

declare("Device.ManagementServer.ConnectionRequestUsername", {value: daily}, {value: username});
declare("Device.ManagementServer.ConnectionRequestPassword", {value: daily}, {value: password});
declare("Device.ManagementServer.PeriodicInformEnable", {value: daily}, {value: true});
declare("Device.ManagementServer.PeriodicInformInterval", {value: daily}, {value: informInterval});
declare("Device.ManagementServer.PeriodicInformTime", {value: daily}, {value: informTime});

Addendum: I see my default inform sets Device.ManagementServer.ConnectionRequestUsername and Device.ManagementServer.ConnectionRequestPassword which, as far as I can tell, are meant to set the password that the ACS uses when issuing a request to the CPE.
On the contrary, my goal is to set, in a reproducible way, the password that the CPE has to use while contacting the ACS.

I would listen to @rudymartin and put your ACS on a separate VLAN. This is what we’ve done since the beginning.

To answer you original question though, it looks like you have the part sorted out for the ACS to determine what credentials to use when validating the connection request attempt from the CPE. But where are you actually setting the credentials in the device? That could easily be done in the inform script.

//existing inform script

const cpePass = ext("authenticate", "getPassword", DeviceID.SerialNumber);

declare("InternetGatewayDevice.ManagementServer.Username", {value: daily}, {value: username});
declare("InternetGatewayDevice.ManagementServer.Password", {value: daily}, {value: cpePass});

declare("Device.ManagementServer.Username", {value: daily}, {value: username});
declare("Device.ManagementServer.Password", {value: daily}, {value: cpePass});

Not at all!
Setting the credentials on the CPE is not a problem since we have to do a manual provisioning in which our internal software generates a configuration file that we directly import on the CPE. This configuration file also contains the address and the credentials of the ACS.
The problem is that the ACS answers with Authentication failure if I set the (supposed) correct username and password on the CPE. I don’t think it’s a problem of the script since I ran it manually via shell and it returns a proper result. My guess would be that there is some issue in the call to the external script but I can’t figure out where the problem is.

Why are you doing a custom config file per customer? The point of an ACS is move away from that. The only custom config for our devices is basic network information (new interface for ACS managment, and the IP of the ACS). Everything else is sorted out when the CPE is connected. Every boot I check if the config state for the CPE is still valid (has the CPE been moved to a new customer). If the CPE needs to be reprovisioned I set the necessary tags and the other provision scripts take over.


Unfortunately, I currently can’t use that set of features of the ACS.
What I can do, is use the ACS to monitor IP addresses, WiFi / SIP configuration, rollout upgrades, run diagnosis and, on request, enable remote web gui.
Just for context, although it’s absolutely irrelevant for the resolution of the problem, I’m operating on a network I do not own so I can’t (well, I can but it has an unreasonable cost) provide a separate VLAN for ACS and I can’t connect the CPE to the internet unless they have a valid PPPoE credential set. And valid means it’s only feasible for that access, I can’t have a set of PPPoE credentials just for provisioning.
So, how do I sort out the EXT script for authentication?

I would switch everything over to unencrypted for CWMP then fire up wireshark and see exactly what the packets say. The packets don’t lie.

1 Like

If I set cwmp.auth to AUTH("username", "password") corresponding to the credentials I set on the CPE, it works.
So I assume something is wrong in the EXT call. But don’t know what.

Hence why you need to see what the packets say.

Yeah, I’m sure I could but I don’t really see the point.
Without any change on the CPE, if cwmp.auth is fixed, everything goes fine. If cwmp.auth calls the external script, in cwmp logs I see “Authentication failure”.
Therefore, the problem is certainly server side. It would me much more useful to find a way to debug if and what the EXT call returns.

You have two way to check what EXT call return without any problem.
First one - use ext-runner.js (Ext script test into console)
Second one - use test/debug provisioning and log function to see what it return

The location of where to place the file has changed in v1.2. In v1.2, the file needs to be placed in the location specified by GENIEACS_EXT_DIR in the genieacs.env file.

Okay, thank you for pointing this out. I was missing a require that was not needed in the plain npm run.

Now, the CPE->ACS authentication is working fine. Unfortunately, what is not working now, is the ACS->CPE part. I didn’t modify any parameter on that but if I try to summon I now get
Connection request error: Incorrect connection request credentials .

Is there any modification I am supposed to do after having the authentication working correctly?

Connection request username and password get correctly set by the inform script…

The default inform scripts sets up auth for ACS → CPE, not CPE → ACS.

cwmp.connectionRequestAuth is for ACS → CPE
cwmp.auth is for CPE → ACS.

I would try deleting the entry for cwmp.auth and see if all your auth issues go away.

Nope, apparently dropping the cwmp.auth parameter does not change anything.