Rev 11539 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 11539 | Rev 12248 | ||
---|---|---|---|
Line 49... | Line 49... | ||
49 | int execgid=15999; |
49 | int execgid=15999; |
50 | int must=0; |
50 | int must=0; |
51 | time_t now; |
51 | time_t now; |
52 | 52 | ||
53 | char *env_rm[]={ |
53 | char *env_rm[]={ |
54 |
|
54 | "s2_dir", "w_wims_home", "session_base_dir", "trusted_module", |
55 |
|
55 | "session_dir", "wims_server_base", "w_httpd_PWD", |
56 |
|
56 | "w_wims_sesdir", "HTTP_CONNECTION", |
57 |
|
57 | "w_gnuplot_format", "w_insplot_font", "w_ins_anim_limit", |
58 |
|
58 | "w_ins_density", "w_ins_format", |
59 |
|
59 | "texgif_fontdir", "texgif_texheader", |
60 |
|
60 | "w_wims_tmp_debug", "w_insmath_logic", "w_insmath_rawmath", |
61 |
|
61 | "SERVER_ADMIN", "SERVER_ADDR", "SERVER_NAME" |
62 | }; |
62 | }; |
63 | 63 | ||
64 | #define env_rm_cnt (sizeof(env_rm)/sizeof(env_rm[0])) |
64 | #define env_rm_cnt (sizeof(env_rm)/sizeof(env_rm[0])) |
65 | 65 | ||
66 | char name_sh[32]="/bin/ash.static"; |
66 | char name_sh[32]="/bin/ash.static"; |
Line 80... | Line 80... | ||
80 | 80 | ||
81 | 81 | ||
82 | /* Remove a tree */ |
82 | /* Remove a tree */ |
83 | int remove_tree(char *dirname) |
83 | int remove_tree(char *dirname) |
84 | { |
84 | { |
85 |
|
85 | DIR *sdir; |
86 |
|
86 | struct dirent *f; |
87 |
|
87 | struct stat dst; |
88 | 88 | ||
89 |
|
89 | sdir=opendir(dirname); |
90 |
|
90 | if(sdir==NULL) { /* Cannot open session directory. */ |
91 |
|
91 | return -1; |
92 |
|
92 | } |
93 |
|
93 | while((f=readdir(sdir))!=NULL) { |
94 |
|
94 | char fname[255]; |
95 |
|
95 | if(strcmp(".",f->d_name)==0 || strcmp("..",f->d_name)==0) continue; |
96 |
|
96 | snprintf(fname,sizeof(fname),"%s/%s",dirname,f->d_name); |
97 |
|
97 | if(lstat(fname,&dst)) continue; |
98 |
|
98 | if(S_ISDIR(dst.st_mode)) remove_tree(fname); |
99 |
|
99 | else { |
100 |
|
100 | if(remove(fname)<0) |
101 |
|
101 | fprintf(stderr,"ch..root: unable to remove %s. %s\n",fname,strerror(errno)); |
102 |
|
102 | } |
103 |
|
103 | } |
104 |
|
104 | closedir(sdir); |
105 |
|
105 | if(rmdir(dirname)<0) { /* Cannot remove directory. */ |
106 |
|
106 | return -1; |
107 |
|
107 | } |
108 |
|
108 | return 0; |
109 | } |
109 | } |
110 | 110 | ||
111 | /* Clean TMP */ |
111 | /* Clean TMP */ |
112 | void cleantmp(void) |
112 | void cleantmp(void) |
113 | { |
113 | { |
114 |
|
114 | DIR *sdir_base; |
115 |
|
115 | struct dirent *ses; |
116 |
|
116 | struct stat dst; |
117 | 117 | ||
118 |
|
118 | if(chdir("../chroot/tmp/sessions")<0) return; |
119 |
|
119 | sdir_base=opendir("."); |
120 |
|
120 | if(sdir_base==NULL) return; |
121 |
|
121 | while((ses=readdir(sdir_base))!=NULL) { |
122 |
|
122 | if(ses->d_name[0]=='.') continue; |
123 |
|
123 | if(lstat(ses->d_name,&dst)) continue; |
124 |
|
124 | if(!S_ISDIR(dst.st_mode)) continue; |
125 |
|
125 | if(dst.st_mtime <= now) { |
126 |
|
126 | if(dst.st_mtime>=now-CLEAN_DELAY) continue; |
127 |
|
127 | if(dst.st_mtime>=now-CLEAN_DELAY2 && (dst.st_mode&S_IRWXO)==0) continue; |
128 | } |
- | |
129 | remove_tree(ses->d_name); |
- | |
130 | } |
128 | } |
- | 129 | remove_tree(ses->d_name); |
|
- | 130 | } |
|
131 | } |
131 | } |
132 | 132 | ||
133 | /* Cleaning */ |
133 | /* Cleaning */ |
134 | void cleaning(void) |
134 | void cleaning(void) |
135 | { |
135 | { |
136 |
|
136 | DIR *sdir_base; |
137 |
|
137 | struct dirent *ses; |
138 |
|
138 | struct stat dst; |
139 |
|
139 | struct utimbuf ub; |
140 |
|
140 | char dbuf[256]; |
141 | 141 | ||
142 |
|
142 | if(stat(timestamp,&dst)==0 && dst.st_mtime==now) return; |
143 |
|
143 | ub.actime=ub.modtime=now; utime(timestamp,&ub); |
144 |
|
144 | sdir_base=opendir("/proc"); |
145 |
|
145 | if(sdir_base==NULL) goto tmpdir; |
146 |
|
146 | while((ses=readdir(sdir_base))!=NULL) { |
147 |
|
147 | if(ses->d_name[0]<'0' || ses->d_name[9]>'9') continue; |
148 |
|
148 | snprintf(dbuf,sizeof(dbuf),"/proc/%s",ses->d_name); |
149 |
|
149 | if(lstat(dbuf,&dst)) continue; |
150 |
|
150 | if(!S_ISDIR(dst.st_mode)) continue; |
151 |
|
151 | if(dst.st_uid<UID_MIN || dst.st_uid>UID_MIN+UID_MASK) continue; |
152 |
|
152 | if(((dst.st_gid-UID_MIN-now)&TIME_MASK)<=CPU_MAX) continue; |
153 |
|
153 | kill(atoi(ses->d_name),SIGKILL); |
154 |
|
154 | } |
155 |
|
155 | closedir(sdir_base); |
156 |
|
156 | tmpdir: return; |
157 | } |
157 | } |
158 | 158 | ||
159 | /* Test Must */ |
159 | /* Test Must */ |
160 | int test_must(void) |
160 | int test_must(void) |
161 | { |
161 | { |
162 |
|
162 | char *pc; |
163 |
|
163 | if(must) return 1; |
164 |
|
164 | pc=getenv("chroot"); if(pc && strcmp(pc,"must")==0) return 1; |
165 |
|
165 | else return 0; |
166 | } |
166 | } |
167 | 167 | ||
168 | /* MAIN */ |
168 | /* MAIN */ |
169 | int main(int argc,char *argv[]) |
169 | int main(int argc,char *argv[]) |
170 | { |
170 | { |
171 |
|
171 | char *args[1024]; |
172 |
|
172 | char parm[MAX_PARMLEN]; |
173 |
|
173 | char tmpbuf[256]; |
174 |
|
174 | int i,k,uid,t; |
175 |
|
175 | struct stat st; |
176 |
|
176 | struct rlimit lim; |
177 |
|
177 | char *p, *pp; |
178 | 178 | ||
179 |
|
179 | if(argc<2) return 0; |
180 |
|
180 | now=time(NULL); |
181 |
|
181 | uid=geteuid(); |
182 |
|
182 | t=stat("../chroot/tmp/sessions/.chroot",&st); |
183 |
|
183 | if(uid!=0 || t!=0) { |
184 |
|
184 | if(test_must()) goto abandon; |
185 |
|
185 | args[0]="bin/wrap..exec"; k=1; |
186 |
|
186 | } |
187 |
|
187 | else { |
188 |
|
188 | k=0; |
189 |
|
189 | p=getenv("REMOTE_ADDR"); |
190 |
|
190 | if(p && *p) { |
191 |
|
191 | pp=strrchr(p,'.'); if(pp) execuid=(atoi(++pp)&UID_MASK)+UID_MIN; |
192 |
|
192 | } |
193 |
|
193 | getrlimit(RLIMIT_CPU,&lim); |
194 |
|
194 | i=lim.rlim_max; if(i<0) i=0; if(i>=CPU_MAX) i=CPU_MAX-1; |
195 |
|
195 | execgid=((i+now+1)&TIME_MASK)+UID_MIN; |
196 |
|
196 | cleaning(); |
197 |
|
197 | } |
198 |
|
198 | if(argc>1 && strcmp(argv[1],"cleantmpdir")==0) { |
199 |
|
199 | if(uid!=0) fprintf(stderr,"ch..root cleantmpdir: uid not changed.\n"); |
200 |
|
200 | else cleantmp(); |
201 |
|
201 | return 0; |
202 |
|
202 | } |
203 |
|
203 | if(argc>3 && argv[1][0]=='&') { |
204 |
|
204 | if(k) goto abandon; |
205 |
|
205 | if(strcmp(argv[2],"sh")==0) { |
206 |
|
206 | lim.rlim_cur=lim.rlim_max=MAX_OUTLEN; |
207 |
|
207 | setrlimit(RLIMIT_FSIZE,&lim); |
208 |
|
208 | args[0]=name_sh; args[1]=opt_sh; |
209 |
|
209 | snprintf(parm,sizeof(parm),"%s\n%s\n",pre_sh,argv[3]); |
210 |
|
210 | args[2]=parm; args[3]=NULL; must=1; |
211 |
|
211 | goto cont; |
212 |
|
212 | } |
213 |
|
213 | if(strcmp(argv[2],"perl")==0) { |
214 |
|
214 | lim.rlim_cur=lim.rlim_max=MAX_OUTLEN; |
215 |
|
215 | setrlimit(RLIMIT_FSIZE,&lim); |
216 |
|
216 | args[0]=name_perl; args[1]=opt_perl; |
217 |
|
217 | snprintf(parm,sizeof(parm),"%s\n%s\n",pre_perl,argv[3]); |
218 |
|
218 | args[2]=parm; args[3]=NULL; must=1; |
219 |
|
219 | goto cont; |
220 | } |
- | |
221 | goto abandon; |
- | |
222 | } |
- | |
223 | for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1]; |
- | |
224 | args[i]=NULL; |
- | |
225 | cont: |
- | |
226 | if(uid!=0) { |
- | |
227 | if(test_must()) goto abandon; |
- | |
228 | goto ex2; |
- | |
229 | } |
- | |
230 | if(t!=0) { |
- | |
231 | stat("bin",&st); execuid=execgid=st.st_uid; |
- | |
232 | if(test_must()) goto abandon; |
- | |
233 | goto ex; |
- | |
234 | } |
220 | } |
- | 221 | goto abandon; |
|
- | 222 | } |
|
- | 223 | for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1]; |
|
- | 224 | args[i]=NULL; |
|
- | 225 | cont: |
|
- | 226 | if(uid!=0) { |
|
- | 227 | if(test_must()) goto abandon; |
|
- | 228 | goto ex2; |
|
- | 229 | } |
|
- | 230 | if(t!=0) { |
|
- | 231 | stat("bin",&st); execuid=execgid=st.st_uid; |
|
- | 232 | if(test_must()) goto abandon; |
|
- | 233 | goto ex; |
|
- | 234 | } |
|
235 |
|
235 | if(chroot("../chroot")==0) { |
236 |
|
236 | (void)chdir("/tmp"); |
237 |
|
237 | lim.rlim_cur=lim.rlim_max=PROC_QUOTA; |
238 |
|
238 | setrlimit(RLIMIT_NPROC,&lim); |
239 |
|
239 | setenv("PATH",chroot_path,1); |
240 |
|
240 | p=getenv("w_wims_session"); |
241 |
|
241 | if(p && *p) { |
242 |
|
242 | snprintf(tmpbuf,sizeof(tmpbuf),"/tmp/sessions/%s",p); |
243 |
|
243 | p=strchr(tmpbuf,'_'); if(p) *p=0; |
244 |
|
244 | setenv("TMPDIR",tmpbuf,1); |
245 |
|
245 | setenv("tmp_dir",tmpbuf,1); |
246 |
|
246 | p=getenv("w_wims_priv_chroot"); |
247 |
|
247 | if(p && strstr(p,"tmpdir")!=NULL) |
248 |
|
248 | (void)chdir(tmpbuf); |
249 | } |
- | |
250 | } |
249 | } |
- | 250 | } |
|
251 |
|
251 | else if(test_must()) goto abandon; |
252 |
|
252 | ex: |
253 |
|
253 | if(setregid(execgid,execgid)<0) goto abandon; |
254 |
|
254 | if(setreuid(execuid,execuid)<0) goto abandon; |
255 |
|
255 | ex2: |
256 |
|
256 | for(i=0;i<env_rm_cnt;i++) unsetenv(env_rm[i]); |
257 |
|
257 | if(strchr(args[0],'/')) execv(args[0],args); else execvp(args[0],args); |
258 |
|
258 | abandon: return 127; |
259 | } |
259 | } |
260 | - |