1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5
6 This program is Free Software; you can redistribute it and/or
7 modify it under the terms of version three of the GNU Affero General Public
8 License as published by the Free Software Foundation and included
9 in the file LICENSE.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.
20 */
21
22 #include "include/bareos.h"
23 #include "lib/berrno.h"
24
25 #undef ENABLE_KEEP_READALL_CAPS_SUPPORT
26 #if defined(HAVE_SYS_PRCTL_H) && defined(HAVE_SYS_CAPABILITY_H) && \
27 defined(HAVE_PRCTL) && defined(HAVE_SETREUID) && defined(HAVE_LIBCAP)
28 #include <sys/prctl.h>
29 #include <sys/capability.h>
30 #if defined(PR_SET_KEEPCAPS)
31 #define ENABLE_KEEP_READALL_CAPS_SUPPORT
32 #endif
33 #endif
34
35 #ifdef HAVE_AIX_OS
36 #ifndef _AIX51
37 extern "C" int initgroups(const char*, int);
38 #endif
39 #endif
40
41 /*
42 * Lower privileges by switching to new UID and GID if non-NULL.
43 * If requested, keep readall capabilities after switch.
44 */
drop(char * uname,char * gname,bool keep_readall_caps)45 void drop(char* uname, char* gname, bool keep_readall_caps)
46 {
47 #if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
48 struct passwd* passw = NULL;
49 struct group* group = NULL;
50 gid_t gid;
51 uid_t uid;
52 char username[1000];
53
54 Dmsg2(900, "uname=%s gname=%s\n", uname ? uname : "NONE",
55 gname ? gname : "NONE");
56 if (!uname && !gname) { return; /* Nothing to do */ }
57
58 if (uname) {
59 if ((passw = getpwnam(uname)) == NULL) {
60 BErrNo be;
61 Emsg2(M_ERROR_TERM, 0, _("Could not find userid=%s: ERR=%s\n"), uname,
62 be.bstrerror());
63 }
64 } else {
65 if ((passw = getpwuid(getuid())) == NULL) {
66 BErrNo be;
67 Emsg1(M_ERROR_TERM, 0, _("Could not find password entry. ERR=%s\n"),
68 be.bstrerror());
69 } else {
70 uname = passw->pw_name;
71 }
72 }
73 /* Any OS uname pointer may get overwritten, so save name, uid, and gid */
74 bstrncpy(username, uname, sizeof(username));
75 uid = passw->pw_uid;
76 gid = passw->pw_gid;
77 if (gname) {
78 if ((group = getgrnam(gname)) == NULL) {
79 BErrNo be;
80 Emsg2(M_ERROR_TERM, 0, _("Could not find group=%s: ERR=%s\n"), gname,
81 be.bstrerror());
82 }
83 gid = group->gr_gid;
84 }
85 if (initgroups(username, gid)) {
86 BErrNo be;
87 if (gname) {
88 Emsg3(M_ERROR_TERM, 0,
89 _("Could not initgroups for group=%s, userid=%s: ERR=%s\n"), gname,
90 username, be.bstrerror());
91 } else {
92 Emsg2(M_ERROR_TERM, 0, _("Could not initgroups for userid=%s: ERR=%s\n"),
93 username, be.bstrerror());
94 }
95 }
96 if (gname) {
97 if (setgid(gid)) {
98 BErrNo be;
99 Emsg2(M_ERROR_TERM, 0, _("Could not set group=%s: ERR=%s\n"), gname,
100 be.bstrerror());
101 }
102 }
103 if (keep_readall_caps) {
104 #ifdef ENABLE_KEEP_READALL_CAPS_SUPPORT
105 cap_t caps;
106
107 if (prctl(PR_SET_KEEPCAPS, 1)) {
108 BErrNo be;
109 Emsg1(M_ERROR_TERM, 0, _("prctl failed: ERR=%s\n"), be.bstrerror());
110 }
111 if (setreuid(uid, uid)) {
112 BErrNo be;
113 Emsg1(M_ERROR_TERM, 0, _("setreuid failed: ERR=%s\n"), be.bstrerror());
114 }
115 if (!(caps = cap_from_text("cap_dac_read_search=ep"))) {
116 BErrNo be;
117 Emsg1(M_ERROR_TERM, 0, _("cap_from_text failed: ERR=%s\n"),
118 be.bstrerror());
119 }
120 if (cap_set_proc(caps) < 0) {
121 BErrNo be;
122 Emsg1(M_ERROR_TERM, 0, _("cap_set_proc failed: ERR=%s\n"),
123 be.bstrerror());
124 }
125 cap_free(caps);
126 #else
127 Emsg0(
128 M_ERROR_TERM, 0,
129 _("Keep readall caps not implemented this OS or missing libraries.\n"));
130 #endif
131 } else if (setuid(uid)) {
132 BErrNo be;
133 Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), username);
134 }
135 #endif
136 }
137