retire C version
This commit is contained in:
parent
3bcf1fee82
commit
cedb591baf
0
rust/Cargo.lock → Cargo.lock
generated
0
rust/Cargo.lock → Cargo.lock
generated
193
qsni.c
193
qsni.c
@ -1,193 +0,0 @@
|
|||||||
/* Copyright (c) 2018 Albert S. <mail at quitesimple dot org>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <linux/limits.h>
|
|
||||||
#define NET_CLS_DIR "/sys/fs/cgroup/net_cls/"
|
|
||||||
#define IPTABLES_PROFILES_DIR "/etc/qsni.d/"
|
|
||||||
|
|
||||||
//exits if we are already inside a profile.
|
|
||||||
void ensure_outside_profile()
|
|
||||||
{
|
|
||||||
FILE *fp = fopen("/proc/self/cgroup", "r");
|
|
||||||
if(fp == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed to open cgroup file\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *line = NULL;
|
|
||||||
size_t n = 0;
|
|
||||||
while(getline(&line, &n, fp) != -1)
|
|
||||||
{
|
|
||||||
char *id = line;
|
|
||||||
char *tmp = strchr(id, ':');
|
|
||||||
if(tmp == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Misformated cgroups file\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
*tmp = 0;
|
|
||||||
++tmp;
|
|
||||||
char *controllers = tmp;
|
|
||||||
tmp = strchr(controllers, ':');
|
|
||||||
if(tmp == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Misformated cgroups file\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
*tmp = 0;
|
|
||||||
++tmp;
|
|
||||||
|
|
||||||
char *assigned = tmp;
|
|
||||||
|
|
||||||
if(strstr(controllers, "net_cls") != NULL)
|
|
||||||
{
|
|
||||||
if(assigned[0] == '/' && assigned[1] != '\n')
|
|
||||||
{
|
|
||||||
fprintf(stderr, "already assigned to a net class, thus you can't use this binary to change that\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line = NULL;
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_profile(const char *profilepath)
|
|
||||||
{
|
|
||||||
pid_t pid = fork();
|
|
||||||
if(pid == 0)
|
|
||||||
{
|
|
||||||
if(clearenv() != 0)
|
|
||||||
{
|
|
||||||
perror("clearenv");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = execl(profilepath, profilepath, (char *) NULL);
|
|
||||||
if(ret == -1)
|
|
||||||
{
|
|
||||||
perror("execl of child");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(pid > 0)
|
|
||||||
{
|
|
||||||
int status=1;
|
|
||||||
pid_t w = waitpid(pid, &status, 0);
|
|
||||||
if(w == -1)
|
|
||||||
{
|
|
||||||
perror("waitpid");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if(! WIFEXITED(status) || WEXITSTATUS(status) != 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
fprintf(stderr, "profile setup script failed\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(pid == -1)
|
|
||||||
{
|
|
||||||
perror("fork");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
void drop(uid_t u, gid_t g)
|
|
||||||
{
|
|
||||||
if(setgid(g) != 0)
|
|
||||||
{
|
|
||||||
perror("setgid");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if(setuid(u) != 0)
|
|
||||||
{
|
|
||||||
perror("setuid");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assign_to_profile(const char *profilename)
|
|
||||||
{
|
|
||||||
char taskspath[PATH_MAX +1];
|
|
||||||
snprintf(taskspath, sizeof(taskspath), "%s/%s/tasks", NET_CLS_DIR, profilename);
|
|
||||||
|
|
||||||
pid_t mypid = getpid();
|
|
||||||
FILE *fp = fopen(taskspath, "a");
|
|
||||||
if(fp == NULL)
|
|
||||||
{
|
|
||||||
perror("fopen");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
fprintf(fp, "%ld", (long)mypid);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if(argc < 3)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: %s profile command [arguments...]\n", argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
ensure_outside_profile();
|
|
||||||
|
|
||||||
char *profilename = argv[1];
|
|
||||||
|
|
||||||
char profilepath[PATH_MAX +1];
|
|
||||||
snprintf(profilepath, sizeof(profilepath), "%s/%s", IPTABLES_PROFILES_DIR, profilename);
|
|
||||||
int ret = access(profilepath, R_OK);
|
|
||||||
if(ret != 0)
|
|
||||||
{
|
|
||||||
perror("check for profile path failed\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
uid_t myuid = getuid();
|
|
||||||
gid_t myguid = getgid();
|
|
||||||
if(setuid(0) != 0)
|
|
||||||
{
|
|
||||||
perror("setuid");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
init_profile(profilepath);
|
|
||||||
assign_to_profile(profilename);
|
|
||||||
|
|
||||||
drop(myuid, myguid);
|
|
||||||
|
|
||||||
|
|
||||||
argv += 2;
|
|
||||||
int result = execvp(argv[0], argv);
|
|
||||||
if(result == -1)
|
|
||||||
{
|
|
||||||
perror("execv");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user