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