/*************************************************** */
/* Rule Set Based Access Control                     */
/*                                                   */
/* Author and (c) 1999-2007: Amon Ott <ao@rsbac.org> */
/*                                                   */
/* Last modified: 26/Sep/2007                        */
/*************************************************** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <rsbac/types.h>
#include <rsbac/rc_data_structures.h>
#include <rsbac/getname.h>
#include <rsbac/rc_getname.h>
#include <rsbac/syscalls.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include "nls.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/* reserve list room for so many extra items - to avoid racing problems */
#define LISTROOM 10

char * progname;

void use(void)
    {
        printf(gettext("%s (RSBAC %s)\n***\n"), progname, VERSION);
        printf(gettext("Use: %s [switches] rc-target-type id item [role/type [list-of-rights]] [value]\n"), progname);  
        printf(gettext("     %s -c TYPE target-id item source-id [first_role [last_role]],\n"), progname);
        printf(gettext(" -v = verbose, -p = print right names,\n"));
        printf(gettext(" -a = add, not set, -k = revoke, not set,\n"));
        printf(gettext(" -b = accept rights as bitstring,\n"));
        printf(gettext(" -c = copy all/given roles' rights to type from other type,\n"));
        printf(gettext(" -d = delete all roles' rights to this type,\n"));
        printf(gettext(" -i = list items and values\n"));
        printf(gettext(" -t = set relative time-to-live in secs (role/type comp, admin, assign only)\n"));
        printf(gettext(" -T = set absolute time-to-live in secs (role/type comp, admin, assign only)\n"));
        printf(gettext(" -D = set relative time-to-live in days (role/type comp, admin, assign only)\n"));
        printf(gettext(" -V version = supply RSBAC integer version number for upgrading\n"));
        printf(gettext(" -N ta = transaction number (default = value of RSBAC_TA, if set, or 0)\n"));
        printf(gettext(" rc-target-type = ROLE or TYPE,\n"));
        printf(gettext(" id-nr = ROLE or TYPE number,\n"));
        printf(gettext(" item = entry line,\n"));
        printf(gettext(" role/type = for this type only (role/type comp, admin, assign only),\n"));
        printf(gettext(" right = request name or number (type_comp items only),\n"));
        printf(gettext("        also special rights and groups R (read requests),\n"));
        printf(gettext("        RW (read-write), SY (system), SE (security), A (all)\n"));
        exit(1);
    }

int main(int argc, char ** argv)
{
  int res = 0;
  enum rsbac_adf_request_t right;
  rsbac_rc_rights_vector_t rights_vector = 0;
  rsbac_time_t ttl=RSBAC_LIST_TTL_KEEP;
  char tmp1[RSBAC_MAXNAMELEN],tmp2[RSBAC_MAXNAMELEN];
  int i,j;
  rsbac_boolean_t rused = FALSE;
  rsbac_boolean_t wused = FALSE;
  enum rsbac_rc_target_t target;
  union rsbac_rc_target_id_t tid;
  union rsbac_rc_target_id_t subtid;
  enum rsbac_rc_item_t item;
  union rsbac_rc_item_value_t value;
  int verbose=0;
  int printall=0;
  int add=0;
  int revoke=0;
  int bitstring=0;
  int copy=0;
  int delrights=0;
  rsbac_version_t version=RSBAC_VERSION_NR;
  rsbac_list_ta_number_t ta_number = 0;

  progname = argv[0];
  locale_init();
  {
    char * env = getenv("RSBAC_TA");

    if(env)
      ta_number = strtoul(env,0,0);
  }
  while((argc > 1) && (argv[1][0] == '-'))
    {
      char * pos = argv[1];
      pos++;
      while(*pos)
        {
          switch(*pos)
            {
              case 'h':
                use();
                return 0;
              case 'v':
                verbose++;
                break;
              case 'p':
                printall=1;
                break;
              case 'a':
                add=1;
                break;
              case 'k':
                revoke=1;
                break;
              case 'b':
                bitstring=1;
                break;
              case 'c':
                copy=1;
                break;
              case 'd':
                delrights=1;
                break;
              case 't':
                if(argc > 2)
                  {
                    ttl = strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  fprintf(stderr, gettext("%s: missing ttl value for parameter %c\n"), progname, *pos);
                break;
              case 'D':
                if(argc > 2)
                  {
                    ttl = 86400 * strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  fprintf(stderr, gettext("%s: missing ttl value for parameter %c\n"), progname, *pos);
                break;
              case 'T':
                if(argc > 2)
                  {
                    rsbac_time_t now = time(NULL);
                    ttl = strtoul(argv[2], 0, 10);
                    if(ttl > now)
                      {
                        ttl -= now;
                        argc--;
                        argv++;
                      }
                    else
                      {
                        fprintf(stderr,
                                gettext("%s: ttl value for parameter %c is in the past, exiting\n"), progname, *pos);
                        exit(1);
                      }
                  }
                else
                  fprintf(stderr, gettext("%s: missing ttl value for parameter %c\n"), progname, *pos);
                break;
              case 'i':
                {
                  int role_entry_item_list[RSBAC_RC_NR_ROLE_ENTRY_ITEMS] = RSBAC_RC_ROLE_ENTRY_ITEM_LIST;
                  int type_entry_item_list[RSBAC_RC_NR_TYPE_ENTRY_ITEMS] = RSBAC_RC_TYPE_ENTRY_ITEM_LIST;

                  if(   (argc > 2)
                     && ((item = get_rc_item_nr(argv[2])) != RI_none)
                    )
                    {
                      get_rc_item_name(tmp1, item);
                      get_rc_item_param(tmp2, item);
                      printf("%s\t%s\n",tmp1,tmp2);
                      exit(0);
                    }
                  printf(gettext("- items and returned values = see following list:\n"));
                  printf("- ROLE:\n");
                  for (j=0;j<RSBAC_RC_NR_ROLE_ENTRY_ITEMS;j++)
                    {
                      get_rc_item_name(tmp1,role_entry_item_list[j]);
                      get_rc_item_param(tmp2,role_entry_item_list[j]);
                      printf("%s\t%s\n",tmp1,tmp2);
                    }
                  printf("remove_role\t\tRemove role, no value\n");
                  printf("\n- TYPE:\n");
                  for (j=0;j<RSBAC_RC_NR_TYPE_ENTRY_ITEMS;j++)
                    {
                      get_rc_item_name(tmp1,type_entry_item_list[j]);
                      get_rc_item_param(tmp2,type_entry_item_list[j]);
                      printf("%s\t%s\n",tmp1,tmp2);
                    }
                  for (j=RI_type_fd_remove;j<RI_none;j++)
                    {
                      get_rc_item_name(tmp1, j);
                      printf("%s  \tRemove type, no value\n",tmp1);
                    }
                  exit(0);
                }
              case 'V':
                if(argc < 3)
                  {
                    fprintf(stderr, gettext("%s: no version number for switch V\n"), progname);
                    exit(1);
                  }
                version = strtol(argv[2],0,10);
                argv++;
                argc--;
                break;
              case 'N':
                if(argc > 2)
                  {
                    ta_number = strtoul(argv[2], 0, 10);
                    argc--;
                    argv++;
                  }
                else
                  {
                    fprintf(stderr, gettext("%s: missing transaction number value for parameter %c\n"), progname, *pos);
                    exit(1);
                  }
                break;

              default:
                fprintf(stderr, gettext("%s: unknown parameter %c\n"), progname, *pos);
                exit(1);
            }
          pos++;
        }
      argv++;
      argc--;
    }

  if(argc < 4)
    {
      use();
      return 1;
    }  

  target = get_rc_target_nr(argv[1]);
  switch(target)
    {
      case RT_ROLE:
        tid.role = strtol(argv[2],0,10);
        break;
      case RT_TYPE:
        tid.type = strtol(argv[2],0,10);
        break;
      default:
        fprintf(stderr, gettext("Invalid target %s\n"), argv[1]);
        exit(1);
    }
  item = get_rc_item_nr(argv[3]);
  if(item == RI_none)
    {
      fprintf(stderr, gettext("Invalid item %s\n"), argv[3]);
      exit(1);
    }

  if(copy)
    {
      rsbac_rc_type_id_t s_type;
      rsbac_rc_type_id_t t_type;
      rsbac_rc_role_id_t first_role = 0;
      rsbac_rc_role_id_t last_role = RC_role_max_value;
      union rsbac_rc_target_id_t t_subtid;
      __u32 * role_array;
      int nr_roles;
      int tmpres = 0;

      if(argc < 5)
        {
          fprintf(stderr, gettext("Too few arguments with option -c\n"));
          exit(1);
        }
      s_type = strtoul(argv[4],0,10);
      if(s_type > RC_type_max_value)
        {
          fprintf(stderr, gettext("Invalid source type %u\n"), s_type);
          exit(1);
        }
      if(argc > 5)
        {
          first_role = strtoul(argv[5],0,10);
          if(first_role > RC_role_max_value)
            {
              fprintf(stderr, gettext("Invalid first role %u\n"), first_role);
              exit(1);
            }
          last_role = first_role;
        }
      if(argc > 6)
        {
          last_role = strtoul(argv[6],0,10);
          if(last_role > RC_role_max_value)
            {
              fprintf(stderr, gettext("Invalid last role %u\n"), last_role);
              exit(1);
            }
        }
      t_type = tid.type;
      if(t_type > RC_type_max_value)
        {
          fprintf(stderr, gettext("Invalid target type %u\n"), t_type);
          exit(1);
        }
      if(s_type == t_type)
        {
          fprintf(stderr, gettext("Source and target must differ\n"));
          exit(1);
        }
      switch(item)
        {
          case RI_type_comp_fd:
          case RI_type_fd_name:
            item = RI_type_comp_fd;
            break;
          case RI_type_comp_dev:
          case RI_type_dev_name:
            item = RI_type_comp_dev;
            break;
          case RI_type_comp_user:
          case RI_type_user_name:
            item = RI_type_comp_user;
            break;
          case RI_type_comp_process:
          case RI_type_process_name:
            item = RI_type_comp_process;
            break;
          case RI_type_comp_ipc:
          case RI_type_ipc_name:
            item = RI_type_comp_ipc;
            break;
          case RI_type_comp_scd:
          case RI_type_scd_name:
            item = RI_type_comp_scd;
            break;
          case RI_type_comp_group:
          case RI_type_group_name:
            item = RI_type_comp_group;
            break;
          case RI_type_comp_netdev:
          case RI_type_netdev_name:
            item = RI_type_comp_netdev;
            break;
          case RI_type_comp_nettemp:
          case RI_type_nettemp_name:
            item = RI_type_comp_nettemp;
            break;
          case RI_type_comp_netobj:
          case RI_type_netobj_name:
            item = RI_type_comp_netobj;
            break;
          default:
            fprintf(stderr, gettext("Invalid item %s\n"), argv[3]);
            exit(1);
        }
      if(verbose)
        {
          printf(gettext("Copying rights vector %s for type %u to type %u in role(s) %u to %u\n"),
                 get_rc_item_name(tmp1, item),
                 s_type,
                 t_type,
                 first_role,
                 last_role);
        }
      subtid.type = s_type;
      t_subtid.type = t_type;
      nr_roles = rsbac_rc_get_list(ta_number, RT_ROLE, &tid, RI_name, 0, NULL, NULL);
      error_exit(nr_roles);
      nr_roles += LISTROOM;
      role_array = malloc(nr_roles * sizeof(__u32));
      if(!role_array)
        {
          error_exit(-ENOMEM);
        }
      nr_roles = rsbac_rc_get_list(ta_number, RT_ROLE, &tid, RI_name, nr_roles, role_array, NULL);
      for(i=0; i<nr_roles; i++)
        {
          if(   (role_array[i] < first_role)
             || (role_array[i] > last_role)
            )
            continue;
          tid.role = role_array[i];
          if(!(tmpres = rsbac_rc_get_item(ta_number, RT_ROLE, &tid, &subtid, item, &value, &ttl)))
            {
              if((tmpres = rsbac_rc_set_item(ta_number, RT_ROLE, &tid, &t_subtid, item, &value, ttl)))
                {
                  fprintf(stderr, gettext("Changing role %u failed: %s\n"),
                          role_array[i],
                          get_error_name(tmp1, tmpres));
                  res = tmpres;
                }
            }
          else
            {
              if(errno != RSBAC_EINVALIDTARGET)
                {
                  fprintf(stderr, gettext("Reading from role %u failed: %s\n"),
                          role_array[i],
                          get_error_name(tmp1, tmpres));
                  res = tmpres;
                }
            }
        }
      free(role_array);
      exit(res);
    } /* end of type rights copy */

  if(delrights)
    {
      int tmpres = 0;
      rsbac_rc_type_id_t t_type;
      __u32 * role_array;
      int nr_roles;

      t_type = tid.type;
      if(t_type > RC_type_max_value)
        {
          fprintf(stderr, gettext("Invalid target type %u\n"), t_type);
          exit(1);
        }
      switch(item)
        {
          case RI_type_comp_fd:
          case RI_type_fd_name:
            item = RI_type_comp_fd;
            break;
          case RI_type_comp_dev:
          case RI_type_dev_name:
            item = RI_type_comp_dev;
            break;
          case RI_type_comp_user:
          case RI_type_user_name:
            item = RI_type_comp_dev;
            break;
          case RI_type_comp_process:
          case RI_type_process_name:
            item = RI_type_comp_process;
            break;
          case RI_type_comp_ipc:
          case RI_type_ipc_name:
            item = RI_type_comp_ipc;
            break;
          case RI_type_comp_scd:
          case RI_type_scd_name:
            item = RI_type_comp_scd;
            break;
          case RI_type_comp_group:
          case RI_type_group_name:
            item = RI_type_comp_group;
            break;
          case RI_type_comp_netdev:
          case RI_type_netdev_name:
            item = RI_type_comp_netdev;
            break;
          case RI_type_comp_nettemp:
          case RI_type_nettemp_name:
            item = RI_type_comp_nettemp;
            break;
          case RI_type_comp_netobj:
          case RI_type_netobj_name:
            item = RI_type_comp_netobj;
            break;
          default:
            fprintf(stderr, gettext("Invalid item %s\n"), argv[3]);
            exit(1);
        }
      if(verbose)
        {
          printf(gettext("Setting rights vector %s for type %u in all roles to 0\n"),
                 get_rc_item_name(tmp1, item),
                 t_type);
        }
      subtid.type = t_type;
      value.rights = 0;
      nr_roles = rsbac_rc_get_list(ta_number, RT_ROLE, &tid, RI_name, 0, NULL, NULL);
      error_exit(nr_roles);
      nr_roles += LISTROOM;
      role_array = malloc(nr_roles * sizeof(__u32));
      if(!role_array)
        {
          error_exit(-ENOMEM);
        }
      nr_roles = rsbac_rc_get_list(ta_number, RT_ROLE, &tid, RI_name, nr_roles, role_array, NULL);
      if(verbose)
        {
          printf(gettext("%u roles\n"),
                 nr_roles);
        }
      for(i=0; i<nr_roles; i++)
        {
          tid.role = role_array[i];
          if(   (tmpres = rsbac_rc_set_item(ta_number, RT_ROLE, &tid, &subtid, item, &value, 0))
             && (errno != RSBAC_ENOTFOUND)
            )
            {
              fprintf(stderr, gettext("Changing role %u failed: %s\n"),
                      role_array[i],
                      get_error_name(tmp1, tmpres));
              res = tmpres;
            }
        }
      exit(res);
    } /* end of set type rights to 0 */

  switch (item)
    {
      case RI_role_comp:
      case RI_admin_roles:
      case RI_assign_roles:
        if(   (argc == 5)
           && (strlen(argv[4]) == 64)
          )
          {
            rsbac_rc_role_vector_t rvec=0;
            int tmpres;

            strtou64rc(argv[4],&rvec);
            if(verbose)
              {
                printf(gettext("Setting %s of ROLE %i (old bitvector mode)\n"),
                       get_rc_item_name(tmp1, item), tid.role);
              }
            for (i=0; i<64; i++)
              {
                if(rvec & RSBAC_RC_ROLE_VECTOR(i))
                  {
                    if(printall)
                      {
                        printf("  %i to TRUE\n", i);
                      }
                    value.comp = TRUE;
                  }
                else
                  {
                    if(printall)
                      {
                        printf("  %i to FALSE\n", i);
                      }
                    value.comp = FALSE;
                  }
                subtid.role = i;
                if((tmpres = rsbac_rc_set_item(ta_number, RT_ROLE, &tid, &subtid, item, &value, ttl)))
                  {
                    fprintf(stderr, gettext("Setting for role %u failed: %s\n"),
                            i,
                            get_error_name(tmp1, tmpres));
                    res = tmpres;
                  }
              }
            exit(0);
          }
        else
        if(argc==6)
          {
            subtid.role = strtoul(argv[4],0,10);
#if 0
            if(subtid.role > RC_role_max_value)
              {
                fprintf(stderr, gettext("Invalid role %u!\n"),
                        subtid.role);
                exit(1);
              }
#endif
            value.comp = strtol(argv[5],0,10);
            
          }
        else
          {
            fprintf(stderr, gettext("Invalid number of arguments for item %s!\n"),
                    get_rc_item_name(tmp1, item));
            exit(1);
          }
        break;

      case RI_def_fd_ind_create_type:
        if(argc==6)
          {
            subtid.type = strtoul(argv[4],0,10);
            if(subtid.type > RC_type_max_value)
              {
                fprintf(stderr, gettext("Invalid type %u!\n"),
                        subtid.type);
                exit(1);
              }
            value.type_id = strtoul(argv[5],0,10);
          }
        else
          {
            fprintf(stderr, gettext("Invalid number of arguments for item %s!\n"),
                    get_rc_item_name(tmp1, item));
            exit(1);
          }
        break;

      case RI_def_fd_ind_create_type_remove:
        if(argc==5)
          {
            subtid.type = strtoul(argv[4],0,10);
            if(subtid.type > RC_type_max_value)
              {
                fprintf(stderr, gettext("Invalid type %u!\n"),
                        subtid.type);
                exit(1);
              }
          }
        else
          {
            fprintf(stderr, gettext("Invalid number of arguments for item %s!\n"),
                    get_rc_item_name(tmp1, item));
            exit(1);
          }
        break;

      case RI_type_comp_fd:
      case RI_type_comp_dev:
      case RI_type_comp_user:
      case RI_type_comp_process:
      case RI_type_comp_ipc:
      case RI_type_comp_scd:
      case RI_type_comp_group:
      case RI_type_comp_netdev:
      case RI_type_comp_nettemp:
      case RI_type_comp_netobj:
        if(argc<5)
          {
            fprintf(stderr, gettext("parameter comp_type missing\n"));
            exit(1);
          }
        subtid.type = strtoul(argv[4],0,10);
        if(subtid.type > RC_type_max_value)
          {
            fprintf(stderr, gettext("invalid subtid.type %s\n"), argv[4]);
            exit(1);
          }
        if(add || revoke)
          res = rsbac_rc_get_item(ta_number, target, &tid, &subtid, item, &value, NULL);
        error_exit(res);
        if(bitstring)
          {
            if(argc > 5)
              {
                if(strlen(argv[5]) != RCR_NONE)
                  {
                    fprintf(stderr, gettext("Invalid bitstring length %u, must be %u!\n"),
                            strlen(argv[5]),
                            RCR_NONE);
                    exit(1);
                  }
              }
            else
              {
                fprintf(stderr, gettext("No bitstring given!\n"));
                exit(1);
              }
            strtou64rcr(argv[5], &rights_vector);
            argv++;
            argc--;
          }
        else
        for(i=5; i<argc; i++)
          {
            right = get_rc_special_right_nr(argv[i]);
            if((right == R_NONE) || (right == RCR_NONE))
              {
                right = strtol(argv[i],0,10);
                if(   (   (right >= R_NONE)
                       && (right < RSBAC_RC_SPECIAL_RIGHT_BASE)
                      )
                   || (right >= RCR_NONE)
                   || (   (right == 0)
                       && strcmp(argv[i],"0")
                      )
                  )
                  {
                    if(!strcmp(argv[i],"W"))
                      {
                        rights_vector |= RSBAC_WRITE_REQUEST_VECTOR;
                        wused = TRUE;
                      }
                    else
                    if(!strcmp(argv[i],"RW"))
                      {
                        rights_vector |= RSBAC_READ_WRITE_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"SY"))
                      {
                        rights_vector |= RSBAC_SYSTEM_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"SE"))
                      {
                        rights_vector |= RSBAC_SECURITY_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"S"))
                      {
                        rights_vector |= RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"R"))
                      {
                        rights_vector |= RSBAC_READ_REQUEST_VECTOR;
                        rused = TRUE;
                      }
                    else
                    if(!strcmp(argv[i],"UA"))
                      {
                        rights_vector &= RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"A"))
                      {
                        rights_vector |= RSBAC_ALL_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"NWS"))
                      {
                        rights_vector |= RSBAC_NWS_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"NWR"))
                      {
                        rights_vector |= RSBAC_NWR_REQUEST_VECTOR;
                        rused = TRUE;
                      }
                    else
                    if(!strcmp(argv[i],"NWW"))
                      {
                        rights_vector |= RSBAC_NWW_REQUEST_VECTOR;
                        wused = TRUE;
                      }
                    else
                    if(!strcmp(argv[i],"NWC"))
                      {
                        rights_vector |= RSBAC_NWC_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"NWE"))
                      {
                        rights_vector |= RSBAC_NWE_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"NWA"))
                      {
                        rights_vector |= RSBAC_NWA_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"NWF"))
                      {
                        rights_vector |= RSBAC_NWF_REQUEST_VECTOR;
                      }
                    else
                    if(!strcmp(argv[i],"NWM"))
                      {
                        rights_vector |= RSBAC_NWM_REQUEST_VECTOR;
                      }
                    else
                      { /* end of rights */
                        break;
                      }
                  }
              }
            else
              {
                rights_vector |= RSBAC_RC_RIGHTS_VECTOR(right);
              }
          }
        if(printall)
          {
            for (i=0; i<R_NONE; i++)
              if(rights_vector & RSBAC_RC_RIGHTS_VECTOR(i))
                printf("  %s\n", get_request_name(tmp1,i));
            for (i=RSBAC_RC_SPECIAL_RIGHT_BASE; i<RCR_NONE; i++)
              if(rights_vector & RSBAC_RC_RIGHTS_VECTOR(i))
                printf("  %s\n", get_rc_special_right_name(tmp1,i));
          }
        switch(item)
          {
            case RI_none:
              fprintf(stderr, gettext("Invalid item %s\n"), argv[3]);
              exit(1);
            case RI_type_comp_fd:
              rights_vector &= (RSBAC_FD_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_dev:
              rights_vector &= (RSBAC_DEV_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_user:
              rights_vector &= (RSBAC_USER_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_process:
              rights_vector &= (RSBAC_RC_PROCESS_RIGHTS_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_ipc:
              rights_vector &= (RSBAC_IPC_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_scd:
              rights_vector &= (RSBAC_SCD_REQUEST_VECTOR | RSBAC_NONE_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_group:
              rights_vector &= (RSBAC_GROUP_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_netdev:
              rights_vector &= (RSBAC_NETDEV_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_nettemp:
              rights_vector &= (RSBAC_NETTEMP_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            case RI_type_comp_netobj:
              rights_vector &= (RSBAC_NETOBJ_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR);
              break;
            default:
              rights_vector &= RSBAC_RC_ALL_RIGHTS_VECTOR;
          }
        if(add)
          {
            if(verbose)
              {
                printf(gettext("Adding %s rights for ROLE %u to TYPE %u\n"),
                       get_rc_item_name(tmp1, item), tid.role, subtid.type);
              }
            value.rights |= rights_vector;
          }
        else
        if(revoke)
          {
            if(verbose)
              {
                printf(gettext("Revoking %s rights for ROLE %u from TYPE %u\n"),
                       get_rc_item_name(tmp1, item), tid.role, subtid.type);
              }
            value.rights &= ~rights_vector;
          }
        else
          {
            if(verbose)
              {
                printf(gettext("Setting %s rights for ROLE %u to TYPE %u\n"),
                       get_rc_item_name(tmp1, item), tid.role, subtid.type);
              }
            value.rights = rights_vector;
          }
        if(printall)
          {
            for (i=0; i<R_NONE; i++)
              if(rights_vector & RSBAC_RC_RIGHTS_VECTOR(i))
                printf("  %s\n", get_request_name(tmp1,i));
            for (i=RSBAC_RC_SPECIAL_RIGHT_BASE; i<RCR_NONE; i++)
              if(rights_vector & RSBAC_RC_RIGHTS_VECTOR(i))
                printf("  %s\n", get_rc_special_right_name(tmp1,i));
          }
        break;

      case RI_name:
      case RI_type_fd_name:
      case RI_type_dev_name:
      case RI_type_ipc_name:
      case RI_type_user_name:
      case RI_type_process_name:
      case RI_type_group_name:
      case RI_type_netdev_name:
      case RI_type_nettemp_name:
      case RI_type_netobj_name:
        if(argc<5)
          {
            fprintf(stderr, gettext("parameter name missing\n"));
            exit(1);
          }
        if(strlen(argv[4]) >= RSBAC_RC_NAME_LEN)
          {
            fprintf(stderr, gettext("Name string too long\n"));
            exit(1);
          }
        strcpy(value.name, argv[4]);
        break;

      case RI_admin_type:
        if(argc<5)
          {
            fprintf(stderr, gettext("parameter admin_type missing\n"));
            exit(1);
          }
        value.admin_type = get_rc_admin_nr(argv[4]);
        if(value.admin_type == RC_none)
          value.admin_type = strtol(argv[4],0,10);
        break;

      case RI_boot_role:
        if(argc<5)
          {
            fprintf(stderr, gettext("parameter boot_role missing\n"));
            exit(1);
          }
        value.boot_role = strtol(argv[4],0,10);
        break;

      case RI_req_reauth:
	if(argc<5)
	{
		fprintf(stderr, gettext("parameter req_reauth missing\n"));
		exit(1);
	}
	value.req_reauth = strtol(argv[4],0,10);
	break;

      default:
        if(argc>4)
          value.u_dummy = strtoul(argv[4],0,10);
        else
          value.dummy = -1;
    }
  res = rsbac_rc_set_item(ta_number, target, &tid, &subtid, item, &value, ttl);
  error_exit(res);
  exit(0);
}
