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
24 #undef ENABLE_KEEP_READALL_CAPS_SUPPORT
25 #if defined(HAVE_SYS_PRCTL_H) && defined(HAVE_SYS_CAPABILITY_H) && \
26 defined(HAVE_PRCTL) && defined(HAVE_SETREUID) && defined(HAVE_LIBCAP)
27 #include <sys/prctl.h>
28 #include <sys/capability.h>
29 #if defined(PR_SET_KEEPCAPS)
30 #define ENABLE_KEEP_READALL_CAPS_SUPPORT
31 #endif
32 #endif
33
34 #ifdef HAVE_AIX_OS
35 #ifndef _AIX51
36 extern "C" int initgroups(const char *,int);
37 #endif
38 #endif
39
40 /*
41 * Lower privileges by switching to new UID and GID if non-NULL.
42 * If requested, keep readall capabilities after switch.
43 */
drop(char * uname,char * gname,bool keep_readall_caps)44 void drop(char *uname, char *gname, bool keep_readall_caps)
45 {
46 #if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
47 struct passwd *passw = NULL;
48 struct group *group = NULL;
49 gid_t gid;
50 uid_t uid;
51 char username[1000];
52
53 Dmsg2(900, "uname=%s gname=%s\n", uname?uname:"NONE", gname?gname:"NONE");
54 if (!uname && !gname) {
55 return; /* Nothing to do */
56 }
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, _("Could not initgroups for group=%s, userid=%s: ERR=%s\n"),
89 gname, username, be.bstrerror());
90 } else {
91 Emsg2(M_ERROR_TERM, 0, _("Could not initgroups for userid=%s: ERR=%s\n"),
92 username, be.bstrerror());
93 }
94 }
95 if (gname) {
96 if (setgid(gid)) {
97 BErrNo be;
98 Emsg2(M_ERROR_TERM, 0, _("Could not set group=%s: ERR=%s\n"), gname,
99 be.bstrerror());
100 }
101 }
102 if (keep_readall_caps) {
103 #ifdef ENABLE_KEEP_READALL_CAPS_SUPPORT
104 cap_t caps;
105
106 if (prctl(PR_SET_KEEPCAPS, 1)) {
107 BErrNo be;
108 Emsg1(M_ERROR_TERM, 0, _("prctl failed: ERR=%s\n"), be.bstrerror());
109 }
110 if (setreuid(uid, uid)) {
111 BErrNo be;
112 Emsg1(M_ERROR_TERM, 0, _("setreuid failed: ERR=%s\n"), be.bstrerror());
113 }
114 if (!(caps = cap_from_text("cap_dac_read_search=ep"))) {
115 BErrNo be;
116 Emsg1(M_ERROR_TERM, 0, _("cap_from_text failed: ERR=%s\n"), be.bstrerror());
117 }
118 if (cap_set_proc(caps) < 0) {
119 BErrNo be;
120 Emsg1(M_ERROR_TERM, 0, _("cap_set_proc failed: ERR=%s\n"), be.bstrerror());
121 }
122 cap_free(caps);
123 #else
124 Emsg0(M_ERROR_TERM, 0, _("Keep readall caps not implemented this OS or missing libraries.\n"));
125 #endif
126 } else if (setuid(uid)) {
127 BErrNo be;
128 Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), username);
129 }
130 #endif
131 }
132