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

« back to all changes in this revision

Viewing changes to trampoline/trampoline.c

  • Committer: mattgiuca
  • Date: 2008-01-29 23:52:19 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:329
Converted Console from an "app" into a "plugin". It can now be plugged in to
any app.
Added "plugins" directory in www. Added "console" plugin. This contains all of
the functionality of what was previously the console app, but modularized so
it can be imported by another app.

apps/console: Removed most of the logic (moved to plugins/console). Replaced
with a simple import of the console plugin. Should behave exactly the same.
apps/tutorial: As proof of concept, imported the console plugin. It now
appears at the bottom of the page (yet to make it have "pop up" behaviour).

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
 
 
43
/* conf.h is admin-configured by the setup process.
 
44
 * It defines jail_base.
 
45
 */
 
46
#include "conf.h"
 
47
 
 
48
/* Returns TRUE if the given uid is allowed to execute trampoline.
 
49
 * Only root or the web server should be allowed to execute.
 
50
 * This is determined by the whitelist allowed_uids in conf.h.
 
51
 */
 
52
int uid_allowed(int uid)
 
53
{
 
54
    int i;
 
55
    /* root is always allowed to execute trampoline */
 
56
    if (uid == 0)
 
57
        return 1;
 
58
    /* loop over all allowed_uids */
 
59
    for (i=(sizeof(allowed_uids)/sizeof(*allowed_uids))-1; i>=0; i--)
 
60
    {
 
61
        if (allowed_uids[i] == uid)
 
62
            return 1;
 
63
    }
 
64
    /* default to disallowing */
 
65
    return 0;
 
66
}
 
67
 
 
68
/* Turn the process into a daemon using the standard
 
69
 * 2-fork technique.
 
70
 */
 
71
void daemonize(void)
 
72
{
 
73
    pid_t pid, sid;
 
74
 
 
75
    /* already a daemon */
 
76
    if ( getppid() == 1 ) return;
 
77
 
 
78
    /* Fork off the parent process */
 
79
    pid = fork();
 
80
    if (pid < 0) {
 
81
        exit(1);
 
82
    }
 
83
    /* If we got a good PID, then we can exit the parent process. */
 
84
    if (pid > 0) {
 
85
        exit(0);
 
86
    }
 
87
 
 
88
    /* At this point we are executing as the child process */
 
89
 
 
90
    /* Change the file mode mask */
 
91
    umask(0);
 
92
 
 
93
    /* Create a new SID for the child process */
 
94
    sid = setsid();
 
95
    if (sid < 0) {
 
96
        exit(1);
 
97
    }
 
98
 
 
99
    /* Change the current working directory.  This prevents the current
 
100
       directory from being locked; hence not being able to remove it. */
 
101
    if ((chdir("/")) < 0) {
 
102
        exit(1);
 
103
    }
 
104
 
 
105
    /* Redirect standard files to /dev/null */
 
106
    freopen( "/dev/null", "r", stdin);
 
107
    freopen( "/dev/null", "w", stdout);
 
108
    freopen( "/dev/null", "w", stderr);
 
109
}
 
110
 
 
111
static void usage(const char* nm)
 
112
{
 
113
    fprintf(stderr,
 
114
        "usage: %s [-d] <uid> <jail> <cwd> <program> [args...]\n", nm);
 
115
    exit(1);
 
116
}
 
117
 
 
118
int main(int argc, char* const argv[])
 
119
{
 
120
    char* jailpath;
 
121
    char* work_dir;
 
122
    char* prog;
 
123
    char* const * args;
 
124
    int uid;
 
125
    int arg_num = 1;
 
126
    int daemon_mode = 0;
 
127
 
 
128
    /* Disallow execution from all users but the whitelisted ones, and root */
 
129
    if (!uid_allowed(getuid()))
 
130
    {
 
131
        fprintf(stderr, "only the web server may execute trampoline\n");
 
132
        exit(1);
 
133
    }
 
134
 
 
135
    /* Args check and usage */
 
136
    if (argc < 5)
 
137
    {
 
138
        usage(argv[0]);
 
139
    }
 
140
 
 
141
    if (strcmp(argv[arg_num], "-d") == 0)
 
142
    {
 
143
        if (argc < 6)
 
144
        {
 
145
            usage(argv[0]);
 
146
        }
 
147
        daemon_mode = 1;
 
148
        arg_num++;
 
149
    }
 
150
    uid = atoi(argv[arg_num++]);
 
151
    jailpath = argv[arg_num++];
 
152
    work_dir = argv[arg_num++];
 
153
    prog = argv[arg_num];
 
154
    args = argv + arg_num;
 
155
 
 
156
    /* Disallow suiding to the root user */
 
157
    if (uid == 0)
 
158
    {
 
159
        fprintf(stderr, "cannot set up a jail as root\n");
 
160
        exit(1);
 
161
    }
 
162
 
 
163
    /* Jail path must:
 
164
     * Be non-empty
 
165
     * Start with a '/'
 
166
     * Not contain "/.."
 
167
     * Begin with jail_base
 
168
     */
 
169
    if (strlen(jailpath) < 1 || jailpath[0] != '/'
 
170
            || strstr(jailpath, "/..")
 
171
            || strncmp(jailpath, jail_base, strlen(jail_base)))
 
172
    {
 
173
        fprintf(stderr, "bad jail path: %s\n", jailpath);
 
174
        exit(1);
 
175
    }
 
176
 
 
177
    /* chroot into the jail.
 
178
     * Henceforth this process, and its children, cannot see anything above
 
179
     * jailpath. */
 
180
    if (chroot(jailpath))
 
181
    {
 
182
        perror("could not chroot");
 
183
        exit(1);
 
184
    }
 
185
 
 
186
    /* chdir into the specified working directory */
 
187
    if (chdir(work_dir))
 
188
    {
 
189
        perror("could not chdir");
 
190
        exit(1);
 
191
    }
 
192
 
 
193
    /* setuid to the given user ID.
 
194
     * Henceforth we will be running as this user instead of root.
 
195
     */
 
196
    if (setuid(uid))
 
197
    {
 
198
        perror("could not setuid");
 
199
        exit(1);
 
200
    }
 
201
 
 
202
    if (daemon_mode)
 
203
    {
 
204
        daemonize();
 
205
    }
 
206
 
 
207
    /* exec (replace this process with the a new instance of the target
 
208
     * program). Pass along all the arguments.
 
209
     * Note that for script execution, the "program" will be the interpreter,
 
210
     * and the first argument will be the script. */
 
211
    execv(prog, args);
 
212
 
 
213
    /* XXX if (daemon_mode) use syslog? */
 
214
    /* nb exec won't return unless there was an error */
 
215
    perror("could not exec");
 
216
    return 1;
 
217
}