passwd程序功能实现

实验涉及创建一个类/etc/shadow文件aaa,并编写lab2.c程序模拟passwd功能。程序要求root用户能修改所有用户信息,普通用户只能修改自己的。通过一系列步骤,包括文件权限设置、程序编译及权限调整,最终实现安全的用户密码修改操作。测试结果显示程序运行正常,符合预期。

实验内容:

自己编制文件和程序,仿制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用户尝试修改fantasyhehe的密码:

因为shadow文件中存的密码是经过sha-512散列后得到的散列值,这里为了方便查看所以把fantasyhehe两个用户的密码都修改为'1',以做对比:

修改后的aaa文件内容:

可以看出这时fantasy的密码与hehe的密码相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值