1
0
mirror of https://github.com/rd235/cado synced 2025-06-05 21:59:29 +02:00

new feature: conditioned rules in cado.conf

This commit is contained in:
Renzo Davoli
2016-08-04 12:59:42 +02:00
parent 6aaa8cee2f
commit 32c1eb2ab3
5 changed files with 73 additions and 24 deletions

13
cado.c
View File

@@ -67,7 +67,7 @@ int main(int argc, char*argv[])
{
char *progname=basename(argv[0]);
char **user_groups=get_user_groups();
uint64_t okcaps=get_authorized_caps(user_groups);
uint64_t okcaps;
uint64_t reqcaps=0;
uint64_t grantcap=0;
int verbose=0;
@@ -95,7 +95,7 @@ int main(int argc, char*argv[])
fprintf(stderr, "setcap requires root access\n");
exit(2);
}
okcaps = get_authorized_caps(NULL);
okcaps = get_authorized_caps(NULL, -1LL);
okcaps |= 1ULL << CAP_DAC_READ_SEARCH;
if (verbose) {
printf("Capability needed by %s:\n", progname);
@@ -108,13 +108,12 @@ int main(int argc, char*argv[])
exit(0);
}
if (verbose) {
if (verbose && (argc == optind)) {
okcaps=get_authorized_caps(user_groups, -1LL);
printf("Allowed ambient capabilities:\n");
printcapset(okcaps, " ");
}
if (verbose && (argc == optind))
exit(0);
}
if (argc - optind < 2)
usage(progname);
@@ -127,6 +126,8 @@ int main(int argc, char*argv[])
printcapset(reqcaps, " ");
}
okcaps=get_authorized_caps(user_groups, reqcaps);
if (reqcaps & ~okcaps) {
if (verbose) {
printf("Unavailable ambient capabilities:\n");

View File

@@ -13,6 +13,10 @@ Non-comment lines have the following syntax
.nf
\fIlist_of_capabilities\fB:\fI list_of_users_and_groups\fR
.fi
or
.nf
\fIlist_of_capabilities\fB:\fI list_of_users_and_groups\fB:\fR \fIlist_of_auth_commands\fR
.fi
Both \fIlist_of_capabilities\fR and \fIlist_of_users_and_groups\fR are comma separated lists of identifiers.
@@ -22,13 +26,18 @@ have the same meaning).
Items of \fIlist_of_users_and_groups\fR are usernames or groupnames (groupnames must be prefexed by '@').
\fIlist_of_auth_commands\fR is a command or a list of commands separated by semicolon (;). If present, cado runs
all the sequence of commands it grants the capabilities as defined in the current line only if all return zero as
their exit status.
Example of \fBcado.conf\fR file:
.ni
.nf
# Capability Ambient DO configuration file
# cado.conf
net_admin: @netadmin,renzo
net_admin: @netadmin,renzo: /usr/bin/logger cado net_admin $USER; /bin/echo OK
net_admin: @privatenet: /usr/local/lib/cado_autorize_privatenet
net_admin,net_bind_service,net_raw,net_broadcast: @vxvdex
cap_kill: renzo
.fi

View File

@@ -13,6 +13,10 @@ AC_PROG_CC
AC_PROG_INSTALL
# Checks for libraries.
AC_CHECK_LIB([s2argv], [s2argv], [],
[
AC_MSG_ERROR([Could not find S2ARGV library])
])
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h unistd.h])
@@ -22,6 +26,9 @@ AC_CHECK_HEADERS([sys/capability.h],
AC_CHECK_HEADERS([security/pam_appl.h security/pam_misc.h],
[],
[AC_MSG_ERROR([missing PAM headers])])
AC_CHECK_HEADERS([s2argv.h],
[],
[AC_MSG_ERROR([missing S2ARGV headers])])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T

View File

@@ -25,9 +25,11 @@
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/prctl.h>
#include <read_conf.h>
#include <set_ambient_cap.h>
#include <capset_from_namelist.h>
#include <s2argv.h>
#ifndef CONFDIR
#define CONFDIR "/etc"
@@ -35,6 +37,7 @@
#define CADO_CONF CONFDIR "/cado.conf"
/* groupmatch returns 1 if group belongs to grouplist */
static int groupmatch (char *group, char **grouplist) {
for (;*grouplist; grouplist++) {
//printf("%s %s\n",group, *grouplist);
@@ -44,62 +47,91 @@ static int groupmatch (char *group, char **grouplist) {
return 0;
}
uint64_t get_authorized_caps(char **user_groups) {
/* s2argv security, children must drop their capabilities */
static int drop_capabilities(void *useless) {
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
}
/* get_authorized_caps returns the set of authorized capabilities
for the user user_groups[0] belonging to the groups user_groups[1:] */
/* if user_groups==NULL, get_authorized_caps computes the maximum set
of capabilities that cado itself must own to be able to assign */
uint64_t get_authorized_caps(char **user_groups, uint64_t reqset) {
uint64_t ok_caps=0;
FILE *f;
/* cado.conf is not readble by users. Add the capability to do it */
if (user_groups) raise_cap_dac_read_search();
f=fopen(CADO_CONF, "r");
if (f) {
char *line=NULL;
ssize_t len,n=0;
while ((len=getline(&line, &n, f)) > 0) {
/* set s2argv security, children must drop their capabilities */
s2_fork_security=drop_capabilities;
while ((len=getline(&line, &n, f)) > 0 && (reqset & ~ok_caps)) {
//printf("%s",line);
char *scan=line;
char *tokencap;
char *tokenusergroup;
char *tokencondition;
char *tok;
uint64_t capset;
char *tmptok;
int usermatch=0;
/* skip leading spaces */
while (isspace(*scan)) scan++;
if (*scan == 0 || *scan == '#') //comment
continue;
tok=strtok_r(scan, ":", &tmptok);
//printf("%s\n",tok);
tokencap=strtok_r(scan, ":", &tmptok);
//printf("CAP %s\n",tokencap);
tokenusergroup=strtok_r(NULL, ":\n", &tmptok);
//printf("UG %s\n",tokenusergroup);
tokencondition=strtok_r(NULL, ":\n", &tmptok);
//printf("COND %s\n",tokencondition);
capset=0;
if (capset_from_namelist(tok, &capset) < 0)
if (capset_from_namelist(tokencap, &capset) < 0)
continue;
if (user_groups == NULL) {
ok_caps |= capset;
continue;
}
//printf("CAP %s %d\n",tok,thiscap);
while ((tok=strtok_r(NULL, ",\n ",&tmptok)) != NULL) {
while ((tok=strtok_r(tokenusergroup, ",\n ",&tmptok)) != NULL) {
//printf("XX %s\n",tok);
if (*tok=='@') {
if (groupmatch(tok+1, user_groups+1)) {
ok_caps |= capset;
usermatch = 1;
break;
}
} else if (strcmp(tok, user_groups[0]) == 0) {
ok_caps |= capset;
usermatch = 1;
break;
}
tokenusergroup=NULL;
}
if (usermatch) {
if (tokencondition) {
if (system_execsa(tokencondition) == 0)
ok_caps |= capset;
} else
ok_caps |= capset;
}
}
fclose(f);
if (line)
free(line);
}
/* the capability to read cado.conf is no longer needed */
if (user_groups) lower_cap_dac_read_search();
return ok_caps;
}
/* set_self_capability sets the capability set needed by cado itself */
int set_self_capability(uint64_t capset) {
cap_value_t cap;
cap_t caps=cap_init();
int f,rv=-1;
for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
if (capset & (1ULL << cap)) {
/*if (cap_set_flag(caps, CAP_PERMITTED, 1, &cap, CAP_SET) ||
cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_SET)) {*/
if (cap_set_flag(caps, CAP_PERMITTED, 1, &cap, CAP_SET)) {
fprintf(stderr, "Cannot set permitted cap %s\n",cap_to_name(cap));
exit(2);

View File

@@ -2,7 +2,7 @@
#define READ_CONF_H
#include <stdint.h>
uint64_t get_authorized_caps(char **user_groups);
uint64_t get_authorized_caps(char **user_groups, uint64_t reqset);
int set_self_capability(uint64_t capset);