Imported Upstream version 2.8.6
[platform/upstream/man-db.git] / lib / security.c
1 /*
2  * security.c: Routines to aid secure uid operations 
3  *  
4  * Copyright (C) 1994, 1995 Graeme W. Wilford. (Wilf.)
5  * Copyright (C) 2001, 2003, 2004, 2007, 2010, 2011 Colin Watson.
6  *
7  * This file is part of man-db.
8  *
9  * man-db is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * man-db is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with man-db; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  * Mon Aug  8 20:35:30 BST 1994  Wilf. (G.Wilford@ee.surrey.ac.uk) 
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #  include "config.h"
28 #endif /* HAVE_CONFIG_H */
29
30 #include <stdbool.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <errno.h>
36 #include <sys/types.h>
37
38 #include "gettext.h"
39 #define _(String) gettext (String)
40
41 #include "manconfig.h"
42
43 #include "error.h"
44 #include "cleanup.h"
45 #include "pipeline.h"
46
47 #include "security.h"
48
49 #ifdef MAN_OWNER
50
51    /*
52     * This is the name of the user that the preformatted man pages belong to.
53     * If you are running man as a setuid program, you should make sure
54     * that all of the cat pages and the directories that
55     * they live in are writeable by this user.
56     */
57
58 #  include <pwd.h>
59 #  include <unistd.h>
60
61 #  include "idpriv.h"
62
63 uid_t ruid;                             /* initial real user id */
64 uid_t euid;                             /* initial effective user id */
65 uid_t uid;                              /* current euid */
66 gid_t rgid;                             /* initial real group id */
67 gid_t egid;                             /* initial effective group id */
68 gid_t gid;                              /* current egid */
69
70 static struct passwd *man_owner;
71
72 /* Keep a count of how many times we've dropped privileges, and only regain
73  * them if regain_effective_privs() is called an equal number of times.
74  */
75 static int priv_drop_count = 0;
76
77 static void gripe_set_euid (void)
78 {
79         error (FATAL, errno, _("can't set effective uid"));
80 }
81
82 #endif /* MAN_OWNER */
83
84 void init_security (void)
85 {
86 #ifdef MAN_OWNER
87         ruid = getuid ();
88         uid = euid = geteuid ();
89         debug ("ruid=%d, euid=%d\n", (int) ruid, (int) euid);
90         rgid = getgid ();
91         gid = egid = getegid ();
92         debug ("rgid=%d, egid=%d\n", (int) rgid, (int) egid);
93         priv_drop_count = 0;
94         drop_effective_privs ();
95 #endif /* MAN_OWNER */
96 }
97
98 bool running_setuid (void)
99 {
100 #ifdef MAN_OWNER
101         return ruid != euid;
102 #else /* !MAN_OWNER */
103         return false;
104 #endif
105 }
106
107 #ifdef MAN_OWNER
108 /* Return a pointer to the password entry structure for MAN_OWNER. This
109  * structure will be statically stored.
110  */
111 struct passwd *get_man_owner (void)
112 {
113         if (man_owner)
114                 return man_owner;
115
116         man_owner = getpwnam (MAN_OWNER);
117         if (!man_owner)
118                 error (FAIL, 0, _("the setuid man user \"%s\" does not exist"),
119                        MAN_OWNER);
120         assert (man_owner);
121         return man_owner;
122 }
123 #endif /* MAN_OWNER */
124
125 /* 
126  * function to gain user privs by either (a) dropping effective privs 
127  * completely (saved ids) or (b) reversing euid w/ uid.
128  * Ignore if superuser.
129  */
130 void drop_effective_privs (void)
131 {
132 #ifdef MAN_OWNER
133         if (uid != ruid) {
134                 debug ("drop_effective_privs()\n");
135                 if (idpriv_temp_drop ())
136                         gripe_set_euid ();
137                 uid = ruid;
138                 gid = rgid;
139         }
140
141         priv_drop_count++;
142         debug ("++priv_drop_count = %d\n", priv_drop_count);
143 #endif /* MAN_OWNER */
144 }
145
146 /* 
147  * function to (re)gain setuid privs by (a) setting euid from suid or (b)
148  * (re)reversing uid w/ euid. Ignore if superuser.
149  */
150 void regain_effective_privs (void)
151 {
152 #ifdef MAN_OWNER
153         if (priv_drop_count) {
154                 priv_drop_count--;
155                 debug ("--priv_drop_count = %d\n", priv_drop_count);
156                 if (priv_drop_count)
157                         return;
158         }
159
160         if (uid != euid) {
161                 debug ("regain_effective_privs()\n");
162                 if (idpriv_temp_restore ())
163                         gripe_set_euid ();
164
165                 uid = euid;
166                 gid = egid;
167         }
168 #endif /* MAN_OWNER */
169 }
170
171 /* Pipeline command pre-exec hook to permanently drop privileges. */
172 void drop_privs (void *data ATTRIBUTE_UNUSED)
173 {
174 #ifdef MAN_OWNER
175         if (idpriv_drop ())
176                 gripe_set_euid ();
177 #endif /* MAN_OWNER */
178 }