134 行
4.1 KiB
C
134 行
4.1 KiB
C
/* pssh useradd —— 向用户库添加用户 (pssh sshd 用)
|
|
*
|
|
* 默认写入 ~/.pssh/users.conf (-f 可覆盖)。
|
|
* 密码以 SHA256 摘要存储, 不落明文。
|
|
*/
|
|
#include "paze/ssh.h"
|
|
#include "paze/hash.h"
|
|
#include "paze/encoding.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <direct.h>
|
|
#define MKDIR(p) _mkdir(p)
|
|
#else
|
|
#include <sys/stat.h>
|
|
#define MKDIR(p) mkdir(p, 0755)
|
|
#endif
|
|
|
|
static char *read_file(const char *path) {
|
|
FILE *fp = fopen(path, "rb");
|
|
if (!fp) return NULL;
|
|
long sz;
|
|
if (fseek(fp, 0, SEEK_END) != 0 || (sz = ftell(fp)) < 0 ||
|
|
fseek(fp, 0, SEEK_SET) != 0) {
|
|
fclose(fp);
|
|
return NULL;
|
|
}
|
|
char *buf = (char *)malloc((size_t)sz + 1);
|
|
if (!buf) { fclose(fp); return NULL; }
|
|
size_t rd = fread(buf, 1, (size_t)sz, fp);
|
|
fclose(fp);
|
|
buf[rd] = '\0';
|
|
return buf;
|
|
}
|
|
|
|
static int ensure_dir(const char *dir) {
|
|
if (dir[0] == '\0') return 0;
|
|
if (MKDIR(dir) == 0 || errno == EEXIST) return 0;
|
|
return -1;
|
|
}
|
|
|
|
int pssh_cmd_useradd(int argc, char **argv) {
|
|
if (argc < 2) {
|
|
fprintf(stderr,
|
|
"用法: pssh useradd <name> [-pwd <密码>] [-perm <0|1|2>] [-f <file>]\n"
|
|
" -pwd <密码> 必填; 以 SHA256 摘要存储, 不存明文\n"
|
|
" -perm <n> 权限: 0=受限(仅回显), 1=普通(默认, 允许 shell/exec), 2=管理员(全部)\n"
|
|
" -f <file> 用户库文件 (默认 ~/.pssh/users.conf)\n");
|
|
return 1;
|
|
}
|
|
const char *name = argv[1];
|
|
const char *pwd = NULL;
|
|
int perm = PSSH_PERM_USER;
|
|
char path[1024] = "";
|
|
for (int i = 2; i < argc; i++) {
|
|
if (strcmp(argv[i], "-pwd") == 0 && i + 1 < argc) pwd = argv[++i];
|
|
else if (strcmp(argv[i], "-perm") == 0 && i + 1 < argc) perm = atoi(argv[++i]);
|
|
else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) {
|
|
snprintf(path, sizeof(path), "%s", argv[++i]);
|
|
}
|
|
}
|
|
if (!pwd || !*pwd) { fprintf(stderr, "pssh useradd: 需要 -pwd <密码>\n"); return 1; }
|
|
if (strlen(name) >= 64) { fprintf(stderr, "pssh useradd: 用户名过长\n"); return 1; }
|
|
if (perm < PSSH_PERM_GUEST || perm > PSSH_PERM_ADMIN) {
|
|
fprintf(stderr, "pssh useradd: 权限必须是 0/1/2\n");
|
|
return 1;
|
|
}
|
|
|
|
/* 默认用户库路径: ~/.pssh/users.conf */
|
|
if (path[0] == '\0') {
|
|
const char *home = getenv("USERPROFILE");
|
|
if (!home) home = getenv("HOME");
|
|
if (home) snprintf(path, sizeof(path), "%s/.pssh/users.conf", home);
|
|
else snprintf(path, sizeof(path), ".pssh/users.conf");
|
|
}
|
|
|
|
/* SHA256(password) → hex */
|
|
paze_sha256_ctx_t c;
|
|
paze_sha256_init(&c);
|
|
paze_sha256_update(&c, (const uint8_t *)pwd, strlen(pwd));
|
|
uint8_t digest[32];
|
|
paze_sha256_final(&c, digest);
|
|
char hex[65];
|
|
paze_hex_encode(digest, 32, hex);
|
|
hex[64] = '\0';
|
|
|
|
/* 检查重复用户 */
|
|
char *text = read_file(path);
|
|
if (text) {
|
|
static ssh_user_t users[128];
|
|
int n = ssh_userdb_parse(text, users, 128);
|
|
free(text);
|
|
if (n < 0) {
|
|
fprintf(stderr, "pssh useradd: 用户库格式错误: %s\n", path);
|
|
return 1;
|
|
}
|
|
for (int i = 0; i < n; i++) {
|
|
if (strcmp(users[i].name, name) == 0) {
|
|
fprintf(stderr, "pssh useradd: 用户 '%s' 已存在\n", name);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 确保目录存在 */
|
|
char dir[1024];
|
|
snprintf(dir, sizeof(dir), "%s", path);
|
|
char *slash = strrchr(dir, '/');
|
|
#ifdef _WIN32
|
|
if (!slash) slash = strrchr(dir, '\\');
|
|
#endif
|
|
if (slash) {
|
|
*slash = '\0';
|
|
if (ensure_dir(dir) != 0) {
|
|
fprintf(stderr, "pssh useradd: 无法创建目录 %s\n", dir);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
FILE *fp = fopen(path, "a");
|
|
if (!fp) {
|
|
fprintf(stderr, "pssh useradd: 无法写入 %s\n", path);
|
|
return 1;
|
|
}
|
|
fprintf(fp, "%s:%s:%d\n", name, hex, perm);
|
|
fclose(fp);
|
|
|
|
fprintf(stderr, "pssh useradd: 已添加用户 '%s' (perm=%d) → %s\n", name, perm, path);
|
|
return 0;
|
|
}
|