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:
13
cado.c
13
cado.c
@@ -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");
|
||||
|
13
cado.conf.5
13
cado.conf.5
@@ -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
|
||||
|
@@ -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
|
||||
|
52
read_conf.c
52
read_conf.c
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user