/* * michael gebetsroither <michael.geb@gmx.at> * GPL */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #undef _POSIX_SOURCE #include <sys/capability.h> extern int errno; #define checkResults(string, val) { \ if (val) { \ printf("Failed with %d at %s:%i - %s\n", val, string, __LINE__, strerror(errno)); \ } \ } void whoami(void) { printf("uid=%i euid=%i gid=%i\n", getuid(), geteuid(), getgid()); } void listCaps() { cap_t caps = cap_get_proc(); ssize_t y = 0; printf("The process %d was give capabilities %s\n", (int) getpid(), cap_to_text(caps, &y)); fflush(0); cap_free(caps); } int setCaps(cap_t caps, cap_value_t cap_list[], unsigned num_caps) { cap_set_flag(caps, CAP_EFFECTIVE, num_caps, cap_list, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, num_caps, cap_list, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, num_caps, cap_list, CAP_SET); if (cap_set_proc(caps)) { perror("capset()"); return 0; } return 1; } int main(int argc, char **argv) { int stat; whoami(); stat = setuid(geteuid()); checkResults("setuid", stat) stat = setgid(1008); checkResults("setgid", stat); whoami(); pid_t parentPid = getpid(); if(!parentPid) return 1; cap_t caps = cap_init(); /* CAP_NET_RAW - raw sockets CAP_NET_BIND_SERVICE -> ports <1024 CAP_SETUID -> setuid CAP_SETGID -> setgid */ cap_value_t capList[4] = { CAP_NET_RAW, CAP_NET_BIND_SERVICE , CAP_SETUID, CAP_SETGID } ; unsigned num_caps = 4; cap_set_flag(caps, CAP_EFFECTIVE, num_caps, capList, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, num_caps, capList, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, num_caps, capList, CAP_SET); if (cap_set_proc(caps)) { perror("capset()"); return EXIT_FAILURE; } listCaps(); printf("dropping root privs\n"); stat = setuid(1008); checkResults("setuid", stat); whoami(); printf("\ntry to change back to uid=0\n"); checkResults("setuid", seteuid(0)); checkResults("setuid", setuid(0)); checkResults("setuid", setuid(1000)); printf("\nend of permission flicking\n"); whoami(); listCaps(); // could not drop capas CAP_SET_UID/CAP_SET_GID because operation net permittet // error in manpage, CAP_SETPCAP sould not be required to remove capas. // // but CAP_SET_UID/CAP_SET_GID are imho nonworking because we are not root anymore (wtf)? /* printf("dropping caps\n"); cap_clear(caps); // resetting caps storage cap_value_t newCapList[3] = { CAP_SYS_NICE, CAP_NET_RAW, CAP_NET_BIND_SERVICE }; num_caps = 3; //cap_set_flag(caps, CAP_EFFECTIVE, num_caps, newCapList, CAP_SET); //cap_set_flag(caps, CAP_INHERITABLE, num_caps, newCapList, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, num_caps, newCapList, CAP_SET); if (cap_set_proc(caps)) { perror("capset()"); return EXIT_FAILURE; } listCaps(); */ cap_free(caps); return 0; }