Ethereal-dev: [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: Sun, 28 Sep 2003 11:34:45 +0200
Hi!

I've made this patch to allow suid installation for ethereal and tethereal,
and works for me ( Linux 2.4.x ), but should works also for 2.2.x..

Simply add 
#define ENABLE_LINUX_CAPABILITIES 1 
in config.h and in the Makefile:
add capab.c to ETHEREAL_COMMON_SRC and
capab.$(OBJEXT) to ethereal_optional_objects

and apply the patch priv.diff.

The patch add the CAP_NET_ADMIN and CAP_NET_RAW to the allowed set and drop
everything else..
To see the capabilities set before and after the drop, define DEBUG_CAPABILITIES
in capab.c.

On the todo list I've to change drop_priv to use the libcap packaged
instead of capget/capset..

Comments are welcome..;)


-- 
Ciao,
 Emanuele
/* for setresuid declaration */
#define _GNU_SOURCE 

#include <sys/prctl.h>
#include <linux/capability.h>
int   capget(cap_user_header_t, cap_user_data_t);
int   capset(cap_user_header_t, cap_user_data_t);

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

#include <unistd.h>

/* #define DEBUG_CAPABILITIES */

#ifdef DEBUG_CAPABILITIES
void
print_priv()
{
	struct __user_cap_header_struct hdr;
	struct __user_cap_data_struct data;
	int p;

	int uid,euid,suid;
	int gid,egid,sgid;
	getresuid( &uid, &euid, &suid );
	getresgid( &gid, &egid, &sgid );
	hdr.version = _LINUX_CAPABILITY_VERSION;
	hdr.pid = 0;

	if( ( p=prctl( PR_GET_KEEPCAPS, 0,0,0,0 ) ) < 0 ) 
		perror( "prctl:" );
	else 
		printf("KEEPCAPS: %d\n",p );
	if (capget(&hdr, &data)) 
		perror("capget");
	printf
		("uid: %d, euid: %d, suid: %d\ngid: %d. egid: %d, sgid: %d\n"
		 "  effective = 0x%08x, permitted = 0x%08x, inheritable = 0x%08x\n",
		 uid,euid,suid, gid,egid,sgid, 
		 data.effective, data.permitted, data.inheritable);
}

#endif /* DEBUG_CAPABILITIES */

void
drop_priv()
{

	uid_t euid, uid;
	struct __user_cap_header_struct hdr;
	struct __user_cap_data_struct data;

	euid = geteuid();
	uid = getuid();
#ifdef DEBUG_CAPABILITIES
	printf("Before:\n");
	print_priv();
#endif
	if (euid != 0) 
		return;

	hdr.version = _LINUX_CAPABILITY_VERSION;
	hdr.pid = 0;


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


	if (capget(&hdr, &data)) {
		perror("capget");
		exit(1);
	}
	data.permitted = (1UL << CAP_NET_ADMIN) | (1UL << CAP_NET_RAW);
	data.effective = data.inheritable = data.permitted ;
	if (capset(&hdr, &data) != 0) {
		perror("capset");
	}

	if (euid != uid) {
		if (setresuid(uid,uid,uid) < 0) {
			perror("setresuid()");
			exit(1);
		}
	}
	capget(&hdr, &data);
	data.permitted = (1UL << CAP_NET_ADMIN) | (1UL << CAP_NET_RAW);
	data.effective = data.inheritable = data.permitted ;
	if (capset(&hdr, &data) != 0) {
		perror("capset");
	}
#ifdef DEBUG_CAPABILITIES
	printf("After:\n");
	print_priv();
#endif
}
--- /.1/build/ethereal/ethereal-0.9.15.orig/tethereal.c	2003-09-08 05:11:33.000000000 +0200
+++ tethereal.c	2003-09-27 11:38:03.000000000 +0200
@@ -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
--- /.1/build/ethereal/ethereal-0.9.15.orig/gtk/main.c	2003-09-05 04:10:25.000000000 +0200
+++ gtk/main.c	2003-09-27 11:39:01.000000000 +0200
@@ -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