symbian-qemu-0.9.1-12/python-2.6.1/Misc/setuid-prog.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2    Template for a setuid program that calls a script.
       
     3 
       
     4    The script should be in an unwritable directory and should itself
       
     5    be unwritable.  In fact all parent directories up to the root
       
     6    should be unwritable.  The script must not be setuid, that's what
       
     7    this program is for.
       
     8 
       
     9    This is a template program.  You need to fill in the name of the
       
    10    script that must be executed.  This is done by changing the
       
    11    definition of FULL_PATH below.
       
    12 
       
    13    There are also some rules that should be adhered to when writing
       
    14    the script itself.
       
    15 
       
    16    The first and most important rule is to never, ever trust that the
       
    17    user of the program will behave properly.  Program defensively.
       
    18    Check your arguments for reasonableness.  If the user is allowed to
       
    19    create files, check the names of the files.  If the program depends
       
    20    on argv[0] for the action it should perform, check it.
       
    21 
       
    22    Assuming the script is a Bourne shell script, the first line of the
       
    23    script should be
       
    24 	#!/bin/sh -
       
    25    The - is important, don't omit it.  If you're using esh, the first
       
    26    line should be
       
    27 	#!/usr/local/bin/esh -f
       
    28    and for ksh, the first line should be
       
    29 	#!/usr/local/bin/ksh -p
       
    30    The script should then set the variable IFS to the string
       
    31    consisting of <space>, <tab>, and <newline>.  After this (*not*
       
    32    before!), the PATH variable should be set to a reasonable value and
       
    33    exported.  Do not expect the PATH to have a reasonable value, so do
       
    34    not trust the old value of PATH.  You should then set the umask of
       
    35    the program by calling
       
    36 	umask 077 # or 022 if you want the files to be readable
       
    37    If you plan to change directories, you should either unset CDPATH
       
    38    or set it to a good value.  Setting CDPATH to just ``.'' (dot) is a
       
    39    good idea.
       
    40    If, for some reason, you want to use csh, the first line should be
       
    41 	#!/bin/csh -fb
       
    42    You should then set the path variable to something reasonable,
       
    43    without trusting the inherited path.  Here too, you should set the
       
    44    umask using the command
       
    45 	umask 077 # or 022 if you want the files to be readable
       
    46 */
       
    47 
       
    48 #include <unistd.h>
       
    49 #include <stdlib.h>
       
    50 #include <stdio.h>
       
    51 #include <sys/types.h>
       
    52 #include <sys/stat.h>
       
    53 #include <string.h>
       
    54 
       
    55 /* CONFIGURATION SECTION */
       
    56 
       
    57 #ifndef FULL_PATH	/* so that this can be specified from the Makefile */
       
    58 /* Uncomment the following line:
       
    59 #define FULL_PATH	"/full/path/of/script" 
       
    60 * Then comment out the #error line. */
       
    61 #error "You must define FULL_PATH somewhere"
       
    62 #endif
       
    63 #ifndef UMASK
       
    64 #define UMASK		077
       
    65 #endif
       
    66 
       
    67 /* END OF CONFIGURATION SECTION */
       
    68 
       
    69 #if defined(__STDC__) && defined(__sgi)
       
    70 #define environ _environ
       
    71 #endif
       
    72 
       
    73 /* don't change def_IFS */
       
    74 char def_IFS[] = "IFS= \t\n";
       
    75 /* you may want to change def_PATH, but you should really change it in */
       
    76 /* your script */
       
    77 #ifdef __sgi
       
    78 char def_PATH[] = "PATH=/usr/bsd:/usr/bin:/bin:/usr/local/bin:/usr/sbin";
       
    79 #else
       
    80 char def_PATH[] = "PATH=/usr/ucb:/usr/bin:/bin:/usr/local/bin";
       
    81 #endif
       
    82 /* don't change def_CDPATH */
       
    83 char def_CDPATH[] = "CDPATH=.";
       
    84 /* don't change def_ENV */
       
    85 char def_ENV[] = "ENV=:";
       
    86 
       
    87 /*
       
    88    This function changes all environment variables that start with LD_
       
    89    into variables that start with XD_.  This is important since we
       
    90    don't want the script that is executed to use any funny shared
       
    91    libraries.
       
    92 
       
    93    The other changes to the environment are, strictly speaking, not
       
    94    needed here.  They can safely be done in the script.  They are done
       
    95    here because we don't trust the script writer (just like the script
       
    96    writer shouldn't trust the user of the script).
       
    97    If IFS is set in the environment, set it to space,tab,newline.
       
    98    If CDPATH is set in the environment, set it to ``.''.
       
    99    Set PATH to a reasonable default.
       
   100 */
       
   101 void
       
   102 clean_environ(void)
       
   103 {
       
   104 	char **p;
       
   105 	extern char **environ;
       
   106 
       
   107 	for (p = environ; *p; p++) {
       
   108 		if (strncmp(*p, "LD_", 3) == 0)
       
   109 			**p = 'X';
       
   110 		else if (strncmp(*p, "_RLD", 4) == 0)
       
   111 			**p = 'X';
       
   112 		else if (strncmp(*p, "PYTHON", 6) == 0)
       
   113 			**p = 'X';
       
   114 		else if (strncmp(*p, "IFS=", 4) == 0)
       
   115 			*p = def_IFS;
       
   116 		else if (strncmp(*p, "CDPATH=", 7) == 0)
       
   117 			*p = def_CDPATH;
       
   118 		else if (strncmp(*p, "ENV=", 4) == 0)
       
   119 			*p = def_ENV;
       
   120 	}
       
   121 	putenv(def_PATH);
       
   122 }
       
   123 
       
   124 int
       
   125 main(int argc, char **argv)
       
   126 {
       
   127 	struct stat statb;
       
   128 	gid_t egid = getegid();
       
   129 	uid_t euid = geteuid();
       
   130 
       
   131 	/*
       
   132 	   Sanity check #1.
       
   133 	   This check should be made compile-time, but that's not possible.
       
   134 	   If you're sure that you specified a full path name for FULL_PATH,
       
   135 	   you can omit this check.
       
   136 	*/
       
   137 	if (FULL_PATH[0] != '/') {
       
   138 		fprintf(stderr, "%s: %s is not a full path name\n", argv[0],
       
   139 			FULL_PATH);
       
   140 		fprintf(stderr, "You can only use this wrapper if you\n");
       
   141 		fprintf(stderr, "compile it with an absolute path.\n");
       
   142 		exit(1);
       
   143 	}
       
   144 
       
   145 	/*
       
   146 	   Sanity check #2.
       
   147 	   Check that the owner of the script is equal to either the
       
   148 	   effective uid or the super user.
       
   149 	*/
       
   150 	if (stat(FULL_PATH, &statb) < 0) {
       
   151 		perror("stat");
       
   152 		exit(1);
       
   153 	}
       
   154 	if (statb.st_uid != 0 && statb.st_uid != euid) {
       
   155 		fprintf(stderr, "%s: %s has the wrong owner\n", argv[0],
       
   156 			FULL_PATH);
       
   157 		fprintf(stderr, "The script should be owned by root,\n");
       
   158 		fprintf(stderr, "and shouldn't be writeable by anyone.\n");
       
   159 		exit(1);
       
   160 	}
       
   161 
       
   162 	if (setregid(egid, egid) < 0)
       
   163 		perror("setregid");
       
   164 	if (setreuid(euid, euid) < 0)
       
   165 		perror("setreuid");
       
   166 
       
   167 	clean_environ();
       
   168 
       
   169 	umask(UMASK);
       
   170 
       
   171 	while (**argv == '-')	/* don't let argv[0] start with '-' */
       
   172 		(*argv)++;
       
   173 	execv(FULL_PATH, argv);
       
   174 	fprintf(stderr, "%s: could not execute the script\n", argv[0]);
       
   175 	exit(1);
       
   176 }