/etc/passwd- 和/etc/shadow-文件
今天偶尔看到系统里有/etc/passwd- 和/etc/shadow-文件,经测试只要执行过系统的用户操作命令就会产生,如deluser、passwd、chpasswd、adduser等命令,应该是这些命令修改文件前会做备份。
在busybox中,这些命令都会调用以下函数,红色部分为其创建/etc/passwd- 或/etc/shadow-代码:
int FAST_FUNC update_passwd(const char *filename,
const char *name,
const char *new_passwd,
const char *member)
{
#if !(ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP)
#define member NULL
#endif
struct stat sb;
struct flock lock;
FILE *old_fp;
FILE *new_fp;
char *fnamesfx;
char *sfx_char;
char *name_colon;
unsigned user_len;
int old_fd;
int new_fd;
int i;
int changed_lines;
int ret = -1; /* failure */
/* used as a bool: "are we modifying /etc/shadow?" */
#if ENABLE_FEATURE_SHADOWPASSWDS
const char *shadow = strstr(filename, "shadow");
#else
# define shadow NULL
#endif
filename = xmalloc_follow_symlinks(filename);
if (filename == NULL)
return ret;
check_selinux_update_passwd(name);
/* New passwd file, "/etc/passwd+" for now */
fnamesfx = xasprintf("%s+", filename);
sfx_char = &fnamesfx[strlen(fnamesfx)-1];
name_colon = xasprintf("%s:", name);
user_len = strlen(name_colon);
if (shadow)
old_fp = fopen(filename, "r+");
else
old_fp = fopen_or_warn(filename, "r+");
if (!old_fp) {
if (shadow)
ret = 0; /* missing shadow is not an error */
goto free_mem;
}
old_fd = fileno(old_fp);
selinux_preserve_fcontext(old_fd);
/* Try to create "/etc/passwd+". Wait if it exists. */
i = 30;
do {
// FIXME: on last iteration try w/o O_EXCL but with O_TRUNC?
new_fd = open(fnamesfx, O_WRONLY|O_CREAT|O_EXCL, 0600);
if (new_fd >= 0) goto created;
if (errno != EEXIST) break;
usleep(100000); /* 0.1 sec */
} while (--i);
bb_perror_msg("can't create '%s'", fnamesfx);
goto close_old_fp;
created:
if (!fstat(old_fd, &sb)) {
fchmod(new_fd, sb.st_mode & 0777); /* ignore errors */
fchown(new_fd, sb.st_uid, sb.st_gid);
}
errno = 0;
new_fp = xfdopen_for_write(new_fd);
/* Backup file is "/etc/passwd-" */
*sfx_char = '-';
/* Delete old backup */
i = (unlink(fnamesfx) && errno != ENOENT);
/* Create backup as a hardlink to current */
if (i || link(filename, fnamesfx))
bb_perror_msg("warning: can't create backup copy '%s'",
fnamesfx);
*sfx_char = '+';
/* Lock the password file before updating */
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
if (fcntl(old_fd, F_SETLK, &lock) < 0)
bb_perror_msg("warning: can't lock '%s'", filename);
lock.l_type = F_UNLCK;
/* Read current password file, write updated /etc/passwd+ */
changed_lines = 0;
while (1) {
char *cp, *line;
line = xmalloc_fgetline(old_fp);
if (!line) /* EOF/error */
break;
if (strncmp(name_colon, line, user_len) != 0) {
fprintf(new_fp, "%s\n", line);
goto next;
}
/* We have a match with "name:"... */
cp = line + user_len; /* move past name: */
#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP
if (member) {
/* It's actually /etc/group+, not /etc/passwd+ */
if (ENABLE_FEATURE_ADDUSER_TO_GROUP
&& applet_name[0] == 'a'
) {
/* Add user to group */
fprintf(new_fp, "%s%s%s\n", line,
last_char_is(line, ':') ? "" : ",",
member);
changed_lines++;
} else if (ENABLE_FEATURE_DEL_USER_FROM_GROUP
/* && applet_name[0] == 'd' */
) {
/* Delete user from group */
char *tmp;
const char *fmt = "%s";
/* find the start of the member list: last ':' */
cp = strrchr(line, ':');
/* cut it */
*cp++ = '\0';
/* write the cut line name:passwd:gid:
* or name:!:: */
fprintf(new_fp, "%s:", line);
/* parse the tokens of the member list */
tmp = cp;
while ((cp = strsep(&tmp, ",")) != NULL) {
if (strcmp(member, cp) != 0) {
fprintf(new_fp, fmt, cp);
fmt = ",%s";
} else {
/* found member, skip it */
changed_lines++;
}
}
fprintf(new_fp, "\n");
}
} else
#endif
if ((ENABLE_PASSWD && applet_name[0] == 'p')
|| (ENABLE_CHPASSWD && applet_name[0] == 'c')
) {
/* Change passwd */
cp = strchrnul(cp, ':'); /* move past old passwd */
if (shadow && *cp == ':') {
/* /etc/shadow's field 3 (passwd change date) needs updating */
/* move past old change date */
cp = strchrnul(cp + 1, ':');
/* "name:" + "new_passwd" + ":" + "change date" + ":rest of line" */
fprintf(new_fp, "%s%s:%u%s\n", name_colon, new_passwd,
(unsigned)(time(NULL)) / (24*60*60), cp);
} else {
/* "name:" + "new_passwd" + ":rest of line" */
fprintf(new_fp, "%s%s%s\n", name_colon, new_passwd, cp);
}
changed_lines++;
} /* else delete user or group: skip the line */
next:
free(line);
}
if (changed_lines == 0) {
#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP
if (member) {
if (ENABLE_ADDGROUP && applet_name[0] == 'a')
bb_error_msg("can't find %s in %s", name, filename);
if (ENABLE_DELGROUP && applet_name[0] == 'd')
bb_error_msg("can't find %s in %s", member, filename);
}
#endif
if ((ENABLE_ADDUSER || ENABLE_ADDGROUP)
&& applet_name[0] == 'a' && !member
) {
/* add user or group */
fprintf(new_fp, "%s%s\n", name_colon, new_passwd);
changed_lines++;
}
}
fcntl(old_fd, F_SETLK, &lock);
/* We do want all of them to execute, thus | instead of || */
errno = 0;
if ((ferror(old_fp) | fflush(new_fp) | fsync(new_fd) | fclose(new_fp))
|| rename(fnamesfx, filename)
) {
/* At least one of those failed */
bb_perror_nomsg();
goto unlink_new;
}
/* Success: ret >= 0 */
ret = changed_lines;
unlink_new:
if (ret < 0)
unlink(fnamesfx);
close_old_fp:
fclose(old_fp);
free_mem:
free(fnamesfx);
free((char *)filename);
free(name_colon);
return ret;
}
/etc/passwd- 和/etc/shadow-文件的更多相关文章
- etc/passwd 和 /etc/shadow 文件内容及其解释
/etc/passwd 和 /etc/shadow 文件内容及其解释 默认情况下,/etc/passwd 存储有关本地用户的信息 /etc/passwd 采用以下格式: 1)username ...
- linux下/etc/passwd和/etc/shadow文件
/etc/passwd文件中保存的是用户的账号信息,而/etc/shadow文件中保存的是用户的口令信息. 一 /etc/passwd 一个用户对应着该文件中一行记录,一行记录由若干个字段组成,字段之 ...
- linux中/etc/passwd和/etc/shadow文件说明
/etc/passwd是用来存储登陆用户信息: [root@localhost test]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x ...
- linux 系统中 /etc/passwd 和 /etc/shadow文件详解
链接地址:http://blog.csdn.net/yaofeino1/article/details/54616440
- linux用户和组管理,/etc/passwd 、/etc/shadow和/etc/group 文件内容解释
与用户相关的系统配置文件主要有/etc/passwd 和/etc/shadow,其中/etc/shadow是用户资讯的加密文件,比如用户的密码口令的加密保存等: /etc/passwd 和/etc/s ...
- linux 里 /etc/passwd 、/etc/shadow和/etc/group 文件内容解释
•/etc/passwd文件用于存放用户账户信息,每行代表一个账户,每个账户的各项信息用冒号分割,例如: root:x:::root:/root:/bin/bash username:password ...
- linux用户和组管理,/etc/passwd 、/etc/shadow和/etc/group --学习
一./etc/passwd 和/etc/shadow解释 与用户相关的系统配置文件主要有/etc/passwd 和/etc/shadow,其中/etc/shadow是用户资讯的加密文件,比如用户的密码 ...
- /etc/passwd&/etc/shadow文件分析
/etc/passwd该目录存储的是操作系统用户信息,该文件为所有用户可见.给linux系统添加一个帐号:useradd -g mysql -d /home/test -m test(:新建一个用户t ...
- Linux中/etc/passwd文件与/etc/shadow文件解析.
此文章转载自"慧可",用来学习. 1. /etc/passwd文件 1.1 /etc/passwd文件内容格式 用户名: 密码 : uid : gid :用户描述:主目录:登陆s ...
- /etc/shadow,/etc/passwd,/etc/shadow,/etc/passwd文件的内容解释
1.1 /etc/passwd文件内容格式 该目录存储的是操作系统用户信息,该文件为所有用户可见 用户名: 密码 : uid : gid :用户描述:主目录:登陆shell 举个 ...
随机推荐
- spring aop 之annotation
1.CutPointInterface public interface CutPointInterface { void method(); } 2.CutPointClass @Component ...
- SharePreferences
SharePreferences是一种轻量级的数据存储方式,它是以key-value的形式保存在 data/data/<packagename>/shared_prefs 下的xml文件中 ...
- 解决在html中引入font-awesome的css文件后, 图标显示不出来
今天小颖在做项目时,需要在html文件中引入font-awesome.min.css,但是引入后: 以前小颖在用font-awesome库里的图标时,都是直接从node中下包,然后在main.js中引 ...
- jmeter中split分隔字符
jmeter中自带了split函数,但是,注意但是,不能使用"-",","等等符合,否则会报错. 没办法,转投入beanshell的怀抱,使用split,发现& ...
- B - Is It A Tree?
来源 hdu 1325 A tree is a well-known data structure that is either empty (null, void, nothing) or is a ...
- [LintCode] Max Points on a Line 共线点个数
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...
- nodejs的koa2框架
官网文档 cnpm i --save-dev koa2 koa-router koa-body koa-static request npm install --save koa2 const koa ...
- day9 九、函数
一.函数 1.函数:可以完成特定功能的代码块,函数就是存放代码块的容器 2.定义函数的语法: 函数四部分:(函数执行的本质:执行函数体,得到函数返回值) ①函数名 ②函数体 ③返回值 ④参数 用def ...
- db2 cpu使用率高问题分析处理
性能调优步骤 明确问题->收集数据->分析数据->细化.定位问题->优化 环境: db2 问题:%usr CPU高,大约99%,db2sysc进程使用的最多 收集数据 ---系 ...
- ubuntu汉化
寻找 Simplified Chinese,点击下面的apply 回到这里在最下面找到刚刚安装的语言,是灰色的,左键点击,将它拖到最上面,点击应用到整个系统,配置完成.重启系统就变成中文了. 晚上不要 ...