From aa07fea7db66bd0f4bd264655ab8c3f47bfebe12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Mon, 5 Apr 1999 15:07:59 -0700
Subject: [PATCH] more security stuff...

Rev: src/modules/files/efuns.c:1.68
Rev: src/modules/files/file.c:1.145
Rev: src/modules/system/system.c:1.64
Rev: src/security.c:1.13
Rev: src/security.h:1.5
Rev: src/signal_handler.c:1.121
---
 src/modules/files/efuns.c   | 29 ++++++++++++++--
 src/modules/files/file.c    |  6 ++--
 src/modules/system/system.c | 60 +++++++++++++++++++++++++++++++--
 src/security.c              |  2 --
 src/security.h              | 67 ++++++++++++++++++++++++++++++++++++-
 src/signal_handler.c        | 52 ++++++++++++++++++++++++++--
 6 files changed, 203 insertions(+), 13 deletions(-)

diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index 2a252705ac..7c9a14adda 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -19,11 +19,12 @@
 #include "backend.h"
 #include "operators.h"
 #include "builtin_functions.h"
+#include "security.h"
 
 #include "file_machine.h"
 #include "file.h"
 
-RCSID("$Id: efuns.c,v 1.67 1999/03/12 20:30:11 mast Exp $");
+RCSID("$Id: efuns.c,v 1.68 1999/04/05 22:07:38 hubbe Exp $");
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -103,7 +104,6 @@ struct array *encode_stat(struct stat *s)
   return a;
 }
 
-
 void f_file_stat(INT32 args)
 {
   struct stat st;
@@ -115,8 +115,12 @@ void f_file_stat(INT32 args)
   if(sp[-args].type != T_STRING)
     error("Bad argument 1 to file_stat()\n");
 
+  VALID_FILE_IO("file_stat","read");
+
   s = sp[-args].u.string->str;
   l = (args>1 && !IS_ZERO(sp+1-args))?1:0;
+
+
   THREADS_ALLOW_UID();
 #ifdef HAVE_LSTAT
   if(l)
@@ -148,6 +152,8 @@ void f_filesystem_stat( INT32 args )
   unsigned int free_sectors;
   unsigned int total_sectors;
 
+  VALID_FILE_IO("filesystem_stat","read");
+
   get_all_args( "filesystem_stat", args, "%s", &path );
 
   if(sp[-1].u.string->len < 2 || path[1] != ':')
@@ -381,6 +387,8 @@ void f_werror(INT32 args)
     args=1;
   }
 
+  VALID_FILE_IO("werror","werror");
+
   write_to_stderr(sp[-args].u.string->str, sp[-args].u.string->len);
   pop_n_elems(args);
 }
@@ -397,6 +405,8 @@ void f_rm(INT32 args)
   if(sp[-args].type != T_STRING)
     error("Bad argument 1 to rm().\n");
 
+  VALID_FILE_IO("rm","write");
+
   s = sp[-args].u.string->str;
   
   THREADS_ALLOW_UID();
@@ -441,6 +451,9 @@ void f_mkdir(INT32 args)
 
     mode = sp[1-args].u.integer;
   }
+
+  VALID_FILE_IO("mkdir","write");
+
   s=sp[-args].u.string->str;
 #if MKDIR_ARGS == 2
   THREADS_ALLOW_UID();
@@ -511,6 +524,8 @@ void f_get_dir(INT32 args)
   struct array *a=0;
   char *path;
 
+  VALID_FILE_IO("get_dir","read");
+
   get_all_args("get_dir",args,"%s",&path);
 
 #if defined(_REENTRANT) && defined(HAVE_READDIR_R)
@@ -687,6 +702,8 @@ void f_cd(INT32 args)
   if(sp[-args].type != T_STRING)
     error("Bad argument 1 to cd()\n");
 
+  VALID_FILE_IO("cd","status");
+
   i=chdir(sp[-args].u.string->str) != -1;
   pop_n_elems(args);
   push_int(i);
@@ -744,6 +761,12 @@ void f_exece(INT32 args)
   if(args < 2)
     error("Too few arguments to exece().\n");
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("exece: permission denied.\n");
+#endif
+
+
   e=0;
   en=0;
   switch(args)
@@ -847,6 +870,8 @@ void f_mv(INT32 args)
   if(sp[-args+1].type != T_STRING)
     error("Bad argument 2 to mv().\n");
 
+  VALID_FILE_IO("mv","write");
+
   i=rename((char *)sp[-args].u.string->str, 
 	   (char *)sp[-args+1].u.string->str);
 
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index 14c918f6a8..64a2888558 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: file.c,v 1.144 1999/04/02 02:07:40 hubbe Exp $");
+RCSID("$Id: file.c,v 1.145 1999/04/05 22:07:39 hubbe Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -1274,12 +1274,12 @@ static void file_open(INT32 args)
 	{
 	  case 0: /* return 0 */
 	    ERRNO=EPERM;
-	    pop_n_elems(args-1);
+	    pop_n_elems(args+1);
 	    push_int(0);
 	    return;
 	    
 	  case 1: /* return 1 */
-	    pop_n_elems(args-1);
+	    pop_n_elems(args+1);
 	    push_int(1);
 	    return;
 	    
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index d47e0e889b..9522ca4ab3 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -1,5 +1,5 @@
 /*
- * $Id: system.c,v 1.63 1999/03/12 17:49:51 mast Exp $
+ * $Id: system.c,v 1.64 1999/04/05 22:07:59 hubbe Exp $
  *
  * System-call module for Pike
  *
@@ -15,7 +15,7 @@
 #include "system_machine.h"
 #include "system.h"
 
-RCSID("$Id: system.c,v 1.63 1999/03/12 17:49:51 mast Exp $");
+RCSID("$Id: system.c,v 1.64 1999/04/05 22:07:59 hubbe Exp $");
 #ifdef HAVE_WINSOCK_H
 #include <winsock.h>
 #endif
@@ -34,6 +34,7 @@ RCSID("$Id: system.c,v 1.63 1999/03/12 17:49:51 mast Exp $");
 #include "builtin_functions.h"
 #include "constants.h"
 #include "pike_memory.h"
+#include "security.h"
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -189,6 +190,8 @@ void f_hardlink(INT32 args)
   char *to;
   int err;
 
+  VALID_FILE_IO("hardlink","write");
+
   get_all_args("hardlink",args, "%s%s", &from, &to);
 
   THREADS_ALLOW_UID();
@@ -212,6 +215,8 @@ void f_symlink(INT32 args)
   char *to;
   int err;
 
+  VALID_FILE_IO("symlink","write");
+
   get_all_args("symlink",args, "%s%s", &from, &to);
 
   THREADS_ALLOW_UID();
@@ -236,6 +241,8 @@ void f_readlink(INT32 args)
   char *buf;
   int err;
 
+  VALID_FILE_IO("readlink","read");
+
   get_all_args("readlink",args, "%s", &path);
 
   buflen = 100;
@@ -282,6 +289,8 @@ void f_resolvepath(INT32 args)
   char *buf;
   int err;
 
+  VALID_FILE_IO("resolvepath","read");
+
   get_all_args("resolvepath", args, "%s", &path);
 
   buflen = 100;
@@ -316,6 +325,8 @@ void f_umask(INT32 args)
 {
   int oldmask;
 
+  VALID_FILE_IO("umask","status");
+
   if (args) {
     int setmask;
     get_all_args("umask", args, "%d", &setmask);
@@ -337,6 +348,8 @@ void f_chmod(INT32 args)
   int mode;
   int err;
 
+  VALID_FILE_IO("chmod","write");
+
   get_all_args("chmod", args, "%s%i", &path, &mode);
   THREADS_ALLOW_UID();
   do {
@@ -357,6 +370,8 @@ void f_chown(INT32 args)
   int gid;
   int err;
 
+  VALID_FILE_IO("chown","write");
+
   get_all_args("chown", args, "%s%i%i", &path, &uid, &gid);
   THREADS_ALLOW_UID();
   do {
@@ -377,6 +392,13 @@ void f_initgroups(INT32 args)
   char *user;
   int err;
   INT32 group;
+
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("initgroups: permission denied.\n");
+#endif
+  
+  VALID_FILE_IO("initgroups","status");
   get_all_args("initgroups", args, "%s%i", &user, &group);
   err = initgroups(user, group);
   if (err < 0) {
@@ -392,6 +414,12 @@ void f_cleargroups(INT32 args)
 {
   static gid_t gids[1] = { 65534 };	/* To safeguard against stupid OS's */
   int err;
+
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("cleargroups: permission denied.\n");
+#endif
+
   pop_n_elems(args);
   err = setgroups(0, gids);
   if (err < 0) {
@@ -410,6 +438,11 @@ void f_setgroups(INT32 args)
   INT32 size;
   int err;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("setgroups: permission denied.\n");
+#endif
+
   get_all_args("setgroups", args, "%a", &arr);
   if ((size = arr->size)) {
     gids = (gid_t *)xalloc(arr->size * sizeof(gid_t));
@@ -477,6 +510,11 @@ void f_setuid(INT32 args)
 {
   INT32 id;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("setuid: permission denied.\n");
+#endif
+
   get_all_args("setuid", args, "%i", &id);
  
   if(id == -1) {
@@ -497,6 +535,10 @@ void f_setgid(INT32 args)
 {
   int id;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("setgid: permission denied.\n");
+#endif
   get_all_args("setgid", args, "%i", &id);
  
   if(id == -1) {
@@ -519,6 +561,10 @@ void f_seteuid(INT32 args)
   int id;
   int err;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("seteuid: permission denied.\n");
+#endif
   get_all_args("seteuid", args, "%i", &id);
  
   if(id == -1) {
@@ -546,6 +592,11 @@ void f_setegid(INT32 args)
   int id;
   int err;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("setegid: permission denied.\n");
+#endif
+
   get_all_args("setegid", args, "%i", &id);
 
   if(id == -1)
@@ -624,6 +675,11 @@ void f_chroot(INT32 args)
 {
   int res;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("chroot: permission denied.\n");
+#endif
+
 #ifdef HAVE_FCHROOT
   check_all_args("chroot", args, BIT_STRING|BIT_OBJECT, 0);
 #else
diff --git a/src/security.c b/src/security.c
index b53ab15224..10ca304aa2 100644
--- a/src/security.c
+++ b/src/security.c
@@ -2,8 +2,6 @@
 
 /* To do:
  * controls for file->pipe()
- * controls for kill/create_process/signal
- * controls for all/most functions in the system module
  * controls for all/most functions in spider
  * controls for threads
  */
diff --git a/src/security.h b/src/security.h
index 26415fccdf..fbf693ff58 100644
--- a/src/security.h
+++ b/src/security.h
@@ -59,11 +59,74 @@ struct pike_creds
 
 #define FREE_PROT(X) do { if((X)->prot) free_object((X)->prot); (X)->prot=0; }while(0)
 
+#define VALID_FILE_IO(name, access_type)				\
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))				\
+  {									\
+    int e;								\
+    struct svalue *base_sp=sp-args;					\
+									\
+    if(!CHECK_SECURITY(SECURITY_BIT_CONDITIONAL_IO))			\
+      error(name ": Permission denied.\n");				\
+									\
+    push_constant_text(name);						\
+    push_constant_text(access_type);					\
+									\
+    for(e=0;e<args;e++) push_svalue(base_sp+e);				\
+									\
+    safe_apply(OBJ2CREDS(current_creds)->user,"valid_io",args+2);	\
+									\
+    switch(sp[-1].type)							\
+    {									\
+      case T_ARRAY:							\
+      case T_OBJECT:							\
+      case T_MAPPING:							\
+	assign_svalue(sp-args-1,sp-1);					\
+	pop_n_elems(args);						\
+	return;								\
+									\
+      case T_INT:							\
+	switch(sp[-1].u.integer)					\
+	{								\
+	  case 0: /* return 0 */					\
+	    errno=EPERM;						\
+	    pop_n_elems(args+1);					\
+	    push_int(0);						\
+	    return;							\
+									\
+	  case 1: /* return 1 */					\
+	    pop_n_elems(args+1);					\
+	    push_int(1);						\
+	    return;							\
+	    								\
+	  case 2: /* ok */						\
+	    pop_stack();						\
+	    break;							\
+	    								\
+	  case 3: /* permission denied */				\
+	    error(name ": permission denied.\n");			\
+	    								\
+	  default:							\
+	    error("Error in user->valid_io, wrong return value.\n");	\
+	}								\
+	break;								\
+									\
+      default:								\
+	error("Error in user->valid_io, wrong return type.\n");		\
+									\
+      case T_STRING:							\
+	assign_svalue(sp-args-1,sp-1);					\
+        pop_stack();							\
+    }									\
+  }
+
+
 extern struct object *current_creds;
 /* Prototypes begin here */
 void init_pike_security(void);
 /* Prototypes end here */
-   
+
+
+
 #else
 
 #define INITIALIZE_PROT(X)
@@ -73,6 +136,8 @@ void init_pike_security(void);
 
 #define init_pike_security()
 
+#define VALID_FILE_IO(name, type)
+
 #endif
 
 #endif
diff --git a/src/signal_handler.c b/src/signal_handler.c
index 5d986d3118..136cbb9036 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.c
@@ -21,9 +21,10 @@
 #include "module_support.h"
 #include "operators.h"
 #include "builtin_functions.h"
+#include "security.h"
 #include <signal.h>
 
-RCSID("$Id: signal_handler.c,v 1.120 1999/04/02 20:52:48 hubbe Exp $");
+RCSID("$Id: signal_handler.c,v 1.121 1999/04/05 22:07:12 hubbe Exp $");
 
 #ifdef HAVE_PASSWD_H
 # include <passwd.h>
@@ -508,6 +509,11 @@ static void f_signal(int args)
   int signum;
   sigfunctype func;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("signal: permission denied.\n");
+#endif
+
   check_signals(0,0,0);
 
   if(args < 1)
@@ -1029,6 +1035,10 @@ static void f_pid_status_set_priority(INT32 args)
 {
   char *to;
   int r;
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("pid_status_wait: permission denied.\n");
+#endif
   get_all_args("set_priority", args, "%s", &to);
   r = set_priority( THIS->pid, to );
   pop_n_elems(args);
@@ -1387,6 +1397,10 @@ void f_set_priority( INT32 args )
 {
   int pid;
   char *plevel;
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("set_priority: permission denied.\n");
+#endif
   if(args == 1)
   {
     pid = 0;
@@ -1528,6 +1542,11 @@ void f_create_process(INT32 args)
   struct svalue *tmp;
   int e;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("Process.create_process: permission denied.\n");
+#endif
+
   check_all_args("create_process",args, BIT_ARRAY, BIT_MAPPING | BIT_VOID, 0);
 
   switch(args)
@@ -2120,11 +2139,14 @@ void f_create_process(INT32 args)
     storage.disabled = 1;
 #endif
 
+    do
+    {
 #if defined(HAVE_FORK1) && defined(_REENTRANT)
-    pid=fork1();
+      pid=fork1();
 #else
-    pid=fork();
+      pid=fork();
 #endif
+    }while(pid == -1 && (errno==EAGAIN || errno==EINTR));
 
     UNSET_ONERROR(err);
 
@@ -2457,6 +2479,10 @@ void f_fork(INT32 args)
   if(num_threads >1)
     error("You cannot use fork in a multithreaded application.\n");
 #endif
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("fork: permission denied.\n");
+#endif
 
 /*   THREADS_ALLOW_UID(); */
 #if 0 && defined(HAVE_FORK1) && defined(_REENTRANT)
@@ -2518,6 +2544,11 @@ static void f_kill(INT32 args)
   int pid;
   int res;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("kill: permission denied.\n");
+#endif
+
   if(args < 2)
     error("Too few arguments to kill().\n");
 
@@ -2553,6 +2584,11 @@ void f_kill(INT32 args)
 {
   HANDLE proc=INVALID_HANDLE_VALUE;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("kill: permission denied.\n");
+#endif
+
   if(args < 2)
     error("Too few arguments to kill().\n");
 
@@ -2625,6 +2661,11 @@ static void f_alarm(INT32 args)
 {
   long seconds;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("alarm: permission denied.\n");
+#endif
+
   if(args < 1)
     error("Too few arguments to signame()\n");
 
@@ -2646,6 +2687,11 @@ static void f_ualarm(INT32 args)
 #endif /* !HAVE_UALARM */
   long useconds;
 
+#ifdef PIKE_SECURITY
+  if(!CHECK_SECURITY(SECURITY_BIT_SECURITY))
+    error("ualarm: permission denied.\n");
+#endif
+
   if(args < 1)
     error("Too few arguments to ualarm()\n");
 
-- 
GitLab