]>
git.proxmox.com Git - mirror_frr.git/blob - lib/privs.c
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
29 /* internal privileges state */
30 static struct _zprivs_t
33 cap_t caps
; /* caps storage */
34 cap_value_t
*syscaps_p
; /* system permitted caps */
35 cap_value_t
*syscaps_i
; /* system inheritable caps */
36 int sys_num_p
; /* number of syscaps_p */
37 int sys_num_i
; /* number of syscaps_i */
38 #endif /* HAVE_LCAPS */
39 uid_t zuid
, /* uid to run as */
40 zsuid
; /* saved uid */
41 gid_t zgid
; /* gid to run as */
42 gid_t vtygrp
; /* gid for vty sockets */
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
] = CAP_FOWNER
75 /* convert zebras privileges to system capabilities */
77 zcaps2sys (zebra_capabilities_t
*zcaps
, int num
)
85 syscaps
= (cap_value_t
*) XCALLOC ( MTYPE_PRIVS
,
86 (sizeof(cap_value_t
) * num
) );
89 zlog_err ("zcap2sys: could not XCALLOC!");
93 for (i
=0; i
< num
; i
++)
95 syscaps
[i
] = cap_map
[zcaps
[i
]];
101 /* set or clear the effective capabilities to/from permitted */
103 zprivs_change_caps (zebra_privs_ops_t op
)
105 cap_flag_value_t cflag
;
107 if (op
== ZPRIVS_RAISE
)
109 else if (op
== ZPRIVS_LOWER
)
114 if ( !cap_set_flag (zprivs_state
.caps
, CAP_EFFECTIVE
,
115 zprivs_state
.sys_num_p
, zprivs_state
.syscaps_p
, cflag
))
116 return cap_set_proc (zprivs_state
.caps
);
120 zebra_privs_current_t
121 zprivs_state_caps (void)
124 cap_flag_value_t val
;
126 for (i
=0; i
< zprivs_state
.sys_num_p
; i
++)
128 if ( cap_get_flag (zprivs_state
.caps
, zprivs_state
.syscaps_p
[i
],
129 CAP_EFFECTIVE
, &val
) )
130 zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s",
133 return ZPRIVS_RAISED
;
135 return ZPRIVS_LOWERED
;
138 #endif /* HAVE_LCAPS */
141 zprivs_change_uid (zebra_privs_ops_t op
)
144 if (op
== ZPRIVS_RAISE
)
145 return seteuid (zprivs_state
.zsuid
);
146 else if (op
== ZPRIVS_LOWER
)
147 return seteuid (zprivs_state
.zuid
);
152 zebra_privs_current_t
153 zprivs_state_uid (void)
155 return ( (zprivs_state
.zuid
== geteuid()) ? ZPRIVS_LOWERED
: ZPRIVS_RAISED
);
159 zprivs_change_null (zebra_privs_ops_t op
)
164 zebra_privs_current_t
165 zprivs_state_null (void)
167 return ZPRIVS_RAISED
;
172 zprivs_init(struct zebra_privs_t
*zprivs
)
174 struct passwd
*pwentry
= NULL
;
175 struct group
*grentry
= NULL
;
179 zlog_err ("zprivs_init: called with NULL arg!");
184 if (! (zprivs
->user
|| zprivs
->group
185 || zprivs
->cap_num_p
|| zprivs
->cap_num_i
) )
187 zprivs
->change
= zprivs_change_null
;
188 zprivs
->current_state
= zprivs_state_null
;
194 if ( (pwentry
= getpwnam (zprivs
->user
)) )
196 zprivs_state
.zuid
= pwentry
->pw_uid
;
200 zlog_err ("privs_init: could not lookup supplied user");
207 if (zprivs
->vty_group
)
208 /* Add the vty_group to the supplementary groups so it can be chowned to */
210 if ( (grentry
= getgrnam (zprivs
->vty_group
)) )
212 zprivs_state
.vtygrp
= grentry
->gr_gid
;
213 if ( setgroups (1, &zprivs_state
.vtygrp
) )
215 zlog_err ("privs_init: could not setgroups, %s",
222 zlog_err ("privs_init: could not lookup supplied user");
229 if ( (grentry
= getgrnam (zprivs
->group
)) )
231 zprivs_state
.zgid
= grentry
->gr_gid
;
235 zlog_err ("privs_init: could not lookup supplied user");
238 /* change group now, forever. uid we do later */
239 if ( setregid (zprivs_state
.zgid
, zprivs_state
.zgid
) )
241 zlog_err ("zprivs_init: could not setregid, %s",
248 zprivs_state
.syscaps_p
= zcaps2sys (zprivs
->caps_p
, zprivs
->cap_num_p
);
249 zprivs_state
.sys_num_p
= zprivs
->cap_num_p
;
250 zprivs_state
.syscaps_i
= zcaps2sys (zprivs
->caps_i
, zprivs
->cap_num_i
);
251 zprivs_state
.sys_num_i
= zprivs
->cap_num_i
;
253 /* Tell kernel we want caps maintained across uid changes */
254 if ( prctl(PR_SET_KEEPCAPS
, 1, 0, 0, 0) == -1 )
256 zlog_err("privs_init: could not set PR_SET_KEEPCAPS, %s",
261 if ( !zprivs_state
.syscaps_p
)
263 zlog_warn ("privs_init: capabilities enabled, but no capabilities supplied");
266 if ( !(zprivs_state
.caps
= cap_init()) )
268 zlog_err ("privs_init: failed to cap_init, %s", strerror (errno
) );
272 /* we have caps, we have no need to ever change back the original user */
273 if (zprivs_state
.zuid
)
275 if ( setreuid (zprivs_state
.zuid
, zprivs_state
.zuid
) )
277 zlog_err ("zprivs_init (cap): could not setreuid, %s",
283 if ( cap_clear (zprivs_state
.caps
) )
285 zlog_err ("privs_init: failed to cap_clear, %s", strerror (errno
));
289 /* set permitted caps */
290 cap_set_flag(zprivs_state
.caps
, CAP_PERMITTED
,
291 zprivs_state
.sys_num_p
, zprivs_state
.syscaps_p
, CAP_SET
);
292 cap_set_flag(zprivs_state
.caps
, CAP_EFFECTIVE
,
293 zprivs_state
.sys_num_p
, zprivs_state
.syscaps_p
, CAP_SET
);
295 /* set inheritable caps, if any */
296 if (zprivs_state
.sys_num_i
)
298 cap_set_flag(zprivs_state
.caps
, CAP_INHERITABLE
,
299 zprivs_state
.sys_num_i
, zprivs_state
.syscaps_i
, CAP_SET
);
302 /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as
303 * and when, and only when, they are needed.
305 if ( cap_set_proc (zprivs_state
.caps
) )
307 zlog_err ("privs_init: initial cap_set_proc failed");
311 /* set methods for the caller to use */
312 zprivs
->change
= zprivs_change_caps
;
313 zprivs
->current_state
= zprivs_state_caps
;
315 #elif !defined(HAVE_LCAPS)
316 /* we dont have caps. we'll need to maintain rid and saved uid
317 * and change euid back to saved uid (who we presume has all neccessary
318 * privileges) whenever we are asked to raise our privileges.
320 zprivs_state
.zsuid
= geteuid();
321 if ( zprivs_state
.zuid
)
323 if ( setreuid (-1, zprivs_state
.zuid
) )
325 zlog_err ("privs_init (uid): could not setreuid, %s", strerror (errno
));
330 zprivs
->change
= zprivs_change_uid
;
331 zprivs
->current_state
= zprivs_state_uid
;
332 #endif /* HAVE_LCAPS */
336 zprivs_terminate (void)
341 if (zprivs_state
.caps
)
342 cap_clear (zprivs_state
.caps
);
344 if ( cap_set_proc (zprivs_state
.caps
) )
346 zlog_err ("privs_terminate: cap_set_proc failed, %s",
351 if (zprivs_state
.sys_num_p
)
352 XFREE (MTYPE_PRIVS
, zprivs_state
.syscaps_p
);
354 if (zprivs_state
.sys_num_i
)
355 XFREE (MTYPE_PRIVS
, zprivs_state
.syscaps_i
);
357 cap_free (zprivs_state
.caps
);
359 if (zprivs_state
.zuid
)
361 if ( setreuid (zprivs_state
.zuid
, zprivs_state
.zuid
) )
363 zlog_err ("privs_terminate: could not setreuid, %s",
368 #endif /* HAVE_LCAPS */
373 zprivs_get_ids(struct zprivs_ids_t
*ids
)
376 ids
->uid_priv
= getuid();
377 (zprivs_state
.zuid
) ? (ids
->uid_normal
= zprivs_state
.zuid
)
378 : (ids
->uid_normal
= -1);
379 (zprivs_state
.zgid
) ? (ids
->gid_normal
= zprivs_state
.zgid
)
380 : (ids
->gid_normal
= -1);
381 (zprivs_state
.vtygrp
) ? (ids
->gid_vty
= zprivs_state
.vtygrp
)
382 : (ids
->gid_vty
= -1);