|
0
|
1 #include <sys/stat.h>
|
|
|
2 #include <sys/types.h>
|
|
|
3 #include <unistd.h>
|
|
|
4 #include <stdio.h>
|
|
|
5 #include <errno.h>
|
|
|
6 #include <stdlib.h>
|
|
|
7 #include <pwd.h>
|
|
|
8 #include <grp.h> // declares struct group
|
|
|
9 #include <libgen.h> // for dirname
|
|
|
10 #include <string.h> // for strcpy
|
|
|
11
|
|
|
12 /* cpy.c David Hoover 1/20/12
|
|
|
13 usage:
|
|
|
14 cpy from.file to.file login
|
|
|
15
|
|
|
16 cpy copies a file from one location to another, and then sets the ownership to a given user. The
|
|
|
17 program is expected to be setuid and owned by root.
|
|
|
18
|
|
|
19 */
|
|
|
20
|
|
|
21 int notWriteable(char *file, char *user)
|
|
|
22 /* Returns 1 if file not writeable by given user */
|
|
|
23 {
|
|
|
24 struct stat fileStat;
|
|
|
25 struct passwd *own,*usr;
|
|
|
26 struct group *grp;
|
|
|
27 int i=0;
|
|
|
28
|
|
|
29 usr = getpwnam(user);
|
|
|
30
|
|
|
31 /* does user exist? */
|
|
|
32 if (! usr)
|
|
|
33 {
|
|
|
34 fprintf(stderr,"%s: No such user\n",user);
|
|
|
35 exit(1);
|
|
|
36 }
|
|
|
37
|
|
|
38 /* must be able to stat file */
|
|
|
39 if (stat(file, &fileStat) < 0)
|
|
|
40 {
|
|
|
41 fprintf(stderr,"%s: No such directory\n",file);
|
|
|
42 exit(1);
|
|
|
43 }
|
|
|
44
|
|
|
45 /* get the owner and group information for the file */
|
|
|
46 own = getpwuid(fileStat.st_uid);
|
|
|
47 grp = getgrgid(fileStat.st_gid);
|
|
|
48
|
|
|
49 /* does the file owner match the argument? */
|
|
|
50 // if (!strcmp(own->pw_name,user))
|
|
|
51 if (usr->pw_uid == fileStat.st_uid)
|
|
|
52 {
|
|
|
53 // printf("owners match!\n");
|
|
|
54
|
|
|
55 /* is file writeable? */
|
|
|
56 if (fileStat.st_mode & S_IWUSR)
|
|
|
57 {
|
|
|
58 // printf("%s is writeable by %s\n",file,user);
|
|
|
59 return 0;
|
|
|
60 }
|
|
|
61 else
|
|
|
62 {
|
|
|
63 // printf("%s is not writeable by %s\n",file,user);
|
|
|
64 }
|
|
|
65 }
|
|
|
66 else {
|
|
|
67 // printf("owners don't match!\n");
|
|
|
68 }
|
|
|
69
|
|
|
70 /* is the file group readable by the given group? */
|
|
|
71 if (fileStat.st_mode & S_IWGRP)
|
|
|
72 {
|
|
|
73 // printf("%s is writeable by group %s\n",file,grp->gr_name);
|
|
|
74
|
|
|
75
|
|
|
76 /* is the user's gid the same as the file? */
|
|
|
77 // printf("%d\n",usr->pw_gid);
|
|
|
78 // printf("%d\n",fileStat.st_gid);
|
|
|
79 if (usr->pw_gid == fileStat.st_gid)
|
|
|
80 {
|
|
|
81 // printf("groups match!\n");
|
|
|
82
|
|
|
83 /* if the path a directory is it executable? */
|
|
|
84 if (S_ISDIR(fileStat.st_mode))
|
|
|
85 {
|
|
|
86 if (fileStat.st_mode & S_IXGRP)
|
|
|
87 {
|
|
|
88 return 0;
|
|
|
89 }
|
|
|
90 }
|
|
|
91 else {
|
|
|
92 return 0;
|
|
|
93 }
|
|
|
94 }
|
|
|
95 else
|
|
|
96 {
|
|
|
97
|
|
|
98 /* is the user a member of the group that owns the file? */
|
|
|
99 while(grp->gr_mem[i] != NULL)
|
|
|
100 {
|
|
|
101 if(!strcmp(grp->gr_mem[i],user))
|
|
|
102 {
|
|
|
103 // printf("%s is a member of the %s group\n",user,grp->gr_name);
|
|
|
104 /* if the path a directory is it executable? */
|
|
|
105 if (S_ISDIR(fileStat.st_mode))
|
|
|
106 {
|
|
|
107 if (fileStat.st_mode & S_IXGRP)
|
|
|
108 {
|
|
|
109 return 0;
|
|
|
110 }
|
|
|
111 }
|
|
|
112 else {
|
|
|
113 return 0;
|
|
|
114 }
|
|
|
115 }
|
|
|
116 i++;
|
|
|
117 }
|
|
|
118
|
|
|
119 // printf("%s is not a member of the %s group\n",user,grp->gr_name);
|
|
|
120
|
|
|
121 }
|
|
|
122 }
|
|
|
123 else
|
|
|
124 {
|
|
|
125 // printf("%s is not writeable by group %s\n",file,grp->gr_name);
|
|
|
126 }
|
|
|
127
|
|
|
128 /* is the e world writeable? */
|
|
|
129 if (fileStat.st_mode & S_IWOTH)
|
|
|
130 {
|
|
|
131 // printf("%s is world writeable\n",file);
|
|
|
132 return 0;
|
|
|
133 }
|
|
|
134 else
|
|
|
135 {
|
|
|
136 // printf("%s is not world writeable\n",file);
|
|
|
137 }
|
|
|
138
|
|
|
139 return 1;
|
|
|
140 }
|
|
|
141
|
|
|
142 int notReadable(char *file, char *user)
|
|
|
143 /* Returns 1 if file not readable by given user */
|
|
|
144 {
|
|
|
145 struct stat fileStat;
|
|
|
146 struct passwd *own,*usr;
|
|
|
147 struct group *grp;
|
|
|
148 int i=0;
|
|
|
149
|
|
|
150 usr = getpwnam(user);
|
|
|
151
|
|
|
152 /* does user exist? */
|
|
|
153 if (! usr)
|
|
|
154 {
|
|
|
155 fprintf(stderr,"%s: No such user\n",user);
|
|
|
156 exit(1);
|
|
|
157 }
|
|
|
158
|
|
|
159 /* must be able to stat file */
|
|
|
160 if (stat(file, &fileStat) < 0)
|
|
|
161 {
|
|
|
162 fprintf(stderr,"%s: No such directory\n",file);
|
|
|
163 exit(1);
|
|
|
164 }
|
|
|
165
|
|
|
166 /* get the owner and group information for the file */
|
|
|
167 own = getpwuid(fileStat.st_uid);
|
|
|
168 grp = getgrgid(fileStat.st_gid);
|
|
|
169
|
|
|
170 /* does the file owner match the argument? */
|
|
|
171 // if (!strcmp(own->pw_name,user))
|
|
|
172 if (usr->pw_uid == fileStat.st_uid)
|
|
|
173 {
|
|
|
174 // printf("owners match!\n");
|
|
|
175
|
|
|
176 /* is file readable? */
|
|
|
177 if (fileStat.st_mode & S_IRUSR)
|
|
|
178 {
|
|
|
179 // printf("%s is readable by %s\n",file,user);
|
|
|
180 return 0;
|
|
|
181 }
|
|
|
182 else
|
|
|
183 {
|
|
|
184 // printf("%s is not readable by %s\n",file,user);
|
|
|
185 }
|
|
|
186 }
|
|
|
187 else {
|
|
|
188 // printf("owners don't match!\n");
|
|
|
189 }
|
|
|
190
|
|
|
191 /* is the file group readable by the given group? */
|
|
|
192 if (fileStat.st_mode & S_IRGRP)
|
|
|
193 {
|
|
|
194 // printf("%s is readable by group %s\n",file,grp->gr_name);
|
|
|
195
|
|
|
196
|
|
|
197 /* is the user's gid the same as the file? */
|
|
|
198 // printf("%d\n",usr->pw_gid);
|
|
|
199 // printf("%d\n",fileStat.st_gid);
|
|
|
200 if (usr->pw_gid == fileStat.st_gid)
|
|
|
201 {
|
|
|
202 // printf("groups match!\n");
|
|
|
203
|
|
|
204 /* if the path a directory is it executable? */
|
|
|
205 if (S_ISDIR(fileStat.st_mode))
|
|
|
206 {
|
|
|
207 if (fileStat.st_mode & S_IXGRP)
|
|
|
208 {
|
|
|
209 return 0;
|
|
|
210 }
|
|
|
211 }
|
|
|
212 else {
|
|
|
213 return 0;
|
|
|
214 }
|
|
|
215 }
|
|
|
216 else
|
|
|
217 {
|
|
|
218
|
|
|
219 /* is the user a member of the group that owns the file? */
|
|
|
220 while(grp->gr_mem[i] != NULL)
|
|
|
221 {
|
|
|
222 if(!strcmp(grp->gr_mem[i],user))
|
|
|
223 {
|
|
|
224 // printf("%s is a member of the %s group\n",user,grp->gr_name);
|
|
|
225 /* if the path a directory is it executable? */
|
|
|
226 if (S_ISDIR(fileStat.st_mode))
|
|
|
227 {
|
|
|
228 if (fileStat.st_mode & S_IXGRP)
|
|
|
229 {
|
|
|
230 return 0;
|
|
|
231 }
|
|
|
232 }
|
|
|
233 else {
|
|
|
234 return 0;
|
|
|
235 }
|
|
|
236 }
|
|
|
237 i++;
|
|
|
238 }
|
|
|
239
|
|
|
240 // printf("%s is not a member of the %s group\n",user,grp->gr_name);
|
|
|
241
|
|
|
242 }
|
|
|
243 }
|
|
|
244 else
|
|
|
245 {
|
|
|
246 // printf("%s is not readable by group %s\n",file,grp->gr_name);
|
|
|
247 }
|
|
|
248
|
|
|
249 /* is the e world readable? */
|
|
|
250 if (fileStat.st_mode & S_IROTH)
|
|
|
251 {
|
|
|
252 // printf("%s is world readable\n",file);
|
|
|
253 return 0;
|
|
|
254 }
|
|
|
255 else
|
|
|
256 {
|
|
|
257 // printf("%s is not world readable\n",file);
|
|
|
258 }
|
|
|
259
|
|
|
260 return 1;
|
|
|
261 }
|
|
|
262
|
|
|
263 int copyFile(char *src, char *dst)
|
|
|
264 {
|
|
|
265 // printf("Copying %s to %s\n",src,dst);
|
|
|
266
|
|
7
|
267 char *c;
|
|
0
|
268 FILE *fs,*ft;
|
|
|
269 struct stat fileStat;
|
|
7
|
270 size_t st=10000000;
|
|
|
271 int numr,numw;
|
|
0
|
272
|
|
|
273 /* must be able to stat file */
|
|
|
274 if (stat(src, &fileStat) < 0)
|
|
|
275 {
|
|
|
276 fprintf(stderr,"%s: No such file\n",src);
|
|
|
277 exit(1);
|
|
|
278 }
|
|
|
279
|
|
|
280 /* is path a regular file? */
|
|
|
281 if (S_ISDIR(fileStat.st_mode))
|
|
|
282 {
|
|
|
283 fprintf(stderr,"%s: Is a directory\n",src);
|
|
|
284 exit(1);
|
|
|
285 }
|
|
|
286
|
|
|
287 fs = fopen(src,"r");
|
|
|
288 if (fs==NULL) {
|
|
|
289 fprintf(stderr,"Can't read from file %s!\n",src);
|
|
|
290 exit(1);
|
|
|
291 }
|
|
|
292 ft = fopen(dst,"w");
|
|
|
293 if (ft==NULL) {
|
|
|
294 fprintf(stderr,"Can't write to file %s!\n",dst);
|
|
|
295 exit(1);
|
|
|
296 }
|
|
7
|
297
|
|
|
298 c=malloc(st);
|
|
|
299 while(feof(fs)==0)
|
|
|
300 {
|
|
|
301 if((numr=fread(c,1,st,fs))!=st)
|
|
|
302 {
|
|
|
303 if(ferror(fs)!=0)
|
|
|
304 {
|
|
|
305 fprintf(stderr,"read file error.\n");
|
|
|
306 exit(1);
|
|
|
307 }
|
|
|
308 else if(feof(fs)!=0);
|
|
|
309 }
|
|
|
310 if((numw=fwrite(c,1,numr,ft))!=numr)
|
|
|
311 {
|
|
|
312 fprintf(stderr,"write file error.\n");
|
|
|
313 exit(1);
|
|
|
314 }
|
|
|
315 }
|
|
0
|
316
|
|
|
317 fclose(fs);
|
|
|
318 fclose(ft);
|
|
7
|
319 free(c);
|
|
0
|
320
|
|
|
321 return 0;
|
|
|
322
|
|
|
323 }
|
|
|
324
|
|
|
325 int chownToGivenUser(char *file, char *user)
|
|
|
326 /* chown a file to the given user */
|
|
|
327 {
|
|
|
328 struct passwd *usr;
|
|
|
329
|
|
|
330 usr = getpwnam(user);
|
|
|
331
|
|
|
332 // printf("UID = %d\n",usr->pw_uid);
|
|
|
333 // printf("GID = %d\n",usr->pw_gid);
|
|
|
334
|
|
|
335 // printf("chown %s %d,%d\n",file,usr->pw_uid,usr->pw_gid);
|
|
|
336 if (chown(file,usr->pw_uid,usr->pw_gid))
|
|
|
337 {
|
|
|
338 fprintf(stderr,"Can't chown %s\n",file);
|
|
|
339 exit(1);
|
|
|
340 }
|
|
|
341 return 0;
|
|
|
342 }
|
|
|
343
|
|
|
344 int explodePath(char *file, char *user)
|
|
|
345 /* Returns 1 if file not readable by given user */
|
|
|
346 {
|
|
|
347 char **path;
|
|
|
348 char *dir;
|
|
|
349 char newfile[10000];
|
|
|
350 int i;
|
|
|
351
|
|
|
352 strcpy(newfile,file);
|
|
|
353 if (!notReadable(newfile,user))
|
|
|
354 {
|
|
|
355 dir = dirname(newfile);
|
|
|
356 if (strcmp(dir,"/"))
|
|
|
357 explodePath(dir,user);
|
|
|
358 }
|
|
|
359 else
|
|
|
360 {
|
|
|
361 fprintf(stderr,"%s: Permission denied.\n",file);
|
|
|
362 exit(1);
|
|
|
363 }
|
|
|
364
|
|
|
365 return 0;
|
|
|
366 }
|
|
|
367
|
|
|
368 main(int argc, char **argv)
|
|
|
369 {
|
|
|
370 char *dir;
|
|
|
371 char newfile[10000];
|
|
|
372 struct stat fileStat;
|
|
|
373
|
|
|
374 /* must have two arguments */
|
|
|
375 if (argc != 4)
|
|
|
376 {
|
|
|
377 fprintf(stderr,"usage: cpy source dest user\n");
|
|
|
378 exit(1);
|
|
|
379 }
|
|
|
380
|
|
7
|
381 if (!strncmp(argv[2],"/data",5) || !strncmp(argv[2],"/home",5))
|
|
|
382 {
|
|
|
383
|
|
0
|
384 /* is filepath writeable by given user? */
|
|
7
|
385 strcpy(newfile,argv[2]);
|
|
|
386 dir = dirname(newfile);
|
|
|
387 if (!notWriteable(dir,argv[3]))
|
|
|
388 {
|
|
0
|
389
|
|
|
390 /* is filepath readable by given user? */
|
|
7
|
391 explodePath(dir,argv[3]);
|
|
0
|
392
|
|
|
393 /* dest file must not exist yet */
|
|
7
|
394 if (!(stat(argv[2], &fileStat) < 0))
|
|
|
395 {
|
|
|
396 fprintf(stderr,"%s: File already exists.\n",argv[2]);
|
|
|
397 exit(1);
|
|
|
398 }
|
|
0
|
399
|
|
|
400 /* copy the file and change the owner */
|
|
7
|
401 copyFile(argv[1],argv[2]);
|
|
|
402 chownToGivenUser(argv[2],argv[3]);
|
|
|
403 }
|
|
|
404 else
|
|
|
405 {
|
|
|
406 fprintf(stderr,"%s: Permission denied.\n",argv[2]);
|
|
|
407 exit(1);
|
|
|
408 }
|
|
0
|
409 }
|
|
|
410 else
|
|
|
411 {
|
|
|
412 fprintf(stderr,"%s: Permission denied.\n",argv[2]);
|
|
|
413 exit(1);
|
|
|
414 }
|
|
|
415
|
|
|
416 exit(0);
|
|
|
417 }
|