4 * Copyright (C) 2003 Paul Jakma.
6 * This file is part of GNU Zebra.
8 * GNU Zebra is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 /* internal privileges state */
31 static struct _zprivs_t
34 cap_t caps
; /* caps storage */
35 cap_value_t
*syscaps_p
; /* system permitted caps */
36 cap_value_t
*syscaps_i
; /* system inheritable caps */
37 int sys_num_p
; /* number of syscaps_p */
38 int sys_num_i
; /* number of syscaps_i */
39 #endif /* HAVE_LCAPS */
40 uid_t zuid
, /* uid to run as */
41 zsuid
; /* saved uid */
42 gid_t zgid
; /* gid to run as */
45 /* externally exported but not directly accessed functions */
47 int zprivs_change_caps (zebra_privs_ops_t
);
48 zebra_privs_current_t
zprivs_state_caps (void);
49 #endif /* HAVE_LCAPS */
50 int zprivs_change_uid (zebra_privs_ops_t
);
51 zebra_privs_current_t
zprivs_state_uid (void);
52 int zprivs_change_null (zebra_privs_ops_t
);
53 zebra_privs_current_t
zprivs_state_null (void);
54 void zprivs_terminate (void);
60 [ZCAP_SETGID
] = CAP_SETGID
,
61 [ZCAP_SETUID
] = CAP_SETUID
,
62 [ZCAP_BIND
] = CAP_NET_BIND_SERVICE
,
63 [ZCAP_BROADCAST
] = CAP_NET_BROADCAST
,
64 [ZCAP_ADMIN
] = CAP_NET_ADMIN
,
65 [ZCAP_RAW
] = CAP_NET_RAW
,
66 [ZCAP_CHROOT
] = CAP_SYS_CHROOT
,
67 [ZCAP_NICE
] = CAP_SYS_NICE
,
68 [ZCAP_PTRACE
] = CAP_SYS_PTRACE
,
69 [ZCAP_DAC_OVERRIDE
] = CAP_DAC_OVERRIDE
,
70 [ZCAP_READ_SEARCH
] = CAP_DAC_READ_SEARCH
,
71 [ZCAP_SYS_ADMIN
] = CAP_SYS_ADMIN
,
72 [ZCAP_FOWNER
] = ZCAP_FOWNER
75 static cap_value_t cap_setuid_value
[] = { CAP_SETUID
};
77 /* convert zebras privileges to system capabilities */
79 zcaps2sys (zebra_capabilities_t
*zcaps
, int num
)
87 syscaps
= (cap_value_t
*) XCALLOC ( MTYPE_PRIVS
,
88 (sizeof(cap_value_t
) * num
) );
91 zlog_err ("zcap2sys: could not XCALLOC!");
95 for (i
=0; i
< num
; i
++)
97 syscaps
[i
] = cap_map
[zcaps
[i
]];
103 /* set or clear the effective capabilities to/from permitted */
105 zprivs_change_caps (zebra_privs_ops_t op
)
107 cap_flag_value_t cflag
;
109 if (op
== ZPRIVS_RAISE
)
111 else if (op
== ZPRIVS_LOWER
)
116 if ( !cap_set_flag (zprivs_state
.caps
, CAP_EFFECTIVE
,
117 zprivs_state
.sys_num_p
, zprivs_state
.syscaps_p
, cflag
))
118 return cap_set_proc (zprivs_state
.caps
);
122 zebra_privs_current_t
123 zprivs_state_caps (void)
126 cap_flag_value_t val
;
128 for (i
=0; i
< zprivs_state
.sys_num_p
; i
++)
130 if ( cap_get_flag (zprivs_state
.caps
, zprivs_state
.syscaps_p
[i
],
131 CAP_EFFECTIVE
, &val
) )
132 zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s",
135 return ZPRIVS_RAISED
;
137 return ZPRIVS_LOWERED
;
140 #endif /* HAVE_LCAPS */
143 zprivs_change_uid (zebra_privs_ops_t op
)
146 if (op
== ZPRIVS_RAISE
)
147 return seteuid (zprivs_state
.zsuid
);
148 else if (op
== ZPRIVS_LOWER
)
149 return seteuid (zprivs_state
.zuid
);
154 zebra_privs_current_t
155 zprivs_state_uid (void)
157 return ( (zprivs_state
.zuid
== geteuid()) ? ZPRIVS_LOWERED
: ZPRIVS_RAISED
);
161 zprivs_change_null (zebra_privs_ops_t op
)
166 zebra_privs_current_t
167 zprivs_state_null (void)
169 return ZPRIVS_RAISED
;
174 zprivs_init(struct zebra_privs_t
*zprivs
)
176 struct passwd
*pwentry
= NULL
;
177 struct group
*grentry
= NULL
;
180 if (! (zprivs
->user
|| zprivs
->group
181 || zprivs
->cap_num_p
|| zprivs
->cap_num_i
) )
183 zprivs
->change
= zprivs_change_null
;
184 zprivs
->current_state
= zprivs_state_null
;
190 if ( (pwentry
= getpwnam (zprivs
->user
)) )
191 zprivs_state
.zuid
= pwentry
->pw_uid
;
194 zlog_err ("privs_init: could not lookup supplied user");
201 if ( (grentry
= getgrnam (zprivs
->user
)) )
202 zprivs_state
.zgid
= grentry
->gr_gid
;
205 zlog_err ("privs_init: could not lookup supplied user");
209 /* change group now, forever. uid we do later */
210 if ( setregid (zprivs_state
.zgid
, zprivs_state
.zgid
) )
212 zlog_err ("privs_init: could not setregid");
218 zprivs_state
.syscaps_p
= zcaps2sys (zprivs
->caps_p
, zprivs
->cap_num_p
);
219 zprivs_state
.sys_num_p
= zprivs
->cap_num_p
;
220 zprivs_state
.syscaps_i
= zcaps2sys (zprivs
->caps_i
, zprivs
->cap_num_i
);
221 zprivs_state
.sys_num_i
= zprivs
->cap_num_i
;
223 /* Tell kernel we want caps maintained across uid changes */
224 if ( prctl(PR_SET_KEEPCAPS
, 1, 0, 0, 0) == -1 )
226 zlog_err("privs_init: could not set PR_SET_KEEPCAPS, %s",
231 if ( !zprivs_state
.syscaps_p
)
233 zlog_warn ("privs_init: capabilities enabled, but no capabilities supplied");
236 if ( !(zprivs_state
.caps
= cap_init()) )
238 zlog_err ("privs_init: failed to cap_init, %s", strerror (errno
) );
242 if ( cap_clear (zprivs_state
.caps
) )
244 zlog_err ("privs_init: failed to cap_clear, %s", strerror (errno
));
248 /* set permitted caps */
249 cap_set_flag(zprivs_state
.caps
, CAP_PERMITTED
,
250 zprivs_state
.sys_num_p
, zprivs_state
.syscaps_p
, CAP_SET
);
251 cap_set_flag(zprivs_state
.caps
, CAP_EFFECTIVE
,
252 zprivs_state
.sys_num_p
, zprivs_state
.syscaps_p
, CAP_SET
);
254 /* still need CAP_SETUID for the moment */
255 cap_set_flag(zprivs_state
.caps
, CAP_PERMITTED
,
256 1, cap_setuid_value
, CAP_SET
);
257 cap_set_flag(zprivs_state
.caps
, CAP_EFFECTIVE
,
258 1, cap_setuid_value
, CAP_SET
);
260 /* set inheritable caps, if any */
261 if (zprivs_state
.sys_num_i
)
263 cap_set_flag(zprivs_state
.caps
, CAP_INHERITABLE
,
264 zprivs_state
.sys_num_i
, zprivs_state
.syscaps_i
, CAP_SET
);
267 /* apply caps. CAP_EFFECTIVE is clear bar cap_setuid_value.
268 * we'll raise the caps as and when, and only when, they are needed.
270 if ( cap_set_proc (zprivs_state
.caps
) )
272 zlog_err ("privs_init: initial cap_set_proc failed");
276 /* we have caps, we have no need to ever change back the original user */
277 if (zprivs_state
.zuid
)
279 if ( setreuid (zprivs_state
.zuid
, zprivs_state
.zuid
) )
281 zlog_err ("privs_init (cap): could not setreuid, %s", strerror (errno
) );
286 /* No more need for cap_setuid_value */
287 cap_set_flag(zprivs_state
.caps
, CAP_PERMITTED
,
288 1, cap_setuid_value
, CAP_CLEAR
);
289 cap_set_flag(zprivs_state
.caps
, CAP_EFFECTIVE
,
290 1, cap_setuid_value
, CAP_CLEAR
);
291 if ( cap_set_proc (zprivs_state
.caps
) )
293 zlog_err ("privs_init: cap_set_proc failed to clear cap_setuid, %s",
298 zprivs
->change
= zprivs_change_caps
;
299 zprivs
->current_state
= zprivs_state_caps
;
301 #elif !defined(HAVE_LCAPS)
302 /* we dont have caps. we'll need to maintain rid and saved uid
303 * and change euid back to saved uid (who we presume has all neccessary
304 * privileges) whenever we are asked to raise our privileges.
306 zprivs_state
.zsuid
= geteuid();
307 if ( zprivs_state
.zuid
)
309 if ( setreuid (-1, zprivs_state
.zuid
) )
311 zlog_err ("privs_init (uid): could not setreuid, %s", strerror (errno
));
316 zprivs
->change
= zprivs_change_uid
;
317 zprivs
->current_state
= zprivs_state_uid
;
318 #endif /* HAVE_LCAPS */
322 zprivs_terminate (void)
327 if (zprivs_state
.caps
)
328 cap_clear (zprivs_state
.caps
);
330 if ( cap_set_proc (zprivs_state
.caps
) )
332 zlog_err ("privs_terminate: cap_set_proc failed, %s",
337 if (zprivs_state
.sys_num_p
)
338 XFREE (MTYPE_PRIVS
, zprivs_state
.syscaps_p
);
340 if (zprivs_state
.sys_num_i
)
341 XFREE (MTYPE_PRIVS
, zprivs_state
.syscaps_i
);
343 cap_free (zprivs_state
.caps
);
345 if (zprivs_state
.zuid
)
347 if ( setreuid (zprivs_state
.zuid
, zprivs_state
.zuid
) )
349 zlog_err ("privs_terminate: could not setreuid, %s",
354 #endif /* HAVE_LCAPS */