踩坑之路-用户Uid分配

问题背景

开启密码管理功能后,在多个控制台跑脚本反复创建用户并设置密码和删除用户,概率性出现用户设置密码时提示输入旧密码。

定位过程

GDB跟踪进程发现,当配置密码管理功能后,如果配置的用户的密码需要先判断是否修改的是自己的密码(根据UID判断,系统中创建设备用户时,会分配一个UID,该UID分配方式为从头开始查找第一个未使用的)。如果是修改自己的密码,为了增强安全性,防止修改其他用户的密码,需要输入老密码,在老密码验证成功后才能输入新密码。即当出现如下时序时,会出现此问题:

  1. 新增用户A,分配的用户UID为1,用户A登录设备,该登录的控制台中的环境变量存储的UID为1,此时将用户A删除,值为1的UID释放。
  2. 新增用户B,分配的用户UID为1,在A登录的控制台中修改用户B密码,此时有由于用户B的UID为1,需要先输入用户B的旧密码。

问题定位了,怎么解决这个问题呢?首先密码管理使能后的安全检查为对外的规格,不能修改。首先想到的是在判断是自己时增加条件,以增强是否是修改自己的密码,经过仔细考虑之后发现不可行,因为不管是用户名还是uid等等信息都可能是相同的。

后来考虑是否可以在删除时增加限制,当用户在线时不让删除用户的配置,由于设备用户中有用户在线数的数据,刚开始想通过这个数据是否为0进行限制,后来发现不可行,因为用户登录设备分为认证、授权、计费流程,这三个流程均可以配置是否走本地用户上线,而用户在线数只有计费走本地用户上线时才会增加,导致会有多中流程该计数不准,通过该计数判断,问题解决不了,还能有什么办法呢?

突然想到,既然是用户在线信息,linux有专门的/var/run/utmp文件存储用户在线信息,为什么还需要自己判断呢,只需要查找这个文件中是否有当前要删除的用户就行了。由于utmp文件数据访问需要使用系统函数查找,目前没有根据用户名查找记录的功能,使用这个文件数据之前,需要遍历查找是否有满足条件的数据,先看看这个文件相关的函数。

UTMP相关函数

#include <utmp.h>----头文件

int utmpname(const char file);
设置下面utmp函数访问的文件,如果没有设置,则默认为_PATH_UTMP,不过一般会手动设置一次。

void setutent(void);
将指针放到文件的开头,一般访问文件之前,先调用这个函数。

struct utmp getutent(void);
从utmp文件中读取一行,当有数据时,返回当前行的用户数据,当返回值为空时,代表没有信息。特别的,可以用这个函数不停遍历,直至遍历到最后一项数据。

struct utmp getutid(const struct utmp ut);
从utmp中的当前文件位置向前搜索,如果ut->ut_type是RUN_LVL、BOOT_TIME、NEW_TIME或OLD_TIME,该函数将返回第一个ut_type字段与ut->ut_type匹配的数据,如果ut->ut_type是INIT_PROCESS、LOGIN_PROCESS, USER_PROCESS或DEAD_PROCESS,该函数将返回第一个ut_id字段与ut->ut_id匹配的数据。

struct utmp getutline(const struct utmp ut);
从当前文件位置向前搜索utmp文件,仅搜索ut_type为USER_PROCESS或LOGIN_PROCESS的数据,并返回第一条符合要求的数据。

struct utmp pututline(const struct utmp ut);
将用户信息写入到utmp文件,根据getutid()获取文件中的合适位置,即当发现有数据时,覆盖原有数据,如果没有数据时,在文件末尾追加数据。

void endutent(void);
关闭utmp文件,当使用完上面的utmp相关的函数后,调用该函数关闭文件。

总结

修改关键代码如下:

/* 指定需要操作的utmp文件 */
(VOID) utmpname(_PATH_UTMP);
setutent();
pstEntry = getutent();
while (NULL != pstEntry)
{
    if ( 0 == strcmp(username, pstEntry->ut_user))
    {
        /* 有用户在线 ,且uid一致 */
        if ((USER_PROCESS == pstTmp->ut_type) &&(Uid == pstTmp->ut_uid))
        {
        	/* 将f返回值置为 True*/
        	bIsCurUser = true;
        } 
    }
    pstEntry = getutent();
}
endutent();

当发现问题与线用户信息有关时,首先想想是不是与utmp有关,是否能通过utmp中的数据进行判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值