diff options
-rw-r--r-- | include/usage.h | 4 | ||||
-rw-r--r-- | loginutils/Config.in | 9 | ||||
-rw-r--r-- | loginutils/addgroup.c | 143 | ||||
-rw-r--r-- | scripts/defconfig | 1 |
4 files changed, 114 insertions, 43 deletions
diff --git a/include/usage.h b/include/usage.h index f4edf0556..c729532e5 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -12,9 +12,9 @@ | |||
12 | #define __BB_USAGE_H__ | 12 | #define __BB_USAGE_H__ |
13 | 13 | ||
14 | #define addgroup_trivial_usage \ | 14 | #define addgroup_trivial_usage \ |
15 | "[-g GID] group_name [user_name]" | 15 | "[-g GID]"USE_FEATURE_ADDUSER_TO_GROUP(" [user_name]")" group_name" |
16 | #define addgroup_full_usage \ | 16 | #define addgroup_full_usage \ |
17 | "Add a group to the system" \ | 17 | "Add a group to the system"USE_FEATURE_ADDUSER_TO_GROUP(" or add an user to a group") \ |
18 | "\n\nOptions:\n" \ | 18 | "\n\nOptions:\n" \ |
19 | " -g GID Specify gid" | 19 | " -g GID Specify gid" |
20 | 20 | ||
diff --git a/loginutils/Config.in b/loginutils/Config.in index 03a638c00..1d52cdfe5 100644 --- a/loginutils/Config.in +++ b/loginutils/Config.in | |||
@@ -59,6 +59,15 @@ config ADDGROUP | |||
59 | help | 59 | help |
60 | Utility for creating a new group account. | 60 | Utility for creating a new group account. |
61 | 61 | ||
62 | config FEATURE_ADDUSER_TO_GROUP | ||
63 | bool "Support for adding users to groups" | ||
64 | default n | ||
65 | depends on ADDGROUP | ||
66 | help | ||
67 | If called with two non-option arguments, | ||
68 | addgroup will add an existing user to an | ||
69 | existing group. | ||
70 | |||
62 | config DELGROUP | 71 | config DELGROUP |
63 | bool "delgroup" | 72 | bool "delgroup" |
64 | default n | 73 | default n |
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 78250a418..5aefda6ff 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c | |||
@@ -1,9 +1,10 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * addgroup - add users to /etc/passwd and /etc/shadow | 3 | * addgroup - add groups to /etc/group and /etc/gshadow |
4 | * | 4 | * |
5 | * Copyright (C) 1999 by Lineo, inc. and John Beppu | 5 | * Copyright (C) 1999 by Lineo, inc. and John Beppu |
6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> | 6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> |
7 | * Copyright (C) 2007 by Tito Ragusa <farmatito@tiscali.it> | ||
7 | * | 8 | * |
8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
9 | * | 10 | * |
@@ -11,48 +12,40 @@ | |||
11 | 12 | ||
12 | #include "busybox.h" | 13 | #include "busybox.h" |
13 | 14 | ||
14 | /* make sure gr_name isn't taken, make sure gid is kosher | 15 | static void xgroup_study(struct group *g) |
15 | * return 1 on failure */ | ||
16 | static int group_study(struct group *g) | ||
17 | { | 16 | { |
18 | enum { max = 65000 }; | 17 | enum { max = 65000 }; |
19 | FILE *etc_group; | 18 | /* Use a particular gid. */ |
20 | gid_t desired; | 19 | int desired = (g->gr_gid > 0); |
21 | /* Using _r function to avoid static buffers pulled in */ | 20 | |
22 | char buffer[256]; | 21 | /* Make sure gr_name is unused */ |
23 | struct group grp; | 22 | if (getgrnam(g->gr_name)) { |
24 | struct group *result; | 23 | goto error; |
25 | 24 | } | |
26 | etc_group = xfopen(bb_path_group_file, "r"); | 25 | |
27 | 26 | /* Check if the desired gid is free or | |
28 | /* make sure gr_name isn't taken, make sure gid is kosher */ | 27 | find the first free one */ |
29 | desired = g->gr_gid; | 28 | do { |
30 | while (!fgetgrent_r(etc_group, &grp, buffer, sizeof(buffer), &result)) { | 29 | if (g->gr_gid == max) { /* out of bounds: exit */ |
31 | if ((strcmp(grp.gr_name, g->gr_name)) == 0) { | 30 | bb_error_msg_and_die("no gids left"); |
32 | bb_error_msg_and_die("%s: group already in use", g->gr_name); | ||
33 | } | 31 | } |
34 | if ((desired) && grp.gr_gid == desired) { | 32 | if (!getgrgid(g->gr_gid)) { |
35 | bb_error_msg_and_die("%d: gid already in use", | 33 | return; /* ok */ |
36 | desired); | ||
37 | } | 34 | } |
38 | if ((grp.gr_gid > g->gr_gid) && (grp.gr_gid < max)) { | 35 | if (desired) { /* the desired gid is already in use: exit */ |
39 | g->gr_gid = grp.gr_gid; | 36 | g->gr_name = itoa(g->gr_gid); |
37 | goto error; | ||
40 | } | 38 | } |
41 | } | 39 | g->gr_gid++; |
42 | if (ENABLE_FEATURE_CLEAN_UP) | 40 | } while (1); |
43 | fclose(etc_group); | ||
44 | 41 | ||
45 | /* gid */ | 42 | error: |
46 | g->gr_gid++; | 43 | /* exit */ |
47 | if (desired) { | 44 | bb_error_msg_and_die("%s: already in use", g->gr_name); |
48 | g->gr_gid = desired; | ||
49 | } | ||
50 | /* return 1; */ | ||
51 | return 0; | ||
52 | } | 45 | } |
53 | 46 | ||
54 | /* append a new user to the passwd file */ | 47 | /* append a new user to the passwd file */ |
55 | static int addgroup(char *group, gid_t gid, const char *user) | 48 | static void new_group(char *group, gid_t gid) |
56 | { | 49 | { |
57 | FILE *file; | 50 | FILE *file; |
58 | struct group gr; | 51 | struct group gr; |
@@ -60,16 +53,14 @@ static int addgroup(char *group, gid_t gid, const char *user) | |||
60 | /* make sure gid and group haven't already been allocated */ | 53 | /* make sure gid and group haven't already been allocated */ |
61 | gr.gr_gid = gid; | 54 | gr.gr_gid = gid; |
62 | gr.gr_name = group; | 55 | gr.gr_name = group; |
63 | if (group_study(&gr)) | 56 | xgroup_study( &gr); |
64 | return 1; | ||
65 | 57 | ||
66 | /* add entry to group */ | 58 | /* add entry to group */ |
67 | file = xfopen(bb_path_group_file, "a"); | 59 | file = xfopen(bb_path_group_file, "a"); |
68 | /* group:passwd:gid:userlist */ | 60 | /* group:passwd:gid:userlist */ |
69 | fprintf(file, "%s:%s:%d:%s\n", group, "x", gr.gr_gid, user); | 61 | fprintf(file, "%s:x:%d:\n", group, gr.gr_gid); |
70 | if (ENABLE_FEATURE_CLEAN_UP) | 62 | if (ENABLE_FEATURE_CLEAN_UP) |
71 | fclose(file); | 63 | fclose(file); |
72 | |||
73 | #if ENABLE_FEATURE_SHADOWPASSWDS | 64 | #if ENABLE_FEATURE_SHADOWPASSWDS |
74 | file = fopen_or_warn(bb_path_gshadow_file, "a"); | 65 | file = fopen_or_warn(bb_path_gshadow_file, "a"); |
75 | if (file) { | 66 | if (file) { |
@@ -78,15 +69,60 @@ static int addgroup(char *group, gid_t gid, const char *user) | |||
78 | fclose(file); | 69 | fclose(file); |
79 | } | 70 | } |
80 | #endif | 71 | #endif |
72 | } | ||
73 | |||
74 | #if ENABLE_FEATURE_ADDUSER_TO_GROUP | ||
75 | static void add_user_to_group(char **args, | ||
76 | const char *path, | ||
77 | FILE *(*fopen_func)(const char *fileName, const char *mode)) | ||
78 | { | ||
79 | char *line; | ||
80 | int len = strlen(args[1]); | ||
81 | llist_t *plist = NULL; | ||
82 | FILE *group_file; | ||
83 | |||
84 | group_file = fopen_func(path, "r"); | ||
81 | 85 | ||
82 | /* return 1; */ | 86 | if (!group_file) return; |
83 | return 0; | 87 | |
88 | while ((line = xmalloc_getline(group_file))) { | ||
89 | /* Find the group */ | ||
90 | if (!strncmp(line, args[1], len) | ||
91 | && line[len] == ':' | ||
92 | ) { | ||
93 | /* Add the new user */ | ||
94 | line = xasprintf("%s%s%s", line, | ||
95 | last_char_is(line, ':') ? "" : ",", | ||
96 | args[0]); | ||
97 | } | ||
98 | llist_add_to_end(&plist, line); | ||
99 | } | ||
100 | |||
101 | if (ENABLE_FEATURE_CLEAN_UP) { | ||
102 | fclose(group_file); | ||
103 | group_file = fopen_func(path, "w"); | ||
104 | while ((line = llist_pop(&plist))) { | ||
105 | if (group_file) | ||
106 | fprintf(group_file, "%s\n", line); | ||
107 | free(line); | ||
108 | } | ||
109 | if (group_file) | ||
110 | fclose(group_file); | ||
111 | } else { | ||
112 | group_file = fopen_func(path, "w"); | ||
113 | if (group_file) | ||
114 | while ((line = llist_pop(&plist))) | ||
115 | fprintf(group_file, "%s\n", line); | ||
116 | } | ||
84 | } | 117 | } |
118 | #endif | ||
85 | 119 | ||
86 | /* | 120 | /* |
87 | * addgroup will take a login_name as its first parameter. | 121 | * addgroup will take a login_name as its first parameter. |
88 | * | 122 | * |
89 | * gid can be customized via command-line parameters. | 123 | * gid can be customized via command-line parameters. |
124 | * If called with two non-option arguments, addgroup | ||
125 | * will add an existing user to an existing group. | ||
90 | */ | 126 | */ |
91 | int addgroup_main(int argc, char **argv); | 127 | int addgroup_main(int argc, char **argv); |
92 | int addgroup_main(int argc, char **argv) | 128 | int addgroup_main(int argc, char **argv) |
@@ -101,11 +137,36 @@ int addgroup_main(int argc, char **argv) | |||
101 | } | 137 | } |
102 | /* move past the commandline options */ | 138 | /* move past the commandline options */ |
103 | argv += optind; | 139 | argv += optind; |
140 | argc -= optind; | ||
104 | 141 | ||
105 | /* need to be root */ | 142 | /* need to be root */ |
106 | if (geteuid()) { | 143 | if (geteuid()) { |
107 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | 144 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); |
108 | } | 145 | } |
109 | 146 | ||
110 | return addgroup(argv[0], gid, argv[1] ? argv[1] : ""); | 147 | #if ENABLE_FEATURE_ADDUSER_TO_GROUP |
148 | if (argc == 2) { | ||
149 | struct group *gr; | ||
150 | |||
151 | /* check if group and user exist */ | ||
152 | xuname2uid(argv[0]); /* unknown user: exit */ | ||
153 | xgroup2gid(argv[1]); /* unknown group: exit */ | ||
154 | /* check if user is already in this group */ | ||
155 | gr = getgrnam(argv[1]); | ||
156 | for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) { | ||
157 | if (!strcmp(argv[0], *(gr->gr_mem))) { | ||
158 | /* user is already in group: do nothing */ | ||
159 | return EXIT_SUCCESS; | ||
160 | } | ||
161 | } | ||
162 | add_user_to_group(argv, bb_path_group_file, xfopen); | ||
163 | #if ENABLE_FEATURE_SHADOWPASSWDS | ||
164 | add_user_to_group(argv, bb_path_gshadow_file, fopen_or_warn); | ||
165 | #endif /* ENABLE_FEATURE_SHADOWPASSWDS */ | ||
166 | } else | ||
167 | #endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */ | ||
168 | new_group(argv[0], gid); | ||
169 | |||
170 | /* Reached only on success */ | ||
171 | return EXIT_SUCCESS; | ||
111 | } | 172 | } |
diff --git a/scripts/defconfig b/scripts/defconfig index 42f3605da..6864b2fa6 100644 --- a/scripts/defconfig +++ b/scripts/defconfig | |||
@@ -347,6 +347,7 @@ CONFIG_FEATURE_SHADOWPASSWDS=y | |||
347 | CONFIG_USE_BB_SHADOW=y | 347 | CONFIG_USE_BB_SHADOW=y |
348 | CONFIG_USE_BB_PWD_GRP=y | 348 | CONFIG_USE_BB_PWD_GRP=y |
349 | CONFIG_ADDGROUP=y | 349 | CONFIG_ADDGROUP=y |
350 | CONFIG_FEATURE_ADDUSER_TO_GROUP=y | ||
350 | CONFIG_DELGROUP=y | 351 | CONFIG_DELGROUP=y |
351 | CONFIG_ADDUSER=y | 352 | CONFIG_ADDUSER=y |
352 | CONFIG_DELUSER=y | 353 | CONFIG_DELUSER=y |