]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/priv.c
Backport from BEE
[bacula/bacula] / bacula / src / lib / priv.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16
17 #include "bacula.h"
18
19 #undef ENABLE_KEEP_READALL_CAPS_SUPPORT
20 #if defined(HAVE_SYS_PRCTL_H) && defined(HAVE_SYS_CAPABILITY_H) && \
21    defined(HAVE_PRCTL) && defined(HAVE_SETREUID) && defined(HAVE_LIBCAP)
22 # include <sys/prctl.h>
23 # include <sys/capability.h>
24 # if defined(PR_SET_KEEPCAPS)
25 #  define ENABLE_KEEP_READALL_CAPS_SUPPORT
26 # endif
27 #endif
28
29 #ifdef HAVE_AIX_OS
30 # ifndef _AIX51
31 extern "C" int initgroups(const char *,int);
32 # endif
33 #endif
34
35 /*
36  * Lower privileges by switching to new UID and GID if non-NULL.
37  * If requested, keep readall capabilities after switch.
38  */
39 void drop(char *uname, char *gname, bool keep_readall_caps)
40 {
41 #if   defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
42    struct passwd *passw = NULL;
43    struct group *group = NULL;
44    gid_t gid;
45    uid_t uid;
46    char username[1000];
47
48    Dmsg2(900, "uname=%s gname=%s\n", uname?uname:"NONE", gname?gname:"NONE");
49    if (!uname && !gname) {
50       return;                            /* Nothing to do */
51    }
52
53    if (uname) {
54       if ((passw = getpwnam(uname)) == NULL) {
55          berrno be;
56          Emsg2(M_ERROR_TERM, 0, _("Could not find userid=%s: ERR=%s\n"), uname,
57             be.bstrerror());
58       }
59    } else {
60       if ((passw = getpwuid(getuid())) == NULL) {
61          berrno be;
62          Emsg1(M_ERROR_TERM, 0, _("Could not find password entry. ERR=%s\n"),
63             be.bstrerror());
64       } else {
65          uname = passw->pw_name;
66       }
67    }
68    /* Any OS uname pointer may get overwritten, so save name, uid, and gid */
69    bstrncpy(username, uname, sizeof(username));
70    uid = passw->pw_uid;
71    gid = passw->pw_gid;
72    if (gname) {
73       if ((group = getgrnam(gname)) == NULL) {
74          berrno be;
75          Emsg2(M_ERROR_TERM, 0, _("Could not find group=%s: ERR=%s\n"), gname,
76             be.bstrerror());
77       }
78       gid = group->gr_gid;
79    }
80    if (initgroups(username, gid)) {
81       berrno be;
82       if (gname) {
83          Emsg3(M_ERROR_TERM, 0, _("Could not initgroups for group=%s, userid=%s: ERR=%s\n"),
84             gname, username, be.bstrerror());
85       } else {
86          Emsg2(M_ERROR_TERM, 0, _("Could not initgroups for userid=%s: ERR=%s\n"),
87             username, be.bstrerror());
88       }
89    }
90    if (gname) {
91       if (setgid(gid)) {
92          berrno be;
93          Emsg2(M_ERROR_TERM, 0, _("Could not set group=%s: ERR=%s\n"), gname,
94             be.bstrerror());
95       }
96    }
97    if (keep_readall_caps) {
98 #ifdef ENABLE_KEEP_READALL_CAPS_SUPPORT
99       cap_t caps;
100
101       if (prctl(PR_SET_KEEPCAPS, 1)) {
102          berrno be;
103          Emsg1(M_ERROR_TERM, 0, _("prctl failed: ERR=%s\n"), be.bstrerror());
104       }
105       if (setreuid(uid, uid)) {
106          berrno be;
107          Emsg1(M_ERROR_TERM, 0, _("setreuid failed: ERR=%s\n"), be.bstrerror());
108       }
109       if (!(caps = cap_from_text("cap_dac_read_search=ep"))) {
110          berrno be;
111          Emsg1(M_ERROR_TERM, 0, _("cap_from_text failed: ERR=%s\n"), be.bstrerror());
112       }
113       if (cap_set_proc(caps) < 0) {
114          berrno be;
115          Emsg1(M_ERROR_TERM, 0, _("cap_set_proc failed: ERR=%s\n"), be.bstrerror());
116       }
117       cap_free(caps);
118 #else
119       Emsg0(M_ERROR_TERM, 0, _("Keep readall caps not implemented this OS or missing libraries.\n"));
120 #endif
121    } else if (setuid(uid)) {
122       berrno be;
123       Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), username);
124    }
125 #endif
126 }