Subversion Repositories wimsdev

Rev

Rev 3840 | Rev 11128 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3840 Rev 7076
Line 13... Line 13...
13
 *  You should have received a copy of the GNU General Public License
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
16
 */
17
 
17
 
18
        /* Change root and exec */
18
/* Change root and exec */
19
 
19
 
20
#define PROC_QUOTA 15
20
#define PROC_QUOTA 15
21
#define UID_MIN 10000
21
#define UID_MIN 10000
22
#define UID_MASK 127
22
#define UID_MASK 127
23
#define CPU_MAX 4096
23
#define CPU_MAX 4096
Line 59... Line 59...
59
      "texgif_fontdir", "texgif_texheader",
59
      "texgif_fontdir", "texgif_texheader",
60
      "w_wims_tmp_debug", "w_insmath_logic", "w_insmath_rawmath",
60
      "w_wims_tmp_debug", "w_insmath_logic", "w_insmath_rawmath",
61
      "SERVER_ADMIN", "SERVER_ADDR", "SERVER_NAME"
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";
67
char opt_sh[32]="-c";
67
char opt_sh[32]="-c";
68
char *pre_sh="\
68
char *pre_sh="\
69
cd $TMPDIR || exit\n\
69
cd $TMPDIR || exit\n\
Line 76... Line 76...
76
char *pre_perl="\
76
char *pre_perl="\
77
chdir($ENV{TMPDIR}) || exit;\n\
77
chdir($ENV{TMPDIR}) || exit;\n\
78
chdir(\"/\") && exit;\n\
78
chdir(\"/\") && exit;\n\
79
";
79
";
80
 
80
 
-
 
81
 
81
        /* remove a tree */
82
/* Remove a tree */
82
int remove_tree(char *dirname)
83
int remove_tree(char *dirname)
83
{
84
{
84
    DIR *sdir;
85
    DIR *sdir;
85
    struct dirent *f;
86
    struct dirent *f;
86
    struct stat dst;
87
    struct stat dst;
87
 
88
 
88
    sdir=opendir(dirname);
89
    sdir=opendir(dirname);
89
    if(sdir==NULL) {   /* Cannot open session directory. */
90
    if(sdir==NULL) {   /* Cannot open session directory. */
90
        return -1;
91
       return -1;
91
    }
92
    }
92
    while((f=readdir(sdir))!=NULL) {
93
    while((f=readdir(sdir))!=NULL) {
93
        char fname[255];
94
        char fname[255];
94
        if(strcmp(".",f->d_name)==0 || strcmp("..",f->d_name)==0) continue;
95
        if(strcmp(".",f->d_name)==0 || strcmp("..",f->d_name)==0) continue;
95
        snprintf(fname,sizeof(fname),"%s/%s",dirname,f->d_name);
96
        snprintf(fname,sizeof(fname),"%s/%s",dirname,f->d_name);
96
        if(lstat(fname,&dst)) continue;
97
        if(lstat(fname,&dst)) continue;
97
        if(S_ISDIR(dst.st_mode)) remove_tree(fname);
98
        if(S_ISDIR(dst.st_mode)) remove_tree(fname);
98
        else {
99
        else {
99
            if(remove(fname)<0)
100
            if(remove(fname)<0)
100
              fprintf(stderr,"ch..root: unable to remove %s. %s\n",fname,strerror(errno));
101
              fprintf(stderr,"ch..root: unable to remove %s. %s\n",fname,strerror(errno));
101
        }
102
        }
102
    }
103
    }
103
    closedir(sdir);
104
    closedir(sdir);
104
    if(rmdir(dirname)<0) {      /* Cannot remove directory. */
105
    if(rmdir(dirname)<0) {  /* Cannot remove directory. */
105
        return -1;
106
       return -1;
106
    }
107
    }
107
    return 0;
108
    return 0;
108
}
109
}
109
 
110
 
-
 
111
/* Clean TMP */
110
void cleantmp(void)
112
void cleantmp(void)
111
{
113
{
112
    DIR *sdir_base;
114
    DIR *sdir_base;
113
    struct dirent *ses;
115
    struct dirent *ses;
114
    struct stat dst;
116
    struct stat dst;
115
   
117
   
116
    if(chdir("../chroot/tmp/sessions")<0) return;
118
    if(chdir("../chroot/tmp/sessions")<0) return;
117
    sdir_base=opendir(".");
119
    sdir_base=opendir(".");
118
    if(sdir_base==NULL) return;
120
    if(sdir_base==NULL) return;
119
    while((ses=readdir(sdir_base))!=NULL) {
121
    while((ses=readdir(sdir_base))!=NULL) {
120
        if(ses->d_name[0]=='.') continue;
122
        if(ses->d_name[0]=='.') continue;
121
        if(lstat(ses->d_name,&dst)) continue;
123
        if(lstat(ses->d_name,&dst)) continue;
122
        if(!S_ISDIR(dst.st_mode)) continue;
124
        if(!S_ISDIR(dst.st_mode)) continue;
123
        if(dst.st_mtime <= now) {
125
        if(dst.st_mtime <= now) {
124
            if(dst.st_mtime>=now-CLEAN_DELAY) continue;
126
            if(dst.st_mtime>=now-CLEAN_DELAY) continue;
125
            if(dst.st_mtime>=now-CLEAN_DELAY2 && (dst.st_mode&S_IRWXO)==0) continue;
127
            if(dst.st_mtime>=now-CLEAN_DELAY2 && (dst.st_mode&S_IRWXO)==0) continue;
126
        }
128
        }
127
        remove_tree(ses->d_name);
129
        remove_tree(ses->d_name);
128
    }
130
    }
129
}
131
}
130
 
132
 
-
 
133
/* Cleaning */
131
void cleaning(void)
134
void cleaning(void)
132
{
135
{
133
    DIR *sdir_base;
136
    DIR *sdir_base;
134
    struct dirent *ses;
137
    struct dirent *ses;
135
    struct stat dst;
138
    struct stat dst;
Line 139... Line 142...
139
    if(stat(timestamp,&dst)==0 && dst.st_mtime==now) return;
142
    if(stat(timestamp,&dst)==0 && dst.st_mtime==now) return;
140
    ub.actime=ub.modtime=now; utime(timestamp,&ub);
143
    ub.actime=ub.modtime=now; utime(timestamp,&ub);
141
    sdir_base=opendir("/proc");
144
    sdir_base=opendir("/proc");
142
    if(sdir_base==NULL) goto tmpdir;
145
    if(sdir_base==NULL) goto tmpdir;
143
    while((ses=readdir(sdir_base))!=NULL) {
146
    while((ses=readdir(sdir_base))!=NULL) {
144
        if(ses->d_name[0]<'0' || ses->d_name[9]>'9') continue;
147
        if(ses->d_name[0]<'0' || ses->d_name[9]>'9') continue;
145
        snprintf(dbuf,sizeof(dbuf),"/proc/%s",ses->d_name);
148
        snprintf(dbuf,sizeof(dbuf),"/proc/%s",ses->d_name);
146
        if(lstat(dbuf,&dst)) continue;
149
        if(lstat(dbuf,&dst)) continue;
147
        if(!S_ISDIR(dst.st_mode)) continue;
150
        if(!S_ISDIR(dst.st_mode)) continue;
148
        if(dst.st_uid<UID_MIN || dst.st_uid>UID_MIN+UID_MASK) continue;
151
        if(dst.st_uid<UID_MIN || dst.st_uid>UID_MIN+UID_MASK) continue;
149
        if(((dst.st_gid-UID_MIN-now)&TIME_MASK)<=CPU_MAX) continue;
152
        if(((dst.st_gid-UID_MIN-now)&TIME_MASK)<=CPU_MAX) continue;
150
        kill(atoi(ses->d_name),SIGKILL);
153
        kill(atoi(ses->d_name),SIGKILL);
151
    }
154
    }
152
    closedir(sdir_base);
155
    closedir(sdir_base);
153
    tmpdir: return;
156
    tmpdir: return;
154
}
157
}
155
 
158
 
-
 
159
/* Test Must */
156
int test_must(void)
160
int test_must(void)
157
{
161
{
158
    char *pc;
162
    char *pc;
159
    if(must) return 1;
163
    if(must) return 1;
160
    pc=getenv("chroot"); if(pc && strcmp(pc,"must")==0) return 1;
164
    pc=getenv("chroot"); if(pc && strcmp(pc,"must")==0) return 1;
161
    else return 0;
165
    else return 0;
162
}
166
}
163
 
167
 
-
 
168
/* MAIN */
164
int main(int argc,char *argv[])
169
int main(int argc,char *argv[])
165
{
170
{
166
    char *args[1024];
171
    char *args[1024];
167
    char parm[MAX_PARMLEN];
172
    char parm[MAX_PARMLEN];
168
    char tmpbuf[256];
173
    char tmpbuf[256];
Line 174... Line 179...
174
    if(argc<2) return 0;
179
    if(argc<2) return 0;
175
    now=time(NULL);
180
    now=time(NULL);
176
    uid=geteuid();
181
    uid=geteuid();
177
    t=stat("../chroot/tmp/sessions/.chroot",&st);
182
    t=stat("../chroot/tmp/sessions/.chroot",&st);
178
    if(uid!=0 || t!=0) {
183
    if(uid!=0 || t!=0) {
179
        if(test_must()) goto abandon;
184
        if(test_must()) goto abandon;
180
        args[0]="bin/wrap..exec"; k=1;
185
        args[0]="bin/wrap..exec"; k=1;
181
    }
186
    }
182
    else {
187
    else {
183
        k=0;
188
        k=0;
184
        p=getenv("REMOTE_ADDR"); if(p && *p) {
189
        p=getenv("REMOTE_ADDR");
-
 
190
        if(p && *p) {
185
            pp=strrchr(p,'.'); if(pp) execuid=(atoi(++pp)&UID_MASK)+UID_MIN;
191
            pp=strrchr(p,'.'); if(pp) execuid=(atoi(++pp)&UID_MASK)+UID_MIN;
186
        }
192
        }
187
        getrlimit(RLIMIT_CPU,&lim);
193
        getrlimit(RLIMIT_CPU,&lim);
188
        i=lim.rlim_max; if(i<0) i=0; if(i>=CPU_MAX) i=CPU_MAX-1;
194
        i=lim.rlim_max; if(i<0) i=0; if(i>=CPU_MAX) i=CPU_MAX-1;
189
        execgid=((i+now+1)&TIME_MASK)+UID_MIN;
195
        execgid=((i+now+1)&TIME_MASK)+UID_MIN;
190
        cleaning();
196
        cleaning();
191
    }
197
    }
192
    if(argc>1 && strcmp(argv[1],"cleantmpdir")==0) {
198
    if(argc>1 && strcmp(argv[1],"cleantmpdir")==0) {
193
        if(uid!=0) fprintf(stderr,"ch..root cleantmpdir: uid not changed.\n");
199
        if(uid!=0) fprintf(stderr,"ch..root cleantmpdir: uid not changed.\n");
194
        else cleantmp();
200
        else cleantmp();
195
        return 0;
201
        return 0;
196
    }
202
    }
197
    if(argc>3 && argv[1][0]=='&') {
203
    if(argc>3 && argv[1][0]=='&') {
198
        if(k) goto abandon;
204
        if(k) goto abandon;
199
        if(strcmp(argv[2],"sh")==0) {
205
        if(strcmp(argv[2],"sh")==0) {
200
            lim.rlim_cur=lim.rlim_max=MAX_OUTLEN;
206
            lim.rlim_cur=lim.rlim_max=MAX_OUTLEN;
201
            setrlimit(RLIMIT_FSIZE,&lim);
207
            setrlimit(RLIMIT_FSIZE,&lim);
202
            args[0]=name_sh; args[1]=opt_sh;
208
            args[0]=name_sh; args[1]=opt_sh;
203
            snprintf(parm,sizeof(parm),"%s\n%s\n",pre_sh,argv[3]);
209
            snprintf(parm,sizeof(parm),"%s\n%s\n",pre_sh,argv[3]);
204
            args[2]=parm; args[3]=NULL; must=1;
210
            args[2]=parm; args[3]=NULL; must=1;
205
            goto cont;
211
            goto cont;
206
        }
212
        }
207
        if(strcmp(argv[2],"perl")==0) {
213
        if(strcmp(argv[2],"perl")==0) {
208
            lim.rlim_cur=lim.rlim_max=MAX_OUTLEN;
214
            lim.rlim_cur=lim.rlim_max=MAX_OUTLEN;
209
            setrlimit(RLIMIT_FSIZE,&lim);
215
            setrlimit(RLIMIT_FSIZE,&lim);
210
            args[0]=name_perl; args[1]=opt_perl;
216
            args[0]=name_perl; args[1]=opt_perl;
211
            snprintf(parm,sizeof(parm),"%s\n%s\n",pre_perl,argv[3]);
217
            snprintf(parm,sizeof(parm),"%s\n%s\n",pre_perl,argv[3]);
212
            args[2]=parm; args[3]=NULL; must=1;
218
            args[2]=parm; args[3]=NULL; must=1;
213
            goto cont;
219
            goto cont;
214
        }
220
        }
215
        goto abandon;
221
        goto abandon;
216
    }
222
    }
217
    for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1];
223
    for(i=0;i<1000 && i<argc; i++) args[i+k]=argv[i+1];
218
    args[i]=NULL;
224
    args[i]=NULL;
219
    cont:
225
    cont:
220
    if(uid!=0) {
226
    if(uid!=0) {
221
        if(test_must()) goto abandon;
227
        if(test_must()) goto abandon;
222
        goto ex2;
228
        goto ex2;
223
    }
229
    }
224
    if(t!=0) {
230
    if(t!=0) {
225
        stat("bin",&st); execuid=execgid=st.st_uid;
231
        stat("bin",&st); execuid=execgid=st.st_uid;
226
        if(test_must()) goto abandon;
232
        if(test_must()) goto abandon;
227
        goto ex;
233
        goto ex;
228
    }
234
    }
229
    if(chroot("../chroot")==0) {
235
    if(chroot("../chroot")==0) {
230
        (void)chdir("/tmp");
236
        (void)chdir("/tmp");
231
        lim.rlim_cur=lim.rlim_max=PROC_QUOTA;
237
        lim.rlim_cur=lim.rlim_max=PROC_QUOTA;
232
        setrlimit(RLIMIT_NPROC,&lim);
238
        setrlimit(RLIMIT_NPROC,&lim);
233
        setenv("PATH",chroot_path,1);
239
        setenv("PATH",chroot_path,1);
234
        p=getenv("w_wims_session"); if(p && *p) {
240
        p=getenv("w_wims_session");
-
 
241
        if(p && *p) {
235
            snprintf(tmpbuf,sizeof(tmpbuf),"/tmp/sessions/%s",p);
242
            snprintf(tmpbuf,sizeof(tmpbuf),"/tmp/sessions/%s",p);
236
            p=strchr(tmpbuf,'_'); if(p) *p=0;
243
            p=strchr(tmpbuf,'_'); if(p) *p=0;
237
            setenv("TMPDIR",tmpbuf,1);
244
            setenv("TMPDIR",tmpbuf,1);
238
            setenv("tmp_dir",tmpbuf,1);
245
            setenv("tmp_dir",tmpbuf,1);
239
            p=getenv("w_wims_priv_chroot");
246
            p=getenv("w_wims_priv_chroot");
240
            if(p && strstr(p,"tmpdir")!=NULL)
247
            if(p && strstr(p,"tmpdir")!=NULL)
241
              (void)chdir(tmpbuf);
248
              (void)chdir(tmpbuf);
242
        }
249
        }
243
    }
250
    }
244
    else if(test_must()) goto abandon;
251
    else if(test_must()) goto abandon;
245
    ex:
252
    ex:
246
    if(setregid(execgid,execgid)<0) goto abandon;
253
    if(setregid(execgid,execgid)<0) goto abandon;
247
    if(setreuid(execuid,execuid)<0) goto abandon;
254
    if(setreuid(execuid,execuid)<0) goto abandon;