Revert "tpws,nfqws : remove cap library dependency"

This reverts commit 3c76e45692038077249b63a9666b11d930f8e283.
This commit is contained in:
bol-van 2020-01-20 15:10:49 +03:00
parent 81a6ece230
commit eb6f962ba3
15 changed files with 155 additions and 169 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,6 @@
CC ?= gcc
CFLAGS += -std=c99 -s -O3
LIBS = -lnetfilter_queue -lnfnetlink -lz
LIBS = -lnetfilter_queue -lnfnetlink -lcap -lz
SRC_FILES = *.c
all: nfqws
@ -10,4 +10,3 @@ nfqws: $(SRC_FILES)
clean:
rm -f nfqws *.o

View File

@ -5,26 +5,26 @@
#include <unistd.h>
#include <fcntl.h>
bool checkpcap(uint64_t caps)
bool setpcap(cap_value_t *caps, int ncaps)
{
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
struct __user_cap_data_struct cd[2];
uint32_t c0 = (uint32_t)caps;
uint32_t c1 = (uint32_t)(caps>>32);
cap_t capabilities;
return !capget(&ch,cd) && (cd[0].effective & c0)==c0 && (cd[0].effective & c1)==c1;
}
bool setpcap(uint64_t caps)
{
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
struct __user_cap_data_struct cd[2];
cd[0].effective = cd[0].permitted = (uint32_t)caps;
cd[0].inheritable = 0;
cd[1].effective = cd[1].permitted = (uint32_t)(caps>>32);
cd[1].inheritable = 0;
if (!(capabilities = cap_init()))
return false;
return !capset(&ch,cd);
if (ncaps && (cap_set_flag(capabilities, CAP_PERMITTED, ncaps, caps, CAP_SET) ||
cap_set_flag(capabilities, CAP_EFFECTIVE, ncaps, caps, CAP_SET)))
{
cap_free(capabilities);
return false;
}
if (cap_set_proc(capabilities))
{
cap_free(capabilities);
return false;
}
cap_free(capabilities);
return true;
}
int getmaxcap()
{
@ -40,25 +40,27 @@ int getmaxcap()
}
bool dropcaps()
{
uint64_t caps = (1<<CAP_NET_ADMIN)|(1<<CAP_NET_RAW);
// must have CAP_SETPCAP at the end. its required to clear bounding set
cap_value_t cap_values[] = { CAP_NET_ADMIN,CAP_NET_RAW,CAP_SETPCAP };
int capct = sizeof(cap_values) / sizeof(*cap_values);
int maxcap = getmaxcap();
if (setpcap(caps|(1<<CAP_SETPCAP)))
if (setpcap(cap_values, capct))
{
for (int cap = 0; cap <= maxcap; cap++)
{
if (prctl(PR_CAPBSET_DROP, cap)<0)
if (cap_drop_bound(cap))
{
fprintf(stderr, "could not drop bound cap %d\n", cap);
fprintf(stderr, "could not drop cap %d\n", cap);
perror("cap_drop_bound");
}
}
}
// now without CAP_SETPCAP
if (!setpcap(caps))
if (!setpcap(cap_values, capct - 1))
{
perror("setpcap");
return checkpcap(caps);
return false;
}
return true;
}

View File

@ -4,7 +4,7 @@
#include <sys/types.h>
#include <stdbool.h>
bool setpcap(uint64_t caps);
bool setpcap(cap_value_t *caps, int ncaps);
int getmaxcap();
bool dropcaps();
bool droproot(uid_t uid, gid_t gid);

View File

@ -1,6 +1,6 @@
CC ?= gcc
CFLAGS += -std=c99 -s -O3
LIBS = -lz
LIBS = -lz -lcap
SRC_FILES = *.c
all: tpws

View File

@ -1,126 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "sec.h"
#include <sys/prctl.h>
#include <unistd.h>
#include <fcntl.h>
bool checkpcap(uint64_t caps)
{
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
struct __user_cap_data_struct cd[2];
uint32_t c0 = (uint32_t)caps;
uint32_t c1 = (uint32_t)(caps>>32);
return !capget(&ch,cd) && (cd[0].effective & c0)==c0 && (cd[0].effective & c1)==c1;
}
bool setpcap(uint64_t caps)
{
struct __user_cap_header_struct ch = {_LINUX_CAPABILITY_VERSION_3, getpid()};
struct __user_cap_data_struct cd[2];
cd[0].effective = cd[0].permitted = (uint32_t)caps;
cd[0].inheritable = 0;
cd[1].effective = cd[1].permitted = (uint32_t)(caps>>32);
cd[1].inheritable = 0;
return !capset(&ch,cd);
}
int getmaxcap()
{
int maxcap = CAP_LAST_CAP;
FILE *F = fopen("/proc/sys/kernel/cap_last_cap", "r");
if (F)
{
int n = fscanf(F, "%d", &maxcap);
fclose(F);
}
return maxcap;
}
bool dropcaps()
{
uint64_t caps = 0;
int maxcap = getmaxcap();
if (setpcap(caps|(1<<CAP_SETPCAP)))
{
for (int cap = 0; cap <= maxcap; cap++)
{
if (prctl(PR_CAPBSET_DROP, cap)<0)
{
fprintf(stderr, "could not drop bound cap %d\n", cap);
perror("cap_drop_bound");
}
}
}
// now without CAP_SETPCAP
if (!setpcap(caps))
{
perror("setpcap");
return checkpcap(caps);
}
return true;
}
bool droproot(uid_t uid, gid_t gid)
{
if (uid || gid)
{
if (prctl(PR_SET_KEEPCAPS, 1L))
{
perror("prctl(PR_SET_KEEPCAPS): ");
return false;
}
if (setgid(gid))
{
perror("setgid: ");
return false;
}
if (setuid(uid))
{
perror("setuid: ");
return false;
}
}
return dropcaps();
}
void daemonize()
{
int pid;
pid = fork();
if (pid == -1)
{
perror("fork: ");
exit(2);
}
else if (pid != 0)
exit(0);
if (setsid() == -1)
exit(2);
if (chdir("/") == -1)
exit(2);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* redirect fd's 0,1,2 to /dev/null */
open("/dev/null", O_RDWR);
int fd;
/* stdin */
fd = dup(0);
/* stdout */
fd = dup(0);
/* stderror */
}
bool writepid(const char *filename)
{
FILE *F;
if (!(F = fopen(filename, "w")))
return false;
fprintf(F, "%d", getpid());
fclose(F);
return true;
}

View File

@ -1,12 +0,0 @@
#pragma once
#include <sys/capability.h>
#include <sys/types.h>
#include <stdbool.h>
bool setpcap(uint64_t caps);
int getmaxcap();
bool dropcaps();
bool droproot(uid_t uid, gid_t gid);
void daemonize();
bool writepid(const char *filename);

View File

@ -20,6 +20,8 @@
#include <netinet/tcp.h>
#include <getopt.h>
#include <pwd.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <time.h>
@ -27,8 +29,7 @@
#include "tpws_conn.h"
#include "hostlist.h"
#include "params.h"
#include "sec.h"
struct params_s params;
bool bHup = false;
@ -421,6 +422,128 @@ void parse_params(int argc, char *argv[])
}
}
static void daemonize()
{
int pid,fd;
pid = fork();
if (pid == -1)
{
perror("fork: ");
exit(2);
}
else if (pid != 0)
exit(0);
if (setsid() == -1)
exit(2);
if (chdir("/") == -1)
exit(2);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* redirect fd's 0,1,2 to /dev/null */
open("/dev/null", O_RDWR);
/* stdin */
fd=dup(0);
/* stdout */
fd=dup(0);
/* stderror */
}
static bool setpcap(cap_value_t *caps,int ncaps)
{
cap_t capabilities;
if (!(capabilities = cap_init()))
return false;
if (ncaps && (cap_set_flag(capabilities, CAP_PERMITTED, ncaps, caps, CAP_SET) ||
cap_set_flag(capabilities, CAP_EFFECTIVE, ncaps, caps, CAP_SET)))
{
cap_free(capabilities);
return false;
}
if (cap_set_proc(capabilities))
{
cap_free(capabilities);
return false;
}
cap_free(capabilities);
return true;
}
static int getmaxcap()
{
int maxcap = CAP_LAST_CAP;
FILE *F = fopen("/proc/sys/kernel/cap_last_cap","r");
if (F)
{
int n=fscanf(F,"%d",&maxcap);
fclose(F);
}
return maxcap;
}
static bool dropcaps()
{
// must have CAP_SETPCAP at the end. its required to clear bounding set
cap_value_t cap_values[] = {CAP_SETPCAP};
int capct=sizeof(cap_values)/sizeof(*cap_values);
int maxcap = getmaxcap();
if (setpcap(cap_values, capct))
{
for(int cap=0;cap<=maxcap;cap++)
{
if (cap_drop_bound(cap))
{
fprintf(stderr,"could not drop cap %d\n",cap);
perror("cap_drop_bound");
}
}
}
// now without CAP_SETPCAP
if (!setpcap(cap_values, capct - 1))
{
perror("setpcap");
return false;
}
return true;
}
static bool droproot()
{
if (params.uid || params.gid)
{
if (prctl(PR_SET_KEEPCAPS, 1L))
{
perror("prctl(PR_SET_KEEPCAPS): ");
return false;
}
if (setgid(params.gid))
{
perror("setgid: ");
return false;
}
if (setuid(params.uid))
{
perror("setuid: ");
return false;
}
}
return dropcaps();
}
static bool writepid(const char *filename)
{
FILE *F;
if (!(F=fopen(filename,"w")))
return false;
fprintf(F,"%d",getpid());
fclose(F);
return true;
}
static bool find_listen_addr(struct sockaddr_storage *salisten, bool bindll, int *if_index)
@ -683,11 +806,11 @@ int main(int argc, char *argv[]) {
set_ulimit();
if (!droproot(params.uid,params.gid))
if (!droproot())
{
goto exiterr;
}
fprintf(stderr,"Running as UID=%u GID=%u\n",getuid(),getgid());
if (listen(listen_fd, BACKLOG) == -1) {