Logo Search packages:      
Sourcecode: eiciel version File versions  Download package

gestor_acl.cpp

/*
    Eiciel - GNOME editor of ACL file permissions.
    Copyright (C) 2004-2005 Roger Ferrer Ibáñez

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#include "gestor_acl.hpp"

GestorACL::GestorACL(const string& nomF) throw (GestorACLException)
      : nomFitxer(nomF) 
{
      // Primer obtindrem els permisos UGO
      // i informacio del fitxer
      obtenirPermisosUGO();

      obtenirACLAccess();

      // Si es un directori obtenim les ACL default
      if (esDir)
      {
            obtenirACLDefault();
      }

      generarRepresentacioTextual();
}

void GestorACL::obtenirPermisosUGO()
{
      struct stat buffer;
      if (stat(nomFitxer.c_str(), &buffer) == -1)
      {
            throw GestorACLException(Glib::locale_to_utf8(strerror(errno)));
      }

      // Comprovem si es un fitxer regular o un directori
      if (!S_ISREG(buffer.st_mode) && !S_ISDIR(buffer.st_mode))
      {
            throw GestorACLException(_("Only regular files or directories supported")); // De moment...
      }

      // Ens apuntem si es un directori
      esDir = S_ISDIR(buffer.st_mode);

      // Llegim els permisos
      // Permisos d'usuari propietari
      // permisosPropietari.lectura = buffer.st_mode & S_IRUSR;
      // permisosPropietari.escriptura = buffer.st_mode & S_IWUSR;
      // permisosPropietari.execucio = buffer.st_mode & S_IXUSR;

      // // Permisos del grup propietari
      // permisosGrup.lectura = buffer.st_mode & S_IRGRP;
      // permisosGrup.escriptura = buffer.st_mode & S_IWGRP;
      // permisosGrup.execucio = buffer.st_mode & S_IXGRP;

      // // Permisos de la resta del mon mundial
      // permisosAltres.lectura = buffer.st_mode & S_IROTH;
      // permisosAltres.escriptura = buffer.st_mode & S_IWOTH;
      // permisosAltres.execucio = buffer.st_mode & S_IXOTH;

      // Obtenim el nom de l'usuari
      uidPropietari = buffer.st_uid;
      struct passwd* u = getpwuid(buffer.st_uid);

      if (u == NULL)
      {
            stringstream ss;
            ss << "(" << buffer.st_uid << ")"; 
            nomPropietari = ss.str();
      }
      else
      {
            nomPropietari = u->pw_name;
      }

      // Obtenim el nom del grup
      struct group* g = getgrgid(buffer.st_gid);

      if (g == NULL)
      {
            stringstream ss;
            ss << "(" << buffer.st_gid << ")"; 
            nomGrup = ss.str();
      }
      else
      {
            nomGrup = g->gr_name;
      }
}


void GestorACL::obtenirACLAccess()
{
      aclUsuari.clear();
      aclGrup.clear();
      hiHaMascara = false;
      // Obtenim l'acl d'accés
      acl_t aclFitxer = acl_get_file(nomFitxer.c_str(), ACL_TYPE_ACCESS);

    if (aclFitxer == (acl_t) NULL)
    {
        throw GestorACLException(Glib::locale_to_utf8(strerror(errno)));
    }

      // Obtenim totes les entries
      acl_entry_t entradaACL;
      acl_permset_t conjuntPermisos;
      acl_tag_t tipusTagACL;

      int trobat = acl_get_entry(aclFitxer, ACL_FIRST_ENTRY, &entradaACL);
      int index = 0;
      while (trobat == 1)
      {
            acl_get_permset(entradaACL, &conjuntPermisos);
            acl_get_tag_type(entradaACL, &tipusTagACL);

            if (tipusTagACL == ACL_USER || tipusTagACL == ACL_GROUP)
            {
                  // Es una entradeta de tipus usuari
                  // Ara hem de saber els permisos
                  entrada_acl novaACL;
                  novaACL.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  novaACL.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  novaACL.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
                  // Obtenim el qualificador
                  if (tipusTagACL == ACL_USER)
                  {
                        void* ptr_aclUsuari = acl_get_qualifier(entradaACL);
                        uid_t* idUsuari = (uid_t*) ptr_aclUsuari;
                        struct passwd* p = getpwuid(*idUsuari);
                        novaACL.nomValid = (p != NULL);
                        if (p == NULL) 
                        {
                              stringstream ss;
                              ss << "(" << *idUsuari << ")";
                              novaACL.nom = ss.str();
                        }
                        else 
                        {
                              novaACL.nom = p->pw_name;
                        }
                        novaACL.qualificador = *idUsuari;
                        acl_free(ptr_aclUsuari);

                        aclUsuari.push_back(novaACL);
                  }
                  else
                  {
                        void* ptr_aclGrup = acl_get_qualifier(entradaACL);
                        gid_t* idGrup = (gid_t*) ptr_aclGrup;
                        novaACL.qualificador = *idGrup;
                        struct group* g = getgrgid(*idGrup);
                        novaACL.nomValid = (g != NULL);
                        if (g == NULL)
                        {
                              stringstream ss;
                              ss << "(" << *idGrup << ")";
                              novaACL.nom = ss.str();
                        }
                        else
                        {
                              novaACL.nom = g->gr_name;
                        }
                        acl_free(ptr_aclGrup);

                        aclGrup.push_back(novaACL);
                  }
            }
            else if (tipusTagACL == ACL_MASK)
            {
                  // La mascara ACL
                  hiHaMascara = true;
                  mascaraACL.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  mascaraACL.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  mascaraACL.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
            }
            else if (tipusTagACL == ACL_USER_OBJ)
            {
                  permisosPropietari.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  permisosPropietari.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  permisosPropietari.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
                  
            }
            else if (tipusTagACL == ACL_GROUP_OBJ)
            {
                  permisosGrup.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  permisosGrup.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  permisosGrup.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);

            }
            else if (tipusTagACL == ACL_OTHER)
            {
                  permisosAltres.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  permisosAltres.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  permisosAltres.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
            }

            trobat = acl_get_entry(aclFitxer, ACL_NEXT_ENTRY, &entradaACL);
            index++;
      }

      acl_free(aclFitxer);
}

void GestorACL::obtenirACLDefault()
{
      hiHaDefaultMascara = hiHaDefaultUsuari = hiHaDefaultGrup = hiHaDefaultAltres = false;
      defaultACLUsuari.clear();
      defaultACLGrup.clear();
      acl_t aclFitxer = acl_get_file(nomFitxer.c_str(), ACL_TYPE_DEFAULT);

      // Obtenim totes les entries
      acl_entry_t entradaACL;
      acl_permset_t conjuntPermisos;
      acl_tag_t tipusTagACL;

      int trobat = acl_get_entry(aclFitxer, ACL_FIRST_ENTRY, &entradaACL);
      while (trobat == 1)
      {
            acl_get_permset(entradaACL, &conjuntPermisos);
            acl_get_tag_type(entradaACL, &tipusTagACL);

            if (tipusTagACL == ACL_USER || tipusTagACL == ACL_GROUP)
            {
                  // Es una entradeta de tipus usuari
                  // Ara hem de saber els permisos
                  entrada_acl novaACL;
                  novaACL.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  novaACL.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  novaACL.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
                  // Obtenim el qualificador
                  if (tipusTagACL == ACL_USER)
                  {
                        void* ptr_idUsuari = acl_get_qualifier(entradaACL);
                        uid_t* idUsuari = (uid_t*)ptr_idUsuari;
                        struct passwd* p = getpwuid(*idUsuari);
                        novaACL.nomValid = (p != NULL);
                        if (p == NULL) 
                        {
                              stringstream ss;
                              ss << "(" << *idUsuari << ")";
                              novaACL.nom = ss.str();
                        }
                        else 
                        {
                              novaACL.nom = p->pw_name;
                        }
                        novaACL.qualificador = *idUsuari;
                        acl_free(ptr_idUsuari);

                        defaultACLUsuari.push_back(novaACL);
                  }
                  else
                  {
                        void* ptr_idGrup = acl_get_qualifier(entradaACL);
                        gid_t* idGrup = (gid_t*)ptr_idGrup;
                        novaACL.qualificador = *idGrup;
                        struct group* g = getgrgid(*idGrup);
                        novaACL.nomValid = (g != NULL);
                        if (g == NULL)
                        {
                              stringstream ss;
                              ss << "(" << *idGrup << ")";
                              novaACL.nom = ss.str();
                        }
                        else
                        {
                              novaACL.nom = g->gr_name;
                        }
                        acl_free(ptr_idGrup);

                        defaultACLGrup.push_back(novaACL);
                  }
            }
            else if (tipusTagACL == ACL_USER_OBJ)
            {
                  // És l'entrada per defecte d'usuari
                  hiHaDefaultUsuari = true;
                  defaultUsuari.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  defaultUsuari.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  defaultUsuari.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
            }
            else if (tipusTagACL == ACL_GROUP_OBJ)
            {
                  // És l'entrada per defecte del grup
                  hiHaDefaultGrup = true;
                  defaultGrup.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  defaultGrup.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  defaultGrup.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
            }
            else if (tipusTagACL == ACL_OTHER)
            {
                  // És l'entrada per defecte dels altres
                  hiHaDefaultAltres = true;
                  defaultAltres.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  defaultAltres.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  defaultAltres.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
            }
            else if (tipusTagACL == ACL_MASK)
            {
                  // La mascara ACL
                  hiHaDefaultMascara = true;
                  defaultMascara.lectura = ACL_GET_PERM(conjuntPermisos, ACL_READ);
                  defaultMascara.escriptura = ACL_GET_PERM(conjuntPermisos, ACL_WRITE);
                  defaultMascara.execucio = ACL_GET_PERM(conjuntPermisos, ACL_EXECUTE);
            }

            trobat = acl_get_entry(aclFitxer, ACL_NEXT_ENTRY, &entradaACL);
      }

      acl_free(aclFitxer);
}

void GestorACL::generarRepresentacioTextual()
{
      textACLAccess.clear();

      textACLAccess += "u::" + permisStr(permisosPropietari) + "\n";
      for (vector<entrada_acl>::iterator i = aclUsuari.begin();
                  i != aclUsuari.end(); i++)
      {
            textACLAccess += "u:" + escriureNom(*i) + ":" + permisStr(*i) + "\n";
      }
      
      textACLAccess += "g::" + permisStr(permisosGrup) + "\n";
      for (vector<entrada_acl>::iterator i = aclGrup.begin();
                  i != aclGrup.end(); i++)
      {
            textACLAccess += "g:" + escriureNom(*i) + ":" + permisStr(*i) + "\n";
      }

      if (hiHaMascara)
      {
            textACLAccess += "m::" + permisStr(mascaraACL) + "\n";
      }
      textACLAccess += "o::" + permisStr(permisosAltres) + "\n";

      textACLDefault.clear();
      if (esDir)
      {
            if (hiHaDefaultUsuari)
            {
                  textACLDefault += "u::" + permisStr(defaultUsuari) + "\n";
            }
            if (hiHaDefaultGrup)
            {
                  textACLDefault += "g::" + permisStr(defaultGrup) + "\n";
            }
            if (hiHaDefaultAltres)
            {
                  textACLDefault += "o::" + permisStr(defaultAltres) + "\n";
            }

            for (vector<entrada_acl>::iterator i = defaultACLUsuari.begin();
                        i != defaultACLUsuari.end(); i++)
            {
                  textACLDefault += "u:" + escriureNom(*i) + ":" + permisStr(*i) + "\n";
            }
            for (vector<entrada_acl>::iterator i = defaultACLGrup.begin();
                        i != defaultACLGrup.end(); i++)
            {
                  textACLDefault += "g:" + escriureNom(*i) + ":" + permisStr(*i) + "\n";
            }

            if (hiHaDefaultMascara)
            {
                  textACLDefault += "m::" + permisStr(defaultMascara) + "\n";
            }
      }
}

string GestorACL::escriureNom(entrada_acl& eacl)
{
      if (eacl.nomValid)
      {
            return eacl.nom;
      }
      else
      {
            stringstream ss;
            ss << eacl.qualificador;
            return ss.str();
      }
}

string GestorACL::permisStr(permisos_t& p)
{
      string s;
      s.clear();
      s += (p.lectura ? "r" : "-");
      s += (p.escriptura ? "w" : "-");
      s += (p.execucio ? "x" : "-");
      return s;
}

void GestorACL::modificarACLUsuari(const string& nomUsuari, const permisos_t& permisos)
{
      modificarACLGenerica(nomUsuari, aclUsuari, permisos);
      actualitzarCanvisACLAccess();
}

void GestorACL::modificarACLGrup(const string& nomGrup, const permisos_t& permisos)
{
      modificarACLGenerica(nomGrup, aclGrup, permisos);
      actualitzarCanvisACLAccess();
}

void GestorACL::actualitzarCanvisACLAccess()
{
      // Si hi ha alguna entrada d'usuari o grup
      // hi ha d'haver una màscara
      if ((aclUsuari.size() + aclGrup.size()) > 0)
      {
            if (!hiHaMascara)
            {
                  calculaMascaraAccess();
            }
      }
      else // Sino no cal màscara
      {
            hiHaMascara = false;
      }
      generarRepresentacioTextual();
      aplicarCanvisAlFitxer();
}

void GestorACL::modificarDefaultACLUsuari(const string& nomUsuari, const permisos_t& permisos)
{
      modificarACLGenerica(nomUsuari, defaultACLUsuari, permisos);
      actualitzarCanvisACLDefault();
}

void GestorACL::modificarDefaultACLGrup(const string& nomGrup, const permisos_t& permisos)
{
      modificarACLGenerica(nomGrup, defaultACLGrup, permisos);
      actualitzarCanvisACLDefault();
}

void GestorACL::actualitzarCanvisACLDefault()
{
      if ((defaultACLUsuari.size() + defaultACLGrup.size()) > 0)
      {
            emplenaACLDefaultNecessaries();
      }

      generarRepresentacioTextual();
      aplicarCanvisAlFitxer();
}

void GestorACL::emplenaACLDefaultNecessaries()
{
      if (!hiHaDefaultUsuari)
      {
            hiHaDefaultUsuari = true;
            defaultUsuari.lectura = permisosPropietari.lectura;
            defaultUsuari.escriptura = permisosPropietari.escriptura;
            defaultUsuari.execucio = permisosPropietari.execucio;
      }
      if (!hiHaDefaultGrup)
      {
            hiHaDefaultGrup = true;
            defaultGrup.lectura = permisosGrup.lectura;
            defaultGrup.escriptura = permisosGrup.escriptura;
            defaultGrup.execucio = permisosGrup.execucio;
      }
      if (!hiHaDefaultAltres)
      {
            hiHaDefaultAltres = true;
            defaultAltres.lectura = permisosAltres.lectura;
            defaultAltres.escriptura = permisosAltres.escriptura;
            defaultAltres.execucio = permisosAltres.execucio;
      }
      if (!hiHaDefaultMascara)
      {
            hiHaDefaultMascara = true;
            defaultMascara = permisos_t(7);
      }
}

void GestorACL::modificarACLGenerica(const string& nom, vector<entrada_acl>& llistaACL, const permisos_t& permisos)
{
      EquivalenciaACL equivACL(nom);
      vector<entrada_acl>::iterator i = find_if(llistaACL.begin(), llistaACL.end(), equivACL);
      if (i != llistaACL.end()) // Hi és
      {
            i->lectura = permisos.lectura;
            i->escriptura = permisos.escriptura;
            i->execucio = permisos.execucio;
      }
      else // No hi és
      {
            entrada_acl eacl;
            eacl.nomValid = true;
            eacl.nom = nom;
            eacl.lectura = permisos.lectura;
            eacl.escriptura = permisos.escriptura;
            eacl.execucio = permisos.execucio;
            llistaACL.push_back(eacl);
      }
}

void GestorACL::eliminarACLUsuari(const string& nomUsuari)
{
      eliminarACLGenerica(nomUsuari, aclUsuari);
      actualitzarCanvisACLAccess();
}

void GestorACL::eliminarACLGrup(const string& nomGrup)
{
      eliminarACLGenerica(nomGrup, aclGrup);
      actualitzarCanvisACLAccess();
}

void GestorACL::eliminarDefaultACLUsuari(const string& nomUsuari)
{
      eliminarACLGenerica(nomUsuari, defaultACLUsuari);
      actualitzarCanvisACLDefault();
}

void GestorACL::eliminarDefaultACLGrup(const string& nomGrup)
{
      eliminarACLGenerica(nomGrup, defaultACLGrup);
      actualitzarCanvisACLDefault();
}

void GestorACL::eliminarACLGenerica(const string& nom, vector<entrada_acl>& llistaACL)
{
      EquivalenciaACL equivACL(nom);
      llistaACL.erase(remove_if(llistaACL.begin(), llistaACL.end(), equivACL), llistaACL.end());
}

void GestorACL::aplicarCanvisAlFitxer()
{
      // Obtenim la ACL de la representacio textual
      acl_t aclAccess = acl_from_text(textACLAccess.c_str());
      if (aclAccess == NULL)
      {
            std::cerr << "ACL is wrong!!!" << endl << textACLAccess.c_str() << endl;
            
            throw GestorACLException(_("Textual representation of the ACL is wrong"));
      }
    if (acl_set_file(nomFitxer.c_str(), ACL_TYPE_ACCESS, aclAccess) != 0)
      {
            throw GestorACLException(Glib::locale_to_utf8(strerror(errno)));
      }

      if (esDir)
      {
            // Buidem primer la ACL
            if (acl_delete_def_file(nomFitxer.c_str()) != 0)
            {
                  throw GestorACLException(Glib::locale_to_utf8(strerror(errno)));
            }

            // i si hi ha algo ho posem, aixi evitem problemes amb FreeBSD 5.x
            if (textACLDefault.size() > 0)
            {
                  acl_t aclDefault = acl_from_text(textACLDefault.c_str());
                  if (aclAccess == NULL)
                  {
                        std::cerr << "Default ACL is wrong!!!" << endl << textACLDefault.c_str() << endl;
                        throw GestorACLException(_("Default textual representation of the ACL is wrong"));
                  }

                  if (acl_set_file(nomFitxer.c_str(), ACL_TYPE_DEFAULT, aclDefault) != 0)
                  {
                        throw GestorACLException(Glib::locale_to_utf8(strerror(errno)));
                  }
            }
      }
      acl_free(aclAccess);
}


void GestorACL::buidarACLDefecte()
{
      hiHaDefaultUsuari = hiHaDefaultGrup = hiHaDefaultAltres = hiHaDefaultMascara = false;
      defaultACLUsuari.clear();     
      defaultACLGrup.clear(); 
      actualitzarCanvisACLDefault();
}

void GestorACL::buidarTotesLesACL()
{
      aclUsuari.clear();
      aclGrup.clear();
      hiHaMascara = false;
      hiHaDefaultUsuari = false;
      hiHaDefaultGrup = false;
      hiHaDefaultAltres = false;
      hiHaDefaultMascara = false;
      generarRepresentacioTextual();
      aplicarCanvisAlFitxer();
}

void GestorACL::calculaMascaraAccess()
{
      // De moment afegirem una màscara laxa
      hiHaMascara = true;
      mascaraACL = permisos_t(7);
      generarRepresentacioTextual();
}

void GestorACL::modificarPermisosPropietari(permisos_t& p)
{
      permisosPropietari = p;
      actualitzarCanvisACLAccess();
}

void GestorACL::modificarPermisosGrup(permisos_t& p)
{
      permisosGrup = p;
      actualitzarCanvisACLAccess();
}

void GestorACL::modificarPermisosAltres(permisos_t& p)
{
      permisosAltres = p;
      actualitzarCanvisACLAccess();
}

void GestorACL::modificarMascara(permisos_t& p)
{
      hiHaMascara = true;
      mascaraACL = p;
      actualitzarCanvisACLAccess();
}

void GestorACL::modificarPermisosDefaultPropietari(permisos_t& p)
{
      hiHaDefaultUsuari = true;
      defaultUsuari = p;
      emplenaACLDefaultNecessaries();
      actualitzarCanvisACLDefault();
}

void GestorACL::modificarPermisosDefaultGrup(permisos_t& p)
{
      hiHaDefaultGrup = true;
      defaultGrup = p;
      emplenaACLDefaultNecessaries();
      actualitzarCanvisACLDefault();
}

void GestorACL::modificarPermisosDefaultAltres(permisos_t& p)
{
      hiHaDefaultAltres = true;
      defaultAltres = p;
      emplenaACLDefaultNecessaries();
      actualitzarCanvisACLDefault();
}

void GestorACL::modificarMascaraDefault(permisos_t& p)
{
      hiHaDefaultMascara = true;
      defaultMascara = p;
      emplenaACLDefaultNecessaries();
      actualitzarCanvisACLDefault();
}

void GestorACL::creaACLDefecte()
{
      emplenaACLDefaultNecessaries();
      actualitzarCanvisACLDefault();
}

Generated by  Doxygen 1.6.0   Back to index