我想使用 C++ 更改任何 Linux 用户密码,任何解决方案都会很棒。
我需要手动完成,这意味着打开文件(不能使用 system()):
似乎我也需要锁定这些文件。有打开.txt文件和读取内容的c代码示例,但无法读取大内容,这也是问题。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <stdlib.h>
#include <string>
const char* path = "/tmp/log.txt";
void read_file()
{
int fd;
char buf[1000];
int i;
fd = open(path, O_RDONLY);
flock(fd, LOCK_SH);
for(i=0; i < 255 ; i++) {
read(fd, &buf[i], 1);
usleep(10 * 10); // 10 ms
}
flock(fd, LOCK_UN);
close(fd);
printf("reader: %#x: %s\n", getpid(), buf);
usleep(10 * 10); // 10 ms
}
void reader()
{
read_file();
exit(0);
}
int main()
{
setlinebuf(stdout);
reader();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在理想的解决方案中,它必须像这样工作:
有人可以解释我需要使用哪个文件来更改密码以及如何正确打开它而不伤害系统吗?如何准确编辑密码所在的那一行?
目前我正在 Ubuntu 16.04 上工作。
编辑
我在评论中看到普通用户无法访问这些文件。一个评论是授予每个用户更改任何用户密码的权限。那么如果一个用户有权编辑这些文件并更改任何用户的密码呢?安全打开和编辑系统文件shadow,保存和关闭它的方法也是如此。我需要以某种方式锁定它或如何访问它?
这里是shadow文件结构,因为所有可以看到有特殊的散列或隐窝密码,因此,如果变化是正常和保存文件,密码必须改变。
我使用用户名获取用户数据的代码:
#include <stdio.h>
#include <pwd.h>
#include <iostream>
using namespace std;
int main()
{
struct passwd *p_entry1, *p_entry2;
char* username;
cout<<"Insert username: ";
cin>>username;
/* Find user data by entered username */
p_entry1 = getpwnam(username);
printf("username = %s = %s"
" userid = %d group id = %d"
" real name = %s directory = %s"
" primary shell = %s",
p_entry1->pw_name, p_entry1->pw_passwd,
p_entry1->pw_uid, p_entry1->pw_gid,
p_entry1->pw_gecos, p_entry1->pw_dir,
p_entry1->pw_shell);
}
Run Code Online (Sandbox Code Playgroud)
要更改用户的密码,您可以使用putpwent和putspent从功能<pwd.h>和<shadow.h>分别。这样您就不需要显式读取、解析和写入 passwd 和 shadow 文件。
关于权限:
如果您不愿意以 root 身份运行您的程序,另一种方法是为您的可执行文件授予setuid权限,就像passwd可执行文件本身一样。
chown root.root <executable>
chmod u+s <executable>
Run Code Online (Sandbox Code Playgroud)
一个setuid方案是根据其拥有者的特权/权限(在这种情况下执行root),所以你授予的二进制所有者的特权/权限。
如果您的二进制文件归所有者所有root并且具有suid权限,则它将能够更改/etc/passwd和任何其他只能root访问的文件。这非常方便,但同时也可能非常危险。例如,如果您的程序有错误或不可预见的情况,恶意用户可能会利用它来获得系统中的 root 权限/访问权限。
编写安全程序似乎很简单,但它有各种问题。祝你好运!