实验内容:
自己编制文件和程序,仿制passwd程序修改/etc/shadow的功能,包括:
a) 自己设置一个类/etc/shadow文件aaa,该文件中约定好内容格式,和读取该文件的程序相配合,文件中包括超级用户及其内容、普通用户及其内容。
b) 编制程序使得:Root用户能够读取和修改aaa文件中所有用户的内容,普通用户仅能够读取和修改aaa文件中属于自己用户的内容。
c) 普通用户能以root身份执行所编制的类passwd程序。
实验过程:
步骤1.
首先要模拟一个/etc/shadow文件,取名为aaa。将shadow中的内容完全粘贴过来,同时修改aaa的拥有者以及文件权限位与shadow文件相同,如图1:
步骤2.
编写lab2.c程序,模拟passwd功能
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <shadow.h>
#include <sys/types.h>
#include <pwd.h>
#include <crypt.h>
#include <stdlib.h>
int main(int argc,char**argv)
{
char judgeInput[2][7]={"show","change"};
uid_t ruid,euid,suid;
int temp;
int showBranch,changeBranch;
showBranch=!strcmp(judgeInput[0],argv[1]);
changeBranch=!strcmp(judgeInput[1],argv[1]);
/*---------------------判断输入是否合法-------------------------*/
if(!((argc==2 && showBranch) || (argc==4 && changeBranch)))
{
printf("Error order!Please input again!\n");
printf("For example:\n./lab2 show\n./lab2 change userName passWord\n");
return -1;
}
/*------------------------------------------------------------*/
if((temp=getresuid(&ruid,&euid,&suid))==-1)
perror("getresuid failed!\n");
else
printf("ruid=%d euid=%d suid=%d\n",ruid,euid,suid);
/*---------------------获得当前用户名---------------------*/
struct passwd* cur;
cur=getpwuid(getuid());
/*---------------------------------------------------------------*/
/*------------------------------------show branch-----------------------------------*/
if(showBranch)
{
struct spwd* p;
FILE *fs;
fs=fopen("aaa","r");
if(!ruid)
{
while((p=fgetspent(fs))!=NULL)
{
printf("Login name:%s\nEncrypted password:%s\nLast change:%ld\nMin age:%ld\nMax age:%ld\nWarn:%ld\nInact:%ld\nExpire:%ld\nFlag:%ld\n\n",p->sp_namp,p->sp_pwdp,p->sp_lstchg,p->sp_min,p->sp_max,p->sp_warn,p->sp_inact,p->sp_expire,p->sp_flag);
}
}
else
{ while((p=fgetspent(fs))!=NULL)
{
if(!strcmp(cur->pw_name,p->sp_namp))
printf("Login name:%s\nEncrypted password:%s\nLast change:%ld\nMin age:%ld\nMax age:%ld\nWarn:%ld\nInact:%ld\nExpire:%ld\nFlag:%ld\n\n",p->sp_namp,p->sp_pwdp,p->sp_lstchg,p->sp_min,p->sp_max,p->sp_warn,p->sp_inact,p->sp_expire,p->sp_flag);
}
}
fclose(fs);
return 0;
}
/*-----------------------------------------------------------------------------------*/
/*------------------------------------change branch----------------------------------*/
char newPassword[10];
char *cryptedPassword;
char userTochange[10];
strcpy(userTochange,argv[2]);
strcpy(newPassword,argv[3]);
struct spwd store[100],*p;
int total=0;
int i;
FILE *fs;
fs=fopen("aaa","r");
int flag=0;
/*----------------------------root 用户可以随意更改任何人的passwd----------------------*/
if(!ruid)
{
while((p=fgetspent(fs))!=NULL)
{
store[total]=*p;
store[total].sp_namp=malloc(strlen(p->sp_namp)+1);
store[total].sp_pwdp=malloc(strlen(p->sp_pwdp)+1);
strcpy(store[total].sp_namp,p->sp_namp);
if(!strcmp(p->sp_namp,userTochange))
{
cryptedPassword=crypt(newPassword,"$6$FaUYKA8B$CUuItcF");
strcpy(store[total].sp_pwdp,cryptedPassword);
flag=1;
}
else
{
strcpy(store[total].sp_pwdp,p->sp_pwdp);
}
total++;
}
}
/*----------------------------------------------------------------------------------*/
/*------------------------------普通用户只能更改自己的passwd--------------------------*/
else
{
if(!strcmp(cur->pw_name,userTochange))
{
while((p=fgetspent(fs))!=NULL)
{
store[total]=*p;
store[total].sp_namp=malloc(strlen(p->sp_namp)+1);
store[total].sp_pwdp=malloc(strlen(p->sp_pwdp)+1);
strcpy(store[total].sp_namp,p->sp_namp);
if(!strcmp(p->sp_namp,userTochange))
{
cryptedPassword=crypt(newPassword,"$6$FaUYKA8B$CUuItcF");
strcpy(store[total].sp_pwdp,cryptedPassword);
flag=1;
}
else
{
strcpy(store[total].sp_pwdp,p->sp_pwdp);
}
total++;
}
}
/*----------------要修改的不是当前用户则直接退出----------------------*/
}
/*------------------------------------------------------------------------------------------------*/
fclose(fs);
if(!flag)
{
printf("failed to change the passwd!\n");
return -1;
}
/*------------------------修改成功,写回--------------------------------*/
else
{
printf("change success!\n");
fs=fopen("aaa","w");
for(i=0;i<total;i++)
putspent(&store[i],fs);
fclose(fs);
}
return 0;
}
步骤3.
编译生成可执行文件lab2,然后将lab2的拥有者以及权限位修改的与系统passwd相同。整个编译修改过程用一个小脚本来实现:
修改后与系统的passwd命令作对比:
步骤4:
测试lab2(passwd)程序。
非法输入:
普通用户读取:
Root用户读取:
普通用户尝试修改自己(fantasy)和修改其他用户(hehe)的密码:
root用户尝试修改fantasy和hehe的密码:
因为shadow文件中存的密码是经过sha-512散列后得到的散列值,这里为了方便查看所以把fantasy和hehe两个用户的密码都修改为'1',以做对比:
修改后的aaa文件内容:
可以看出这时fantasy的密码与hehe的密码相同。
实验涉及创建一个类/etc/shadow文件aaa,并编写lab2.c程序模拟passwd功能。程序要求root用户能修改所有用户信息,普通用户只能修改自己的。通过一系列步骤,包括文件权限设置、程序编译及权限调整,最终实现安全的用户密码修改操作。测试结果显示程序运行正常,符合预期。

1万+

被折叠的 条评论
为什么被折叠?



