comparison cpx.c @ 0:c772c8912663

Uploaded
author david-hoover
date Tue, 28 Feb 2012 12:36:45 -0500
parents
children e5a905df7e0b
comparison
equal deleted inserted replaced
-1:000000000000 0:c772c8912663
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 /* cpx.c David Hoover 1/13/11
13 usage:
14 cpx from.file to.file login
15
16 cpx copies a file from one location to another, but only if the original file is owned by the given login. The
17 program is expected to be setuid and owned by root.
18
19 */
20
21 int notReadable(char *file, char *user)
22 /* Returns 1 if file not readable 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 file\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 readable? */
56 if (fileStat.st_mode & S_IRUSR)
57 {
58 // printf("%s is readable by %s\n",file,user);
59 return 0;
60 }
61 else
62 {
63 // printf("%s is not readable 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_IRGRP)
72 {
73 // printf("%s is readable 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 readable by group %s\n",file,grp->gr_name);
126 }
127
128 /* is the e world readable? */
129 if (fileStat.st_mode & S_IROTH)
130 {
131 // printf("%s is world readable\n",file);
132 return 0;
133 }
134 else
135 {
136 // printf("%s is not world readable\n",file);
137 }
138
139 return 1;
140 }
141
142 int copyFile(char *src, char *dst)
143 {
144 // printf("Copying %s to %s\n",src,dst);
145
146 int c;
147 FILE *fs,*ft;
148 struct stat fileStat;
149
150 /* must be able to stat file */
151 if (stat(src, &fileStat) < 0)
152 {
153 fprintf(stderr,"%s: No such file\n",src);
154 exit(1);
155 }
156
157 /* is path a regular file? */
158 if (S_ISDIR(fileStat.st_mode))
159 {
160 fprintf(stderr,"%s: Is a directory\n",src);
161 exit(1);
162 }
163
164 fs = fopen(src,"r");
165 if (fs==NULL) {
166 fprintf(stderr,"Can't read from file %s!\n",src);
167 exit(1);
168 }
169 ft = fopen(dst,"w");
170 if (ft==NULL) {
171 fprintf(stderr,"Can't write to file %s!\n",dst);
172 exit(1);
173 }
174
175 c = getc(fs);
176 while (c != EOF) {
177 putc(c,ft);
178 c = getc(fs);
179 }
180
181 fclose(fs);
182 fclose(ft);
183
184 return 0;
185
186 }
187
188 int chownToUser(char *file)
189 /* chown a file to the user running cpx */
190 {
191 uid_t uid;
192 gid_t gid;
193
194 uid = getuid();
195 gid = getgid();
196
197 // printf("UID = %d\n",uid);
198 // printf("GID = %d\n",gid);
199
200 // printf("chown %s %d,%d\n",file,uid,gid);
201 if (chown(file,uid,gid))
202 {
203 fprintf(stderr,"Can't chown %s\n",file);
204 exit(1);
205 }
206 return 0;
207 }
208
209 int explodePath(char *file, char *user)
210 /* Returns 1 if file not readable by given user */
211 {
212 char **path;
213 char *dir;
214 char newfile[10000];
215 int i;
216
217 strcpy(newfile,file);
218 if (!notReadable(newfile,user))
219 {
220 dir = dirname(newfile);
221 if (strcmp(dir,"/"))
222 explodePath(dir,user);
223 }
224 else
225 {
226 fprintf(stderr,"%s: Permission denied.\n",file);
227 exit(1);
228 }
229
230 return 0;
231 }
232
233 main(int argc, char **argv)
234 {
235
236 /* must have two arguments */
237 if (argc != 4)
238 {
239 fprintf(stderr,"usage: cpx source dest user\n");
240 exit(1);
241 }
242
243 /* is file readable by given user? */
244 explodePath(argv[1],argv[3]);
245
246 /* copy the file and change the owner */
247 copyFile(argv[1],argv[2]);
248 chownToUser(argv[2]);
249
250 exit(0);
251 }