文件
PazeSSH/apps/useradd/main.c
T

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;
}