405e412004-04-06Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */ #ifndef SECURITY_H #define SECURITY_H
6df8332013-06-13Martin Nilsson #include "global.h"
405e412004-04-06Martin Nilsson #ifdef PIKE_SECURITY #include "object.h" #define SECURITY_BIT_INDEX 1 /* index read-only */ #define SECURITY_BIT_SET_INDEX 2 /* set index */ #define SECURITY_BIT_CALL 4 /* call functions (and clone?) */ #define SECURITY_BIT_SECURITY 8 /* Do anything :) */ #define SECURITY_BIT_NOT_SETUID 16 #define SECURITY_BIT_CONDITIONAL_IO 32 #define SECURITY_BIT_DESTRUCT 64 typedef unsigned char pike_security_bits; struct pike_creds { struct object *user; struct object *default_creds; pike_security_bits data_bits; pike_security_bits may_always; }; #define CHECK_VALID_CREDS(X) (X) #define CHECK_VALID_UID(X) (X) #define OBJ2CREDS(O) ((struct pike_creds *)(CHECK_VALID_CREDS(O)->storage)) #define CURRENT_CREDS \ (Pike_interpreter.frame_pointer ? Pike_interpreter.frame_pointer->current_creds : Pike_interpreter.current_creds) /* Do we need a 'may never' ? */ #define CHECK_SECURITY(BIT) \ (!CURRENT_CREDS || (OBJ2CREDS(CURRENT_CREDS)->may_always & (BIT))) #define CHECK_DATA_SECURITY(DATA,BIT) (\ CHECK_SECURITY(BIT) || \
b643222004-06-30Martin Nilsson  ( (DATA)->prot && ( (OBJ2CREDS((DATA)->prot)->data_bits & (BIT)) || \ (OBJ2CREDS((DATA)->prot)->user == OBJ2CREDS(CURRENT_CREDS)->user))) )
405e412004-04-06Martin Nilsson  #define CHECK_DATA_SECURITY_OR_ERROR(DATA,BIT,ERR) do { \
b643222004-06-30Martin Nilsson  if(!CHECK_DATA_SECURITY(DATA,BIT)) \
405e412004-04-06Martin Nilsson  Pike_error ERR; \ }while(0)
b643222004-06-30Martin Nilsson #define CHECK_SECURITY_OR_ERROR(BIT,ERR) do { \ if(!CHECK_SECURITY(BIT)) \ Pike_error ERR; \
405e412004-04-06Martin Nilsson  }while(0) #define ASSERT_SECURITY_ROOT(FUNC) CHECK_SECURITY_OR_ERROR( \ SECURITY_BIT_SECURITY, (FUNC ": permission denied.\n")) #define SET_CURRENT_CREDS(O) do { struct object *_o=(O); \ if(Pike_interpreter.frame_pointer) \ { \ if(Pike_interpreter.frame_pointer->current_creds) \ free_object(Pike_interpreter.frame_pointer->current_creds); \ Pike_interpreter.frame_pointer->current_creds = CHECK_VALID_UID(_o); \ }else{ \ if(Pike_interpreter.current_creds) \ free_object(Pike_interpreter.current_creds); \ Pike_interpreter.current_creds = CHECK_VALID_UID(_o); \ } \ if (_o) \ add_ref(_o); \ }while(0) #define INITIALIZE_PROT(X) \ do { if(CURRENT_CREDS) add_ref((X)->prot=CHECK_VALID_CREDS(OBJ2CREDS(CURRENT_CREDS)->default_creds?OBJ2CREDS(CURRENT_CREDS)->default_creds:CURRENT_CREDS)); else (X)->prot=0; }while(0) #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=Pike_sp-args; \ \ if(!CHECK_SECURITY(SECURITY_BIT_CONDITIONAL_IO)) \ Pike_error(name ": Permission denied.\n"); \ \
7cf0162014-05-22Per Hedbor  push_text(name); \ push_text(access_type); \
405e412004-04-06Martin Nilsson  \ for(e=0;e<args;e++) push_svalue(base_sp+e); \ \ safe_apply(OBJ2CREDS(CURRENT_CREDS)->user,"valid_io",args+2); \ \
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(Pike_sp[-1])) \
405e412004-04-06Martin Nilsson  { \ case PIKE_T_ARRAY: \ case PIKE_T_OBJECT: \ case PIKE_T_MAPPING: \ assign_svalue(Pike_sp-args-1,Pike_sp-1); \ pop_n_elems(args); \ return; \ \ case PIKE_T_INT: \ switch(Pike_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 */ \ Pike_error(name ": permission denied.\n"); \ \ default: \ Pike_error("Error in user->valid_io, wrong return value.\n"); \ } \ break; \ \ case PIKE_T_STRING: \ assign_svalue(Pike_sp-args-1,Pike_sp-1); \ pop_stack(); \ break; \ \ default: \ Pike_error("Error in user->valid_io, wrong return type.\n"); \ break; \ } \ } /* Prototypes begin here */ void init_pike_security(void); void exit_pike_security(void); /* Prototypes end here */ #else #define INITIALIZE_PROT(X) #define FREE_PROT(X) #define CHECK_SECURITY_OR_ERROR(BIT,ERR) #define ASSERT_SECURITY_ROOT(FUNC) #define CHECK_DATA_SECURITY_OR_ERROR(DATA,BIT,ERR) #define init_pike_security() #define exit_pike_security() #define VALID_FILE_IO(name, type) #endif #endif