addgroup.c 6.2 KB

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