From f8789876f559649793a100c0e452309f84078fc2 Mon Sep 17 00:00:00 2001 From: stswangzhiping <59632378+stswangzhiping@users.noreply.github.com> Date: Mon, 4 May 2026 14:17:28 +0800 Subject: [PATCH] feat: add share_key for Samba password, sync smbpasswd on startup Co-authored-by: Cursor --- bin/clawd.js | 11 +++++++++++ lib/client.js | 1 + lib/config.js | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/bin/clawd.js b/bin/clawd.js index 5c49f7b..559193a 100755 --- a/bin/clawd.js +++ b/bin/clawd.js @@ -7,6 +7,7 @@ require('../lib/systemd-env'); const path = require('path'); const { exec } = require('child_process'); const { ClawClient } = require('../lib/client'); +const config = require('../lib/config'); const log = require('../lib/logger'); const { pollSms } = require('../drivers/sim/sms-reader'); @@ -17,6 +18,16 @@ exec(`bash "${bindScript}"`, (err, stdout, stderr) => { else log.info('clawd', `bind-quectel-serial: ok`); }); +// 同步 Samba 共享密码(idempotent,失败不影响主流程) +const cfg = config.load(); +if (cfg.share_key) { + const shareKey = cfg.share_key.replace(/'/g, "'\\''"); + exec(`printf '%s\\n%s\\n' '${shareKey}' '${shareKey}' | smbpasswd -a sts -s 2>/dev/null`, (err) => { + if (err) log.warn('clawd', `smbpasswd sync failed (samba not installed?): ${err.message}`); + else log.info('clawd', 'smbpasswd synced for user sts'); + }); +} + let smsTimer = null; let smsPolling = false; diff --git a/lib/client.js b/lib/client.js index c52349f..f81ffc6 100644 --- a/lib/client.js +++ b/lib/client.js @@ -377,6 +377,7 @@ class ClawClient { token: this._cfg.token ?? null, version: CLAWD_VERSION, ssh_secret_key: this._cfg.ssh_secret_key ?? null, + share_key: this._cfg.share_key ?? null, headscale_joined: headscale.isInstalled() && headscale.isJoined(this._cfg.headscale_server || 'https://hs.claw.cutos.ai'), local_ip: getLocalIps(), local_networks: getLocalNetworks(), diff --git a/lib/config.js b/lib/config.js index 37031bc..490ec3a 100644 --- a/lib/config.js +++ b/lib/config.js @@ -20,6 +20,7 @@ const DEFAULTS = { /** 云端已激活:用于启动/重连时立即点亮 alarm(pwr),不等首包 connected */ activated: false, ssh_secret_key: null, + share_key: null, headscale_server: 'https://hs.claw.cutos.ai', }; @@ -28,6 +29,33 @@ function _generateSshSecretKey() { return 'sk-' + bytes.toString('hex'); } +/** + * 生成可读性好的 Samba 共享密码,格式:xxxxxx-xxxxxx-xxxxXX(三段各6字符,连字符分隔)。 + * 最后一段包含至少1个大写字母和1个数字,其余为小写字母。 + * 示例:juqhuf-hykgyh-mykGi3 + */ +function _generateShareKey() { + const crypto = require('crypto'); + const lower = 'abcdefghijklmnopqrstuvwxyz'; + const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const digits = '0123456789'; + + function rndChars(chars, n) { + const bytes = crypto.randomBytes(n); + return Array.from(bytes).map(b => chars[b % chars.length]).join(''); + } + + const g1 = rndChars(lower, 6); + const g2 = rndChars(lower, 6); + // 第三段:4个小写 + 1个大写 + 1个数字,随机打乱顺序 + const g3raw = (rndChars(lower, 4) + rndChars(upper, 1) + rndChars(digits, 1)).split(''); + for (let i = g3raw.length - 1; i > 0; i--) { + const j = crypto.randomBytes(1)[0] % (i + 1); + [g3raw[i], g3raw[j]] = [g3raw[j], g3raw[i]]; + } + return `${g1}-${g2}-${g3raw.join('')}`; +} + function load() { let cfg; try { @@ -41,10 +69,16 @@ function load() { } if (!cfg) cfg = Object.assign({}, DEFAULTS); + let dirty = false; if (!cfg.ssh_secret_key) { cfg.ssh_secret_key = _generateSshSecretKey(); - save(cfg); + dirty = true; } + if (!cfg.share_key) { + cfg.share_key = _generateShareKey(); + dirty = true; + } + if (dirty) save(cfg); return cfg; }