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/Jun/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             rsbac_printk(KERN_WARNING
00093                    "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00094                    get_error_name(tmp,err));
00095             rsbac_kfree(tmp);
00096           }
00097         return FALSE;
00098       }
00099     if(result)
00100       return(TRUE);
00101 
00102     /* add group and role rights */
00103     /* group everyone */
00104     err = rsbac_acl_get_single_right(target,
00105                                      tid,
00106                                      ACLS_GROUP,
00107                                      RSBAC_ACL_GROUP_EVERYONE,
00108                                      request,
00109                                      &result);
00110     if(err)
00111       {
00112         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00113 
00114         if(tmp)
00115           {
00116             rsbac_printk(KERN_WARNING
00117                    "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00118                    get_error_name(tmp,err));
00119             rsbac_kfree(tmp);
00120           }
00121         return FALSE;
00122       }
00123     if(result)
00124       return(TRUE);
00125 
00126     #if defined(CONFIG_RSBAC_RC)
00127     /* use process role */
00128     /* first get role */
00129     i_tid.process = caller_pid;
00130     if (rsbac_get_attr(RC,
00131                        T_PROCESS,
00132                        i_tid,
00133                        A_rc_role,
00134                        &i_attr_val1,
00135                        FALSE))
00136       {
00137         rsbac_printk(KERN_WARNING
00138                "rsbac_acl_check_right(): rsbac_get_attr() for process rc_role returned error!\n");
00139       }
00140     else
00141       {
00142         err = rsbac_acl_get_single_right(target,
00143                                          tid,
00144                                          ACLS_ROLE,
00145                                          i_attr_val1.rc_role,
00146                                          request,
00147                                          &result);
00148         if(err)
00149           {
00150             char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00151 
00152             if(tmp)
00153               {
00154                 get_error_name(tmp,err);
00155                 rsbac_printk(KERN_WARNING
00156                        "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00157                        tmp);
00158                 rsbac_kfree(tmp);
00159               }
00160             return FALSE;
00161           }
00162         if(result)
00163           return(TRUE);
00164       }
00165     #endif
00166 
00167     /* other groups */
00168     /* first get user groups */
00169     group_p = NULL;
00170     err = rsbac_acl_get_user_groups(0, user, &group_p, NULL);
00171     if(err<0)
00172       {
00173         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00174 
00175         if(tmp)
00176           {
00177             rsbac_printk(KERN_WARNING
00178                    "rsbac_acl_check_right(): rsbac_acl_get_user_groups() returned error %s!\n",
00179                    get_error_name(tmp,err));
00180             rsbac_kfree(tmp);
00181           }
00182         return err;
00183       }
00184     for(i=0; i<err; i++)
00185       {
00186         tmperr = rsbac_acl_get_single_right(target,
00187                                             tid,
00188                                             ACLS_GROUP,
00189                                             group_p[i],
00190                                             request,
00191                                             &result);
00192         if(tmperr)
00193           {
00194             char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00195 
00196             if(tmp)
00197               {
00198                 rsbac_printk(KERN_WARNING
00199                        "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
00200                        get_error_name(tmp, tmperr));
00201                 rsbac_kfree(tmp);
00202               }
00203             if(group_p)
00204               rsbac_vfree(group_p);
00205             return FALSE;
00206           }
00207         if(result)
00208           {
00209             if(group_p)
00210               rsbac_vfree(group_p);
00211             return(TRUE);
00212           }
00213       }
00214     if(group_p)
00215       rsbac_vfree(group_p);
00216 
00217     /* SUPERVISOR? */
00218 #ifdef CONFIG_RSBAC_ACL_LEARN
00219     result = rsbac_acl_check_super(target, tid, user);
00220     if(   !result
00221        && (request < R_NONE)
00222       )
00223       {
00224         switch(target)
00225           {
00226             case T_FILE:
00227             case T_DIR:
00228             case T_FIFO:
00229             case T_SYMLINK:
00230               if(rsbac_acl_learn_fd)
00231                 {
00232                   char * tmp;
00233                   enum rsbac_acl_subject_type_t  subj_type;
00234                        rsbac_acl_subject_id_t    subj_id;
00235                        rsbac_acl_rights_vector_t rights;
00236                        rsbac_time_t              ttl;
00237 
00238                   tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00239                   if(tmp)
00240                     {
00241                       char * target_type_name;
00242 
00243                       target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00244                       if(target_type_name)
00245                         {
00246                           char * target_id_name;
00247 
00248                           #ifdef CONFIG_RSBAC_LOG_FULL_PATH
00249                           target_id_name
00250                            = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
00251                           /* max. path name len + some extra */
00252                           #else
00253                           target_id_name = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
00254                           /* max. file name len + some extra */
00255                           #endif
00256                           if(target_id_name)
00257                             {
00258                               get_request_name(tmp,request);
00259                               get_target_name(target_type_name, target, target_id_name, tid);
00260                               rsbac_printk(KERN_INFO
00261                                            "rsbac_acl_check_right(): auto_learn_fd: granting right %s for user %u to target_type %s, tid %s!\n",
00262                                            tmp,
00263                                            user,
00264                                            target_type_name,
00265                                            target_id_name);
00266                               rsbac_kfree(target_id_name);
00267                             }
00268                           rsbac_kfree(target_type_name);
00269                         }
00270                     }
00271                   subj_type = ACLS_USER;
00272                   subj_id = user;
00273                   rights = RSBAC_REQUEST_VECTOR(request);
00274                   ttl = 0;
00275                   err = rsbac_acl_add_to_acl_entry(0, target, tid, subj_type, subj_id, rights, ttl);
00276                   if(tmp)
00277                     {
00278                       if(err)
00279                         {
00280                           rsbac_printk(KERN_WARNING
00281                                        "rsbac_acl_check_right(): rsbac_acl_add_to_acl_entry() returned error %s!\n",
00282                                        get_error_name(tmp,err));
00283                         }
00284                       rsbac_kfree(tmp);
00285                     }
00286                   result = TRUE;
00287                 }
00288               break;
00289 
00290             default:
00291               break;
00292           }
00293       }
00294     return result;
00295 #else
00296     return rsbac_acl_check_super(target, tid, user);
00297 #endif
00298   }
00299 
00300 rsbac_boolean_t rsbac_acl_check_forward(enum  rsbac_target_t target,
00301                                 union rsbac_target_id_t tid,
00302                                       rsbac_uid_t user,
00303                                       rsbac_acl_rights_vector_t rights)
00304   {
00305     rsbac_acl_rights_vector_t i_rights = 0;
00306     rsbac_acl_rights_vector_t i_rvec = ((rsbac_acl_rights_vector_t) 1 << ACLR_FORWARD) | rights;
00307     int                       err=0;
00308 
00309 
00310     /* Only check implemented targets */
00311     switch(target)
00312       {
00313         case T_FILE:
00314         case T_DIR:
00315         case T_FIFO:
00316         case T_SYMLINK:
00317         case T_DEV:
00318         case T_IPC:
00319         case T_SCD:
00320         case T_USER:
00321         case T_PROCESS:
00322 #ifdef CONFIG_RSBAC_ACL_UM_PROT
00323         case T_GROUP:
00324 #endif
00325 #ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
00326         case T_NETDEV:
00327 #endif
00328 #ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
00329         case T_NETTEMP_NT:
00330         case T_NETTEMP:
00331         case T_NETOBJ:
00332 #endif
00333           break;
00334         default:
00335           return TRUE;
00336       }
00337     /* get effective rights */
00338     err = rsbac_acl_sys_get_rights(0, target, tid, ACLS_USER, (rsbac_acl_subject_id_t) user, &i_rights, TRUE);
00339     if(err)
00340       {
00341         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00342 
00343         if(tmp)
00344           {
00345             rsbac_printk(KERN_WARNING
00346                    "rsbac_acl_check_forward(): rsbac_acl_sys_get_rights() returned error %s!\n",
00347                    get_error_name(tmp,err));
00348             rsbac_kfree(tmp);
00349           }
00350         return FALSE;
00351       }
00352     if((i_rights & i_rvec) == i_rvec)
00353       return(TRUE);
00354     else
00355       return(FALSE);
00356   }
00357 
00358 /************************************************* */
00359 /*          Externally visible functions           */
00360 /************************************************* */
00361 
00362 enum rsbac_adf_req_ret_t
00363    rsbac_adf_request_acl (enum  rsbac_adf_request_t     request,
00364                                 rsbac_pid_t             caller_pid,
00365                           enum  rsbac_target_t          target,
00366                           union rsbac_target_id_t       tid,
00367                           enum  rsbac_attribute_t       attr,
00368                           union rsbac_attribute_value_t attr_val,
00369                                 rsbac_uid_t             owner)
00370   {
00371     switch (request)
00372       {
00373         case R_READ_ATTRIBUTE:
00374         case R_MODIFY_ATTRIBUTE:
00375             switch(attr)
00376               { /* owner must be changed by other request to prevent inconsistency */
00377                 case A_owner:
00378                   if(request == R_READ_ATTRIBUTE)
00379                     return(GRANTED);
00380                   else
00381                     return(NOT_GRANTED);
00382 
00383                 /* Only protect AUTH, if asked to by configuration */
00384                 #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
00385                 case A_auth_may_setuid:
00386                 case A_auth_may_set_cap:
00387                 case A_auth_start_uid:
00388                 case A_auth_start_euid:
00389                 case A_auth_start_gid:
00390                 case A_auth_start_egid:
00391                 case A_auth_learn:
00392                 case A_auth_program_file:
00393                 case A_auth_add_f_cap:
00394                 case A_auth_remove_f_cap:
00395                   tid.scd = AST_auth_administration;
00396                   if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
00397                     return(GRANTED);
00398                   else
00399                     return(NOT_GRANTED);
00400                 #endif
00401 
00402                 #ifdef CONFIG_RSBAC_ACL_GEN_PROT
00403                 case A_pseudo:
00404                 case A_log_array_low:
00405                 case A_log_array_high:
00406                 case A_log_program_based:
00407                 case A_log_user_based:
00408                 case A_symlink_add_remote_ip:
00409                 case A_symlink_add_uid:
00410                 case A_symlink_add_rc_role:
00411                 case A_linux_dac_disable:
00412                 case A_fake_root_uid:
00413                 case A_audit_uid:
00414                 case A_auid_exempt:
00415                 case A_remote_ip:
00416                   if (!rsbac_acl_check_right(target, tid, owner, caller_pid, request))
00417                     return(NOT_GRANTED);
00418                   else
00419                     return(GRANTED);
00420                 #endif
00421 
00422                 #ifdef CONFIG_RSBAC_ACL_LEARN
00423                 case A_acl_learn:
00424                   /* check supervisor on target */
00425                   if(rsbac_acl_check_super(target,
00426                                            tid,
00427                                            owner))
00428                     return(GRANTED);
00429                   else
00430                     return(NOT_GRANTED);
00431                 #endif
00432 
00433                 /* All attributes (remove target!) */
00434                 case A_none:
00435                   if (!rsbac_acl_check_right(target, tid, owner, caller_pid, request))
00436                     return(NOT_GRANTED);
00437                   #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
00438                   tid.scd = AST_auth_administration;
00439                   if (!rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
00440                     return(NOT_GRANTED);
00441                   #endif
00442                   return(GRANTED);
00443 
00444                 default:
00445                   return(DO_NOT_CARE);
00446               }
00447 
00448         case R_SWITCH_MODULE:
00449             switch(target)
00450               {
00451                 case T_NONE:
00452                     if(   (attr_val.switch_target != ACL)
00453                        #ifdef CONFIG_RSBAC_SOFTMODE
00454                        && (attr_val.switch_target != SOFTMODE)
00455                        #endif
00456                        #ifdef CONFIG_RSBAC_FREEZE
00457                        && (attr_val.switch_target != FREEZE)
00458                        #endif
00459                        #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
00460                        && (attr_val.switch_target != AUTH)
00461                        #endif
00462                       )
00463                       return(DO_NOT_CARE);
00464 
00465                     tid.scd = ST_other;
00466                     if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
00467                       return(GRANTED);
00468                     else
00469                       return(NOT_GRANTED);
00470 
00471                 /* all other cases are unknown */
00472                 default:
00473                   return(DO_NOT_CARE);
00474               }
00475 
00476 /*********************/
00477         default:
00478           if(target == T_NONE)
00479             {
00480               target = T_SCD;
00481               tid.scd = ST_other;
00482             }
00483           if (rsbac_acl_check_right(target, tid, owner, caller_pid, request))
00484             return(GRANTED);
00485           else
00486             return(NOT_GRANTED);
00487       }
00488   } /* end of rsbac_adf_request_acl() */
00489 
00490 
00491 /*****************************************************************************/
00492 /* If the request returned granted and the operation is performed,           */
00493 /* the following function can be called by the AEF to get all aci set        */
00494 /* correctly. For write accesses that are performed fully within the kernel, */
00495 /* this is usually not done to prevent extra calls, including R_CLOSE for    */
00496 /* cleaning up.                                                              */
00497 /* The second instance of target specification is the new target, if one has */
00498 /* been created, otherwise its values are ignored.                           */
00499 /* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
00500 
00501 inline int  rsbac_adf_set_attr_acl(
00502                       enum  rsbac_adf_request_t     request,
00503                             rsbac_pid_t             caller_pid,
00504                       enum  rsbac_target_t          target,
00505                       union rsbac_target_id_t       tid,
00506                       enum  rsbac_target_t          new_target,
00507                       union rsbac_target_id_t       new_tid,
00508                       enum  rsbac_attribute_t       attr,
00509                       union rsbac_attribute_value_t attr_val,
00510                             rsbac_uid_t             owner)
00511   {
00512     /* Nothing to be done here */
00513     return 0;
00514   } /* end of rsbac_adf_set_attr_acl() */
00515 
00516 /* end of rsbac/adf/acl/main.c */

Generated on Sun May 21 14:30:49 2006 for RSBAC by  doxygen 1.4.2