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

Reply via email to