免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4338 | 回复: 8
打印 上一主题 下一主题

[C] [原创]linux下非交互方式修改用户密码程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-28 16:19 |只看该作者 |倒序浏览
cpasswd.rar (1.31 KB, 下载次数: 56)
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>


#define CP_OK 0
#define CP_ERR_PARAMETER 1
#define CP_ERR_NO_OLDPASSWD 2
#define CP_ERR_NO_NEWPASSWD 3
#define CP_ERR_PIPE 3
#define CP_ERR_FORK 4
#define CP_ERR_DUP 5
#define CP_ERR_WRONG_PASSWD 6
#define CP_ERR_SIMPLE_CHK 7
#define CP_ERR_NO_MATCH 8
#define CP_ERR_OTHER 9

int main(int argc, char *argv[])
{

    int fd_w[2],fd_r[2],ret;
    char buf[256];
    char prompt_1[]="New password:";
    char prompt_2[]="Retype new password:";
    char prompt_3[]="(current) UNIX password:";
    char prompt_4[]="passwd: Authentication token manipulation error";
    char prompt_5[]="BAD PASSWORD";
    char prompt_6[]="Sorry, passwords do not match";

    int i=0;
    pid_t pid;
    fd_set readset;

    uid_t userid;
    char new_password[256]={0};
    char old_password[256]={0};
    char user_name[256]={0};
    struct timeval tv;

    int ch;
    while((ch = getopt(argc,argv,"n:u:h"))!= -1)
    {
        switch(ch)
        {
            case 'n':
                strncpy(new_password,optarg,30);
                strncat(new_password,"\n",1);
                break;
            case 'o':
                strncpy(old_password,optarg,30);
                strncat(old_password,"\n",1);
                break;
            case 'u':
                strncpy(user_name,optarg,30);
                break;
            default:
                printf("usage:%s -n new_password [ -o old_password :is needs if not root ] [ -u username :can use only root ]\n",argv[0]);
                return CP_ERR_PARAMETER;
        }
    }

    if(strlen(new_password) == 0)
    {
        printf("you must specify a new password by parameter -n\n");
        printf("usage:%s -n new_password [ -o old_password :is needs if not root ] [ -u username :can use only root ]\n",argv[0]);
        return CP_ERR_NO_NEWPASSWD;
    }
   
    userid = getuid();
    if(userid != 0)/*not root*/
    {
        if(strlen(old_password) == 0)
        {
            printf("the current password is needs\n");
            return CP_ERR_NO_OLDPASSWD;
        }
    }
   
    FD_ZERO(&readset);
    if(pipe(fd_w) != 0)
    {
        perror("pipe");
        return CP_ERR_PIPE;
    }

    if(pipe(fd_r) != 0)
    {
        perror("pipe");
        return CP_ERR_PIPE;
    }


    FD_SET(fd_w[0],&readset);
    pid=fork();
    if(pid < 0)
    {
        perror("fork");
        return CP_ERR_FORK;
    }
    else if(pid==0)/*child*/
    {

        if(dup2(fd_r[0], STDIN_FILENO) != STDIN_FILENO)
        {
            perror("dup2");
            return CP_ERR_DUP;
        }

        if(dup2(fd_w[1], STDERR_FILENO) != STDERR_FILENO)
        {
            perror("dup2");
            return CP_ERR_DUP;
        }

        close(fd_r[1]);
        close(fd_w[0]);
        close(STDOUT_FILENO);
        if(strlen(user_name))
        {
            execl("/usr/bin/passwd","passwd",user_name,(char *)0);   
        }
        else
        {
            execl("/usr/bin/passwd","passwd",(char *)0);
        }
    }
    else/*parent*/
    {

        close(fd_r[0]);
        close(fd_w[1]);
        /* Wait up to 3 seconds. */
        tv.tv_sec = 3;
        tv.tv_usec = 0;      
        for(;;)
        {
            memset(buf,0,256);
            ret=select(fd_w[0]+1,&readset,NULL,NULL,&tv);
            if(ret < 0)
            {
                return CP_ERR_OTHER;
            }

            if(FD_ISSET(fd_w[0],&readset))
            {
                read(fd_w[0],buf,256);
            }
            else
            {
                return CP_ERR_OTHER;
            }

            if(strlen(buf))
            {
                if(userid != 0)
                {
                    
                    if (strstr(buf,prompt_3))
                    {
                        write(fd_r[1],old_password,strlen(old_password));
                    }
                    if(strstr(buf,prompt_4))
                    {   
                        return CP_ERR_WRONG_PASSWD;
                    }
                    if( strstr(buf,prompt_5))
                    {
                        return CP_ERR_SIMPLE_CHK;
                    }   
                    if(strstr(buf,prompt_6))
                    {
                        return CP_ERR_NO_MATCH;
                    }


                }
                if(strstr(buf,prompt_1) || strstr(buf,prompt_2))
                {
                    write(fd_r[1],new_password,strlen(new_password));
                    i++;
                    if(i==2)
                    {
                        return CP_OK;
                    }
                }
            }
        }
    }
}

论坛徽章:
0
2 [报告]
发表于 2009-04-28 19:07 |只看该作者
十分鼓励一下

但是,使用Shell去做这件事更恰当



  1. sed -i -e 's/^username:[^:]+/username:`echo passwd|sha1sum|awk \'{print $1}\'`/' /etc/shadow
复制代码

论坛徽章:
0
3 [报告]
发表于 2009-04-28 19:08 |只看该作者
另外,passwd的源代码,可以免费获取

论坛徽章:
0
4 [报告]
发表于 2009-04-28 19:12 |只看该作者
同意LS

以前我也经常写一些小程序去完成一些简单操作

现在发同用shell更方便

论坛徽章:
0
5 [报告]
发表于 2009-04-28 20:15 |只看该作者
楼上的方法在普通用户模式下可行吗?再者这个程序提出了一个不用expect控制交互程序的方法,在很多地方应该有一定借鉴意义。

论坛徽章:
0
6 [报告]
发表于 2009-04-28 20:19 |只看该作者
另外sha1sum的计算结果在我的机器上跟shadow里面完全不一样啊。我的机器是redhat 9.0

论坛徽章:
0
7 [报告]
发表于 2009-04-28 22:44 |只看该作者
学习一下

论坛徽章:
0
8 [报告]
发表于 2009-04-29 11:28 |只看该作者
原帖由 weiqiboy 于 2009-4-28 20:19 发表
另外sha1sum的计算结果在我的机器上跟shadow里面完全不一样啊。我的机器是redhat 9.0

你发现了,那最好


我给出的只是一个思路,不是最终的方案

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2009-04-29 11:40 |只看该作者
想自己写程序改密码是好事,引导好了,可以叩开一扇大门的。
伪终端,粘着位
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP