/************************************************* */
/* Rule Set Based Access Control                   */
/* Implementation of the Access Control Decision   */
/* Facility (ADF) - Authentification module        */
/* File: rsbac/adf/auth/syscalls.c                 */
/*                                                 */
/* Author and (c) 1999,2000: Amon Ott              */
/*                                                 */
/* Last modified: 26/Sep/2000                      */
/************************************************* */

#include <linux/string.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/malloc.h>
#include <rsbac/types.h>
#include <rsbac/aci.h>
#include <rsbac/error.h>
#include <rsbac/acl.h>
#include <rsbac/getname.h>
#include <rsbac/acl_getname.h>
#include <rsbac/helpers.h>
#include <rsbac/debug.h>

#ifndef NULL
#define NULL ((void *) 0)
#endif

/************************************************* */
/*           Global Variables                      */
/************************************************* */

/************************************************* */
/*          Internal Help functions                */
/************************************************* */

boolean rsbac_acl_check_super(enum  rsbac_target_t target,
                              union rsbac_target_id_t tid,
                                    rsbac_uid_t user)
  {
    boolean                   i_result = FALSE;
    int                       err=0, tmperr;
    int                       i;
    rsbac_acl_group_id_t    * group_p;
    #if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
    union rsbac_target_id_t       i_tid;
    union rsbac_attribute_value_t i_attr_val1;
    #endif

    /* Only check implemented targets */
    switch(target)
      {
        case T_FILE:
        case T_DIR:
        case T_DEV:
        case T_IPC:
        case T_SCD:
        case T_USER:
        case T_PROCESS:
          break;
        default:
          return TRUE;
      }
    /* own right */
    err = rsbac_acl_get_super(target, tid, ACLS_USER, (rsbac_acl_subject_id_t) user, &i_result);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_check_super(): rsbac_acl_get_super() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
        return FALSE;
      }
    if(i_result)
      return(TRUE);

    /* try SUPERVISOR for group and role */
    /* group everyone */
    err = rsbac_acl_get_super(target, tid, ACLS_GROUP, RSBAC_ACL_GROUP_EVERYONE,
                              &i_result);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_check_super(): rsbac_acl_get_super() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
        return FALSE;
      }
    if(i_result)
      return(TRUE);

    #if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
    /* use user role */
    /* first get role */
    i_tid.user = user;
    if (rsbac_get_attr(T_USER,
                       i_tid,
                       A_rc_def_role,
                       &i_attr_val1,
                       FALSE))
      {
        printk(KERN_WARNING
               "rsbac_acl_check_super(): rsbac_get_attr() for process rc_role returned error!\n");
      }
    else
      {
        err = rsbac_acl_get_super(target, tid, ACLS_ROLE, i_attr_val1.rc_role,
                                  &i_result);
        if(err)
          {
            char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

            if(tmp)
              {
                printk(KERN_WARNING
                       "rsbac_acl_check_super(): rsbac_acl_get_super() returned error %s!\n",
                       get_error_name(tmp,err));
                kfree(tmp);
              }
            return FALSE;
          }
        if(i_result)
          return(TRUE);
      }
    #endif

    /* other groups */
    /* first get user groups */
    group_p = NULL;
    err = rsbac_acl_get_user_groups(user, &group_p);
    if(err<0)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_check_super(): rsbac_acl_get_user_groups() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
        return err;
      }
    for(i=0; i<err; i++)
      {
        tmperr = rsbac_acl_get_super(target, tid, ACLS_GROUP, group_p[i],
                                     &i_result);
        if(tmperr)
          {
            char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

            if(tmp)
              {
                printk(KERN_WARNING
                       "rsbac_acl_check_super(): rsbac_acl_get_super() returned error %s!\n",
                       get_error_name(tmp,tmperr));
                kfree(tmp);
              }
            kfree(group_p);
            return FALSE;
          }
        if(i_result)
          {
            kfree(group_p);
            return(TRUE);
          }
      }
    if(group_p)
      kfree(group_p);

    /* give up */
    return FALSE;
  };


#if defined(CONFIG_RSBAC_ACL)
boolean rsbac_acl_check_forward(enum  rsbac_target_t target,
                                union rsbac_target_id_t tid,
                                      rsbac_uid_t user,
                                      rsbac_acl_rights_vector_t rights);

boolean rsbac_acl_check_super(enum  rsbac_target_t target,
                              union rsbac_target_id_t tid,
                                    rsbac_uid_t user);

boolean rsbac_acl_check_right(enum  rsbac_target_t target,
                              union rsbac_target_id_t tid,
                                    rsbac_uid_t user,
                              enum  rsbac_adf_request_t request);
#endif

/************************************************* */
/*          Externally visible functions           */
/************************************************* */

int rsbac_acl_sys_set_acl_entry (enum   rsbac_target_t              target,
                                 union  rsbac_target_id_t           tid,
                                 enum   rsbac_acl_subject_type_t    subj_type,
                                        rsbac_acl_subject_id_t      subj_id,
                                        rsbac_acl_rights_vector_t   rights)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL)
    rsbac_uid_t user;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
    /* first try access control right (SUPERVISOR try is included) */
    if(!rsbac_acl_check_right(target, tid, user, ACLR_ACCESS_CONTROL))
      {
        /* no access control -> try forward for these rights */
        if(!rsbac_acl_check_forward(target, tid, user, rights))
          {
            char * rights_string = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
            char * target_id_name
              = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. path name len + some extra */
            #else
            char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. file name len + some extra */
            #endif

            u64tostracl(rights_string, rights);
            get_acl_subject_type_name(subject_type_name, subj_type);
            get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
            rsbac_printk(KERN_INFO
                   "rsbac_acl_sys_set_acl_entry(): setting rights %s for %s %u to %s %s denied for user %u!\n",
                   rights_string,
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_set_acl_entry(): setting rights %s for %s %u to %s %s denied for user %u!\n",
                   rights_string,
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(rights_string);
            kfree(subject_type_name);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
      }
    if(rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
      {
        /* you must have SUPERVISOR to set SUPERVISOR */
        if(!rsbac_acl_check_super(target, tid, user))
          {
            char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
            char * target_id_name
              = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. path name len + some extra */
            #else
            char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. file name len + some extra */
            #endif

            get_acl_subject_type_name(subject_type_name, subj_type);
            get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
            rsbac_printk(KERN_INFO
                   "rsbac_acl_sys_set_acl_entry(): setting SUPERVISOR for %s %u to %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_set_acl_entry(): setting SUPERVISOR for %s %u to %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(subject_type_name);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
      }
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Set ACL. */
    err = rsbac_acl_set_acl_entry(target, tid, subj_type, subj_id, rights);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_set_acl_entry(): rsbac_acl_set_acl_entry() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_remove_acl_entry (enum   rsbac_target_t              target,
                                 union  rsbac_target_id_t           tid,
                                 enum   rsbac_acl_subject_type_t    subj_type,
                                        rsbac_acl_subject_id_t      subj_id)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL)
    rsbac_uid_t user;
    rsbac_acl_rights_vector_t res_rights = 0;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
    /* first try access control right (SUPERVISOR is included) */
    if(!rsbac_acl_check_right(target, tid, user, ACLR_ACCESS_CONTROL))
      {
        char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
        char * target_id_name
          = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. path name len + some extra */
        #else
        char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. file name len + some extra */
        #endif

        get_acl_subject_type_name(subject_type_name, subj_type);
        get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
        rsbac_printk(KERN_INFO
               "rsbac_acl_sys_remove_acl_entry(): removing ACL entry for %s %u at %s %s denied for user %u!\n",
               subject_type_name,
               subj_id,
               target_type_name,
               target_id_name,
               user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
        printk(KERN_INFO
               "rsbac_acl_sys_remove_acl_entry(): removing ACL entry for %s %u at %s %s denied for user %u!\n",
               subject_type_name,
               subj_id,
               target_type_name,
               target_id_name,
               user);
#endif
        kfree(subject_type_name);
        kfree(target_type_name);
        kfree(target_id_name);
        return(-EPERM);
      }

    err = rsbac_acl_get_rights(target, tid, subj_type, subj_id, &res_rights, FALSE);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_remove_acl_entry(): rsbac_acl_get_rights() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
        return err;
      }
    if(res_rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
      {
        /* you must have SUPERVISOR to remove an entry with SUPERVISOR */
        if(!rsbac_acl_check_super(target, tid, user))
          {
            char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
            char * target_id_name
              = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. path name len + some extra */
            #else
            char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. file name len + some extra */
            #endif

            get_acl_subject_type_name(subject_type_name, subj_type);
            get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
            rsbac_printk(KERN_INFO
                   "rsbac_acl_sys_remove_acl_entry(): removing ACL entry with SUPERVISOR for %s %u at %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_remove_acl_entry(): removing ACL entry with SUPERVISOR for %s %u at %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(subject_type_name);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
      }
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Set ACL. */
    err = rsbac_acl_remove_acl_entry(target, tid, subj_type, subj_id);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_remove_acl_entry(): rsbac_acl_remove_acl_entry() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_remove_acl (enum   rsbac_target_t              target,
                                 union  rsbac_target_id_t           tid)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL)
    rsbac_uid_t user;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
    /* check SUPERVISOR */
    if(!rsbac_acl_check_super(target, tid, user))
      {
        char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
        char * target_id_name
          = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. path name len + some extra */
        #else
        char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. file name len + some extra */
        #endif

        get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
        rsbac_printk(KERN_INFO
               "rsbac_acl_sys_remove_acl(): removing ACL from %s %s denied for user %u!\n",
               target_type_name,
               target_id_name,
               user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
        printk(KERN_INFO
               "rsbac_acl_sys_remove_acl(): removing ACL from %s %s denied for user %u!\n",
               target_type_name,
               target_id_name,
               user);
#endif
        kfree(target_type_name);
        kfree(target_id_name);
        return(-EPERM);
      }
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Set ACL. */
    err = rsbac_acl_remove_acl(target, tid);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_remove_acl(): rsbac_acl_remove_acl() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_add_to_acl_entry (enum   rsbac_target_t              target,
                                 union  rsbac_target_id_t           tid,
                                 enum   rsbac_acl_subject_type_t    subj_type,
                                        rsbac_acl_subject_id_t      subj_id,
                                        rsbac_acl_rights_vector_t   rights)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL)
    rsbac_uid_t user;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
    /* first try access control right (SUPERVISOR is included) */
    if(!rsbac_acl_check_right(target, tid, user, ACLR_ACCESS_CONTROL))
      {
        /* no access control -> try forward for these rights */
        if(!rsbac_acl_check_forward(target, tid, user, rights))
          {
            char * rights_string = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
            char * target_id_name
              = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. path name len + some extra */
            #else
            char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. file name len + some extra */
            #endif

            u64tostracl(rights_string, rights);
            get_acl_subject_type_name(subject_type_name, subj_type);
            get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
            rsbac_printk(KERN_INFO
                   "rsbac_acl_sys_add_to_acl_entry(): adding rights %s for %s %u to %s %s denied for user %u!\n",
                   rights_string,
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_add_to_acl_entry(): adding rights %s for %s %u to %s %s denied for user %u!\n",
                   rights_string,
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(rights_string);
            kfree(subject_type_name);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
      }
    if(rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
      {
        /* you must have SUPERVISOR to add SUPERVISOR */
        if(!rsbac_acl_check_super(target, tid, user))
          {
            char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
            char * target_id_name
              = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. path name len + some extra */
            #else
            char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. file name len + some extra */
            #endif

            get_acl_subject_type_name(subject_type_name, subj_type);
            get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
            rsbac_printk(KERN_INFO
                   "rsbac_acl_sys_add_to_acl_entry(): adding SUPERVISOR for %s %u to %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_add_to_acl_entry(): adding SUPERVISOR for %s %u to %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(subject_type_name);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
      }
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Set ACL. */
    err = rsbac_acl_add_to_acl_entry(target, tid, subj_type, subj_id, rights);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_add_to_acl_entry(): rsbac_acl_add_to_acl_entry() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_remove_from_acl_entry (enum   rsbac_target_t              target,
                                 union  rsbac_target_id_t           tid,
                                 enum   rsbac_acl_subject_type_t    subj_type,
                                        rsbac_acl_subject_id_t      subj_id,
                                        rsbac_acl_rights_vector_t   rights)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL)
    rsbac_uid_t user;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
    /* first try access control right (SUPERVISOR is included) */
    if(!rsbac_acl_check_right(target, tid, user, ACLR_ACCESS_CONTROL))
      {
        char * rights_string = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
        char * target_id_name
          = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. path name len + some extra */
        #else
        char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. file name len + some extra */
        #endif

        u64tostracl(rights_string, rights);
        get_acl_subject_type_name(subject_type_name, subj_type);
        get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
        rsbac_printk(KERN_INFO
               "rsbac_acl_sys_remove_from_acl_entry(): removing rights %s for %s %u to %s %s denied for user %u!\n",
               rights_string,
               subject_type_name,
               subj_id,
               target_type_name,
               target_id_name,
               user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
        printk(KERN_INFO
               "rsbac_acl_sys_remove_from_acl_entry(): removing rights %s for %s %u to %s %s denied for user %u!\n",
               rights_string,
               subject_type_name,
               subj_id,
               target_type_name,
               target_id_name,
               user);
#endif
        kfree(rights_string);
        kfree(subject_type_name);
        kfree(target_type_name);
        kfree(target_id_name);
        return(-EPERM);
      }
    if(rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
      {
        /* you must have SUPERVISOR to revoke SUPERVISOR */
        if(!rsbac_acl_check_super(target, tid, user))
          {
            char * subject_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
            char * target_id_name
              = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. path name len + some extra */
            #else
            char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
            /* max. file name len + some extra */
            #endif

            get_acl_subject_type_name(subject_type_name, subj_type);
            get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
            rsbac_printk(KERN_INFO
                   "rsbac_acl_sys_remove_from_acl_entry(): removing SUPERVISOR for %s %u to %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_remove_from_acl_entry(): removing SUPERVISOR for %s %u to %s %s denied for user %u!\n",
                   subject_type_name,
                   subj_id,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(subject_type_name);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
      }
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Remove ACL. */
    err = rsbac_acl_remove_from_acl_entry(target, tid, subj_type, subj_id, rights);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_remove_from_acl_entry(): rsbac_acl_remove_from_acl_entry() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_set_mask    (enum   rsbac_target_t              target,
                               union  rsbac_target_id_t           tid,
                                      rsbac_acl_rights_vector_t   mask)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL) || defined (CONFIG_RSBAC_ACL_SUPER_FILTER)
    rsbac_uid_t user;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
#endif
#if defined(CONFIG_RSBAC_ACL)
    /* first try access control right (SUPERVISOR is included) */
    if(!rsbac_acl_check_right(target, tid, user, ACLR_ACCESS_CONTROL))
      {
        char * rights_string = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        char * target_type_name = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
        char * target_id_name
          = kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. path name len + some extra */
        #else
        char * target_id_name = kmalloc(2 * RSBAC_MAXNAMELEN, GFP_KERNEL);
        /* max. file name len + some extra */
        #endif

        u64tostracl(rights_string, mask);
        get_target_name(target_type_name, target, target_id_name, tid);
#ifdef CONFIG_RSBAC_RMSG
        rsbac_printk(KERN_INFO
                     "rsbac_acl_sys_set_mask(): setting mask %s for %s %s denied for user %u!\n",
                     rights_string,
                     target_type_name,
                     target_id_name,
                     user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
            printk(KERN_INFO
                   "rsbac_acl_sys_set_mask(): setting mask %s for %s %s denied for user %u!\n",
                   rights_string,
                   target_type_name,
                   target_id_name,
                   user);
#endif
            kfree(rights_string);
            kfree(target_type_name);
            kfree(target_id_name);
            return(-EPERM);
          }
#endif /* CONFIG_RSBAC_ACL */

#ifdef CONFIG_RSBAC_ACL_SUPER_FILTER
    if(!(mask & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR))
      { /* trial to mask out SUPERVISOR */
        rsbac_acl_rights_vector_t res_rights = 0;

        /* you must have direct SUPERVISOR as a USER to set a mask without SUPERVISOR */
        /* get direct own rights (still uses default_fd_rights) */
        err = rsbac_acl_get_rights(target, tid, ACLS_USER, user, &res_rights, FALSE);
        if(err)
          return -RSBAC_EREADFAILED;
        if(!(res_rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR))
          mask |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
      }
#else
    /* SUPERVISOR must never be masked out */
    mask |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
#endif

    /* OK, checks passed. Set mask. */
    err = rsbac_acl_set_mask(target, tid, mask);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_set_mask(): rsbac_acl_set_mask() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_remove_user(rsbac_uid_t uid)
  {
    int err=0;

/* check only in non-maint mode */
#if defined(CONFIG_RSBAC_ACL)
    rsbac_uid_t user;
    union rsbac_target_id_t tid;

    if(rsbac_get_owner(&user))
      return -RSBAC_EREADFAILED;
    tid.user = uid;
    /* first try access control right (SUPERVISOR is included) */
    if(!rsbac_acl_check_right(T_USER, tid, user, R_DELETE))
      {
#ifdef CONFIG_RSBAC_RMSG
        rsbac_printk(KERN_INFO
                     "rsbac_acl_sys_remove_user(): removing all data for user %u denied for user %u!\n",
                     uid,
                     user);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
        printk(KERN_INFO
               "rsbac_acl_sys_remove_user(): removing all data for user %u denied for user %u!\n",
               uid,
               user);
#endif
        return(-EPERM);
      }
#endif /* CONFIG_RSBAC_ACL */

#ifdef CONFIG_RSBAC_RMSG
    rsbac_printk(KERN_INFO
                 "rsbac_acl_sys_remove_user(): removing all data for user %u!\n",
                 uid);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
    printk(KERN_INFO
           "rsbac_acl_sys_remove_user(): removing all data for user %u!\n",
           uid);
#endif
    /* OK, checks passed. Set mask. */
    err = rsbac_acl_remove_user(uid);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_remove_user(): rsbac_acl_remove_user() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

/*********/

int rsbac_acl_sys_get_mask    (enum   rsbac_target_t              target,
                               union  rsbac_target_id_t           tid,
                                      rsbac_acl_rights_vector_t * mask_p)
  {
    int err=0;

/* no check */
#if defined(CONFIG_RSBAC_ACL)
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Get mask. */
    err = rsbac_acl_get_mask(target, tid, mask_p);
    if(err)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_get_mask(): rsbac_acl_get_mask() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

int rsbac_acl_sys_get_rights (enum   rsbac_target_t              target,
                                 union  rsbac_target_id_t           tid,
                                 enum   rsbac_acl_subject_type_t    subj_type,
                                        rsbac_acl_subject_id_t      subj_id,
                                        rsbac_acl_rights_vector_t * rights_p,
                                        boolean                     effective)
  {
    int err=0;
    rsbac_acl_rights_vector_t res_rights;
    #if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
    union rsbac_target_id_t       i_tid;
    union rsbac_attribute_value_t i_attr_val1;
    #endif

    /* no check (Attention: rsbac_acl_check_forward depends on this to be allowed!) */
#if defined(CONFIG_RSBAC_ACL)
#endif /* CONFIG_RSBAC_ACL */

    if(   (subj_type == ACLS_USER)
       && (subj_id == RSBAC_NO_USER)
      )
      rsbac_get_owner((rsbac_uid_t *) &subj_id);
    /* OK, check passed. Call ACL. */
    if(effective)
      {
        /* inherited own rights */
        res_rights = 0;
        err = rsbac_acl_get_rights(target, tid, subj_type, subj_id, &res_rights, TRUE);
        if(err)
          {
            char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

            if(tmp)
              {
                printk(KERN_WARNING
                       "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
                       get_error_name(tmp,err));
                kfree(tmp);
              }
            return err;
          }
        *rights_p = res_rights;
        /* add group and role rights, if normal user */
        if(subj_type == ACLS_USER)
          {
            rsbac_acl_group_id_t * group_p;
            int                    i;
            int                    tmperr;

            /* group everyone */
            res_rights = 0;
            err = rsbac_acl_get_rights(target, tid, ACLS_GROUP, RSBAC_ACL_GROUP_EVERYONE,
                                       &res_rights, TRUE);
            if(err)
              {
                char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

                if(tmp)
                  {
                    printk(KERN_WARNING
                           "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
                           get_error_name(tmp,err));
                    kfree(tmp);
                  }
                return err;
              }
            *rights_p |= res_rights;

            /* other groups */
            /* first get user groups */
            group_p = NULL;
            err = rsbac_acl_get_user_groups(subj_id, &group_p);
            if(err<0)
              {
                char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

                if(tmp)
                  {
                    printk(KERN_WARNING
                           "rsbac_acl_sys_get_rights(): rsbac_acl_get_user_groups() returned error %s!\n",
                           get_error_name(tmp,err));
                    kfree(tmp);
                  }
                return err;
              }
            for(i=0; i<err; i++)
              {
                res_rights = 0;
                tmperr = rsbac_acl_get_rights(target, tid, ACLS_GROUP, group_p[i],
                                              &res_rights, TRUE);
                if(tmperr)
                  {
                    char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

                    if(tmp)
                      {
                        printk(KERN_WARNING
                               "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
                               get_error_name(tmp,err));
                        kfree(tmp);
                      }
                    if(group_p)
                      kfree(group_p);
                    return tmperr;
                  }
                *rights_p |= res_rights;
              }
            if(group_p)
              kfree(group_p);

            #if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
            /* use user role */
            /* first get role */
            i_tid.user = subj_id;
            if (rsbac_get_attr(T_USER,
                               i_tid,
                               A_rc_def_role,
                               &i_attr_val1,
                               FALSE))
              {
                printk(KERN_WARNING
                       "rsbac_acl_sys_get_rights(): rsbac_get_attr() for process rc_role returned error!\n");
              }
            else
              {
                res_rights = 0;
                err = rsbac_acl_get_rights(target, tid, ACLS_ROLE, i_attr_val1.rc_role,
                                           &res_rights, TRUE);
                if(err)
                  {
                    char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

                    if(tmp)
                      {
                        printk(KERN_WARNING
                               "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
                               get_error_name(tmp,err));
                        kfree(tmp);
                      }
                    return err;
                  }
                *rights_p |= res_rights;
              }
            #endif

            /* check for SUPERVISOR right, if not yet there */
            if(   !(*rights_p & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
               && rsbac_acl_check_super(target, tid, subj_id)
              )
              *rights_p |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
          }
        else /* not ACLS_USER */
          {
            if(!(*rights_p & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR))
              {
                boolean i_result = FALSE;

                /* check for SUPERVISOR right */
                /* own right */
                err = rsbac_acl_get_super(target, tid, subj_type, subj_id, &i_result);
                if(err)
                  {
                    char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

                    if(tmp)
                      {
                        printk(KERN_WARNING
                               "rsbac_acl_sys_get_rights(): rsbac_acl_get_super() returned error %s!\n",
                               get_error_name(tmp,err));
                        kfree(tmp);
                      }
                  }
                else
                  if(i_result)
                    *rights_p |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
              }
          }
      }
    else /* not effective = direct */
      {
        /* direct own rights (still uses default_fd_rights) */
        res_rights = 0;
        err = rsbac_acl_get_rights(target, tid, subj_type, subj_id, &res_rights, FALSE);
        if(!err)
          *rights_p = res_rights;
      }
    return err;
  }

int rsbac_acl_sys_get_tlist (enum   rsbac_target_t              target,
                             union  rsbac_target_id_t           tid,
                             struct rsbac_acl_entry_t           entry_array[],
                                    u_int                       maxnum)
  {
    int err=0;

    /* no check */
#if defined(CONFIG_RSBAC_ACL)
#endif /* CONFIG_RSBAC_ACL */

    /* OK, check passed. Call ACL. */
    err = rsbac_acl_get_tlist(target, tid, entry_array, maxnum);
    if(err<0)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_WARNING
                   "rsbac_acl_sys_get_tlist(): rsbac_acl_get_tlist() returned error %s!\n",
                   get_error_name(tmp,err));
            kfree(tmp);
          }
      }
    return err;
  }

/*********** Groups ***********/

int rsbac_acl_sys_group(enum  rsbac_acl_group_syscall_type_t call,
                        union rsbac_acl_group_syscall_arg_t arg)
  {
    int err = -RSBAC_EINVALIDREQUEST;
    char * k_name;
    rsbac_acl_group_id_t k_group;
    struct rsbac_acl_group_entry_t entry;
    rsbac_uid_t caller;

    if(call >= ACLGS_none)
      return -RSBAC_EINVALIDREQUEST;
    if(rsbac_get_owner(&caller))
      return -RSBAC_EREADFAILED;

    if(rsbac_debug_aef_acl)
      {
        char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);

        if(tmp)
          {
            printk(KERN_DEBUG
                   "rsbac_acl_sys_group(): %s called\n",
                   get_acl_group_syscall_name(tmp,call));
            kfree(tmp);
          }
      }
    
    switch(call)
      {
        case ACLGS_add_group:
          if(arg.add_group.type >= ACLG_NONE)
            {
              err = -RSBAC_EINVALIDVALUE;
              break;
            }
          k_name = rsbac_getname(arg.add_group.name);
          if(!k_name)
            {
              err = -RSBAC_EINVALIDVALUE;
              break;
            }
          err = rsbac_get_user((char *)&k_group, (char *)arg.add_group.group_id_p, sizeof(k_group));
          if(err)
            break;
          err = rsbac_acl_add_group(caller,
                                    arg.add_group.type,
                                    k_name,
                                    &k_group);
          rsbac_putname(k_name);
          if(!err)
            err = rsbac_put_user((char *)&k_group, (char *) arg.add_group.group_id_p, sizeof(k_group));
          break;

        case ACLGS_change_group:
          if(arg.change_group.type >= ACLG_NONE)
            {
              err = -RSBAC_EINVALIDVALUE;
              break;
            }
          err = rsbac_acl_get_group_entry(arg.change_group.id, &entry);
          if(err)
            break;
          /* check owner only, if non-maint */
          #if defined(CONFIG_RSBAC_ACL)
          if(entry.owner != caller)
            {
#ifdef CONFIG_RSBAC_RMSG
              rsbac_printk(KERN_INFO
                           "rsbac_acl_group(): changing group %u denied for user %u - not owner!\n",
                           entry.id,
                           caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
              printk(KERN_INFO
                     "rsbac_acl_group(): changing group %u denied for user %u - not owner!\n",
                     entry.id,
                     caller);
#endif
              err = -EPERM;
              break;
            }
          #endif
          {
            char * k_name;

            k_name = rsbac_getname(arg.change_group.name);
            if(k_name)
              {
                err = rsbac_acl_change_group(arg.change_group.id,
                                             arg.change_group.owner,
                                             arg.change_group.type,
                                             k_name);
                putname(k_name);
              }
            else
              err = -RSBAC_EINVALIDVALUE;
          }
          break;

        case ACLGS_remove_group:
          err = rsbac_acl_get_group_entry(arg.remove_group.id, &entry);
          if(err)
            break;
          /* check owner only, if non-maint */
          #if defined(CONFIG_RSBAC_ACL)
          if(entry.owner != caller)
            {
#ifdef CONFIG_RSBAC_RMSG
              rsbac_printk(KERN_INFO
                           "rsbac_acl_group(): removing group %u denied for user %u - not owner!\n",
                           entry.id,
                           caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
              printk(KERN_INFO
                     "rsbac_acl_group(): removing group %u denied for user %u - not owner!\n",
                     entry.id,
                     caller);
#endif
              err = -EPERM;
              break;
            }
          #endif
          err = rsbac_acl_remove_group(arg.remove_group.id);
          break;

        case ACLGS_get_group_entry:
          if(!arg.get_group_entry.entry_p)
            {
              err = -RSBAC_EINVALIDPOINTER;
              break;
            }
          if(!arg.get_group_entry.id)
            { /* Everyone -> fill by hand */
              entry.id=0;
              entry.owner=RSBAC_NO_USER;
              entry.type=ACLG_GLOBAL;
              strcpy(entry.name, "Everyone");
              err=0;
            }
          else
            {
              err = rsbac_acl_get_group_entry(arg.get_group_entry.id,
                                              &entry);
            }
          if(!err)
            {
              if(  (entry.owner != caller)
                 &&(entry.type != ACLG_GLOBAL)
                )
                {
#ifdef CONFIG_RSBAC_RMSG
                  rsbac_printk(KERN_INFO
                               "rsbac_acl_group(): getting group entry %u denied for user %u - neither owner nor global!\n",
                               entry.id,
                               caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
                  printk(KERN_INFO
                         "rsbac_acl_group(): getting group entry %u denied for user %u - neither owner nor global!\n",
                         entry.id,
                         caller);
#endif
                  err = -EPERM;
                }
              else
                err = rsbac_put_user((char *)&entry, (char *)arg.get_group_entry.entry_p, sizeof(entry));
            }
          break;

        case ACLGS_list_groups:
          if(arg.list_groups.maxnum <= 0)
            {
              err = -RSBAC_EINVALIDVALUE;
              break;
            }
          if(!arg.list_groups.group_entry_array)
            {
              err = -RSBAC_EINVALIDPOINTER;
              break;
            }
          {
            struct rsbac_acl_group_entry_t entry_array[arg.list_groups.maxnum];
            int tmperr=0;

            if(arg.list_groups.include_global)
              {
                entry_array[0].id=0;
                entry_array[0].owner=RSBAC_NO_USER;
                entry_array[0].type=ACLG_GLOBAL;
                strcpy(entry_array[0].name, "Everyone");
                err=1;
              }
            else
              err=0;
            if(arg.list_groups.maxnum > err)
              {
                tmperr = rsbac_acl_list_groups(caller,
                                               arg.list_groups.include_global,
                                               &entry_array[err],
                                               arg.list_groups.maxnum - err);
              }
            if(tmperr>=0)
              {
                err+=tmperr;
                tmperr = rsbac_put_user((char *)entry_array,
                                        (char *)arg.list_groups.group_entry_array,
                                        err * sizeof(entry_array[0]));
                if(tmperr)
                  err=tmperr;
              }
          }
          break;

        case ACLGS_add_member:
          /* check owner only, if non-maint */
          #if defined(CONFIG_RSBAC_ACL)
          err = rsbac_acl_get_group_entry(arg.add_member.group, &entry);
          if(err)
            break;
          if(entry.owner != caller)
            {
#ifdef CONFIG_RSBAC_RMSG
              rsbac_printk(KERN_INFO
                           "rsbac_acl_group(): adding group member to group %u denied for user %u - not owner!\n",
                           entry.id,
                           caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
              printk(KERN_INFO
                     "rsbac_acl_group(): adding group member to group %u denied for user %u - not owner!\n",
                     entry.id,
                     caller);
#endif
              err = -EPERM;
              break;
            }
          #endif
          err = rsbac_acl_add_group_member(arg.add_member.group, arg.add_member.user);
          break;

        case ACLGS_remove_member:
          /* check owner only, if non-maint */
          #if defined(CONFIG_RSBAC_ACL)
          err = rsbac_acl_get_group_entry(arg.remove_member.group, &entry);
          if(err)
            break;
          if(entry.owner != caller)
            {
#ifdef CONFIG_RSBAC_RMSG
              rsbac_printk(KERN_INFO
                           "rsbac_acl_group(): removing group member from group %u denied for user %u - not owner!\n",
                           entry.id,
                           caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
              printk(KERN_INFO
                     "rsbac_acl_group(): removing group member from group %u denied for user %u - not owner!\n",
                     entry.id,
                     caller);
#endif
              err = -EPERM;
              break;
            }
          #endif
          err = rsbac_acl_remove_group_member(arg.remove_member.group, arg.remove_member.user);
          break;

        case ACLGS_get_user_groups:
          {
            rsbac_acl_group_id_t * group_p = NULL;

            if(arg.get_user_groups.maxnum <= 0)
              {
                err = -RSBAC_EINVALIDVALUE;
                break;
              }
            if(!arg.get_user_groups.group_array)
              {
                err = -RSBAC_EINVALIDPOINTER;
                break;
              }
            if(arg.get_user_groups.user == RSBAC_NO_USER)
              arg.get_user_groups.user = caller;
            #if defined(CONFIG_RSBAC_ACL)
            else
              if(arg.get_user_groups.user != caller)
                {
#ifdef CONFIG_RSBAC_RMSG
                  rsbac_printk(KERN_INFO
                               "rsbac_acl_group(): getting user groups for user %u denied for user %u!\n",
                               arg.get_user_groups.user,
                               caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
                  printk(KERN_INFO
                         "rsbac_acl_group(): getting user groups for user %u denied for user %u!\n",
                         arg.get_user_groups.user,
                         caller);
#endif
                  err = -EPERM;
                  break;
                }
            #endif
            err = rsbac_acl_get_user_groups(arg.get_user_groups.user, &group_p);
            if(err>0)
              {
                int tmperr;

                err = min(err, arg.get_user_groups.maxnum);
                tmperr = rsbac_put_user((char *)group_p,
                                        (char *)arg.get_user_groups.group_array,
                                        err * sizeof(*group_p));
                if(tmperr)
                  err=tmperr;
              }
            if(group_p)
              kfree(group_p);
            break;
          }

        case ACLGS_get_group_members:
          if(   (arg.get_group_members.maxnum <= 0)
             || !arg.get_group_members.group
            )
            {
              err = -RSBAC_EINVALIDVALUE;
              break;
            }
          if(!arg.get_group_members.user_array)
            {
              err = -RSBAC_EINVALIDPOINTER;
              break;
            }
          err = rsbac_acl_get_group_entry(arg.get_group_members.group,
                                          &entry);
          if(err)
            break;
          if(  (entry.owner != caller)
             &&(entry.type != ACLG_GLOBAL)
            )
            {
#ifdef CONFIG_RSBAC_RMSG
              rsbac_printk(KERN_INFO
                           "rsbac_acl_group(): getting group members of group %u denied for user %u - neither owner nor global!\n",
                           entry.id,
                           caller);
#endif
#ifndef CONFIG_RSBAC_RMSG_EXCL
              printk(KERN_INFO
                     "rsbac_acl_group(): getting group members of group %u denied for user %u - neither owner nor global!\n",
                     entry.id,
                     caller);
#endif
              err = -EPERM;
              break;
            }
          {
            rsbac_uid_t user_array[arg.get_group_members.maxnum];

            err = rsbac_acl_get_group_members(arg.get_group_members.group,
                                              user_array,
                                              arg.get_group_members.maxnum);
            if(err>0)
              {
                int tmperr;

                tmperr = rsbac_put_user((char *)user_array,
                                        (char *)arg.get_group_members.user_array,
                                        err * sizeof(rsbac_uid_t));
                if(tmperr)
                  err=tmperr;
              }
          }
          break;

        default:
      }
    return(err);
  };

/* end of rsbac/adf/acl/syscalls.c */
