Index: Makefile.in =================================================================== --- Makefile.in (revision 33503) +++ Makefile.in (working copy) @@ -50,7 +50,7 @@ # CFLAGS = $(DEFS) $(INCLS) STATIC = LDFLAGS = @LDFLAGS@ $(DBGFLAGS) $(STATIC) -LIBS = @LIBNBASE_LIBS@ @LIBNSOCK_LIBS@ @LIBPCRE_LIBS@ @LIBPCAP_LIBS@ $(OPENSSL_LIBS) libnetutil/libnetutil.a @LIBDNET_LIBS@ @LIBLUA_LIBS@ @LIBLINEAR_LIBS@ @LIBS@ +LIBS = @LIBNBASE_LIBS@ @LIBNSOCK_LIBS@ @LIBPCRE_LIBS@ @LIBPCAP_LIBS@ @LIBCAP_LIBS@ $(OPENSSL_LIBS) libnetutil/libnetutil.a @LIBDNET_LIBS@ @LIBLUA_LIBS@ @LIBLINEAR_LIBS@ @LIBS@ OPENSSL_LIBS = @OPENSSL_LIBS@ # LIBS = -lefence @LIBS@ # LIBS = -lrmalloc @LIBS@ Index: NmapOps.cc =================================================================== --- NmapOps.cc (revision 33503) +++ NmapOps.cc (working copy) @@ -273,6 +273,30 @@ return strdup(url.c_str()); } +#ifdef HAVE_LIBCAP +static bool has_capabilities() { + bool has_all_capabilities = true; + cap_t current_cap = cap_get_proc(); + cap_flag_value_t flag_value; + + if (cap_get_flag(current_cap, CAP_NET_RAW, CAP_EFFECTIVE, &flag_value) == -1) + has_all_capabilities = false; // since cap_get_flag is unable to check for capabilities + has_all_capabilities &= flag_value; + + if (cap_get_flag(current_cap, CAP_NET_ADMIN, CAP_EFFECTIVE, &flag_value) == -1) + has_all_capabilities = false; // since cap_get_flag is unable to check for capabilities + has_all_capabilities &= flag_value; + + if (cap_get_flag(current_cap, CAP_NET_BIND_SERVICE, CAP_EFFECTIVE, &flag_value) == -1) + has_all_capabilities = false; // since cap_get_flag is unable to check for capabilities + has_all_capabilities &= flag_value; + + cap_free(current_cap); + + return has_all_capabilities; +} +#endif + void NmapOps::Initialize() { setaf(AF_INET); #if defined WIN32 || defined __amigaos__ @@ -282,6 +306,10 @@ isr00t = 1; else if (getenv("NMAP_UNPRIVILEGED")) isr00t = 0; +#ifdef HAVE_LIBCAP + else if (has_capabilities()) + isr00t = 1; +#endif else isr00t = !(geteuid()); #endif Index: configure.ac =================================================================== --- configure.ac (revision 33503) +++ configure.ac (working copy) @@ -365,6 +365,64 @@ AC_SUBST(OPENSSL_LIBS) +# We test whether they specified libcap desires explicitly +use_libcap="yes" +specialcapdir="" +AC_ARG_WITH(libcap, +AC_HELP_STRING([--with-libcap=DIR],[Use optional libcap libs and includes from [DIR]/lib/ and [DIR]/include/)]), # Check this string +[ case "$with_libcap" in + yes) + ;; + no) + use_libcap="no" + ;; + *) + specialcapdir="$with_libcap" + CPPFLAGS="$CPPFLAGS -I$with_libcap/include" # To check + LDFLAGS="$LDFLAGS -L$with_libcap/lib" # To check + ;; + esac] +) + +# If they didn't specify it, we try to find it +if test "$use_libcap" = "yes" -a -z "$specialcapdir"; then + AC_CHECK_HEADER(sys/capability.h,, + [ use_libcap="no" + if test "$with_cap" = "yes"; then + AC_MSG_ERROR([libcap was explicitly requested but sys/capability.h was not found. Try the --with-libcap=DIR argument to give the location of libcap or run configure with --without-libcap.]) + fi + AC_MSG_WARN([Failed to find sys/capability.h so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument]) + ]) + +# use_libcap="yes" given explicitly in next rule to avoid adding lib to $LIBS + if test "$use_libcap" = "yes"; then + AC_CHECK_LIB(cap, cap_get_flag, + [ use_libcap="yes" ], + [ use_libcap="no" + if test "$with_libcap" = "yes"; then + AC_MSG_ERROR([libcap was explicitly requested but libcap was not found. Try the --with-libcap=DIR argument to give the location of libcap or run configure with --without-libcap.]) + fi + AC_MSG_WARN([Failed to find libcap so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument]) ]) + fi + if test "$use_libcap" = "yes"; then + AC_CHECK_LIB(cap, cap_get_proc, + [ use_libcap="yes" ], + [ use_libcap="no" + if test "$with_libcap" = "yes"; then + AC_MSG_ERROR([libcap was explicitly requested but libcap was not found. Try the --with-libcap=DIR argument to give the location of libcap or run configure with --without-libcap.]) + fi + AC_MSG_WARN([Failed to find libcap so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument]) ]) + fi +fi + +LIBCAP_LIBS= +if test "$use_libcap" = "yes"; then + AC_DEFINE(HAVE_LIBCAP, 1, [We can check for capabilities and use them if possible]) + LIBCAP_LIBS="-lcap" +fi + +AC_SUBST(LIBCAP_LIBS) + dnl Check whether libpcap is already available have_libpcap=no Index: nmap.h =================================================================== --- nmap.h (revision 33503) +++ nmap.h (working copy) @@ -243,6 +243,10 @@ #include #endif +#ifdef HAVE_LIBCAP +#include +#endif + /*#include *//* defines struct arphdr needed for if_ether.h */ // #if HAVE_NET_IF_H // #ifndef NET_IF_H /* why doesn't OpenBSD do this?! */ Index: nmap_config.h.in =================================================================== --- nmap_config.h.in (revision 33503) +++ nmap_config.h.in (working copy) @@ -188,6 +188,8 @@ #undef HAVE_OPENSSL +#undef HAVE_LIBCAP + #undef STUPID_SOLARIS_CHECKSUM_BUG #undef SOLARIS_BPF_PCAP_CAPTURE Index: configure =================================================================== --- configure (revision 33503) +++ configure (working copy) @@ -672,6 +672,7 @@ PCAP_CLEAN PCAP_BUILD PCAP_DEPENDS +LIBCAP_LIBS OPENSSL_LIBS NPING_DIST_CLEAN NPING_CLEAN @@ -779,6 +780,7 @@ with_zenmap with_nping with_openssl +with_libcap with_libpcap with_libpcre with_libdnet @@ -1434,6 +1436,8 @@ --without-nping Skip installation of the Nping utility --with-openssl=DIR Use optional openssl libs and includes from [DIR]/lib/ and [DIR]/include/openssl/) + --with-libcap=DIR Use optional libcap libs and includes from + [DIR]/lib/ and [DIR]/include/) --with-libpcap=DIR Look for pcap in DIR/include and DIR/libs. --with-libpcap=included Always use version included with Nmap --with-libpcre=DIR Use an existing (compiled) pcre lib from DIR/include @@ -6169,6 +6173,157 @@ fi + +# We test whether they specified libcap desires explicitly +use_libcap="yes" +specialcapdir="" + +# Check whether --with-libcap was given. +if test "${with_libcap+set}" = set; then : + withval=$with_libcap; # Check this string + case "$with_libcap" in + yes) + ;; + no) + use_libcap="no" + ;; + *) + specialcapdir="$with_libcap" + CPPFLAGS="$CPPFLAGS -I$with_libcap/include" # To check + LDFLAGS="$LDFLAGS -L$with_libcap/lib" # To check + ;; + esac + +fi + + +# If they didn't specify it, we try to find it +if test "$use_libcap" = "yes" -a -z "$specialcapdir"; then + ac_fn_c_check_header_mongrel "$LINENO" "sys/capability.h" "ac_cv_header_sys_capability_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_capability_h" = xyes; then : + +else + use_libcap="no" + if test "$with_cap" = "yes"; then + as_fn_error $? "libcap was explicitly requested but sys/capability.h was not found. Try the --with-libcap=DIR argument to give the location of libcap or run configure with --without-libcap." "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find sys/capability.h so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument" >&5 +$as_echo "$as_me: WARNING: Failed to find sys/capability.h so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument" >&2;} + +fi + + + +# use_libcap="yes" given explicitly in next rule to avoid adding lib to $LIBS + if test "$use_libcap" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_get_flag in -lcap" >&5 +$as_echo_n "checking for cap_get_flag in -lcap... " >&6; } +if ${ac_cv_lib_cap_cap_get_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cap_get_flag (); +int +main () +{ +return cap_get_flag (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_cap_cap_get_flag=yes +else + ac_cv_lib_cap_cap_get_flag=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_cap_get_flag" >&5 +$as_echo "$ac_cv_lib_cap_cap_get_flag" >&6; } +if test "x$ac_cv_lib_cap_cap_get_flag" = xyes; then : + use_libcap="yes" +else + use_libcap="no" + if test "$with_libcap" = "yes"; then + as_fn_error $? "libcap was explicitly requested but libcap was not found. Try the --with-libcap=DIR argument to give the location of libcap or run configure with --without-libcap." "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find libcap so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument" >&5 +$as_echo "$as_me: WARNING: Failed to find libcap so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument" >&2;} +fi + + fi + if test "$use_libcap" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_get_proc in -lcap" >&5 +$as_echo_n "checking for cap_get_proc in -lcap... " >&6; } +if ${ac_cv_lib_cap_cap_get_proc+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cap_get_proc (); +int +main () +{ +return cap_get_proc (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_cap_cap_get_proc=yes +else + ac_cv_lib_cap_cap_get_proc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_cap_get_proc" >&5 +$as_echo "$ac_cv_lib_cap_cap_get_proc" >&6; } +if test "x$ac_cv_lib_cap_cap_get_proc" = xyes; then : + use_libcap="yes" +else + use_libcap="no" + if test "$with_libcap" = "yes"; then + as_fn_error $? "libcap was explicitly requested but libcap was not found. Try the --with-libcap=DIR argument to give the location of libcap or run configure with --without-libcap." "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find libcap so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument" >&5 +$as_echo "$as_me: WARNING: Failed to find libcap so libcap will not be used. If it is installed you can try the --with-libcap=DIR argument" >&2;} +fi + + fi +fi + +LIBCAP_LIBS= +if test "$use_libcap" = "yes"; then + +$as_echo "#define HAVE_LIBCAP 1" >>confdefs.h + + LIBCAP_LIBS="-lcap" +fi + + have_libpcap=no