Whamcloud - gitweb
018ef52baf612894ac9802104e6a6a5a760f555b
[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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <ctype.h>
41 #include <sys/types.h>
42 #include <pwd.h>
43 #include <grp.h>
44 #include <sys/wait.h>
45
46 #define DEBUG 0
47
48 #ifndef NGROUPS_MAX
49 #define NGROUPS_MAX 32
50 #endif
51
52 static const char usage[] =
53 "Usage: %s -u user_id [-g grp_id] [-v euid] [-j egid] [-G[gid0,gid1,...]] command\n"
54 "  -u user_id           switch to UID user_id\n"
55 "  -g grp_id            switch to GID grp_id\n"
56 "  -v euid              switch euid to UID\n"
57 "  -j egid              switch egid to GID\n"
58 "  -G[gid0,gid1,...]    set supplementary groups\n";
59
60 void Usage_and_abort(const char *name)
61 {
62         fprintf(stderr, usage, name);
63         exit(-1);
64 }
65
66 int main(int argc, char **argv)
67 {
68         char **my_argv, *name = argv[0], *grp;
69         int status, c, i;
70         int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
71         uid_t user_id = 0;
72         gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
73         int euid_is_set = 0, egid_is_set = 0;
74         uid_t euid = 0;
75         gid_t egid = 0;
76
77         if (argc == 1) {
78                 fprintf(stderr, "No parameter count\n");
79                 Usage_and_abort(name);
80         }
81
82         // get UID and GID
83         while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) {
84                 switch (c) {
85                 case 'u':
86                         if (!isdigit(optarg[0])) {
87                                 struct passwd *pw = getpwnam(optarg);
88                                 if (pw == NULL) {
89                                         fprintf(stderr, "parameter '%s' bad\n",
90                                                 optarg);
91                                         Usage_and_abort(name);
92                                 }
93                                 user_id = pw->pw_uid;
94                         } else {
95                                 user_id = (uid_t)atoi(optarg);
96                         }
97                         uid_is_set = 1;
98                         if (!gid_is_set)
99                                 grp_id = user_id;
100                         break;
101
102                 case 'g':
103                         if (!isdigit(optarg[0])) {
104                                 struct group *gr = getgrnam(optarg);
105                                 if (gr == NULL) {
106                                         fprintf(stderr, "getgrname %s failed\n",
107                                                 optarg);
108                                         Usage_and_abort(name);
109                                 }
110                                 grp_id = gr->gr_gid;
111                         } else {
112                                 grp_id = (gid_t)atoi(optarg);
113                         }
114                         gid_is_set = 1;
115                         break;
116
117                 case 'v':
118                         if (!isdigit(optarg[0])) {
119                                 struct passwd *pw = getpwnam(optarg);
120                                 if (pw == NULL) {
121                                         fprintf(stderr, "parameter '%s' bad\n",
122                                                 optarg);
123                                         Usage_and_abort(name);
124                                 }
125                                 euid = pw->pw_uid;
126                         } else {
127                                 euid = (uid_t)atoi(optarg);
128                         }
129                         euid_is_set = 1;
130                         break;
131
132                 case 'j':
133                         if (!isdigit(optarg[0])) {
134                                 struct group *gr = getgrnam(optarg);
135                                 if (gr == NULL) {
136                                         fprintf(stderr, "getgrname %s failed\n",
137                                                 optarg);
138                                         Usage_and_abort(name);
139                                 }
140                                 egid = gr->gr_gid;
141                         } else {
142                                 egid = (gid_t)atoi(optarg);
143                         }
144                         egid_is_set = 1;
145                         break;
146
147                 case 'G':
148                         num_supp = 0;
149                         if (optarg == NULL || !isdigit(optarg[0]))
150                                 break;
151                         while ((grp = strsep(&optarg, ",")) != NULL) {
152                                 printf("adding supp group %d\n", atoi(grp));
153                                 supp_groups[num_supp++] = atoi(grp);
154                                 if (num_supp >= NGROUPS_MAX)
155                                         break;
156                         }
157                         break;
158
159                 default:
160                 case 'h':
161                         Usage_and_abort(name);
162                         break;
163                 }
164         }
165
166         if (!uid_is_set) {
167                 fprintf(stderr, "Must specify uid to run.\n");
168                 Usage_and_abort(name);
169         }
170
171         if (optind == argc) {
172                 fprintf(stderr, "Must specify command to run.\n");
173                 Usage_and_abort(name);
174         }
175
176         // assemble the command
177         my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind));
178         if (my_argv == NULL) {
179                 fprintf(stderr, "Error in allocating memory. (%s)\n",
180                         strerror(errno));
181                 exit(-1);
182         }
183
184         for (i = optind; i < argc; i++) {
185                 my_argv[i-optind] = argv[i];
186                 //printf("%s\n",my_argv[i-optind]);
187         }
188         my_argv[i-optind] = NULL;
189
190 #if DEBUG
191         system("whoami");
192 #endif
193
194         // set GID
195         if (!egid_is_set)
196                 egid = grp_id;
197         status = setregid(grp_id, egid);
198         if (status == -1) {
199                  fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n",
200                          grp_id, egid, errno, strerror(errno) );
201                  exit(-1);
202         }
203
204         if (num_supp >= 0) {
205                 status = setgroups(num_supp, supp_groups);
206                 if (status == -1) {
207                         perror("setting supplementary groups");
208                         exit(-1);
209                 }
210         }
211
212         // set UID
213         if (!euid_is_set)
214                 euid = user_id;
215         status = setreuid(user_id, euid);
216         if(status == -1) {
217                   fprintf(stderr,"Cannot change uid to %d/%d, errno=%d (%s)\n",
218                            user_id, euid, errno, strerror(errno) );
219                   exit(-1);
220         }
221
222         fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:",
223                 user_id, grp_id, euid, egid);
224         for (i = 0; i < num_supp; i++)
225                 fprintf(stderr, " %d", supp_groups[i]);
226         fprintf(stderr, "\n");
227
228         for (i = 0; i < argc - optind; i++)
229                  fprintf(stderr, " [%s]", my_argv[i]);
230
231         fprintf(stderr, "\n");
232         fflush(stderr);
233
234         // The command to be run
235         execvp(my_argv[0], my_argv);
236         fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0],
237                 errno, strerror(errno));
238         exit(-1);
239 }