addgroup.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * addgroup - add groups to /etc/group and /etc/gshadow
  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 or later, see file LICENSE in this source tree.
  10. */
  11. //config:config ADDGROUP
  12. //config: bool "addgroup (8.6 kb)"
  13. //config: default y
  14. //config: select LONG_OPTS
  15. //config: help
  16. //config: Utility for creating a new group account.
  17. //config:
  18. //config:config FEATURE_ADDUSER_TO_GROUP
  19. //config: bool "Support adding users to groups"
  20. //config: default y
  21. //config: depends on ADDGROUP
  22. //config: help
  23. //config: If called with two non-option arguments,
  24. //config: addgroup will add an existing user to an
  25. //config: existing group.
  26. //applet:IF_ADDGROUP(APPLET_NOEXEC(addgroup, addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP, addgroup))
  27. //kbuild:lib-$(CONFIG_ADDGROUP) += addgroup.o
  28. //usage:#define addgroup_trivial_usage
  29. //usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP"
  30. //usage:#define addgroup_full_usage "\n\n"
  31. //usage: "Add a group" IF_FEATURE_ADDUSER_TO_GROUP(" or add a user to a group") "\n"
  32. //usage: "\n -g GID Group id"
  33. //usage: "\n -S Create a system group"
  34. #include "libbb.h"
  35. #if CONFIG_LAST_SYSTEM_ID < CONFIG_FIRST_SYSTEM_ID
  36. #error Bad LAST_SYSTEM_ID or FIRST_SYSTEM_ID in .config
  37. #endif
  38. #if CONFIG_LAST_ID < CONFIG_LAST_SYSTEM_ID
  39. #error Bad LAST_ID or LAST_SYSTEM_ID in .config
  40. #endif
  41. #define OPT_GID (1 << 0)
  42. #define OPT_SYSTEM_ACCOUNT (1 << 1)
  43. static void xgroup_study(struct group *g)
  44. {
  45. unsigned max = CONFIG_LAST_ID;
  46. /* Make sure gr_name is unused */
  47. if (getgrnam(g->gr_name)) {
  48. bb_error_msg_and_die("%s '%s' in use", "group", g->gr_name);
  49. /* these format strings are reused in adduser and addgroup */
  50. }
  51. /* if a specific gid is requested, the --system switch and */
  52. /* min and max values are overridden, and the range of valid */
  53. /* gid values is set to [0, INT_MAX] */
  54. if (!(option_mask32 & OPT_GID)) {
  55. if (option_mask32 & OPT_SYSTEM_ACCOUNT) {
  56. g->gr_gid = CONFIG_FIRST_SYSTEM_ID;
  57. max = CONFIG_LAST_SYSTEM_ID;
  58. } else {
  59. g->gr_gid = CONFIG_LAST_SYSTEM_ID + 1;
  60. }
  61. }
  62. /* Check if the desired gid is free
  63. * or find the first free one */
  64. while (1) {
  65. if (!getgrgid(g->gr_gid)) {
  66. return; /* found free group: return */
  67. }
  68. if (option_mask32 & OPT_GID) {
  69. /* -g N, cannot pick gid other than N: error */
  70. bb_error_msg_and_die("%s '%s' in use", "gid", itoa(g->gr_gid));
  71. /* this format strings is reused in adduser and addgroup */
  72. }
  73. if (g->gr_gid == max) {
  74. /* overflowed: error */
  75. bb_error_msg_and_die("no %cids left", 'g');
  76. /* this format string is reused in adduser and addgroup */
  77. }
  78. g->gr_gid++;
  79. }
  80. }
  81. /* append a new user to the passwd file */
  82. static void new_group(char *group, gid_t gid)
  83. {
  84. struct group gr;
  85. char *p;
  86. /* make sure gid and group haven't already been allocated */
  87. gr.gr_gid = gid;
  88. gr.gr_name = group;
  89. xgroup_study(&gr);
  90. /* add entry to group */
  91. p = xasprintf("x:%u:", (unsigned) gr.gr_gid);
  92. if (update_passwd(bb_path_group_file, group, p, NULL) < 0)
  93. exit(EXIT_FAILURE);
  94. if (ENABLE_FEATURE_CLEAN_UP)
  95. free(p);
  96. #if ENABLE_FEATURE_SHADOWPASSWDS
  97. /* /etc/gshadow fields:
  98. * 1. Group name.
  99. * 2. Encrypted password.
  100. * If set, non-members of the group can join the group
  101. * by typing the password for that group using the newgrp command.
  102. * If the value is of this field ! then no user is allowed
  103. * to access the group using the newgrp command. A value of !!
  104. * is treated the same as a value of ! only it indicates
  105. * that a password has never been set before. If the value is null,
  106. * only group members can log into the group.
  107. * 3. Group administrators (comma delimited list).
  108. * Group members listed here can add or remove group members
  109. * using the gpasswd command.
  110. * 4. Group members (comma delimited list).
  111. */
  112. /* Ignore errors: if file is missing we assume admin doesn't want it */
  113. update_passwd(bb_path_gshadow_file, group, "!::", NULL);
  114. #endif
  115. }
  116. //FIXME: upstream addgroup has no short options! NOT COMPATIBLE!
  117. static const char addgroup_longopts[] ALIGN1 =
  118. "gid\0" Required_argument "g"
  119. "system\0" No_argument "S"
  120. ;
  121. /*
  122. * addgroup will take a login_name as its first parameter.
  123. *
  124. * gid can be customized via command-line parameters.
  125. * If called with two non-option arguments, addgroup
  126. * will add an existing user to an existing group.
  127. */
  128. int addgroup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  129. int addgroup_main(int argc UNUSED_PARAM, char **argv)
  130. {
  131. #if ENABLE_FEATURE_ADDUSER_TO_GROUP
  132. unsigned opts;
  133. #endif
  134. const char *gid = "0";
  135. /* need to be root */
  136. if (geteuid()) {
  137. bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
  138. }
  139. /* Syntax:
  140. * addgroup group
  141. * addgroup --gid num group
  142. * addgroup user group
  143. * Check for min, max and missing args */
  144. #if ENABLE_FEATURE_ADDUSER_TO_GROUP
  145. opts =
  146. #endif
  147. getopt32long(argv, "^" "g:S" "\0" "-1:?2", addgroup_longopts,
  148. &gid
  149. );
  150. /* move past the commandline options */
  151. argv += optind;
  152. //argc -= optind;
  153. #if ENABLE_FEATURE_ADDUSER_TO_GROUP
  154. if (argv[1]) {
  155. struct group *gr;
  156. if (opts & OPT_GID) {
  157. /* -g was there, but "addgroup -g num user group"
  158. * is a no-no */
  159. bb_show_usage();
  160. }
  161. /* check if group and user exist */
  162. xuname2uid(argv[0]); /* unknown user: exit */
  163. gr = xgetgrnam(argv[1]); /* unknown group: exit */
  164. /* check if user is already in this group */
  165. for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) {
  166. if (strcmp(argv[0], *(gr->gr_mem)) == 0) {
  167. /* user is already in group: do nothing */
  168. return EXIT_SUCCESS;
  169. }
  170. }
  171. if (update_passwd(bb_path_group_file, argv[1], NULL, argv[0]) < 0) {
  172. return EXIT_FAILURE;
  173. }
  174. # if ENABLE_FEATURE_SHADOWPASSWDS
  175. update_passwd(bb_path_gshadow_file, argv[1], NULL, argv[0]);
  176. # endif
  177. } else
  178. #endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
  179. {
  180. die_if_bad_username(argv[0]);
  181. new_group(argv[0], xatou_range(gid, 0, CONFIG_LAST_ID));
  182. }
  183. /* Reached only on success */
  184. return EXIT_SUCCESS;
  185. }