Ethereal-dev: Re: [Ethereal-dev] Patch for Linux Capabilities

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Emanuele Caratti <wiz@xxxxxxxxx>
Date: Sat, 1 Nov 2003 16:33:51 +0100
On Wed, Oct 29, 2003 at 06:24:35PM -0800, Guy Harris wrote:

> >On the todo list I've to change drop_priv to use the libcap packaged
> >instead of capget/capset..
> 
> ...and update the configure scripts so that it'll automatically figure 
> out whether to use the capability bits - "config.h" and "Makefile" are 
> files generated by the configure script.

Ok... Now I've a patch also for configure.in and Makefile.am.
The capability support is by default off.
If enabled, via configure command line  --enable-linux-capab, the
sys/capability.h must exist.

The capab.c now use the library libcap, so it not tied to a specific
kernel. If needed I can put back the code to use the non portable
capset/capget, and add a configure switch or something similar....

....comments are welcome! :)

-- 
Ciao,
 Emanuele
Index: configure.in
===================================================================
RCS file: /usr/src/build/cvsroot/ethereal/configure.in,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.3
diff -u -u -r1.1.1.1 -r1.1.1.1.2.3
--- configure.in	8 Sep 2003 03:13:14 -0000	1.1.1.1
+++ configure.in	1 Nov 2003 15:07:46 -0000	1.1.1.1.2.3
@@ -525,6 +525,26 @@
 
 AM_CONDITIONAL(SETUID_INSTALL, test x$enable_setuid_install = xyes)
 
+dnl Linux Capabilities
+AC_ARG_ENABLE(linux-capab,
+[  --enable-linux-capab [default=no (Needs libcap!)]],enable_linux_capab=$enableval,enable_linux_capab=no)
+
+AC_MSG_CHECKING(whether to use linux capability )
+if test "x$enable_linux_capab" = "xno" ; then
+	AC_MSG_RESULT(no)
+else
+	AC_MSG_RESULT(yes)
+	AC_CHECK_HEADERS(sys/capability.h)
+	if test "x$ac_cv_header_sys_capability_h" = "xyes" ; then
+		AC_DEFINE(ENABLE_LINUX_CAPABILITIES, 1, [Define to use Linux Capabilities ] )
+		LIBS="$LIBS -lcap"
+	else
+		enable_linux_capab=no
+	fi
+fi
+AM_CONDITIONAL(ENABLE_LINUX_CAPABILITIES, test x$enable_linux_capab = xyes)
+
+
 dnl Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h unistd.h stdarg.h netdb.h)
@@ -853,6 +873,7 @@
 echo "                      Build dftest : $enable_dftest"
 echo ""
 echo "                    Install setuid : $setuid_message"
+echo "                 Linux capabilities: $enable_linux_capab"
 echo "                       Use plugins : $have_plugins"
 echo "               Use GTK+ v2 library : $enable_gtk2"
 if test "x$enable_gtk2" = "xyes" ; then
Index: Makefile.am
===================================================================
RCS file: /usr/src/build/cvsroot/ethereal/Makefile.am,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -u -r1.1.1.1 -r1.1.1.1.2.1
--- Makefile.am	6 Sep 2003 23:22:34 -0000	1.1.1.1
+++ Makefile.am	1 Nov 2003 08:26:50 -0000	1.1.1.1.2.1
@@ -806,6 +806,10 @@
 	summary.h      \
 	ui_util.h
 
+if ENABLE_LINUX_CAPABILITIES
+ethereal_SOURCES+= capab.c
+endif
+
 EXTRA_ethereal_SOURCES = \
 	snprintf.c	\
 	snprintf.h	\
@@ -888,6 +892,10 @@
 	tethereal-tap-register.c \
 	register.c     \
 	tethereal.c
+
+if ENABLE_LINUX_CAPABILITIES
+tethereal_SOURCES+= capab.c
+endif
 
 # Additional libs that I know how to build. These will be
 # linked into the tethereal executable.
Index: tethereal.c
===================================================================
RCS file: /usr/src/build/cvsroot/ethereal/tethereal.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -u -r1.1.1.1 -r1.1.1.1.2.1
--- tethereal.c	8 Sep 2003 03:11:33 -0000	1.1.1.1
+++ tethereal.c	1 Nov 2003 08:26:51 -0000	1.1.1.1.2.1
@@ -68,6 +68,10 @@
 #include "getopt.h"
 #endif
 
+#ifdef ENABLE_LINUX_CAPABILITIES
+void drop_priv();
+#endif
+
 #include <glib.h>
 #include <epan/epan.h>
 #include <epan/filesystem.h>
@@ -798,6 +802,9 @@
   char                 badopt;
   ethereal_tap_list *tli;
 
+#ifdef ENABLE_LINUX_CAPABILITIES
+  drop_priv();
+#endif
   /* Register all dissectors; we must do this before checking for the
      "-G" flag, as the "-G" flag dumps information registered by the
      dissectors, and we must do it before we read the preferences, in
Index: gtk/main.c
===================================================================
RCS file: /usr/src/build/cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -u -r1.1.1.1 -r1.1.1.1.2.1
--- gtk/main.c	5 Sep 2003 02:10:25 -0000	1.1.1.1
+++ gtk/main.c	1 Nov 2003 08:26:55 -0000	1.1.1.1.2.1
@@ -68,6 +68,10 @@
 #include "getopt.h"
 #endif
 
+#ifdef ENABLE_LINUX_CAPABILITIES
+void drop_priv();
+#endif
+
 #ifdef WIN32 /* Needed for console I/O */
 #include <fcntl.h>
 #include <conio.h>
@@ -1546,6 +1550,9 @@
   char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
     OPTSTRING_INIT;
 
+#ifdef ENABLE_LINUX_CAPABILITIES
+  drop_priv();
+#endif
   ethereal_path = argv[0];
 
 #ifdef WIN32
/* capab.c
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>

#include <unistd.h>

#include <sys/capability.h>
#include <sys/prctl.h>

/* #define DEBUG_CAPABILITIES */

#ifdef DEBUG_CAPABILITIES
struct _cap_struct {
	    struct __user_cap_header_struct head;
		    struct __user_cap_data_struct set;
};

void
debug_print_priv(char *text)
{
	cap_t cap;
	struct _cap_struct *c;
	char *s;
	int p;

	int uid,euid,suid;
	int gid,egid,sgid;
	getresuid( &uid, &euid, &suid );
	getresgid( &gid, &egid, &sgid );

	printf("===\n%s\n",text);
	if( (cap = cap_get_proc()) == NULL ) {
		perror("cap_get_proc():");
		exit(1);
	}
	c = cap;
	s=cap_to_text(cap, NULL );
	if( ( p=prctl( PR_GET_KEEPCAPS, 0,0,0,0 ) ) < 0 ) 
		perror( "prctl:" );
	else 
		printf("KEEPCAPS: %d\n",p );
	printf("uid: %d, euid: %d, suid: %d\ngid: %d. egid: %d, sgid: %d\n", uid,euid,suid, gid,egid,sgid );
	printf("Caps: %s\n", s );

	printf("  effective = 0x%08x, permitted = 0x%08x, inheritable = 0x%08x\n",
			c->set.effective, c->set.permitted, c->set.inheritable);

	cap_free(s);
	printf("===\n\n");
}

#else
#define debug_print_priv( x ) 
#endif /* DEBUG_CAPABILITIES */

void
drop_priv()
{

	uid_t euid, uid;
	cap_t cap;

	euid = geteuid();
	uid = getuid();

	debug_print_priv("Before:");

	if (euid != 0) 
		return;

	if( prctl( PR_SET_KEEPCAPS, 1,0,0,0 ) < 0 ) 
		perror( "prctl:" );

	cap=cap_from_text( "cap_net_admin,cap_net_raw=pi" );
	if( cap_set_proc( cap ) < 0 ){
		perror("cap_set_proc(): ");
	}


	debug_print_priv("After cap_set_proc:");

	if (euid != uid) {
		if (setresuid(uid,uid,uid) < 0) {
			perror("setresuid()");
			exit(1);
		}
	}

	debug_print_priv("After setresuid:");

	cap=cap_from_text( "cap_net_admin,cap_net_raw=epi" );
	if( cap_set_proc( cap ) < 0 ){
		perror("cap_set_proc(): ");
	}

	debug_print_priv("After cap_set:");

}