Skip to content

telnet_opener: newer-firmware root password, and don't crash on reboot - #14

Merged
widgetii merged 2 commits into
masterfrom
telnet-newer-firmware-password
Sep 29, 2026
Merged

widgetii merged 2 commits into
masterfrom
telnet-newer-firmware-password

Conversation

@widgetii

Copy link
Copy Markdown
Member

Enabling telnet on a recent Xiongmai camera with telnet_opener.py <ip> hit two problems. Found while restoring telnet on an HI3516EV300_85H50AI (000529B2, build 2021-03-03).

1. Root password changed on newer firmware

The stock telnet login is no longer root / xmhdipc. Builds from 2021 on use root / Hp#!8CocD_g (confirmed on this 000529B2 2021-03-03 build, and the same password is on a 2024 GK7201V200 build). The backup path hard-coded xmhdipc, so it would sit at the password prompt and fail.

  • Adds a TELNET_CREDENTIALS table and a telnet_login() helper that tries each credential and returns the connected socket at the shell prompt (or None).
  • do_backup_via_telnet() uses it instead of hard-coded root/xmhdipc.
  • The "telnet open" message and the README now list both passwords.

2. Traceback when the updater reboots on its own

After the SkipCheck InstallDesc upload, the camera's updater reboots the box by itself. The follow-up DVRIPCam.login() then meets a dropped/silent connection, and dvrip.py raises (TypeError: 'NoneType' object is not subscriptable from data["Ret"]) rather than returning False. That aborted the whole run with a traceback even though telnet was about to come up. That reboot-login is now wrapped, and reported as the camera already rebooting.

Testing

On a live 000529B2 2021-03-03 unit: telnet_login() tries xmhdipc, falls through, logs in with Hp#!8CocD_g, and runs a command. python3 telnet_opener.py <ip> with no flags now enables persistent telnet (telnetctrl=1 in the env, verified with XmEnv -r) and returns cleanly across the self-reboot. python3 -c "import ast; ast.parse(...)" passes; no new imports or names for the CI ruff check.

No behaviour change for older xmhdipc cameras: that credential is tried first.

Two things break telnet_opener on Xiongmai firmware built from 2021 on:

- The stock telnet root password is no longer xmhdipc but Hp#!8CocD_g (seen
  on HI3516EV300_85H50AI 000529B2 build 2021-03-03 and a 2024 GK7201V200
  build). Both are now tried, in a TELNET_CREDENTIALS table, by a new
  telnet_login() helper the backup path uses; the "telnet open" message and
  the README list both.

- After the enable-telnet upload, the updater reboots the camera itself, so
  the follow-up DVRIP login can hit a dropped/empty connection. dvrip.login()
  raises on that (TypeError from data["Ret"] on a None reply) rather than
  returning False, which aborted the whole run with a traceback even though
  telnet came up fine. That login is now guarded.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Support newer Xiongmai telnet passwords and self-rebooting cameras

🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

AI Description

• Try both known root passwords so backups work on older and newer Xiongmai firmware.
• Continue probing for telnet when the updater reboots before the follow-up DVRIP login.
• Document both passwords and show them when telnet opens.
Diagram

graph TD
  Start["Telnet opener"] -->|"telnet closed"| Upload["InstallDesc upload"] --> Reboot["Guard reboot login"] --> Ports["Probe telnet ports"] --> Auth{"Password accepted?"} --> Shell["Telnet shell"] --> Backup["NFS backup"]
  Start -->|"telnet open"| Auth
  Auth -->|"try next"| Auth
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Fix empty replies in DVRIPCam.login
  • ➕ Other DVRIP callers would also receive a clean failure for empty replies.
  • ➖ Changes shared library behavior and still requires handling connection errors during the expected reboot.

Recommendation: Keep the reboot guard local to the updater workflow, where a dropped connection is expected. A shared DVRIP empty-reply fix could be a separate improvement.

Files changed (2) +49 / -14

Bug fix (1) +46 / -14
telnet_opener.pyRetry telnet credentials and tolerate updater-initiated reboot +46/-14

Retry telnet credentials and tolerate updater-initiated reboot

• Adds ordered credential attempts for the backup telnet login, retaining the legacy password first. Guards the follow-up DVRIP login against connection and malformed-response errors during reboot, and displays both known credentials when telnet opens.

telnet_opener.py

Documentation (1) +3 / -0
README.mdDocument the newer stock telnet password +3/-0

Document the newer stock telnet password

• Identifies the password used by observed 2021 and 2024 firmware builds and notes that the tool tries both known credentials.

README.md

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. A reboot can still abort telnet setup ✓ Resolved
Description
enable_telnet_via_dvrip() catches socket errors around the follow-up login but omits
SomethingIsWrongWithCamera, which DVRIPCam.connect() raises instead of propagating an OSError.
If the updater reboots before that connection is established, the exception escapes and the
subsequent telnet probe never runs.
Code

telnet_opener.py[R193-194]

+    except (OSError, TypeError, KeyError, ValueError):
+        print("Camera is not answering DVRIP; it is most likely rebooting already.")
Evidence
The new handler wraps the reconnect login but does not catch the exception that the DVRIP client
raises for a failed socket connection. login() calls connect() when disconnected, and the telnet
polling loop is below the handler.

telnet_opener.py[183-199]
dvrip.py[176-195]
dvrip.py[351-353]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The post-upload reconnect handler misses the exception raised when `DVRIPCam.connect()` cannot connect, so an expected reboot still aborts telnet probing.
## Fix Focus Areas
- telnet_opener.py[183-199]
- dvrip.py[176-195]
## Recommended Fix
Import `SomethingIsWrongWithCamera` from `dvrip` and include it in the post-upload reconnect handler's exception tuple. Continue to the existing telnet polling loop after handling it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread telnet_opener.py Outdated
DVRIPCam.connect() raises SomethingIsWrongWithCamera (a bare Exception, not
an OSError) when the post-upload socket connect fails, which is exactly the
mid-reboot case the guard is for. Without it in the tuple the exception
escaped and the telnet probe never ran.
@widgetii

Copy link
Copy Markdown
Member Author

Fixed in ae07e25: DVRIPCam.connect() raises SomethingIsWrongWithCamera (a bare Exception, not OSError) when the post-upload socket connect fails, which is the mid-reboot case the guard exists for. It's now imported and included in the handler's tuple, so control falls through to the telnet probe as intended.

@widgetii
widgetii merged commit 6ea861a into master Sep 29, 2026
6 checks passed
@widgetii
widgetii deleted the telnet-newer-firmware-password branch September 29, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant