首页 > 其他分享 >APUE03 - 系统数据文件与时间

APUE03 - 系统数据文件与时间

时间:2024-10-30 10:16:59浏览次数:3  
标签:数据文件 密码 passwd APUE03 系统 用户 etc shadow pw

/etc/passwd

在 Linux 和 Unix 系统中,/etc/passwd 是一个重要的系统文件,用于存储用户账户的信息。尽管文件名是 passwd,但它并不保存用户密码(密码通常存储在 /etc/shadow 文件中),而是包含用户的基本信息。

/etc/passwd 文件结构

每行代表一个用户账户,字段由冒号 : 分隔。每行的格式如下:

ruby
复制代码
username:password:UID:GID:GECOS:home:shell

字段说明

  1. username:用户名。

  2. password:加密后的密码的占位符,通常是 x 或 ``,表示实际密码存储在 /etc/shadow 中。

  3. UID:用户的唯一标识符(User ID)。

  4. GID:用户主组的唯一标识符(Group ID)。

  5. GECOS:用户的全名或描述信息(可以包括其他信息,如电话号码)。

  6. home:用户的主目录路径。

  7. shell:用户登录后使用的默认 shell。

示例

以下是 /etc/passwd 文件中的一行示例:

johndoe:x:1001:1001:John Doe,,,:/home/johndoe:/bin/bash

在这个示例中:

  • 用户名是 johndoe

  • 密码字段是 x,表示实际密码在 /etc/shadow 中。

  • UID 和 GID 都是 1001

  • GECOS 字段包含了用户的全名。

  • 用户的主目录是 /home/johndoe

  • 默认 shell 是 /bin/bash

这些信息可以使用下面的 api 获取:

getpwuid //根据用户 ID 获取用户账户信息。
getpwent // 读取下一个用户账户信息。
getpwnam // 根据用户名获取用户账户信息。

他们返回一个 passwd 结构体。

passwd 结构体定义

struct passwd {
    char   *pw_name;   // 用户名
    char   *pw_passwd; // 密码的占位符(通常是 x,表示在 /etc/shadow 中)
    uid_t   pw_uid;    // 用户的唯一标识符(User ID)
    gid_t   pw_gid;    // 用户主组的唯一标识符(Group ID)
    char   *pw_gecos;  // 用户的全名或描述信息
    char   *pw_dir;    // 用户的主目录路径
    char   *pw_shell;  // 用户登录后使用的默认 shell
};

字段说明

  1. **pw_name**:用户名,表示用户的登录名。

  2. **pw_passwd**:密码字段的占位符。通常为 x,表示密码实际上存储在 /etc/shadow 文件中,以提高安全性。

  3. **pw_uid**:用户的唯一标识符(UID),在系统中唯一标识用户。

  4. **pw_gid**:用户主组的唯一标识符(GID),表示该用户所属的主组。

  5. **pw_gecos**:全名或描述信息,可以包括其他信息(如电话号码)。

  6. **pw_dir**:用户的主目录路径,表示该用户的默认工作目录。

  7. **pw_shell**:用户登录后的默认 shell,通常是 /bin/bash/bin/sh 等。

在 Linux 系统中,/etc/passwd 文件曾经用来保存用户的基本信息,包括密码。然而,出于安全考虑,现代的 Linux 系统将密码从 /etc/passwd 移到了更安全的文件中,原因如下:

  1. 可读权限问题/etc/passwd 文件必须对所有用户可读,因为操作系统和很多程序都需要访问其中的用户信息(例如用户 ID、组 ID、用户名等)。如果密码明文或直接可解的哈希值保存在这个文件中,任何用户都可以读取并尝试破解密码,这存在严重的安全风险。

  2. 引入 /etc/shadow 文件:为了保护密码的安全,密码的哈希值现在存储在 /etc/shadow 文件中。这个文件只有超级用户(root)或具备特殊权限的用户才能读取。这样,即使普通用户可以访问 /etc/passwd,他们也无法获取密码的哈希值,从而提高了系统的安全性。

  3. 分离敏感数据:通过将密码信息和其他用户信息分离,操作系统可以更好地保护敏感数据。/etc/passwd 文件保留用户的基础信息,而密码哈希被转移到 /etc/shadow 文件进行更严格的保护。

/etc/group

/etc/group 文件是 Unix 和 Linux 系统中用来定义用户组的配置文件。它是一个纯文本文件,每一行代表一个组,包含以下几个字段,并用冒号 (:) 分隔:

  1. 组名:表示组的名称。

  2. 密码:通常为 x 或为空,表示组密码,几乎很少用到。

  3. GID:组的唯一标识号(Group ID)。

  4. 用户列表:属于该组的用户列表,多个用户用逗号分隔。

例如,/etc/group 文件内容:

root:x:0:
sudo:x:27:user1,user2
users:x:100:
dev:x:101:user3,user4

在这个例子中:

  • root 组的 GID 为 0,没有其他用户。

  • sudo 组的 GID 为 27,成员有 user1 和 user2

  • users 组的 GID 为 100,没有列出成员。

  • dev 组的 GID 为 101,成员有 user3 和 user4

该文件主要用于管理组的成员关系,系统中的很多工具都会参考这个文件进行权限控制。

获取信息的 api:

getgrnam
getgrgid

返回一个 group 结构体:

struct group {
    char   *gr_name;    // 组名(字符串)
    char   *gr_passwd;  // 组密码(不常用,通常为占位符 "x")
    gid_t  gr_gid;      // 组 ID(GID,Group ID)
    char   **gr_mem;    // 指向用户成员列表的指针数组
};

结构体成员说明:

  1. **gr_name**:指向一个字符串,表示组的名称。

  2. **gr_passwd**:指向组密码的字符串(通常不使用,很多系统都用 x 或者 `` 占位)。

  3. **gr_gid**:表示组的 ID,类型是 gid_t,它是一个整数类型。

  4. **gr_mem**:指向一个以空指针结尾的字符串数组,每个字符串是属于该组的用户名。

/etc/shadow

/etc/shadow 文件是 Linux 和 Unix 系统中存储用户密码及相关信息的文件。为了提高安全性,这个文件只能由超级用户(root)和具有适当权限的进程访问。它包含每个用户的加密密码及其他与密码相关的信息,如密码过期时间、修改时间等。

/etc/shadow 文件的每一行对应一个系统用户,字段用冒号(:)分隔。典型的一行如下所示:

username:password:last_change:min:max:warn:inactive:expire:

字段详细说明:

  1. username(用户名):表示该行对应的系统用户名。

  2. password(加密密码):存储用户的加密密码。如果是空的,用户不需要密码即可登录。如果是* 或 !,表示该账户已被禁用或锁定。

  3. last_change(最后一次密码更改日期):表示从 1970 年 1 月 1 日(Unix 时间的起点)到最后一次更改密码的天数。这是一个整数。

  4. min(最短密码更改间隔):表示两次密码修改之间最少需要的天数。

  5. max(最长密码有效期):表示密码可以使用的最长天数,超过此天数后用户必须更改密码。

  6. warn(密码过期警告天数):表示密码到期前系统警告用户需要更改密码的天数。

  7. inactive(密码失效后的宽限天数):密码过期后,账户失效前允许的天数。如果设置为 1,表示不使用此功能。

  8. expire(账户到期时间):表示账户到期时间,是从 1970 年 1 月 1 日算起的天数。如果设置为 1,表示账户永不过期。

例如,/etc/shadow 文件中的一行可能如下:

user1:$6$YdsC1...$laI7op...:18956:7:90:14:7:20000:
  • user1 是用户名。

  • $6$YdsC1...$laI7op... 是加密后的密码(采用了 SHA-512 哈希算法)。

  • 18956 表示从 1970 年 1 月 1 日起算,用户最后一次更改密码的日期。

  • 7 是密码最短更改间隔(7 天)。

  • 90 是密码最长有效期(90 天)。

  • 14 是密码到期前的警告天数。

  • 7 是密码过期后的宽限天数。

  • 20000 是账户到期时间。

安全性:

/etc/shadow 文件比 /etc/passwd 更安全,因为 /etc/passwd 文件是可读的,而 /etc/shadow 只有 root 和具有超级用户权限的用户才能读取。这是为了防止非授权用户访问加密的密码数据,即使密码经过加密处理,也不应向普通用户公开。

获取信息的 api:

struct spwd *getspnam(const char *name);
struct spwd *getspent(void); // 逐行读取 /etc/shadow 文件的内容

其定义如下:

struct spwd {
    char *sp_namp;   // 用户名
    char *sp_pwdp;   // 加密密码
    long sp_lstchg;  // 上次更改密码的日期(从 1970-01-01 起的天数)
    long sp_min;     // 密码最短使用期限(天数)
    long sp_max;     // 密码最长使用期限(天数)
    long sp_warn;    // 密码到期前的警告天数
    long sp_inact;   // 密码过期后的宽限天数
    long sp_expire;  // 账户到期时间(从 1970-01-01 起的天数)
    unsigned long sp_flag; // 保留字段,未使用
};

可以使用 crypt 函数来校验密码:

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

拿 $6$YdsC1...$laI7op... 举例,字符串中的 $ 是分隔符,该字符串被分割成3段:

  • 算法 ID

  • 加密后的串

key 传递登录密码, salt 需要传 $6$YdsC1... 才行,不然 crypt 函数默认是 DES 加密。

时间

time()
gmtime()
gmtime_r()
localtime()
localtime_r()
mktime()
strftime()
asctime()
asctime_r()
ctime()
ctime_r()

这些函数其实都是在做一个变换。

 

time() 函数返回 time_t 类型,在大多数 64 位系统上,time_t 是 long 或 long long 类型,通常是 64 位的有符号整数。

gmtime/localtime 将 time_t 类型转换成 struct tm 类型的指针。

struct tm {
    int tm_sec;   // 秒 [0, 60]
    int tm_min;   // 分 [0, 59]
    int tm_hour;  // 小时 [0, 23]
    int tm_mday;  // 日 [1, 31]
    int tm_mon;   // 月 [0, 11],0 表示 1 月
    int tm_year;  // 年,自 1900 起
    int tm_wday;  // 一周中的第几天 [0, 6],0 表示周日
    int tm_yday;  // 一年中的第几天 [0, 365]
    int tm_isdst; // 夏令时标志,正数表示启用夏令时,0 表示不使用,负数表示未知
};

mktime 将 tm 转 time_t。

strftime 格式化时间。

asctime/ctime 将时间转出可读字符串。

具体函数原型可看man文档。

注意:在 Linux 中,localtime() 函数将时间(通常是从 time() 函数返回的 time_t 类型)转换为本地时间,并返回一个指向 struct tm 结构体的指针。这个指针指向的内存区域是由 C 库内部维护的一个静态对象,因此它的内容可能会被后续调用的时间相关函数(例如再次调用 localtime() 或 gmtime())修改。

需要熟悉一下,linux API 的设计方式,多看文档,文档里面没有提到需要手动释放函数返回的指针,那么就是静态分配方式。

标签:数据文件,密码,passwd,APUE03,系统,用户,etc,shadow,pw
From: https://blog.csdn.net/a5right/article/details/143358010

相关文章

  • golang驱动系统打印机
    参考项目https://github.com/google/cloud-print-connector谷歌云打印机连接器cupslinux系统winspoolwindows系统https://github.com/lxn/winAWindowsAPIwrapperpackagefortheGoProgrammingLanguagehttps://github.com/antonlahti/go-winapiAWind......
  • C#学习 [类型系统] 命名空间(12)
    作用1.组织类System.Console.WriteLine("HelloWorld!");System是一个命名空间,Console是该命名空间中的一个类。可使用using关键字,这样就不必使用完整的名称。usingSystem;Console.WriteLine("HelloWorld!");控制类和方法名称的范围namespaceSampleNamespace;......
  • C#学习 [类型系统] 类型转换(11)
    隐式类型转换C#以安全方式转换数据类型,例如int到string.strings="1";intd=(int)s;显式类型转换用方法完成数据类型转换序号方法描述1ToBoolean把类型转换为布尔型(如果可以转换的话)2ToByte把类型转换为字节类型。3ToChar把类型转换为单......
  • C#学习 [类型系统] 基本类型介绍(10)
    在变量中指定类型声明变量但不初始化inti;MyClassm;声明且初始化inti=0;MyClassm=newMyClass();方法中参数与返回值指定类型publicintgetValue(inti){returni;}内置变量C#提供了一组标准的内置类型,这些类型可供在任何C#程序中使用。基本......
  • C#学习 [类型系统] 泛型(16)
    使用场景在编译时可以不指定具体类型,在具体使用时指定,从而代码具有较高的通用性。示例代码定义publicclassGenericTest<T>{T[]array;publicGenericTest(intsize){array=newT[size];}publicTget(intindex){re......
  • 【JVM第2课】类加载子系统(类加载器、双亲委派)
    类加载系统加载类时分为三个步骤,加载、链接、初始化,下面展开介绍。文章目录1类加载器1.1引导类加载器(BootStrapClassLoader)1.2拓展类加载器(`ExtClassLoader`)1.3应用类加载器(AppClassLoader)1.4双亲委派2链接2.1验证2.2准备2.3解析3初始化3.1定义3.2主要任......
  • 【毕业设计】基于SpringBoot + Vue的物资综合管理系统
    现代企业管理中,如何高效地进行物资管理,确保数据的准确性和安全性,是一项重要的需求。传统的手工管理方式不仅耗时,还容易出错,无法满足信息化时代的高效要求。本文探讨了一种基于Java开发的物资综合管理系统,旨在提供一套高效、可靠的物资管理解决方案。一、项目背景与意义在信息......
  • 基于Spring Boot+Vue的校园求职招聘系统设计与实现,LW+源码+讲解
    摘 要传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装校园求职招聘系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,校园求职招聘系......
  • java计算机毕业设计在线票务系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,在线票务系统已经成为现代生活中不可或缺的一部分。传统的售票方式面临着排队等候、购票速度慢、安全性差等问题,而在线票务......
  • java计算机毕业设计员工管理系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景、意义和目的随着信息技术的迅猛发展,企业管理和运营的方式也在不断变革。传统的手工管理模式已经无法满足现代企业对效率、准确性和实时性的要求。特......