summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--main.cc131
-rw-r--r--overrides1
-rw-r--r--permissions1
4 files changed, 126 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index ff256cf..872551e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
default: insecuresuexec insecuresuexec-noisy
insecuresuexec: main.cc
- clang++ -Wall -Werror -std=c++11 -Os -o $@ $+
+ g++ -Wall -Werror -std=c++11 -Os -o $@ $+
insecuresuexec-noisy: main.cc
- clang++ -Wall -Werror -std=c++11 -Os -o $@ -DNOISY $+
+ g++ -Wall -Werror -std=c++11 -Os -o $@ -DNOISY $+
clean:
rm -f insecuresuexec insecuresuexec-noisy
diff --git a/main.cc b/main.cc
index 61946e3..8448f3f 100644
--- a/main.cc
+++ b/main.cc
@@ -2,6 +2,7 @@
#include <errno.h>
#include <grp.h>
#include <pwd.h>
+#include <regex>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -76,6 +77,7 @@ public:
, max_gid( gids.second )
{
+ DEBUG( "insecuresuexec permission( %u-%u, %u-%u )\n", min_uid, max_uid, min_gid, max_gid );
}
@@ -85,6 +87,31 @@ public:
};
+class override {
+
+ std::regex constraint;
+
+public:
+
+ uid_t uid;
+ gid_t gid;
+
+ override( uid_t _uid, gid_t _gid, const char *ex )
+ : constraint( ex, std::regex_constants::basic )
+ , uid( _uid )
+ , gid( _gid )
+ {
+
+ DEBUG( "insecuresuexec override( %u, %u, %s )\n", _uid, _gid, ex );
+
+ }
+
+ const bool match( const char *str ) {
+ return regex_match( str, constraint, std::regex_constants::match_continuous );
+ }
+
+};
+
template< typename thing > std::pair< thing, thing > parse_pair( const char *line, thing (*parse_one)( const char *part ) ) {
std::pair< thing, thing > ret( 0, -1 );
@@ -130,7 +157,7 @@ template< typename thing > std::pair< thing, thing > parse_pair( const char *lin
}
-permission parse_line( const char *line ) {
+permission parse_permission_line( const char *line ) {
size_t line_len = strcspn( line, "\n" );
assert( line_len > 0 );
@@ -155,6 +182,38 @@ permission parse_line( const char *line ) {
}
+override parse_override_line( const char *line ) {
+
+ size_t line_len = strcspn( line, "\n" );
+ assert( line_len > 0 );
+
+ size_t user_len = strcspn( line, ":" );
+ assert( user_len != line_len );
+
+ size_t group_len = strcspn( line + user_len + 1, " " );
+ assert( group_len != line_len - user_len - 1 );
+
+ size_t ex_len = line_len - user_len - 1 - group_len - 1;
+
+ char user[user_len + 1];
+ strncpy( user, line, user_len );
+ user[user_len] = 0;
+
+ char group[group_len + 1];
+ strncpy( group, line + user_len + 1, group_len );
+ group[group_len] = 0;
+
+ char ex[ex_len + 1];
+ strncpy( ex, line + user_len + 1 + group_len + 1, ex_len );
+ ex[ex_len] = 0;
+
+ uid_t uid_part = parse_user( user );
+ gid_t gid_part = parse_group( group );
+
+ return override( uid_part, gid_part, ex );
+
+}
+
std::vector< permission > * read_permissions( const char *file ) {
FILE *fh = fopen( file, "r" );
@@ -170,7 +229,34 @@ std::vector< permission > * read_permissions( const char *file ) {
size_t line_len = strcspn( line, "\n" );
if ( line_len ) {
- ret->push_back( parse_line( line ) );
+ ret->push_back( parse_permission_line( line ) );
+ };
+
+ };
+
+ if ( line )
+ free( line );
+
+ return ret;
+
+}
+
+std::vector< override > * read_overrides( const char *file ) {
+
+ FILE *fh = fopen( file, "r" );
+ if ( not fh )
+ assert_perror( errno );
+
+ auto *ret = new std::vector< override >( );
+
+ char *line = 0;
+ size_t size = 0;
+
+ for ( ; getline( &line, &size, fh ) != -1; ) {
+
+ size_t line_len = strcspn( line, "\n" );
+ if ( line_len ) {
+ ret->push_back( parse_override_line( line ) );
};
};
@@ -184,6 +270,14 @@ std::vector< permission > * read_permissions( const char *file ) {
int main( int argc, char *argv[] ) {
+ DEBUG( "insecuresuexec is parsing the stored permissions...\n" );
+
+ auto allowed = read_permissions( "/etc/insecuresuexec/permissions" );
+
+ DEBUG( "insecuresuexec is parsing the stored overrides...\n" );
+
+ auto override = read_overrides( "/etc/insecuresuexec/overrides" );
+
if ( argc < 4 ) {
fprintf( stderr, "Usage: %s user group cmd [args..]\n", argv[0] );
return 1;
@@ -199,10 +293,33 @@ int main( int argc, char *argv[] ) {
uid_t uid;
gid_t gid;
- DEBUG( "insecuresuexec is parsing the command-line user and group...\n" );
+ DEBUG( "insecuresuexec is checking the overrides...\n" );
+
+ bool did_override = false;
+ for ( auto i = override->begin( ); i != override->end( ); ++i ) {
+ if ( i->match( cmd ) ) {
- uid = parse_user( user );
- gid = parse_group( group );
+ DEBUG( " cmd matched, now uid=%u gid=%u\n", i->uid, i->gid );
+
+ uid = i->uid;
+ gid = i->gid;
+
+ did_override = true;
+
+ break;
+ };
+ };
+
+ if ( ! did_override ) {
+
+ DEBUG( " no matching override found\n" );
+
+ DEBUG( "insecuresuexec is parsing the command-line user and group...\n" );
+
+ uid = parse_user( user );
+ gid = parse_group( group );
+
+ };
// literally the only hard-coded security check
if ( not uid || not gid ) {
@@ -210,10 +327,6 @@ int main( int argc, char *argv[] ) {
_exit( 1 );
};
- DEBUG( "insecuresuexec is parsing the stored permissions...\n" );
-
- auto allowed = read_permissions( "/etc/insecuresuexec/permissions" );
-
DEBUG( "insecuresuexec is running the configured security checks...\n" );
// the configurable security checks
diff --git a/overrides b/overrides
new file mode 100644
index 0000000..abf3d53
--- /dev/null
+++ b/overrides
@@ -0,0 +1 @@
+www-data:www-data .*/id
diff --git a/permissions b/permissions
new file mode 100644
index 0000000..b229b80
--- /dev/null
+++ b/permissions
@@ -0,0 +1 @@
+www-data:www-data