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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <rsbac/types.h>
#include <rsbac/getname.h>
#include <rsbac/acl_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

#define GROUP_PROG "acl_group"
#define GRANT_PROG "acl_grant"
#define MASK_PROG "acl_mask"
#define GROUPBASE 100000

#define S_IRWU (S_IRUSR | S_IWUSR)
#define S_IRXU (S_IRUSR | S_IXUSR)
#define S_IWXU (S_IWUSR | S_IXUSR)
#define S_IRWG (S_IRGRP | S_IWGRP)
#define S_IRXG (S_IRGRP | S_IXGRP)
#define S_IWXG (S_IWGRP | S_IXGRP)
#define S_IRWO (S_IROTH | S_IWOTH)
#define S_IRXO (S_IROTH | S_IXOTH)
#define S_IWXO (S_IWOTH | S_IXOTH)

#define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
#define S_IRWUGO (S_IRWU | S_IRWG | S_IRWO)

int verbose=0;
int recurse=0;
int printall=0;
int numeric=0;
int create_groups=0;
int only_groups=0;
u_int scripting=0;
union rsbac_attribute_value_t value;
enum rsbac_target_t target;
enum rsbac_attribute_t attr;
char * progname;

void use(void)
    {
      printf(gettext("%s (RSBAC %s)\n***\n"), progname, VERSION);
      printf(gettext("Use: %s [switches] file/dir/scdname(s)\n"), progname);  
      printf(gettext(" -h = this help, -- = no more flags,\n"));
      printf(gettext(" -v = use verbose in scripts, -r = recurse into subdirs,\n"));
      printf(gettext(" -g = also create group entries with members,\n"));
      printf(gettext(" -G = only create group entries with members,\n"));
      printf(gettext(" -p = print right names, -P use private groups\n"));
      printf(gettext(" -n = use numeric user ids where possible\n"));
    }

/* process name with parent values (p_mode = 0, if no parent) */
int process(char * name, u_int p_owner, u_int p_group, u_int p_mode)
  {
    int res = 0;
    char tmp1[120];
    enum rsbac_target_t type=T_NONE;
    char type_n[8] = "";
    struct stat buf;
    int i;
    rsbac_acl_rights_vector_t rights;

    /* do not try reserved name */
    if(!strcmp(name,":DEFAULT:"))
      return 0;

    res = lstat(name,&buf);
    if (res && (res != -EOVERFLOW))
      {
        fprintf(stderr, gettext("stat for %s returned error: %s\n"),
                name,
                strerror(errno));
        return(1);
      }
    if(   (res == -EOVERFLOW)
       || (S_ISREG(buf.st_mode))
       || (S_ISBLK(buf.st_mode))
       || (S_ISCHR(buf.st_mode)) )
      {
        type = T_FILE;
        strcpy(type_n,"FILE");
      }
    else
    if(S_ISDIR(buf.st_mode))
      {
        type = T_DIR;
        strcpy(type_n,"DIR");
      }
    else
    if(S_ISFIFO(buf.st_mode))
      {
        type = T_FIFO;
        strcpy(type_n,"FIFO");
      }
    /* no interest in other types */
    else
      return 0;

    /* no parent or different rights on parent? */
    if(   !p_mode
       || (p_owner != buf.st_uid)
       || (p_group != buf.st_gid)
          /* dirs with same mode as parent can inherit */
       || (   (type == T_DIR)
           && ((p_mode & S_IRWXUGO) != (buf.st_mode & S_IRWXUGO))
          )
          /* R_EXECUTE is never set on dirs here, so inherit by files without 
             x bits is fine, as long as the rw bits are the same */
       || (   (type != T_DIR)
           && ((p_mode & S_IRWUGO) != (buf.st_mode & S_IRWXUGO))
          )
      )
      {
        switch(type)
          {
            case T_DIR:
              if(printall)
                if(verbose)
                  printf("%s -vs USER %u",
                         GRANT_PROG,
                         buf.st_uid);
                else
                  printf("%s -s USER %u",
                         GRANT_PROG,
                         buf.st_uid);
              else
                if(verbose)
                  printf("%s -vsb USER %u",
                         GRANT_PROG,
                         buf.st_uid);
                else
                  printf("%s -sb USER %u",
                         GRANT_PROG,
                         buf.st_uid);
              /* all rights for user (always, if user == root)? */
              if(   ((buf.st_mode & S_IRWXU) == S_IRWXU)
                 || (buf.st_uid == 0)
                )
                {
                  rights = RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR;
                }
              else
              if((buf.st_mode & S_IRWU) == S_IRWU)
                {
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IRXU) == S_IRXU)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
                }
              else
              if((buf.st_mode & S_IWXU) == S_IWXU)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IRUSR) == S_IRUSR)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IWUSR) == S_IWUSR)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IXUSR) == S_IXUSR)
                {
                  rights =   RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
                rights = 0;

              /* Trim EXECUTE away - might be optional later */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
              /* Add system rights, if root */
              if(buf.st_uid == 0)
                rights |= (RSBAC_SYSTEM_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
              /* Trim CHANGE_OWNER away, if not root */
              else
                rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_CHANGE_OWNER);
              /* Add MODIFY_PERMISSIONS_DATA - owner may always do that */
              rights |= RSBAC_ACL_RIGHTS_VECTOR(R_MODIFY_PERMISSIONS_DATA);

              if(printall)
                {
                  for (i=0; i<R_NONE; i++)
                    if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                      printf(" %s", get_request_name(tmp1,i));
                }
              else
                printf(" %s",
                       u64tostracl(tmp1, rights));
              printf(" %s \"%s\"\n",
                     type_n, name);

              /* root gets full access to everyone's dirs - like it or not */
              if(buf.st_uid != 0)
                {
                  if(printall)
                    if(verbose)
                      printf("%s -vs USER %u",
                             GRANT_PROG,
                             0);
                    else
                      printf("%s -s USER %u",
                             GRANT_PROG,
                             0);
                  else
                    if(verbose)
                      printf("%s -vsb USER %u",
                             GRANT_PROG,
                             0);
                    else
                      printf("%s -sb USER %u",
                             GRANT_PROG,
                             0);
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR)
                           & RSBAC_FD_REQUEST_VECTOR;
                  if(printall)
                    {
                      for (i=0; i<R_NONE; i++)
                        if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                          printf(" %s", get_request_name(tmp1,i));
                    }
                  else
                    printf(" %s",
                           u64tostracl(tmp1, rights));
                  printf(" %s \"%s\"\n",
                         type_n, name);
                }


              if(printall)
                if(verbose)
                  printf("%s -vs GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
                else
                  printf("%s -s GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
              else
                if(verbose)
                  printf("%s -vsb GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
                else
                  printf("%s -sb GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
              /* all rights for group? */
              if((buf.st_mode & S_IRWXG) == S_IRWXG)
                {
                  rights = RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR;
                }
              else
              if((buf.st_mode & S_IRWG) == S_IRWG)
                {
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IRXG) == S_IRXG)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
                }
              else
              if((buf.st_mode & S_IWXG) == S_IWXG)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IRGRP) == S_IRGRP)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IWGRP) == S_IWGRP)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IXGRP) == S_IXGRP)
                {
                  rights =   RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
                rights = 0;

              /* Trim EXECUTE away - might be optional later */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
              /* Trim CHANGE_OWNER away - only root may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_CHANGE_OWNER);
              /* Trim MODIFY_PERMISSIONS_DATA away - only owner may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_MODIFY_PERMISSIONS_DATA);

              if(printall)
                {
                  for (i=0; i<R_NONE; i++)
                    if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                      printf(" %s", get_request_name(tmp1,i));
                }
              else
                printf(" %s",
                       u64tostracl(tmp1, rights));
              printf(" %s \"%s\"\n",
                     type_n, name);


              if(printall)
                if(verbose)
                  printf("%s -vs GROUP 0",
                         GRANT_PROG);
                else
                  printf("%s -s GROUP 0",
                         GRANT_PROG);
              else
                if(verbose)
                  printf("%s -vsb GROUP 0",
                         GRANT_PROG);
                else
                  printf("%s -sb GROUP 0",
                         GRANT_PROG);
              /* all rights for others? */
              if((buf.st_mode & S_IRWXO) == S_IRWXO)
                {
                  rights = RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR;
                }
              else
              if((buf.st_mode & S_IRWO) == S_IRWO)
                {
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IRXO) == S_IRXO)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
                }
              else
              if((buf.st_mode & S_IWXO) == S_IWXO)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IROTH) == S_IROTH)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
              if((buf.st_mode & S_IWOTH) == S_IWOTH)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IXOTH) == S_IXOTH)
                {
                  rights =   RSBAC_ACL_RIGHTS_VECTOR(R_CHDIR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_SEARCH);
                }
              else
                rights = 0;

              /* Trim EXECUTE away - might be optional later */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
              /* Trim CHANGE_OWNER away - only root may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_CHANGE_OWNER);
              /* Trim MODIFY_PERMISSIONS_DATA away - only owner may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_MODIFY_PERMISSIONS_DATA);

              if(printall)
                {
                  for (i=0; i<R_NONE; i++)
                    if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                      printf(" %s", get_request_name(tmp1,i));
                }
              else
                printf(" %s",
                       u64tostracl(tmp1, rights));
              printf(" %s \"%s\"\n",
                     type_n, name);

              break;

            /*********************/
            /* handle FILE, FIFO */
            case T_FILE:
            case T_FIFO:
              if(printall)
                if(verbose)
                  printf("%s -vs USER %u",
                         GRANT_PROG,
                         buf.st_uid);
                else
                  printf("%s -s USER %u",
                         GRANT_PROG,
                         buf.st_uid);
              else
                if(verbose)
                  printf("%s -vsb USER %u",
                         GRANT_PROG,
                         buf.st_uid);
                else
                  printf("%s -sb USER %u",
                         GRANT_PROG,
                         buf.st_uid);
              /* all rights for user (always, if user == root)? */
              if((buf.st_mode & S_IRWXU) == S_IRWXU)
                {
                  rights = RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR;
                }
              else
              if((buf.st_mode & S_IRWU) == S_IRWU)
                {
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                }
              else
              if((buf.st_mode & S_IRXU) == S_IRXU)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
                }
              else
              if((buf.st_mode & S_IWXU) == S_IWXU)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IRUSR) == S_IRUSR)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                }
              else
              if((buf.st_mode & S_IWUSR) == S_IWUSR)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IXUSR) == S_IXUSR)
                {
                  rights =   RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
                rights = 0;

              /* Add system and non-exec rights, if root */
              if(buf.st_uid == 0)
                rights |= (RSBAC_SYSTEM_REQUEST_VECTOR | RSBAC_READ_WRITE_REQUEST_VECTOR)
                          & RSBAC_FD_REQUEST_VECTOR
                          & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
              /* Trim CHANGE_OWNER away, if not root */
              else
                rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_CHANGE_OWNER);
              /* Add MODIFY_PERMISSIONS_DATA - owner may always do that */
              rights |= RSBAC_ACL_RIGHTS_VECTOR(R_MODIFY_PERMISSIONS_DATA);

              if(printall)
                {
                  for (i=0; i<R_NONE; i++)
                    if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                      printf(" %s", get_request_name(tmp1,i));
                }
              else
                printf(" %s",
                       u64tostracl(tmp1, rights));
              printf(" %s \"%s\"\n",
                     type_n, name);

              /* root gets full access to everyone's files - like it or not */
              if(buf.st_uid != 0)
                {
                  if(printall)
                    if(verbose)
                      printf("%s -vs USER %u",
                             GRANT_PROG,
                             0);
                    else
                      printf("%s -s USER %u",
                             GRANT_PROG,
                             0);
                  else
                    if(verbose)
                      printf("%s -vsb USER %u",
                             GRANT_PROG,
                             0);
                    else
                      printf("%s -sb USER %u",
                             GRANT_PROG,
                             0);
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR)
                           & RSBAC_FD_REQUEST_VECTOR
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                  /* root can only execute, if one x bit is set */
                  if(   (buf.st_mode & S_IXUSR)
                     || (buf.st_mode & S_IXGRP)
                     || (buf.st_mode & S_IXOTH)
                    )
                    rights |=   RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                              | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC);
                  if(printall)
                    {
                      for (i=0; i<R_NONE; i++)
                        if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                          printf(" %s", get_request_name(tmp1,i));
                    }
                  else
                    printf(" %s",
                           u64tostracl(tmp1, rights));
                  printf(" %s \"%s\"\n",
                         type_n, name);
                }


              if(printall)
                if(verbose)
                  printf("%s -vs GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
                else
                  printf("%s -s GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
              else
                if(verbose)
                  printf("%s -vsb GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
                else
                  printf("%s -sb GROUP %u",
                         GRANT_PROG,
                         GROUPBASE + buf.st_gid);
              /* all rights for group? */
              if((buf.st_mode & S_IRWXG) == S_IRWXG)
                {
                  rights = RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR;
                }
              else
              if((buf.st_mode & S_IRWG) == S_IRWG)
                {
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                }
              else
              if((buf.st_mode & S_IRXG) == S_IRXG)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
                }
              else
              if((buf.st_mode & S_IWXG) == S_IWXG)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IRGRP) == S_IRGRP)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                }
              else
              if((buf.st_mode & S_IWGRP) == S_IWGRP)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IXGRP) == S_IXGRP)
                {
                  rights =   RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
                rights = 0;

              /* Trim CHANGE_OWNER away - only root may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_CHANGE_OWNER);
              /* Trim MODIFY_PERMISSIONS_DATA away - only owner may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_MODIFY_PERMISSIONS_DATA);

              if(printall)
                {
                  for (i=0; i<R_NONE; i++)
                    if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                      printf(" %s", get_request_name(tmp1,i));
                }
              else
                printf(" %s",
                       u64tostracl(tmp1, rights));
              printf(" %s \"%s\"\n",
                     type_n, name);


              if(printall)
                if(verbose)
                  printf("%s -vs GROUP 0",
                         GRANT_PROG);
                else
                  printf("%s -s GROUP 0",
                         GRANT_PROG);
              else
                if(verbose)
                  printf("%s -vsb GROUP 0",
                         GRANT_PROG);
                else
                  printf("%s -sb GROUP 0",
                         GRANT_PROG);
              /* all rights for others? */
              if((buf.st_mode & S_IRWXO) == S_IRWXO)
                {
                  rights = RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR;
                }
              else
              if((buf.st_mode & S_IRWO) == S_IRWO)
                {
                  rights = (RSBAC_READ_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                }
              else
              if((buf.st_mode & S_IRXO) == S_IRXO)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR);
                }
              else
              if((buf.st_mode & S_IWXO) == S_IWXO)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IROTH) == S_IROTH)
                {
                  rights = (RSBAC_READ_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           & ~RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE);
                }
              else
              if((buf.st_mode & S_IWOTH) == S_IWOTH)
                {
                  rights = (RSBAC_WRITE_REQUEST_VECTOR & RSBAC_FD_REQUEST_VECTOR)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
              if((buf.st_mode & S_IXOTH) == S_IXOTH)
                {
                  rights =   RSBAC_ACL_RIGHTS_VECTOR(R_EXECUTE)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_MAP_EXEC)
                           | RSBAC_ACL_RIGHTS_VECTOR(R_GET_STATUS_DATA);
                }
              else
                rights = 0;

              /* Trim CHANGE_OWNER away - only root may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_CHANGE_OWNER);
              /* Trim MODIFY_PERMISSIONS_DATA away - only owner may do that */
              rights &= ~RSBAC_ACL_RIGHTS_VECTOR(R_MODIFY_PERMISSIONS_DATA);

              if(printall)
                {
                  for (i=0; i<R_NONE; i++)
                    if(rights & ((rsbac_acl_rights_vector_t) 1 << i))
                      printf(" %s", get_request_name(tmp1,i));
                }
              else
                printf(" %s",
                       u64tostracl(tmp1, rights));
              printf(" %s \"%s\"\n",
                     type_n, name);

              break;

            default:
              fprintf(stderr, gettext("internal error in switch\n"));
          }

        /* set mask to special rights only */
        if(verbose)
          printf("%s -sv",
                 MASK_PROG);
        else
          printf("%s -s",
                 MASK_PROG);
        if(printall)
          {
            int i;

            for (i=RSBAC_ACL_SPECIAL_RIGHT_BASE; i<ACLR_NONE; i++)
              printf(" %s", get_acl_special_right_name(tmp1,i));
          }
        else
          {
            printf(" %s", u64tostracl(tmp1, RSBAC_ACL_SPECIAL_RIGHTS_VECTOR));
          }
        printf(" %s \"%s\"\n", type_n, name);
      }

    if (   (type == T_DIR)
        && recurse)
      {
        DIR * dir_stream_p;
        struct dirent * dirent_p;
        char name2[PATH_MAX];

        if(S_ISLNK(buf.st_mode))
          return(0);
        if(!(dir_stream_p = opendir(name)))
          {
            fprintf(stderr, gettext("opendir for dir %s returned error: %s\n"),
                   name,
                   strerror(errno));
            return(-2);
          }
        while((dirent_p = readdir(dir_stream_p)))
          {
            if(   (strcmp(".",dirent_p->d_name))
               && (strcmp("..",dirent_p->d_name)) )
              {
                strcpy(name2,name);
                strcat(name2,"/");
                strcat(name2,dirent_p->d_name);
                process(name2, buf.st_uid, buf.st_gid, buf.st_mode);
              }
          }
        closedir(dir_stream_p);
      }
    return(0);
  }

int main(int argc, char ** argv)
{
  int i;

  struct passwd * user_info_p;
  struct group  * group_info_p;
  char gtype = 'G';
  char ** gmem;
  u_int stopflags = FALSE;

  locale_init();
  
  progname = argv[0];
  while((argc > 1) && (argv[1][0] == '-') && !stopflags)
    {
      char * pos = argv[1];
      pos++;
      while(*pos)
        {
          switch(*pos)
            {
              case '-':
                stopflags = TRUE;
                break;
              case 'h':
                use();
                return 0;
              case 'v':
                verbose=1;
                break;
              case 'r':
                recurse=1;
                break;
              case 'g':
                create_groups=1;
                break;
              case 'G':
                create_groups=1;
                only_groups=1;
                break;
              case 'p':
                printall=1;
                break;
              case 'P':
                gtype='P';
                break;
              case 'n':
                numeric=1;
              default:
                fprintf(stderr, gettext("%s: unknown parameter %c\n"), progname, *pos);
                exit(1);
            }
          pos++;
        }
      argv++;
      argc--;
    }
  if (   (argc < 2)
      && !only_groups
     )
    {
      use();
      return 1;
    }

  printf("#\n# linux2acl: convert linux groups and rights to RSBAC ACL rights\n#\n");

  if(create_groups)
    {
      /* Create group entries */
      while((group_info_p = getgrent()))
        {
          printf("%s add_group %c '%s' %u\n",
                 GROUP_PROG,
                 gtype,
                 group_info_p->gr_name,
                 GROUPBASE + group_info_p->gr_gid);
          gmem = group_info_p->gr_mem;
          if(gmem && *gmem)
            {
              printf("%s add_member %u",
                     GROUP_PROG,
                     GROUPBASE + group_info_p->gr_gid);
              while(*gmem)
                {
                  printf(" %s",
                         *gmem);
                  gmem++;
                }
              printf("\n");
            }
          printf("\n");
        }
      endgrent();

      /* Add users to their main groups */
      printf("# User main groups\n");
      while((user_info_p = getpwent()))
        {
          if(numeric)
            printf("%s add_member %u %u\n",
                   GROUP_PROG,
                   GROUPBASE + user_info_p->pw_gid,
                   user_info_p->pw_uid);
          else
            printf("%s add_member %u %s\n",
                   GROUP_PROG,
                   GROUPBASE + user_info_p->pw_gid,
                   user_info_p->pw_name);
        }
      endpwent();
    }

  if(only_groups)
    return(0);

  printf("#\n# Object ACLs\n#\n");

  for (i=1;i < (argc);i++)
    {
      /* process without parent */
      process(argv[i], 0, 0, 0);
    }
  return (0);
}

