deluser.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * deluser/delgroup implementation for busybox
  4. *
  5. * Copyright (C) 1999 by Lineo, inc. and John Beppu
  6. * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
  7. * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
  8. *
  9. * Licensed under GPLv2, see file LICENSE in this source tree.
  10. */
  11. //config:config DELUSER
  12. //config: bool "deluser (9.1 kb)"
  13. //config: default y
  14. //config: help
  15. //config: Utility for deleting a user account.
  16. //config:
  17. //config:config DELGROUP
  18. //config: bool "delgroup (6.4 kb)"
  19. //config: default y
  20. //config: help
  21. //config: Utility for deleting a group account.
  22. //config:
  23. //config:config FEATURE_DEL_USER_FROM_GROUP
  24. //config: bool "Support removing users from groups"
  25. //config: default y
  26. //config: depends on DELGROUP
  27. //config: help
  28. //config: If called with two non-option arguments, deluser
  29. //config: or delgroup will remove an user from a specified group.
  30. // APPLET_NOEXEC:name main location suid_type help
  31. //applet:IF_DELUSER( APPLET_NOEXEC(deluser, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, deluser))
  32. //applet:IF_DELGROUP(APPLET_NOEXEC(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup))
  33. //kbuild:lib-$(CONFIG_DELUSER) += deluser.o
  34. //kbuild:lib-$(CONFIG_DELGROUP) += deluser.o
  35. //usage:#define deluser_trivial_usage
  36. //usage: IF_LONG_OPTS("[--remove-home] ") "USER"
  37. //usage:#define deluser_full_usage "\n\n"
  38. //usage: "Delete USER from the system"
  39. // --remove-home is self-explanatory enough to put it in --help
  40. //usage:#define delgroup_trivial_usage
  41. //usage: IF_FEATURE_DEL_USER_FROM_GROUP("[USER] ")"GROUP"
  42. //usage:#define delgroup_full_usage "\n\n"
  43. //usage: "Delete group GROUP from the system"
  44. //usage: IF_FEATURE_DEL_USER_FROM_GROUP(" or user USER from group GROUP")
  45. #include "libbb.h"
  46. int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  47. int deluser_main(int argc, char **argv)
  48. {
  49. /* User or group name */
  50. char *name;
  51. /* Username (non-NULL only in "delgroup USER GROUP" case) */
  52. char *member;
  53. /* Name of passwd or group file */
  54. const char *pfile;
  55. /* Name of shadow or gshadow file */
  56. const char *sfile;
  57. /* Are we deluser or delgroup? */
  58. int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u'));
  59. #if !ENABLE_LONG_OPTS
  60. const int opt_delhome = 0;
  61. #else
  62. int opt_delhome = 0;
  63. if (do_deluser) {
  64. opt_delhome = getopt32long(argv, "",
  65. "remove-home\0" No_argument "\xff");
  66. argv += opt_delhome;
  67. argc -= opt_delhome;
  68. }
  69. #endif
  70. if (geteuid() != 0)
  71. bb_simple_error_msg_and_die(bb_msg_perm_denied_are_you_root);
  72. name = argv[1];
  73. member = NULL;
  74. switch (argc) {
  75. case 3:
  76. if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || do_deluser)
  77. break;
  78. /* It's "delgroup USER GROUP" */
  79. member = name;
  80. name = argv[2];
  81. /* Fallthrough */
  82. case 2:
  83. if (do_deluser) {
  84. /* "deluser USER" */
  85. struct passwd *pw;
  86. pw = xgetpwnam(name); /* bail out if USER is wrong */
  87. pfile = bb_path_passwd_file;
  88. if (ENABLE_FEATURE_SHADOWPASSWDS)
  89. sfile = bb_path_shadow_file;
  90. if (opt_delhome) {
  91. struct stat st;
  92. /* Make sure home is an actual directory before
  93. * removing it (e.g. users with /dev/null as home) */
  94. if (stat(pw->pw_dir, &st) == 0 && S_ISDIR(st.st_mode))
  95. remove_file(pw->pw_dir, FILEUTILS_RECUR);
  96. }
  97. } else {
  98. struct group *gr;
  99. do_delgroup:
  100. /* "delgroup GROUP" or "delgroup USER GROUP" */
  101. if (do_deluser < 0) { /* delgroup after deluser? */
  102. gr = getgrnam(name);
  103. if (!gr)
  104. return EXIT_SUCCESS;
  105. } else {
  106. gr = xgetgrnam(name); /* bail out if GROUP is wrong */
  107. }
  108. if (!member) {
  109. /* "delgroup GROUP" */
  110. struct passwd *pw;
  111. /* Check if the group is in use */
  112. while ((pw = getpwent()) != NULL) {
  113. if (pw->pw_gid == gr->gr_gid)
  114. bb_error_msg_and_die("'%s' still has '%s' as their primary group!",
  115. pw->pw_name, name);
  116. }
  117. //endpwent();
  118. }
  119. pfile = bb_path_group_file;
  120. if (ENABLE_FEATURE_SHADOWPASSWDS)
  121. sfile = bb_path_gshadow_file;
  122. }
  123. /* Modify pfile, then sfile */
  124. do {
  125. if (update_passwd(pfile, name, NULL, member) == -1)
  126. return EXIT_FAILURE;
  127. if (ENABLE_FEATURE_SHADOWPASSWDS) {
  128. pfile = sfile;
  129. sfile = NULL;
  130. }
  131. } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile);
  132. if (do_deluser > 0) {
  133. /* Delete user from all groups */
  134. if (update_passwd(bb_path_group_file, NULL, NULL, name) == -1)
  135. return EXIT_FAILURE;
  136. if (ENABLE_DELGROUP) {
  137. /* "deluser USER" also should try to delete
  138. * same-named group. IOW: do "delgroup USER"
  139. */
  140. // On debian deluser is a perl script that calls userdel.
  141. // From man userdel:
  142. // If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will
  143. // delete the group with the same name as the user.
  144. do_deluser = -1;
  145. goto do_delgroup;
  146. }
  147. }
  148. return EXIT_SUCCESS;
  149. }
  150. /* Reached only if number of command line args is wrong */
  151. bb_show_usage();
  152. }