Compare commits
2 Commits
4be305d0e2
...
844d3c89ae
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
844d3c89ae | ||
|
|
f8789876f5 |
11
bin/clawd.js
11
bin/clawd.js
@@ -7,6 +7,7 @@ require('../lib/systemd-env');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const { ClawClient } = require('../lib/client');
|
const { ClawClient } = require('../lib/client');
|
||||||
|
const config = require('../lib/config');
|
||||||
const log = require('../lib/logger');
|
const log = require('../lib/logger');
|
||||||
const { pollSms } = require('../drivers/sim/sms-reader');
|
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`);
|
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 smsTimer = null;
|
||||||
let smsPolling = false;
|
let smsPolling = false;
|
||||||
|
|
||||||
|
|||||||
@@ -377,6 +377,7 @@ class ClawClient {
|
|||||||
token: this._cfg.token ?? null,
|
token: this._cfg.token ?? null,
|
||||||
version: CLAWD_VERSION,
|
version: CLAWD_VERSION,
|
||||||
ssh_secret_key: this._cfg.ssh_secret_key ?? null,
|
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'),
|
headscale_joined: headscale.isInstalled() && headscale.isJoined(this._cfg.headscale_server || 'https://hs.claw.cutos.ai'),
|
||||||
local_ip: getLocalIps(),
|
local_ip: getLocalIps(),
|
||||||
local_networks: getLocalNetworks(),
|
local_networks: getLocalNetworks(),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const DEFAULTS = {
|
|||||||
/** 云端已激活:用于启动/重连时立即点亮 alarm(pwr),不等首包 connected */
|
/** 云端已激活:用于启动/重连时立即点亮 alarm(pwr),不等首包 connected */
|
||||||
activated: false,
|
activated: false,
|
||||||
ssh_secret_key: null,
|
ssh_secret_key: null,
|
||||||
|
share_key: null,
|
||||||
headscale_server: 'https://hs.claw.cutos.ai',
|
headscale_server: 'https://hs.claw.cutos.ai',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,6 +29,33 @@ function _generateSshSecretKey() {
|
|||||||
return 'sk-' + bytes.toString('hex');
|
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() {
|
function load() {
|
||||||
let cfg;
|
let cfg;
|
||||||
try {
|
try {
|
||||||
@@ -41,10 +69,16 @@ function load() {
|
|||||||
}
|
}
|
||||||
if (!cfg) cfg = Object.assign({}, DEFAULTS);
|
if (!cfg) cfg = Object.assign({}, DEFAULTS);
|
||||||
|
|
||||||
|
let dirty = false;
|
||||||
if (!cfg.ssh_secret_key) {
|
if (!cfg.ssh_secret_key) {
|
||||||
cfg.ssh_secret_key = _generateSshSecretKey();
|
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;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "clawd",
|
"name": "clawd",
|
||||||
"version": "1.1.9",
|
"version": "1.2.0",
|
||||||
"description": "Claw Box daemon - connects local Linux box to claw.cutos.ai via WebSocket",
|
"description": "Claw Box daemon - connects local Linux box to claw.cutos.ai via WebSocket",
|
||||||
"main": "lib/client.js",
|
"main": "lib/client.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
Reference in New Issue
Block a user