Whamcloud - gitweb
LU-10657 utils: fd leak in mirror_split()
[fs/lustre-release.git] / lustre / tests / runas.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * This file is part of Lustre, http://www.lustre.org/
28  * Lustre is a trademark of Sun Microsystems, Inc.
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <ctype.h>
37 #include <sys/types.h>
38 #include <pwd.h>
39 #include <grp.h>
40 #include <sys/wait.h>
41
42 #define DEBUG 0
43
44 #ifndef NGROUPS_MAX
45 #define NGROUPS_MAX 32
46 #endif
47
48 static const char usage[] =
49 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-G[gid0,gid1,...]] command\n"
50 "  -u user_id           switch to UID user_id\n"
51 "  -g grp_id            switch to GID grp_id\n"
52 "  -v euid              switch euid to UID\n"
53 "  -j egid              switch egid to GID\n"
54 "  -G[gid0,gid1,...]    set supplementary groups\n";
55
56 void Usage_and_abort(const char *name)
57 {
58         fprintf(stderr, usage, name);
59         exit(-1);
60 }
61
62 int main(int argc, char **argv)
63 {
64         char **my_argv, *name = argv[0], *grp;
65         int status, c, i;
66         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
67         uid_t user_id = 0;
68         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
69         int euid_is_set = 0, egid_is_set = 0;
70         uid_t euid = 0;
71         gid_t egid = 0;
72
73         if (argc == 1) {
74                 fprintf(stderr, "No parameter count\n");
75                 Usage_and_abort(name);
76         }
77
78         // get UID and GID
79         while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
80                 switch (c) {
81                 case 'u':
82                         if (!isdigit(optarg[0])) {
83                                 struct passwd *pw = getpwnam(optarg);
84                                 if (pw == NULL) {
85                                         fprintf(stderr, "parameter '%s' bad\n",
86                                                 optarg);
87                                         Usage_and_abort(name);
88                                 }
89                                 user_id = pw->pw_uid;
90                         } else {
91                                 user_id = (uid_t)atoi(optarg);
92                         }
93                         uid_is_set = 1;
94                         if (!gid_is_set)
95                                 grp_id = user_id;
96                         break;
97
98                 case 'g':
99                         if (!isdigit(optarg[0])) {
100                                 struct group *gr = getgrnam(optarg);
101                                 if (gr == NULL) {
102                                         fprintf(stderr, "getgrname %s failed\n",
103                                                 optarg);
104                                         Usage_and_abort(name);
105                                 }
106                                 grp_id = gr->gr_gid;
107                         } else {
108                                 grp_id = (gid_t)atoi(optarg);
109                         }
110                         gid_is_set = 1;
111                         break;
112
113                 case 'v':
114                         if (!isdigit(optarg[0])) {
115                                 struct passwd *pw = getpwnam(optarg);
116                                 if (pw == NULL) {
117                                         fprintf(stderr, "parameter '%s' bad\n",
118                                                 optarg);
119                                         Usage_and_abort(name);
120                                 }
121                                 euid = pw->pw_uid;
122                         } else {
123                                 euid = (uid_t)atoi(optarg);
124                         }
125                         euid_is_set = 1;
126                         break;
127
128                 case 'j':
129                         if (!isdigit(optarg[0])) {
130                                 struct group *gr = getgrnam(optarg);
131                                 if (gr == NULL) {
132                                         fprintf(stderr, "getgrname %s failed\n",
133                                                 optarg);
134                                         Usage_and_abort(name);
135                                 }
136                                 egid = gr->gr_gid;
137                         } else {
138                                 egid = (gid_t)atoi(optarg);
139                         }
140                         egid_is_set = 1;
141                         break;
142
143                 case 'G':
144                         num_supp = 0;
145                         if (optarg == NULL || !isdigit(optarg[0]))
146                                 break;
147                         while ((grp = strsep(&optarg, ",")) != NULL) {
148                                 printf("adding supp group %d\n", atoi(grp));
149                                 supp_groups[num_supp++] = atoi(grp);
150                                 if (num_supp >= NGROUPS_MAX)
151                                         break;
152                         }
153                         break;
154
155                 default:
156                 case 'h':
157                         Usage_and_abort(name);
158                         break;
159                 }
160         }
161
162         if (!uid_is_set) {
163                 fprintf(stderr, "Must specify uid to run.\n");
164                 Usage_and_abort(name);
165         }
166
167         if (optind == argc) {
168                 fprintf(stderr, "Must specify command to run.\n");
169                 Usage_and_abort(name);
170         }
171
172         // assemble the command
173         my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
174         if (my_argv == NULL) {
175                 fprintf(stderr, "Error in allocating memory. (%s)\n",
176                         strerror(errno));
177                 exit(-1);
178         }
179
180         for (i = optind; i < argc; i++) {
181                 my_argv[i-optind] = argv[i];
182                 //printf("%s\n",my_argv[i-optind]);
183         }
184         my_argv[i-optind] = NULL;
185
186 #if DEBUG
187         system("whoami");
188 #endif
189
190         // set GID
191         if (!egid_is_set)
192                 egid = grp_id;
193         status = setregid(grp_id, egid);
194         if (status == -1) {
195                  fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
196                          grp_id, egid, errno, strerror(errno) );
197                  exit(-1);
198         }
199
200         if (num_supp >= 0) {
201                 status = setgroups(num_supp, supp_groups);
202                 if (status == -1) {
203                         perror("setting supplementary groups");
204                         exit(-1);
205                 }
206         }
207
208         // set UID
209         if (!euid_is_set)
210                 euid = user_id;
211         status = setreuid(user_id, euid);
212         if(status == -1) {
213                   fprintf(stderr,"Cannot change uid to %d/%d, errno=%d (%s)\n",
214                            user_id, euid, errno, strerror(errno) );
215                   exit(-1);
216         }
217
218         fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
219                 user_id, grp_id, euid, egid);
220         for (i = 0; i < num_supp; i++)
221                 fprintf(stderr, " %d", supp_groups[i]);
222         fprintf(stderr, "\n");
223
224         for (i = 0; i < argc - optind; i++)
225                  fprintf(stderr, " [%s]", my_argv[i]);
226
227         fprintf(stderr, "\n");
228         fflush(stderr);
229
230         // The command to be run
231         execvp(my_argv[0], my_argv);
232         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
233                 errno, strerror(errno));
234         exit(-1);
235 }