]>
git.ipfire.org Git - people/ms/network.git/blob - src/networkd/main.c
1 /*#############################################################################
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2023 IPFire Network Development Team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
22 #include <linux/capability.h>
25 #include <sys/capability.h>
26 #include <sys/prctl.h>
27 #include <sys/types.h>
33 static int cap_acquire_setpcap(void) {
34 cap_flag_value_t value
;
37 // Fetch current capabilities
38 cap_t caps
= cap_get_proc();
40 // Check if CAP_SETPCAP is already enabled
41 r
= cap_get_flag(caps
, CAP_SETPCAP
, CAP_EFFECTIVE
, &value
);
43 ERROR("The kernel does not seem to know CAP_SETPCAP: %m\n");
47 // It CAP_SETPCAP isn't set, we will try to set it
48 if (value
!= CAP_SET
) {
49 const cap_value_t cap
= CAP_SETPCAP
;
51 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, &cap
, CAP_SET
);
53 ERROR("Could not set CAP_SETPCAP: %m\n");
58 r
= cap_set_proc(caps
);
60 ERROR("Could not acquire effective CAP_SETPCAP capability: %m\n");
72 static cap_flag_value_t
keep_cap(const cap_value_t cap
, const cap_value_t
* keep_caps
) {
73 for (const cap_value_t
* c
= keep_caps
; *c
; c
++) {
81 static int drop_capabilities(void) {
84 const cap_value_t keep_caps
[] = {
92 // Acquire CAP_SETPCAP
93 r
= cap_acquire_setpcap();
97 // Fetch the current set of capabilities
98 cap_t caps
= cap_get_proc();
100 // Drop all capabilities that we do not need
101 for (cap_value_t cap
= 1; cap
<= CAP_LAST_CAP
; cap
++) {
102 // Skip any capabilities we would like to skip
103 cap_flag_value_t flag
= keep_cap(cap
, keep_caps
);
105 // Drop the capability from the bounding set
106 if (flag
== CAP_CLEAR
) {
107 r
= prctl(PR_CAPBSET_DROP
, cap
);
109 ERROR("Could not drop capability from the bounding set: %m\n");
114 r
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, CAP_CLEAR
);
116 ERROR("Could not set capability %d: %m\n", (int)cap
);
120 r
= cap_set_flag(caps
, CAP_PERMITTED
, 1, &cap
, flag
);
122 ERROR("Could not set capability %d: %m\n", (int)cap
);
126 r
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, &cap
, flag
);
128 ERROR("Could not set capability %d: %m\n", (int)cap
);
133 // Restore capabilities
134 r
= cap_set_proc(caps
);
136 ERROR("Could not restore capabilities: %m\n");
147 static int drop_privileges(const char* user
) {
148 struct passwd
* passwd
= NULL
;
151 // Fetch the current user
152 uid_t current_uid
= getuid();
154 // If we have not been launched by root, we will assume that we have already
155 // been launched with a minimal set of privileges.
159 DEBUG("Dropping privileges...\n");
161 // Fetch information about the desired user
162 passwd
= getpwnam(user
);
164 ERROR("Could not find user %s: %m\n", user
);
168 uid_t uid
= passwd
->pw_uid
;
169 gid_t gid
= passwd
->pw_gid
;
172 r
= setresgid(gid
, gid
, gid
);
174 ERROR("Could not change group to %d: %m\n", gid
);
178 // Set any supplementary groups
179 r
= setgroups(0, NULL
);
181 ERROR("Could not set supplementary groups: %m\n");
185 // Do not drop any capabilities when we change to the new user
186 r
= prctl(PR_SET_KEEPCAPS
, 1);
188 ERROR("Could not set PR_SET_KEEPCAPS: %m\n");
192 // Change to the new user
193 r
= setresuid(uid
, uid
, uid
);
195 ERROR("Could not change user to %d: %m\n", uid
);
199 // Reset PR_SET_KEEPCAPS
200 r
= prctl(PR_SET_KEEPCAPS
, 0);
202 ERROR("Could not set PR_SET_KEEPCAPS: %m\n");
207 r
= drop_capabilities();
214 int main(int argc
, char** argv
) {
215 struct nw_daemon
* daemon
= NULL
;
219 r
= drop_privileges("network");
224 r
= nw_daemon_create(&daemon
);
229 r
= nw_daemon_run(daemon
);
233 nw_daemon_unref(daemon
);