netconf-node-topology:login-password/password is supposed to keep the encrypted password of a NETCONF device. However, in some cases a password saved in field may work even if it's not properly encrypted because AAAEncryptionService.decrypt may return the original password when decryption fails.
For example, the following request with unencrypted password
PUT /rests/data/network-topology:network-topology/topology=topology-netconf/node=netconf-mdsal { "network-topology:node": [ { "node-id": "netconf-mdsal", "netconf-node-topology:concurrent-rpc-limit": 0, "netconf-node-topology:schema-cache-directory": "netconf-mdsal", "netconf-node-topology:login-password": { "username": "admin", "password": "adminadmin" }, "netconf-node-topology:default-request-timeout-millis": 1800000, "netconf-node-topology:port": 2830, "netconf-node-topology:tcp-only": false, "netconf-node-topology:host": "127.0.0.1", "netconf-node-topology:actor-response-wait-time": 600, "netconf-node-topology:keepalive-delay": 600 } ] }
makes controller attempt to establish a NETCONF session with adminadmin as the password after failing to decrypt the password:
02:03:07.828 ERROR [opendaylight-cluster-data-notification-dispatcher-58] Failed to decrypt encoded data javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher at com.sun.crypto.provider.CipherCore.prepareInputBuffer(CipherCore.java:888) ~[?:?] at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:730) ~[?:?] at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) ~[?:?] at javax.crypto.Cipher.doFinal(Cipher.java:2205) ~[?:?] at org.opendaylight.aaa.encrypt.impl.AAAEncryptionServiceImpl.decrypt(AAAEncryptionServiceImpl.java:154) ~[?:?] at org.opendaylight.netconf.topology.spi.DefaultNetconfClientConfigurationBuilderFactory.getHandlerFromCredentials(DefaultNetconfClientConfigurationBuilderFactory.java:96) ~[bundleFile:?] at org.opendaylight.netconf.topology.spi.DefaultNetconfClientConfigurationBuilderFactory.createClientConfigurationBuilder(DefaultNetconfClientConfigurationBuilderFactory.java:68) ~[bundleFile:?] at org.opendaylight.netconf.topology.spi.NetconfNodeHandler.<init>(NetconfNodeHandler.java:143) ~[bundleFile:?] at org.opendaylight.netconf.topology.spi.AbstractNetconfTopology.setupConnection(AbstractNetconfTopology.java:142) ~[bundleFile:?] at org.opendaylight.netconf.topology.spi.AbstractNetconfTopology.lockedEnsureNode(AbstractNetconfTopology.java:108) ~[bundleFile:?] at org.opendaylight.netconf.topology.spi.AbstractNetconfTopology.ensureNode(AbstractNetconfTopology.java:96) ~[bundleFile:?] at org.opendaylight.netconf.topology.impl.NetconfTopologyImpl.onDataTreeChanged(NetconfTopologyImpl.java:145) ~[?:?] at org.opendaylight.mdsal.binding.dom.adapter.BindingDOMDataTreeChangeListenerAdapter.onDataTreeChanged(BindingDOMDataTreeChangeListenerAdapter.java:44) ~[bundleFile:?] at org.opendaylight.controller.cluster.datastore.DataTreeChangeListenerActor.dataTreeChanged(DataTreeChangeListenerActor.java:90) ~[bundleFile:?] at org.opendaylight.controller.cluster.datastore.DataTreeChangeListenerActor.handleReceive(DataTreeChangeListenerActor.java:45) ~[bundleFile:?] at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:24) ~[bundleFile:?] at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:20) ~[bundleFile:?] at scala.PartialFunction.applyOrElse(PartialFunction.scala:214) ~[bundleFile:?] at scala.PartialFunction.applyOrElse$(PartialFunction.scala:213) ~[bundleFile:?] at akka.japi.pf.UnitCaseStatement.applyOrElse(CaseStatements.scala:20) ~[bundleFile:?] at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:269) ~[bundleFile:?] at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:270) ~[bundleFile:?] at akka.actor.Actor.aroundReceive(Actor.scala:537) ~[bundleFile:?] at akka.actor.Actor.aroundReceive$(Actor.scala:535) ~[bundleFile:?] at akka.actor.AbstractActor.aroundReceive(AbstractActor.scala:220) ~[bundleFile:?] at akka.actor.ActorCell.receiveMessage(ActorCell.scala:579) ~[bundleFile:?] at akka.actor.ActorCell.invoke(ActorCell.scala:547) ~[bundleFile:?] at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:270) ~[bundleFile:?] at akka.dispatch.Mailbox.run(Mailbox.scala:231) ~[bundleFile:?] at akka.dispatch.Mailbox.exec(Mailbox.scala:243) ~[bundleFile:?] at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[?:?] at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[?:?] at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[?:?] at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[?:?] at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[?:?] 02:03:07.855 WARN [sshd-NetconfSshClient[2914912]-nio2-thread-3] Server at /127.0.0.1:2830 presented unverified EC key: SHA256:3kA4ClemSJjEhFPu1EdCQnWku+XYuWQi33bFFRK90G8
In this case the connection failed because the password is incorrect. But there are many cases where the correct unencrypted password works.
This behavior encourages keeping unencrypted password in the configuration because it may not discovered or it may be simply ignored because it works. Also, this may cause confusion since some may work but some may not.
So the device should not be activated when decryption fails to mitigate the issue.
- blocks
-
NETCONF-1114 Incorrect operational state of device configuration with Invalid encrypted password
- Confirmed
- is blocked by
-
NETCONF-1216 Input length must be multiple of 16 when decrypting with padded cipher
- Resolved
-
NETCONF-1217 Given final block not properly padded. Such issues can arise if a bad key is used during decryption
- Resolved
- relates to
-
AAA-266 AAAEncryptionService does not inform user of Encryption/Decryption failures
- Resolved
- split to
-
NETCONF-1186 Enforce base64 encoding for netconf-keystore
- Resolved