Blender V2.61 - r43446

blenderplayer-wrapper.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is:  none.
00022  *
00023  * Contributor(s): Enrico Fracasso
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * wrapper used to run webplugin with lower privilage: it must be setuid root
00027  */
00028 
00029 
00030 // Enabling O_NOFOLLOW
00031 #define _GNU_SOURCE
00032 
00033 #include <stdio.h>
00034 #include <unistd.h>
00035 
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 
00040 #include <pwd.h>
00041 #include <stdlib.h> // exit
00042 #include <string.h> // memcpy
00043 
00044 #include <signal.h>
00045 
00046 // the blenderplayer id (used by sigterm_handler handler)
00047 pid_t blenderplayer_id = 0;
00048 
00049 
00050 
00051 void print_id()
00052 {
00053     uid_t ruid, euid, suid;
00054 
00055     getresuid(&ruid, &euid, &suid);
00056     printf("Real UID %d, Effective UID %d, Saved UID %d\n", ruid, euid, suid);
00057 
00058 }
00059 
00064 void sigterm_handler(int signum)
00065 {
00066     printf("Signal!!!\n");
00067     if (blenderplayer_id != 0) {
00068         kill(blenderplayer_id, SIGKILL);
00069         printf("Signal sent!!!\n");
00070     }
00071     
00072 }
00073 
00081 int main(int argc, char *argv[])
00082 {
00083     uid_t privid = geteuid();
00084     uid_t caller_id = getuid();
00085 
00088     struct passwd *pw;
00089     pw = getpwnam("nobody"); // make it a param on a config file
00090     uid_t  new_id = pw->pw_uid;
00091 
00092     if (argc != 3) {
00093         fprintf(stderr, "I need two parameters on command line!\n");
00094         exit(EXIT_FAILURE);
00095     }
00096 
00097     /* If the caller is the owner of the file, chown to the privsep user */
00098     const char* file_name = argv[1];
00099     const char* window_id = argv[2];
00100     fprintf(stderr, "File name: %s XID: %s\n", file_name, window_id);
00101 
00102     struct stat stat_data;
00103 
00104     int fd = open(file_name, O_NOFOLLOW);
00105     if (fd == -1 ) {
00106         perror("Cannot open file\n");
00107         exit(EXIT_FAILURE);
00108     }
00109     
00110     if (fstat(fd, &stat_data) != 0) {
00111         perror("Cannot read file\n");
00112         exit(EXIT_FAILURE);
00113     }
00114 
00115     if (stat_data.st_uid != caller_id) {
00116         printf("File not owned by the caller\n");
00117         exit(EXIT_FAILURE);
00118     }
00119 
00120     if (!S_ISREG(stat_data.st_mode)) {
00121         printf("File is not a regular file\n");
00122         exit(EXIT_FAILURE);
00123     }
00124 
00125     if (fchown(fd, new_id, -1) != 0 ){
00126         perror("Cannot chown file\n");
00127         exit(EXIT_FAILURE);
00128     }
00129     
00130     if ( close(fd) != 0) {
00131         perror("Cannot close file\n");
00132         exit(EXIT_FAILURE);
00133     }
00134 
00135 
00136     /* creating Xlib xauth file */
00137     char template[] = "/tmp/blender-auth.XXXXXX";
00138     /* We need a temp file name only; file will be created by xauth later */
00139     char * auth_file_name = mktemp(template);
00140 
00141     const char* display = getenv("DISPLAY");
00142     if (display == NULL) {
00143         fprintf(stderr, "DISPLAY environment variable not found, aborting");
00144         exit(EXIT_FAILURE);
00145     }
00146 
00147     printf("Forking auth....\n");
00148     pid_t id_auth = fork();
00149 
00150     if (id_auth == 0) { //child 
00151 
00152         /* I want to run xauth as caller user */
00153         if (setuid(caller_id) != 0) {
00154             perror("Cannot drop privilages!\n");
00155             exit(EXIT_FAILURE);
00156         }
00157 
00158         
00159         if (setuid(0) != -1) {
00160             perror("Privilages can be restored!\n");
00161             exit(EXIT_FAILURE);
00162         }
00163 
00164         print_id(); 
00165     
00166         int e = execlp ("xauth", "xauth", "-f", auth_file_name, "generate", display, ".", "trusted", (char*)NULL);
00167         perror("Error executing xauth!\n"); 
00168         exit(EXIT_FAILURE);
00169 
00170     } if (id_auth < 0 )  { //error
00171         perror("Cannot fork!\n");
00172         exit(EXIT_FAILURE);
00173     
00174     } else { // parent
00175         int status;
00176         fprintf(stderr, "Waiting for xauth....\n");
00177         wait(&status);
00178         fprintf(stderr, "Done!\n");
00179     }
00180 
00181     /* xauth file must be readable by the privsep user */
00182     if (chown(auth_file_name, new_id, -1) != 0 ){
00183         perror("Cannot chown auth file\n");
00184         exit(EXIT_FAILURE);
00185     }
00186 
00187     signal(SIGTERM, sigterm_handler);
00188     print_id(); 
00189 
00190     blenderplayer_id = fork();
00191     if (blenderplayer_id == 0 ) { //child
00192         
00195         if (setuid(new_id) != 0) {
00196             perror("Cannot drop privilages!\n");
00197             exit(EXIT_FAILURE);
00198         }
00199         
00200         if (setuid(0) != -1) {
00201             perror("Privilages can be restored!\n");
00202             exit(EXIT_FAILURE);
00203         }
00204         
00205         print_id();
00206         fprintf(stderr, "Privilages dropped successfully\n");
00207     
00208         setenv("XAUTHORITY", auth_file_name, 1);
00209     
00210         const char* blenderplayer = "/usr/bin/blenderplayer";
00211         execl(blenderplayer, "blenderplayer", "-i", window_id, file_name, (char*)NULL);
00212     } else {
00214         int status;
00215         fprintf(stderr, "Waiting for blenderplayer....\n");
00216         wait(&status);
00217         fprintf(stderr, "blenderplayer done!\n");
00218 
00219         // We have to remove xauth file and I have to chown blender file back to the original user
00220         if (chown(file_name, caller_id, -1) != 0 ){
00221             perror("Cannot chown file back to original user\n");
00222             exit(EXIT_FAILURE);
00223         }
00224 
00225         if (unlink(auth_file_name) != 0) {
00226             perror("Cannot remove xauth file!\n");
00227             exit(EXIT_FAILURE);
00228         }
00229     
00230     }
00231 
00232     
00233 }
00234