~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to trampoline/trampoline.c

  • Committer: mattgiuca
  • Date: 2008-02-05 01:41:15 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:409
Moved www/conf and www/common to a new directory lib. This separates the "web"
part of IVLE from what is becoming less web oriented (at least from Apache's
standpoint).
Modified setup.py to install this lib directory correctly and write conf in
the right place. Also adds the lib directory to ivle.pth.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* IVLE - Informatics Virtual Learning Environment
 
2
 * Copyright (C) 2007-2008 The University of Melbourne
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 *
 
18
 * Program: Trampoline
 
19
 * Author:  Tom Conway, Matt Giuca
 
20
 * Date:    20/12/2007
 
21
 *
 
22
 * This program runs a given program in a given working dir.
 
23
 * First, it chroots to a jail path and setuids to a given user ID.
 
24
 * This is intented to provide a safe execution environment for arbitrary
 
25
 * programs and scripts.
 
26
 *
 
27
 * Scripts (such as Python programs) should be executed by supplying
 
28
 * "/usr/bin/python" as the program, and the script as the first argument.
 
29
 *
 
30
 * Usage: trampoline uid jail-path working-path program [args...]
 
31
 * Must run as root. Will safely setuid to the supplied uid, checking that it
 
32
 * is not root. Recommended that the file is set up as follows:
 
33
 *  sudo chown root:root trampoline; sudo chroot +s trampoline
 
34
 */
 
35
 
 
36
#include <stdio.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
#include <unistd.h>
 
40
#include <sys/types.h>
 
41
#include <sys/stat.h>
 
42
#include <limits.h>
 
43
 
 
44
/* conf.h is admin-configured by the setup process.
 
45
 * It defines jail_base.
 
46
 */
 
47
#include "conf.h"
 
48
 
 
49
/* Returns TRUE if the given uid is allowed to execute trampoline.
 
50
 * Only root or the web server should be allowed to execute.
 
51
 * This is determined by the whitelist allowed_uids in conf.h.
 
52
 */
 
53
int uid_allowed(int uid)
 
54
{
 
55
    int i;
 
56
    /* root is always allowed to execute trampoline */
 
57
    if (uid == 0)
 
58
        return 1;
 
59
    /* loop over all allowed_uids */
 
60
    for (i=(sizeof(allowed_uids)/sizeof(*allowed_uids))-1; i>=0; i--)
 
61
    {
 
62
        if (allowed_uids[i] == uid)
 
63
            return 1;
 
64
    }
 
65
    /* default to disallowing */
 
66
    return 0;
 
67
}
 
68
 
 
69
/* Turn the process into a daemon using the standard
 
70
 * 2-fork technique.
 
71
 */
 
72
void daemonize(void)
 
73
{
 
74
    pid_t pid, sid;
 
75
 
 
76
    /* already a daemon */
 
77
    if ( getppid() == 1 ) return;
 
78
 
 
79
    /* Fork off the parent process */
 
80
    pid = fork();
 
81
    if (pid < 0) {
 
82
        exit(1);
 
83
    }
 
84
    /* If we got a good PID, then we can exit the parent process. */
 
85
    if (pid > 0) {
 
86
        exit(0);
 
87
    }
 
88
 
 
89
    /* At this point we are executing as the child process */
 
90
 
 
91
    /* Change the file mode mask */
 
92
    umask(0);
 
93
 
 
94
    /* Create a new SID for the child process */
 
95
    sid = setsid();
 
96
    if (sid < 0) {
 
97
        exit(1);
 
98
    }
 
99
 
 
100
    /* Change the current working directory.  This prevents the current
 
101
       directory from being locked; hence not being able to remove it. */
 
102
    if ((chdir("/")) < 0) {
 
103
        exit(1);
 
104
    }
 
105
 
 
106
    /* Redirect standard files to /dev/null */
 
107
    freopen( "/dev/null", "r", stdin);
 
108
    freopen( "/dev/null", "w", stdout);
 
109
    freopen( "/dev/null", "w", stderr);
 
110
}
 
111
 
 
112
static void usage(const char* nm)
 
113
{
 
114
    fprintf(stderr,
 
115
        "usage: %s [-d] <uid> <jail> <cwd> <program> [args...]\n", nm);
 
116
    exit(1);
 
117
}
 
118
 
 
119
int main(int argc, char* const argv[])
 
120
{
 
121
    char* jailpath;
 
122
    char* work_dir;
 
123
    char* prog;
 
124
    char* const * args;
 
125
    int uid;
 
126
    int arg_num = 1;
 
127
    int daemon_mode = 0;
 
128
    char canonical_jailpath[PATH_MAX];
 
129
 
 
130
    /* Disallow execution from all users but the whitelisted ones, and root */
 
131
    if (!uid_allowed(getuid()))
 
132
    {
 
133
        fprintf(stderr, "only the web server may execute trampoline\n");
 
134
        exit(1);
 
135
    }
 
136
 
 
137
    /* Args check and usage */
 
138
    if (argc < 5)
 
139
    {
 
140
        usage(argv[0]);
 
141
    }
 
142
 
 
143
    if (strcmp(argv[arg_num], "-d") == 0)
 
144
    {
 
145
        if (argc < 6)
 
146
        {
 
147
            usage(argv[0]);
 
148
        }
 
149
        daemon_mode = 1;
 
150
        arg_num++;
 
151
    }
 
152
    uid = atoi(argv[arg_num++]);
 
153
    jailpath = argv[arg_num++];
 
154
    work_dir = argv[arg_num++];
 
155
    prog = argv[arg_num];
 
156
    args = argv + arg_num;
 
157
 
 
158
    /* Disallow suiding to the root user */
 
159
    if (uid == 0)
 
160
    {
 
161
        fprintf(stderr, "cannot set up a jail as root\n");
 
162
        exit(1);
 
163
    }
 
164
 
 
165
    /* Jail path must be an absolute path,
 
166
     * and it must begin with jail_base.
 
167
     */
 
168
    if (norm(canonical_jailpath, PATH_MAX, jailpath) != 0)
 
169
    {
 
170
        fprintf(stderr, "bad jail path: %s\n", jailpath);
 
171
        exit(1);
 
172
    }
 
173
    if (strncmp(canonical_jailpath, jail_base, strlen(jail_base)))
 
174
    {
 
175
        fprintf(stderr, "bad jail path: %s\n", jailpath);
 
176
        exit(1);
 
177
    }
 
178
 
 
179
    /* chroot into the jail.
 
180
     * Henceforth this process, and its children, cannot see anything above
 
181
     * canoncial_jailpath. */
 
182
    if (chroot(canonical_jailpath))
 
183
    {
 
184
        perror("could not chroot");
 
185
        exit(1);
 
186
    }
 
187
 
 
188
    /* chdir into the specified working directory */
 
189
    if (chdir(work_dir))
 
190
    {
 
191
        perror("could not chdir");
 
192
        exit(1);
 
193
    }
 
194
 
 
195
    /* setuid to the given user ID.
 
196
     * Henceforth we will be running as this user instead of root.
 
197
     */
 
198
    if (setuid(uid))
 
199
    {
 
200
        perror("could not setuid");
 
201
        exit(1);
 
202
    }
 
203
 
 
204
    if (daemon_mode)
 
205
    {
 
206
        daemonize();
 
207
    }
 
208
 
 
209
    /* exec (replace this process with the a new instance of the target
 
210
     * program). Pass along all the arguments.
 
211
     * Note that for script execution, the "program" will be the interpreter,
 
212
     * and the first argument will be the script. */
 
213
    execv(prog, args);
 
214
 
 
215
    /* XXX if (daemon_mode) use syslog? */
 
216
    /* nb exec won't return unless there was an error */
 
217
    perror("could not exec");
 
218
    return 1;
 
219
}