acl_main.c

Go to the documentation of this file.
00001 /**************************************************** */
00002 /* Rule Set Based Access Control                      */
00003 /* Implementation of the Access Control Decision      */
00004 /* Facility (ADF) - Access Control Lists (ACL)        */
00005 /* File: rsbac/adf/acl/acl_main.c                     */
00006 /*                                                    */
00007 /* Author and (c) 1999-2005: Amon Ott <ao@rsbac.org>  */
00008 /*                                                    */
00009 /* Last modified: 09/Feb/2005                         */
00010 /**************************************************** */
00011 
00012 #include <linux/string.h>
00013 #include <linux/vmalloc.h>
00014 #include <rsbac/aci.h>
00015 #include <rsbac/acl.h>
00016 #include <rsbac/adf_main.h>
00017 #include <rsbac/adf_syshelpers.h>
00018 #include <rsbac/error.h>
00019 #include <rsbac/helpers.h>
00020 #include <rsbac/getname.h>
00021 #include <rsbac/rkmem.h>
00022 #include <rsbac/debug.h>
00023 
00024 /************************************************* */
00025 /*           Global Variables                      */
00026 /************************************************* */
00027 
00028 /************************************************* */
00029 /*          Internal Help functions                */
00030 /************************************************* */
00031 
00032 /* in acl_syscalls.c */
00033 rsbac_boolean_t rsbac_acl_check_super(enum  rsbac_target_t target,
00034                               union rsbac_target_id_t tid,
00035                                     rsbac_uid_t user);
00036 
00037 rsbac_boolean_t rsbac_acl_check_right(enum  rsbac_target_t target,
00038                               union rsbac_target_id_t tid,
00039                                     rsbac_uid_t user,
00040                                     rsbac_pid_t caller_pid,
00041                               enum  rsbac_adf_request_t request)
00042   {
00043     rsbac_boolean_t                   result = FALSE;
00044     int                       err=0, tmperr;
00045     int                       i;
00046     rsbac_acl_group_id_t    * group_p;
00047     #if defined(CONFIG_RSBAC_RC)
00048     union rsbac_target_id_t       i_tid;
00049     union rsbac_attribute_value_t i_attr_val1;
00050     #endif
00051 
00052     /* Only check implemented targets */
00053     switch(target)
00054       {
00055         case T_FILE:
00056         case T_DIR:
00057         case T_FIFO:
00058         case T_SYMLINK:
00059         case T_DEV:
00060         case T_IPC:
00061         case T_SCD:
00062         case T_USER:
00063         case T_PROCESS:
00064 #ifdef CONFIG_RSBAC_ACL_UM_PROT
00065         case T_GROUP:
00066 #endif
00067 #ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
00068         case T_NETDEV:
00069 #endif
00070 #ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
00071         case T_NETTEMP_NT:
00072         case T_NETTEMP:
00073         case T_NETOBJ:
00074 #endif
00075           break;
00076         default:
00077           return TRUE;
00078       }
00079     /* inherited own rights */
00080     err = rsbac_acl_get_single_right(target,
00081                                      tid,
00082                                      ACLS_USER,
00083                                      (rsbac_acl_subject_id_t) user,
00084                                      request,
00085                                      &result);
00086     if(err)
00087       {
00088         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00089 
00090         if(tmp)
00091           {
00092 #ifdef CONFIG_RSBAC_RMSG
00093             rsbac_printk(KERN_WARNING
00094                    "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00095                    get_error_name(tmp,err));
00096 #endif
00097 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00098             if (!rsbac_nosyslog)
00099 #endif
00100             printk(KERN_WARNING
00101                    "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00102                    get_error_name(tmp,err));
00103             rsbac_kfree(tmp);
00104           }
00105         return FALSE;
00106       }
00107     if(result)
00108       return(TRUE);
00109 
00110     /* add group and role rights */
00111     /* group everyone */
00112     err = rsbac_acl_get_single_right(target,
00113                                      tid,
00114                                      ACLS_GROUP,
00115                                      RSBAC_ACL_GROUP_EVERYONE,
00116                                      request,
00117                                      &result);
00118     if(err)
00119       {
00120         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00121 
00122         if(tmp)
00123           {
00124 #ifdef CONFIG_RSBAC_RMSG
00125             rsbac_printk(KERN_WARNING
00126                    "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00127                    get_error_name(tmp,err));
00128 #endif
00129 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00130             if (!rsbac_nosyslog)
00131 #endif
00132             printk(KERN_WARNING
00133                    "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00134                    get_error_name(tmp,err));
00135             rsbac_kfree(tmp);
00136           }
00137         return FALSE;
00138       }
00139     if(result)
00140       return(TRUE);
00141 
00142     #if defined(CONFIG_RSBAC_RC)
00143     /* use process role */
00144     /* first get role */
00145     i_tid.process = caller_pid;
00146     if (rsbac_get_attr(RC,
00147                        T_PROCESS,
00148                        i_tid,
00149                        A_rc_role,
00150                        &i_attr_val1,
00151                        FALSE))
00152       {
00153 #ifdef CONFIG_RSBAC_RMSG
00154         rsbac_printk(KERN_WARNING
00155                "rsbac_acl_check_right(): rsbac_get_attr() for process rc_role returned error!\n");
00156 #endif
00157 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00158         if (!rsbac_nosyslog)
00159 #endif
00160         printk(KERN_WARNING
00161                "rsbac_acl_check_right(): rsbac_get_attr() for process rc_role returned error!\n");
00162       }
00163     else
00164       {
00165         err = rsbac_acl_get_single_right(target,
00166                                          tid,
00167                                          ACLS_ROLE,
00168                                          i_attr_val1.rc_role,
00169                                          request,
00170                                          &result);
00171         if(err)
00172           {
00173             char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00174 
00175             if(tmp)
00176               {
00177                 get_error_name(tmp,err);
00178 #ifdef CONFIG_RSBAC_RMSG
00179                 rsbac_printk(KERN_WARNING
00180                        "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00181                        tmp);
00182 #endif
00183 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00184                 if (!rsbac_nosyslog)
00185 #endif
00186                 printk(KERN_WARNING
00187                        "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00188                        tmp);
00189                 rsbac_kfree(tmp);
00190               }
00191             return FALSE;
00192           }
00193         if(result)
00194           return(TRUE);
00195       }
00196     #endif
00197 
00198     /* other groups */
00199     /* first get user groups */
00200     group_p = NULL;
00201     err = rsbac_acl_get_user_groups(0, user, &group_p, NULL);
00202     if(err<0)
00203       {
00204         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00205 
00206         if(tmp)
00207           {
00208 #ifdef CONFIG_RSBAC_RMSG
00209             rsbac_printk(KERN_WARNING
00210                    "rsbac_acl_check_right(): rsbac_acl_get_user_groups() returned error %s!\n",
00211                    get_error_name(tmp,err));
00212 #endif
00213 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00214             if (!rsbac_nosyslog)
00215 #endif
00216             printk(KERN_WARNING
00217                    "rsbac_acl_check_right(): rsbac_acl_get_user_groups() returned error %s!\n",
00218                    get_error_name(tmp,err));
00219             rsbac_kfree(tmp);
00220           }
00221         return err;
00222       }
00223     for(i=0; i<err; i++)
00224       {
00225         tmperr = rsbac_acl_get_single_right(target,
00226                                             tid,
00227                                             ACLS_GROUP,
00228                                             group_p[i],
00229                                             request,
00230                                             &result);
00231         if(tmperr)
00232           {
00233             char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00234 
00235             if(tmp)
00236               {
00237 #ifdef CONFIG_RSBAC_RMSG
00238                 rsbac_printk(KERN_WARNING
00239                        "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00240                        get_error_name(tmp, tmperr));
00241 #endif
00242 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00243                 if (!rsbac_nosyslog)
00244 #endif
00245                 printk(KERN_WARNING
00246                        "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00247                        get_error_name(tmp, tmperr));
00248                 rsbac_kfree(tmp);
00249               }
00250             if(group_p)
00251               rsbac_vfree(group_p);
00252             return FALSE;
00253           }
00254         if(result)
00255           {
00256             if(group_p)
00257               rsbac_vfree(group_p);
00258             return(TRUE);
00259           }
00260       }
00261     if(group_p)
00262       rsbac_vfree(group_p);
00263 
00264     /* SUPERVISOR? */
00265 #ifdef CONFIG_RSBAC_ACL_LEARN
00266     result = rsbac_acl_check_super(target, tid, user);
00267     if(   !result
00268        && (request < R_NONE)
00269       )
00270       {
00271         switch(target)
00272           {
00273             case T_FILE:
00274             case T_DIR:
00275             case T_FIFO:
00276             case T_SYMLINK:
00277               if(rsbac_acl_learn_fd)
00278                 {
00279                   char * tmp;
00280                   enum rsbac_acl_subject_type_t  subj_type;
00281                        rsbac_acl_subject_id_t    subj_id;
00282                        rsbac_acl_rights_vector_t rights;
00283                        rsbac_time_t              ttl;
00284 
00285                   tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00286                   if(tmp)
00287                     {
00288                       char * target_type_name;
00289 
00290                       target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00291                       if(target_type_name)
00292                         {
00293                           char * target_id_name;
00294 
00295                           #ifdef CONFIG_RSBAC_LOG_FULL_PATH
00296                           target_id_name
00297                            = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
00298                           /* max. path name len + some extra */
00299                           #else
00300                           target_id_name = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
00301                           /* max. file name len + some extra */
00302                           #endif
00303                           if(target_id_name)
00304                             {
00305                               get_request_name(tmp,request);
00306                               get_target_name(target_type_name, target, target_id_name, tid);
00307 #ifdef CONFIG_RSBAC_RMSG
00308                               rsbac_printk(KERN_INFO
00309                                            "rsbac_acl_check_right(): auto_learn_fd: granting right %s for user %u to target_type %s, tid %s!\n",
00310                                            tmp,
00311                                            user,
00312                                            target_type_name,
00313                                            target_id_name);
00314 #endif
00315 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00316                               if (!rsbac_nosyslog)
00317 #endif
00318                               printk(KERN_INFO
00319                                      "rsbac_acl_check_right(): auto_learn_fd: granting right %s for user %u to target_type %s, tid %s!\n",
00320                                      tmp,
00321                                      user,
00322                                      target_type_name,
00323                                      target_id_name);
00324                               rsbac_kfree(target_id_name);
00325                             }
00326                           rsbac_kfree(target_type_name);
00327                         }
00328                     }
00329                   subj_type = ACLS_USER;
00330                   subj_id = user;
00331                   rights = RSBAC_REQUEST_VECTOR(request);
00332                   ttl = 0;
00333                   err = rsbac_acl_add_to_acl_entry(0, target, tid, subj_type, subj_id, rights, ttl);
00334                   if(tmp)
00335                     {
00336                       if(err)
00337                         {
00338 #ifdef CONFIG_RSBAC_RMSG
00339                           rsbac_printk(KERN_WARNING
00340                                        "rsbac_acl_check_right(): rsbac_acl_add_to_acl_entry() returned error %s!\n",
00341                                        get_error_name(tmp,err));
00342 #endif
00343 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00344                           if (!rsbac_nosyslog)
00345 #endif
00346                           printk(KERN_WARNING
00347                                  "rsbac_acl_check_right(): rsbac_acl_add_to_acl_entry() returned error %s!\n",
00348                                  get_error_name(tmp,err));
00349                         }
00350                       rsbac_kfree(tmp);
00351                     }
00352                   result = TRUE;
00353                 }
00354               break;
00355 
00356             default:
00357               break;
00358           }
00359       }
00360     return result;
00361 #else
00362     return rsbac_acl_check_super(target, tid, user);
00363 #endif
00364   }
00365 
00366 rsbac_boolean_t rsbac_acl_check_forward(enum  rsbac_target_t target,
00367                                 union rsbac_target_id_t tid,
00368                                       rsbac_uid_t user,
00369                                       rsbac_acl_rights_vector_t rights)
00370   {
00371     rsbac_acl_rights_vector_t i_rights = 0;
00372     rsbac_acl_rights_vector_t i_rvec = ((rsbac_acl_rights_vector_t) 1 << ACLR_FORWARD) | rights;
00373     int                       err=0;
00374 
00375 
00376     /* Only check implemented targets */
00377     switch(target)
00378       {
00379         case T_FILE:
00380         case T_DIR:
00381         case T_FIFO:
00382         case T_SYMLINK:
00383         case T_DEV:
00384         case T_IPC:
00385         case T_SCD:
00386         case T_USER:
00387         case T_PROCESS:
00388 #ifdef CONFIG_RSBAC_ACL_UM_PROT
00389         case T_GROUP:
00390 #endif
00391 #ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
00392         case T_NETDEV:
00393 #endif
00394 #ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
00395         case T_NETTEMP_NT:
00396         case T_NETTEMP:
00397         case T_NETOBJ:
00398 #endif
00399           break;
00400         default:
00401           return TRUE;
00402       }
00403     /* get effective rights */
00404     err = rsbac_acl_sys_get_rights(0, target, tid, ACLS_USER, (rsbac_acl_subject_id_t) user, &i_rights, TRUE);
00405     if(err)
00406       {
00407         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00408 
00409         if(tmp)
00410           {
00411 #ifdef CONFIG_RSBAC_RMSG
00412             rsbac_printk(KERN_WARNING
00413                    "rsbac_acl_check_forward(): rsbac_acl_sys_get_rights() returned error %s!\n",
00414                    get_error_name(tmp,err));
00415 #endif
00416 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00417             if (!rsbac_nosyslog)
00418 #endif
00419             printk(KERN_WARNING
00420                    "rsbac_acl_check_forward(): rsbac_acl_sys_get_rights() returned error %s!\n",
00421                    get_error_name(tmp,err));
00422             rsbac_kfree(tmp);
00423           }
00424         return FALSE;
00425       }
00426     if((i_rights & i_rvec) == i_rvec)
00427       return(TRUE);
00428     else
00429       return(FALSE);
00430   }
00431 
00432 /************************************************* */
00433 /*          Externally visible functions           */
00434 /************************************************* */
00435 
00436 enum rsbac_adf_req_ret_t
00437    rsbac_adf_request_acl (enum  rsbac_adf_request_t     request,
00438                                 rsbac_pid_t             caller_pid,
00439                           enum  rsbac_target_t          target,
00440                           union rsbac_target_id_t       tid,
00441                           enum  rsbac_attribute_t       attr,
00442                           union rsbac_attribute_value_t attr_val,
00443                                 rsbac_uid_t             owner)
00444   {
00445     switch (request)
00446       {
00447         case R_READ_ATTRIBUTE:
00448         case R_MODIFY_ATTRIBUTE:
00449             switch(attr)
00450               { /* owner must be changed by other request to prevent inconsistency */
00451                 case A_owner:
00452                   if(request == R_READ_ATTRIBUTE)
00453                     return(GRANTED);
00454                   else
00455                     return(NOT_GRANTED);
00456 
00457                 /* Only protect AUTH, if asked to by configuration */
00458                 #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
00459                 case A_auth_may_setuid:
00460                 case A_auth_may_set_cap:
00461                 case A_auth_start_uid:
00462                 case A_auth_learn:
00463                 case A_auth_program_file:
00464                 case A_auth_add_f_cap:
00465                 case A_auth_remove_f_cap:
00466                   tid.scd = AST_auth_administration;
00467                   if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
00468                     return(GRANTED);
00469                   else
00470                     return(NOT_GRANTED);
00471                 #endif
00472 
00473                 #ifdef CONFIG_RSBAC_ACL_GEN_PROT
00474                 case A_pseudo:
00475                 case A_log_array_low:
00476                 case A_log_array_high:
00477                 case A_log_program_based:
00478                 case A_log_user_based:
00479                 case A_symlink_add_uid:
00480                 case A_symlink_add_rc_role:
00481                 case A_linux_dac_disable:
00482                 case A_fake_root_uid:
00483                 case A_audit_uid:
00484                 case A_auid_exempt:
00485                   if (!rsbac_acl_check_right(target, tid, owner, caller_pid, request))
00486                     return(NOT_GRANTED);
00487                   else
00488                     return(GRANTED);
00489                 #endif
00490 
00491                 #ifdef CONFIG_RSBAC_ACL_LEARN
00492                 case A_acl_learn:
00493                   /* check supervisor on target */
00494                   if(rsbac_acl_check_super(target,
00495                                            tid,
00496                                            owner))
00497                     return(GRANTED);
00498                   else
00499                     return(NOT_GRANTED);
00500                 #endif
00501 
00502                 /* All attributes (remove target!) */
00503                 case A_none:
00504                   if (!rsbac_acl_check_right(target, tid, owner, caller_pid, request))
00505                     return(NOT_GRANTED);
00506                   #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
00507                   tid.scd = AST_auth_administration;
00508                   if (!rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
00509                     return(NOT_GRANTED);
00510                   #endif
00511                   return(GRANTED);
00512 
00513                 default:
00514                   return(DO_NOT_CARE);
00515               }
00516 
00517         case R_SWITCH_MODULE:
00518             switch(target)
00519               {
00520                 case T_NONE:
00521                     if(   (attr_val.switch_target != ACL)
00522                        #ifdef CONFIG_RSBAC_SOFTMODE
00523                        && (attr_val.switch_target != SOFTMODE)
00524                        #endif
00525                        #ifdef CONFIG_RSBAC_FREEZE
00526                        && (attr_val.switch_target != FREEZE)
00527                        #endif
00528                        #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
00529                        && (attr_val.switch_target != AUTH)
00530                        #endif
00531                       )
00532                       return(DO_NOT_CARE);
00533 
00534                     tid.scd = ST_other;
00535                     if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
00536                       return(GRANTED);
00537                     else
00538                       return(NOT_GRANTED);
00539 
00540                 /* all other cases are unknown */
00541                 default:
00542                   return(DO_NOT_CARE);
00543               }
00544 
00545 /*********************/
00546         default:
00547           if(target == T_NONE)
00548             {
00549               target = T_SCD;
00550               tid.scd = ST_other;
00551             }
00552           if (rsbac_acl_check_right(target, tid, owner, caller_pid, request))
00553             return(GRANTED);
00554           else
00555             return(NOT_GRANTED);
00556       }
00557   }; /* end of rsbac_adf_request_acl() */
00558 
00559 
00560 /*****************************************************************************/
00561 /* If the request returned granted and the operation is performed,           */
00562 /* the following function can be called by the AEF to get all aci set        */
00563 /* correctly. For write accesses that are performed fully within the kernel, */
00564 /* this is usually not done to prevent extra calls, including R_CLOSE for    */
00565 /* cleaning up.                                                              */
00566 /* The second instance of target specification is the new target, if one has */
00567 /* been created, otherwise its values are ignored.                           */
00568 /* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
00569 
00570 inline int  rsbac_adf_set_attr_acl(
00571                       enum  rsbac_adf_request_t     request,
00572                             rsbac_pid_t             caller_pid,
00573                       enum  rsbac_target_t          target,
00574                       union rsbac_target_id_t       tid,
00575                       enum  rsbac_target_t          new_target,
00576                       union rsbac_target_id_t       new_tid,
00577                       enum  rsbac_attribute_t       attr,
00578                       union rsbac_attribute_value_t attr_val,
00579                             rsbac_uid_t             owner)
00580   {
00581     /* Nothing to be done here */
00582     return(0);
00583   }; /* end of rsbac_adf_set_attr_acl() */
00584 
00585 /* end of rsbac/adf/acl/main.c */

Generated on Fri Jun 17 09:45:18 2005 for RSBAC by  doxygen 1.4.2