]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/privs.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / privs.c
index d3b64cccb639f37b83c2854f191459f54da56ac7..838ff8fc928fae844c6cfad3a9401baf0a45c403 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include <zebra.h>
 #include "log.h"
 #include "privs.h"
 #include "memory.h"
+#include "lib_errors.h"
 
 #ifdef HAVE_CAPABILITIES
 
@@ -289,7 +289,8 @@ zebra_privs_current_t zprivs_state_caps(void)
                if (cap_get_flag(zprivs_state.caps,
                                 zprivs_state.syscaps_p->caps[i], CAP_EFFECTIVE,
                                 &val)) {
-                       zlog_warn(
+                       flog_err(
+                               EC_LIB_SYSTEM_CALL,
                                "zprivs_state_caps: could not cap_get_flag, %s",
                                safe_strerror(errno));
                        return ZPRIVS_UNKNOWN;
@@ -697,13 +698,45 @@ static int getgrouplist(const char *user, gid_t group, gid_t *groups,
 }
 #endif /* HAVE_GETGROUPLIST */
 
-void zprivs_init(struct zebra_privs_t *zprivs)
+struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
+                                   const char *funcname)
+{
+       int save_errno = errno;
+
+       if (!privs)
+               return NULL;
+
+       errno = 0;
+       if (privs->change(ZPRIVS_RAISE)) {
+               zlog_err("%s: Failed to raise privileges (%s)",
+                        funcname, safe_strerror(errno));
+       }
+       errno = save_errno;
+       privs->raised_in_funcname = funcname;
+       return privs;
+}
+
+void _zprivs_lower(struct zebra_privs_t **privs)
+{
+       int save_errno = errno;
+
+       if (!*privs)
+               return;
+
+       errno = 0;
+       if ((*privs)->change(ZPRIVS_LOWER)) {
+               zlog_err("%s: Failed to lower privileges (%s)",
+                        (*privs)->raised_in_funcname, safe_strerror(errno));
+       }
+       errno = save_errno;
+       (*privs)->raised_in_funcname = NULL;
+       *privs = NULL;
+}
+
+void zprivs_preinit(struct zebra_privs_t *zprivs)
 {
        struct passwd *pwentry = NULL;
        struct group *grentry = NULL;
-       gid_t groups[NGROUPS_MAX];
-       int i, ngroups = 0;
-       int found = 0;
 
        if (!zprivs) {
                fprintf(stderr, "zprivs_init: called with NULL arg!\n");
@@ -752,6 +785,18 @@ void zprivs_init(struct zebra_privs_t *zprivs)
 
                zprivs_state.zgid = grentry->gr_gid;
        }
+}
+
+void zprivs_init(struct zebra_privs_t *zprivs)
+{
+       gid_t groups[NGROUPS_MAX];
+       int i, ngroups = 0;
+       int found = 0;
+
+       /* NULL privs */
+       if (!(zprivs->user || zprivs->group || zprivs->cap_num_p
+             || zprivs->cap_num_i))
+               return;
 
        if (zprivs->user) {
                ngroups = sizeof(groups);
@@ -794,6 +839,7 @@ void zprivs_init(struct zebra_privs_t *zprivs)
                }
        }
 
+       zprivs_state.zsuid = geteuid(); /* initial uid */
        /* add groups only if we changed uid - otherwise skip */
        if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid)) {
                if (setgroups(ngroups, groups)) {
@@ -815,6 +861,19 @@ void zprivs_init(struct zebra_privs_t *zprivs)
 
 #ifdef HAVE_CAPABILITIES
        zprivs_caps_init(zprivs);
+
+       /*
+        * If we have initialized the system with no requested
+        * capabilities, change will not have been set
+        * to anything by zprivs_caps_init, As such
+        * we should make sure that when we attempt
+        * to raize privileges that we actually have
+        * a do nothing function to call instead of a
+        * crash :).
+        */
+       if (!zprivs->change)
+               zprivs->change = zprivs_change_null;
+
 #else  /* !HAVE_CAPABILITIES */
        /* we dont have caps. we'll need to maintain rid and saved uid
         * and change euid back to saved uid (who we presume has all neccessary
@@ -847,7 +906,9 @@ void zprivs_terminate(struct zebra_privs_t *zprivs)
        }
 
 #ifdef HAVE_CAPABILITIES
-       zprivs_caps_terminate();
+       if (zprivs->user || zprivs->group || zprivs->cap_num_p
+           || zprivs->cap_num_i)
+               zprivs_caps_terminate();
 #else  /* !HAVE_CAPABILITIES */
        /* only change uid if we don't have the correct one */
        if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) {