1 /* persona.c - handle the persona of the process
2  *
3  * Copyright 1999  Jochen Voss  */
4 
5 static const  char  rcsid[] = "$Id: persona.c 4839 2003-04-13 16:50:02Z voss $";
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #ifdef _XOPEN_SOURCE
12 #define _XOPEN_SOURCE_EXTENDED 1
13 #endif
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 
20 #if defined(__hp9000s800)
21 #include <stdarg.h>
22 #endif
23 
24 #include "moon-buggy.h"
25 
26 
27 /* which method of uid handling is used?  */
28 static  enum { m_NONE, m_SAVED, m_EXCH }  method = m_NONE;
29 
30 /* the current effective user id */
31 static  enum persona  current = pers_GAME;
32 
33 /* The real and effective ids */
34 static  uid_t  user_uid, game_uid;
35 static  gid_t  user_gid, game_gid;
36 
37 
38 void
initialise_persona(void)39 initialise_persona (void)
40 {
41   long int  saved_ids_flag;
42 
43   current = pers_GAME;
44   method = m_NONE;
45 
46   user_uid = getuid ();
47   game_uid = geteuid ();
48   user_gid = getgid ();
49   game_gid = getegid ();
50   if (user_uid == game_uid && user_gid == game_gid)  return;
51 
52   /* check for the POSIX saved id feature.  */
53 #ifdef _POSIX_SAVED_IDS
54   saved_ids_flag = 1;
55 #else  /* not defined(_POSIX_SAVED_IDS) */
56   saved_ids_flag = sysconf (_SC_SAVED_IDS);
57 #endif /* not defined(_POSIX_SAVED_IDS) */
58   if (saved_ids_flag != -1) {
59     method = m_SAVED;
60     return;
61   }
62 
63 #ifdef HAVE_SETREUID
64   method = m_EXCH;
65 #else
66   fputs ("WARNING: setuid/setgid usage not supported on this system!\n",
67 	 stderr);
68   sleep (3);
69   setuid (user_uid);
70   setgid (user_gid);
71   method = m_NONE;
72 #endif
73 }
74 
75 int
is_setgid(void)76 is_setgid (void)
77 /* Return true, iff the game is run setgid and we currently use
78  * privileged access.  */
79 {
80   return  (user_gid != game_gid && current == pers_GAME);
81 }
82 
83 
84 static char *name[] = { "game", "user" };
85 
86 void
set_persona(enum persona pers)87 set_persona (enum persona  pers)
88 /* Switch to process persona (effective user id) PERS.  */
89 {
90   int  res;
91   uid_t  old_uid, new_uid;
92   gid_t  old_gid, new_gid;
93 
94   if (current == pers)  return;
95   switch (pers) {
96   case pers_GAME:
97     old_uid = user_uid;
98     new_uid = game_uid;
99     old_gid = user_gid;
100     new_gid = game_gid;
101     break;
102   case pers_USER:
103     old_uid = game_uid;
104     new_uid = user_uid;
105     old_gid = game_gid;
106     new_gid = user_gid;
107     break;
108   default:
109     abort ();			/* should not happen */
110   }
111 
112   switch (method) {
113   case m_NONE:
114     break;
115   case m_SAVED:
116     res = setuid (new_uid);
117     if (res < 0)  fatal ("Cannot set uid to %s", name[pers]);
118     res = setgid (new_gid);
119     if (res < 0)  fatal ("Cannot set gid to %s", name[pers]);
120     break;
121   case m_EXCH:
122 #ifdef HAVE_SETREUID
123     res = setreuid (old_uid, new_uid);
124     if (res < 0)  fatal ("Cannot switch real/effective uid to %s", name[pers]);
125     res = setregid (old_gid, new_gid);
126     if (res < 0)  fatal ("Cannot switch real/effective gid to %s", name[pers]);
127 #else
128     abort ();			/* should not happen */
129 #endif
130     break;
131   }
132   current = pers;
133 }
134