- 一、UID、EUID、GID、EGID
- 二、代码清单
- 三、切换用户
- 总结
用户信息对于服务器程序的安全性来说是很重要,比如大部分服务器就必须以root身份启动,但不能以root身份运行。
一、UID、EUID、GID、EGID
下面这一组函数可以获取和设置当前进程的真实用户ID(UID)、有效用户ID(EUID)、真实组ID(GID)和有效组ID(EGID):
#include二、代码清单#include uid_t getuid(); uid_t geteuid() gid_t getgid(); gid_t getegid(); int setuid(uid_t uid); int seteuid(uid_t uid); int setgid(gid_t gid); int setegid(gid t gid);
#include#include #include using namespace std; int main() { uid_t uid = getuid(); uid_t euid = geteuid(); cout << "uid:" << uid << ' ' << "euid:" << euid << endl; return 0; }
g++ TestUid.cpp -o test_uid sudo chown root:root test_uid sudo chmod +s test_uid ./test_uid uid:1000 euid:0
从这里可以看出所属权是root的文件test_uid,在设置set-user-id位之后,uid的值是运行该程序的用户UID,euid是该程序所属者UID。
在程序运行的过程中,此进程是特权进程。
实现以root身份启动进程切换为以一个普通用户身份运行:
#include#include using namespace std; static bool switch_to_user(auto user_id, auto gp_id) { if (user_id == 0 && gp_id == 0) return false; auto gid = getgid(); auto uid = getuid(); if ((gid != 0 || uid != 0) && (gid != gp_id || uid != user_id)) return false; if (uid != 0) return false; if ((setgid(gp_id) < 0) || (setuid(user_id) < 0)) return false; return true; } int main() { uid_t old_uid = getuid(); //运行程序者的uid gid_t old_gid = getgid(); //运行程序者的gid cout << "此时uid:" << old_uid << " " << "此时gid:" << old_gid << endl; bool sign = switch_to_user(1000, 1000); if (sign) { cout << "切换成功!" << endl; cout << "此时uid:" << getuid() << " " << "此时gid:" << getgid() << endl; if (setuid(old_uid) == -1 || setgid(old_gid) == -1) cout << "普通用户切换root用户失败!" << endl; else cout << "root用户切换成功" << endl; }else{ cout << "切换失败" << endl; } return 0; }
执行过程:
g++ SwitchUser.cpp -o SwitchUser sudo ./SwitchUser 此时uid:0 此时gid:0 切换成功! 此时uid:1000 此时gid:1000 普通用户切换root用户失败!总结
一个进程拥有两个用户ID:UID和EUID。
EUID存在的目的是方便资源访问:它使得运行程序的用户拥有该程序的有效用户的权限。有效用户为root 的进程称为特权进程。EGID的含义与EUID类似:给运行目标程序的组用户提供有效组的权限。
root用户在运行中可以切换到别的用户,别的用户不能切换回去。



