1303 files changed, 32187 insertions, 57138 deletions
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c index b2d0464..95423d1 100644 --- a/libbb/update_passwd.c +++ b/libbb/update_passwd.c @@ -30,7 +30,18 @@ static void check_selinux_update_passwd(const char *username) if (!seuser) bb_error_msg_and_die("invalid context '%s'", context); if (strcmp(seuser, username) != 0) { - if (selinux_check_passwd_access(PASSWD__PASSWD) != 0) + security_class_t tclass; + access_vector_t av; + + tclass = string_to_security_class("passwd"); + if (tclass == 0) + goto die; + av = string_to_av_perm(tclass, "passwd"); + if (av == 0) + goto die; + + if (selinux_check_passwd_access(av) != 0) + die: bb_error_msg_and_die("SELinux: access denied"); } if (ENABLE_FEATURE_CLEAN_UP) @@ -62,6 +73,8 @@ static void check_selinux_update_passwd(const char *username) only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd + 8) delete a user from all groups: update_passwd(FILE, NULL, NULL, MEMBER) + This function does not validate the arguments fed to it so the calling program should take care of that. @@ -82,7 +95,6 @@ int FAST_FUNC update_passwd(const char *filename, char *fnamesfx; char *sfx_char; char *name_colon; - unsigned user_len; int old_fd; int new_fd; int i; @@ -99,13 +111,13 @@ int FAST_FUNC update_passwd(const char *filename, if (filename == NULL) return ret; - check_selinux_update_passwd(name); + if (name) + 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); + name_colon = xasprintf("%s:", name ? name : ""); if (shadow) old_fp = fopen(filename, "r+"); @@ -167,13 +179,47 @@ int FAST_FUNC update_passwd(const char *filename, line = xmalloc_fgetline(old_fp); if (!line) /* EOF/error */ break; - if (strncmp(name_colon, line, user_len) != 0) { + +#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP + if (!name && member) { + /* Delete member from all groups */ + /* line is "GROUP:PASSWD:[member1[,member2]...]" */ + unsigned member_len = strlen(member); + char *list = strrchr(line, ':'); + while (list) { + list++; + next_list_element: + if (is_prefixed_with(list, member)) { + char c; + changed_lines++; + c = list[member_len]; + if (c == '\0') { + if (list[-1] == ',') + list--; + *list = '\0'; + break; + } + if (c == ',') { + overlapping_strcpy(list, list + member_len + 1); + goto next_list_element; + } + changed_lines--; + } + list = strchr(list, ','); + } + fprintf(new_fp, "%s\n", line); + goto next; + } +#endif + + cp = is_prefixed_with(line, name_colon); + if (!cp) { fprintf(new_fp, "%s\n", line); goto next; } /* We have a match with "name:"... */ - cp = line + user_len; /* move past name: */ + /* cp points past "name:" */ #if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP if (member) { |