• linux用户及密码的存储和校验方法


    /etc/passwd文件

    在passwd中,每一行代表一个用户记录,每条记录分为7个字段,字段间用':'分割,以下是每个字段的描述。

    • 用户名:用户绑定的名字
    • 加密后的密码(可选)
    • 用户id,用来标识用户
    • 用户组id,表示用户所属组
    • 用户描述信息
    • 用户的家目录
    • 用户命令解释器

    如果第二项密码字段为一个小写的'x',则表示用户的密码存储在/etc/shadow文件中,即在/etc/shadow文件中也有一行对应该用户记录的记录。

    /etc/shadow文件

    shadow是一个包含系统帐户密码信息和可选时间信息的文件。shadow文件每一行代表一条记录,每一条记录有9个字段,以下是每个字段的描述。

    登录用户名:必须对应到/etc/passwd文件中的一条记录中的用户登录名

    • 加密密码:加密后的密码字符串
    • 最后一次密码修改日期
    • 用户更改密码前必须等待的最小密码期限
    • 用户必须更改密码的最大密码期限
    • 密码过期警告时间
    • 密码不活动期
    • 用户到期时间
    • 保留,用于将来扩展其他属性

    测试用户

    新建一个用户test,设置密码为test,然后查看其passwd记录以及shadow记录。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    └─$ sudo adduser --home /home/test --shell /bin/bash test

    Adding user `test' ...

    Adding new group `test' (1001) ...

    configuration error - unknown item 'NONEXISTENT' (notify administrator)

    configuration error - unknown item 'PREVENT_NO_AUTH' (notify administrator)

    Adding new user `test' (1001) with group `test' ...

    configuration error - unknown item 'NONEXISTENT' (notify administrator)

    configuration error - unknown item 'PREVENT_NO_AUTH' (notify administrator)

    Creating home directory `/home/test' ...

    Copying files from `/etc/skel' ...

    New password:

    Retype new password:

    passwd: password updated successfully

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    Changing the user information for test

    Enter the new value, or press ENTER for the default

    Full Name []:

    Room Number []:

    Work Phone []:

    Home Phone []:

    Other []:

    Is the information correct? [Y/n] yes

    └─$ cat /etc/passwd | grep test

    test:x:1001:1001:,,,:/home/test:/bin/bash

    └─$ sudo cat /etc/shadow | grep test

    test:$y$j9T$1L/PH8ddqysyageBD6TnF1$MNm4An/z6LHdRq0JEOnFuviXBequ23gbIG8U1A/f4F.:19

    112:0:99999:7:::

    用户验证API

    可使用crypt和shadow的api对用户和密码进行验证

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    #include

    #include

    char *crypt(const char *key, const char *salt);

    /* General shadow password file API */

    #include

    struct spwd *getspnam(const char *name);

    struct spwd *getspent(void);

    void setspent(void);

    void endspent(void);

    struct spwd *fgetspent(FILE *stream);

    struct spwd *sgetspent(const char *s);

    int putspent(const struct spwd *p, FILE *stream);

    int lckpwdf(void);

    int ulckpwdf(void);

    下面的代码实例让用户输入用户名和密码,通过crypt和shadow API进行检验用户输入的用户名和密码是否匹配?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    /*

    * user_auth - Authentication user name and password.

    * @user: user name.

    * @passwd: user password string.

    *

    * on success return 0, return errno on error.

    */

    int user_auth(const char *user, const char *passwd)

    {

      struct spwd *user_spwd;

      char *encrypted_pwd;

        if (!user || !passwd)

          return -EINVAL;

      user_spwd = getspnam(user);

        if (!user_spwd)

          return -errno;

      encrypted_pwd = crypt(passwd, user_spwd->sp_pwdp);

        if (!encrypted_pwd)

          return -errno;

          return abs(strcmp(encrypted_pwd, user_spwd->sp_pwdp));

    }

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

    {

      int ret; 

      char *user = argv[1];

      char *passwd = argv[2];

      ret = user_auth(user, passwd);

      if (ret < 0) {

        printf("user auth failed, ret=%d\n", ret);

        return ret;

    }

      if (ret > 0) {

        printf("passwd not match, auth failed\n");

        return ret;

    }

        printf("auth okay!\n");

        return 0;

    }

    编译该程序是指定链接库crypt

    1

    gcc auth.c -lcrypt

    然后使用该程序验证我们添加的用户test,密码是test,正确的输入用户名和密码时输出结果如下:

    1

    2

    └─$ sudo ./a.out test test

    auth okay!

    如果故意输入错误密码,再次执行得到如下结果:

    1

    2

    └─$ sudo ./a.out test hello

    passwd not match, auth failed

  • 相关阅读:
    HTTP 协议详解-上(Fiddler 抓包演示)
    测试驱动开发 002:VSCode + CMake + Unity 环境搭建
    Java剑指Offer根据前序中序重建二叉树
    linux基础知识学习
    Intellij插件之ExtensionPoints
    SCHNOKA施努卡:缺陷检测工业视觉 机器视觉工件表面缺陷检测
    hdu 3549 Flow Problem(最大流模板题)
    TorchDrug教程--分子生成
    Qt控件设置Icon
    1160 队列安排
  • 原文地址:https://blog.csdn.net/sinat_40572875/article/details/128012995