diff --git a/Makefile.am b/Makefile.am index 47f4a41..6778763 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,10 +1,14 @@ -bin_PROGRAMS = cado scado caprint +bin_PROGRAMS = cado cadrop scado caprint cado_SOURCES = cado.c pam_check.c get_user_groups.c capset_from_namelist.c read_conf.c set_ambient_cap.c \ compute_digest.c file_utils.c scado_parse.c cado_scado_check.c cado_LDADD = -lpam -lpam_misc -lcap -lmhash +cadrop_SOURCES = cadrop.c capset_from_namelist.c set_ambient_cap.c + +cadrop_LDADD = -lcap + caprint_LDADD = -lcap scado_SOURCES = scado.c pam_check.c file_utils.c compute_digest.c capset_from_namelist.c scado_parse.c @@ -14,7 +18,7 @@ scado_LDADD = -lpam -lpam_misc -lcap -lmhash common_nodist = cado_paths.h BUILT_SOURCES = $(common_nodist) -man_MANS = cado.1 caprint.1 scado.1 cado.conf.5 +man_MANS = cado.1 cadrop.1 caprint.1 scado.1 cado.conf.5 install-exec-hook: (useradd -r -s /bin/nologin -g `getent passwd | grep cado | cut -f 3 -d ':'` cado ||\ diff --git a/cadrop.1 b/cadrop.1 new file mode 100644 index 0000000..ec9d360 --- /dev/null +++ b/cadrop.1 @@ -0,0 +1,30 @@ +.TH CADROP 1 "November 26, 2016" "VirtualSquare Labs" +.SH NAME +cadrop \- Capability Ambient Drop +.SH SYNOPSIS +.B cadrop +[ +.I capability_list +[ +.I command +[ +.I args +] +] +] + +.SH DESCRIPTION +Cadrop permits to drop (ambient) capabilities. + +Cadrop launches the command indicated as a parameter ($SHELL if omitted) dropping all the capabilities +listed in the capability_list. + +If the capability_list is also omitted or it matches one of the string "all" or "-", cadrop drops all the capabilities. + +.SH SEE ALSO +\fBcado\fR(1), +\fBcaprint\fR(1), +\fBscado\fR(1), +\fBcado.conf\fR(5), +\fBcapabilities\fR(7) + diff --git a/cadrop.c b/cadrop.c new file mode 100644 index 0000000..e371794 --- /dev/null +++ b/cadrop.c @@ -0,0 +1,66 @@ +/* + * cado: execute a command in a capability ambient + * Copyright (C) 2016 Renzo Davoli, Davide Berardi, University of Bologna + * + * This file is part of cado. + * + * Cado is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see . + * + */ + +#include +#include +#include +#include + +#include +#include + +static int argv1_all(char *s) { + if (s == NULL) + return 1; + if (strcmp(s,"") == 0) + return 1; + if (strcmp(s,"-") == 0) + return 1; + if (strcmp(s,"all") == 0) + return 1; + return 0; +} + +int main(int argc, char *argv[]) { + uint64_t capset = -1; + char *argvsh[]={getenv("SHELL"),NULL}; + switch (argc) { + case 1: + capset = -1; + argv += 1; + break; + default: + if (argv1_all(argv[1])) + capset = -1; + else if (capset_from_namelist(argv[1], &capset) < 0) { + fprintf(stderr, "error parsing capabilities\n"); + exit(2); + } + argv+=2; + break; + } + if (*argv == NULL) argv = argvsh; + drop_ambient_cap(capset); + execvp(argv[0],argv); + perror("exec"); + return 2; +} + diff --git a/set_ambient_cap.c b/set_ambient_cap.c index b5fc57f..8f71786 100644 --- a/set_ambient_cap.c +++ b/set_ambient_cap.c @@ -62,6 +62,32 @@ void set_ambient_cap(uint64_t capset) } } +/* drop the capabilities of the capset */ + +void drop_ambient_cap(uint64_t capset) { + cap_value_t cap; + cap_t caps=cap_get_proc(); + for (cap = 0; cap <= CAP_LAST_CAP; cap++) { + if (capset & (1ULL << cap)) { + if (cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, CAP_CLEAR)) { + fprintf(stderr, "Cannot clear inheritable cap %s\n",cap_to_name(cap)); + exit(2); + } + } + } + cap_set_proc(caps); + cap_free(caps); + + for (cap = 0; cap <= CAP_LAST_CAP; cap++) { + if ((capset & (1ULL << cap))) { + if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, cap, 0, 0)) { + perror("Cannot set cap"); + exit(1); + } + } + } +} + /* turn cap_dac_read_search on and off to have "extra" powers only when needed */ void raise_cap_dac_read_search(void) { cap_value_t cap=CAP_DAC_READ_SEARCH; diff --git a/set_ambient_cap.h b/set_ambient_cap.h index 55e1f06..d696c5f 100644 --- a/set_ambient_cap.h +++ b/set_ambient_cap.h @@ -1,8 +1,11 @@ #ifndef SET_AMBIENT_CAP_H #define SET_AMBIENT_CAP_H +#include void set_ambient_cap(uint64_t capset); +void drop_ambient_cap(uint64_t capset); + void raise_cap_dac_read_search(void); void lower_cap_dac_read_search(void);