zephir.backend.xmlrpceole

Package zephir :: Package backend :: Module xmlrpceole |
[frames] | no frames]

# Source Code for Module zephir.backend.xmlrpceole

      1  # -*- coding: UTF-8 -*-
      2  ###########################################################################
      3  # Eole NG - 2007
      4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
      5  # Licence CeCill  cf /root/LicenceEole.txt
      6  # eole@ac-dijon.fr
      7  #
      8  # xmlrpceole.py
      9  #
     10  # Version modifiée du serveur XMLRPC twisted pour gérer
     11  # l'authentification et la gestion des droits
     12  #
     13  ###########################################################################
     14  import twisted
     15  from twisted.web import http
     16  from twisted.web.resource import ErrorPage
     17  from zephir.backend import config
     18  from zephir.backend.lib_backend import ResourceAuthError
     19
     20  from twisted.internet import defer
     21  from twisted.web import xmlrpc,server
     22  from zephir.eolerpclib import xmlrpclib
     23  import psycopg2 as PgSQL
     24  import time
     25
     26  try:
     27      import ldap
     28  except:
     29      pass
     30
     31
     32 -def convert(objet):
     33      """Transforme les objets unicode contenus dans un objet en chaines
     34      """
     35      if type(objet) == tuple:
     36          l = []
     37          for item in objet:
     38              l.append(convert(item))
     39          return l
     40      if type(objet) == list:
     41          l = []
     42          for item in objet:
     43              l.append(convert(item))
     44          return l
     45      if type(objet) == dict:
     46          dico={}
     47          for cle in objet.keys():
     48              dico[cle] = convert(objet[cle])
     49          return dico
     50      if type(objet) == unicode:
     51          string =  objet.encode(config.charset)
     52          return string
     53      return objet
     54
     55
     56  # serveur sécurisé XMLPRC
     57 -class XMLRPCEole(xmlrpc.XMLRPC):
     58
     59
     60 -    def __init__(self):
     61          xmlrpc.XMLRPC.__init__(self)
     62          # définition des autorisations pour chaque utilisateur
     63          self.serveur_ldap = config.ADRESSE_LDAP
     64          # reload_perms : indique que les permissions ont changé
     65          # et qu'il faut les recharger
     66          self.reload_perms = 0
     67          self.load_groupes()
     68
     69 -    def load_groupes(self):
     70          # chargement des groupes de droits
     71          cx = PgSQL.connect(database='zephir',user='zephir',password=config.DB_PASSWD)
     72          db_cursor = cx.cursor()
     73          db_cursor.execute("""select id,libelle,droits from groupes_droits""")
     74          res = db_cursor.fetchall()
     75          db_cursor.close()
     76          cx.close()
     77          self.groupes={}
     78          for groupe in res:
     79              self.groupes[int(groupe[0])]=[str(res[1]),eval(str(groupe[2]))]
     80
     81 -    def render(self,request):
     82          """examine la requête transmise par le client et apelle la procédure
     83          correspondante si ses autorisations sont suffisantes"""
     84          # test de l'authentification
     85          cred_user = request.getUser()
     86          cred_password = request.getPassword()
     87          # dans le cas de l'utilisateur zephir, on ne fait pas de vérification sur ldap
     88          if cred_user != 'zephir' or cred_password != 'zephir':
     89              # on tente une connexion au serveur ldap avec ce login et mot de passe
     90              retry_auth = 0
     91              while retry_auth < 2:
     92                  try:
     93                      if cred_password == "":
     94                          cred_password = None
     95                      query = ldap.open(self.serveur_ldap)
     96                      if config.LDAP_TLS == "oui":
     97                          query.start_tls_s()
     98                      # on récupère le dn complet de l'utilisateur
     99                      result = query.search_s(config.BASE_LDAP, ldap.SCOPE_SUBTREE, "(uid="+cred_user+")")
    100                      cred_dn = result[0][0]
    101                      query.simple_bind_s(cred_dn,cred_password)
    102                      query.unbind()
    103                  except ldap.SERVER_DOWN:
    104                      print "ldap server not responding, retrying authentification"
    105                      time.sleep(0.3)
    106                      retry_auth += 1
    107                  except:
    108                      # erreur d'authentification
    109                      # on retourne un message d'erreur
    110                      print "\nauthentification incorrecte : ",request.host.host
    111                      errpage = ErrorPage(http.UNAUTHORIZED,"Unauthorized","401 Authentication required")
    112                      return errpage.render(request)
    113                      retry_auth = 2
    114                  else:
    115                      retry_auth = 2
    116                      pass
    117                      # print "\nclient authentifié : ",request.getHost()[1]
    118
    119          request.content.seek(0, 0)
    120          args, functionPath = xmlrpclib.loads(request.content.read())
    121          # Récupération de l'ip de connexion du serveur
    122          ip_publique = None
    123          if functionPath == 'uucp.maj_site':
    124              ip_publique = request.getClientIP()
    125          args_list=[]
    126          if ip_publique is not None:
    127              args_list.append(ip_publique)
    128          for arg in args:
    129              arg_conv=convert(arg)
    130              args_list.append(arg_conv)
    131          args = tuple(args_list)
    132
    133          # on vérifie si l'utilisateur a le droit d'utiliser cette fonction
    134          # on récupère les groupes de droits de l'utilisateur
    135          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
    136          cursor=cx.cursor()
    137          cursor.execute("""select droits from users where login=%s""", (cred_user,))
    138          rs = cursor.fetchone()
    139          cursor.close()
    140          cx.close()
    141          droits = []
    142          # on rassemble toutes les fonctions auxquelles on a droit
    143          if rs == [] or rs is None:
    144              groupe = []
    145          else:
    146              for groupe in eval(rs[0]):
    147                  droits.extend(self.groupes[groupe][1])
    148          try:
    149              # on regarde si on a le droit d'executer la fonction
    150              if functionPath not in droits:
    151                  # fonction interdite
    152                  if request.host.host not in ["localhost", "127.0.0.1"]:
    153                      host_addr = " (%s)" % request.host.host
    154                  else:
    155                      host_addr = ""
    156                  print "\nutilisation de la fonction %s interdite pour %s%s" % (functionPath,cred_user,host_addr)
    157                  errpage = ErrorPage(http.UNAUTHORIZED,"Unauthorized","erreur, ressource %s non autorisée !" % (request.uri))
    158                  return errpage.render(request)
    159          except:
    160              print "\n pas d'autorisations pour " + cred_user + " !"
    161              errpage = ErrorPage(http.UNAUTHORIZED,"Unauthorized","erreur, ressource %s non autorisée !" % (request.uri))
    162              return errpage.render(request)
    163          # fonction autorisée
    164          try:
    165              function = self._getFunction(functionPath)
    166          except xmlrpc.NoSuchFunction:
    167              self._cbRender(
    168                  xmlrpclib.Fault(self.NOT_FOUND, "no such function %s" % functionPath),
    169                  request
    170              )
    171          else:
    172              request.setHeader("content-type", "text/xml")
    173              if config.LOG_ACTIONS and cred_user not in ('zephir','', None):
    174                  try:
    175                      print "ZEPHIR_BACKEND : %s -> %s" % (cred_user, functionPath), args
    176                  except Exception, e:
    177                      print "Erreur lors du log d'une action : ", str(e)
    178              defer.maybeDeferred(function, cred_user, *args).addErrback(
    179                  self.ebRender, request
    180              ).addCallback(
    181                  self._cbRender, request
    182              )
    183          return server.NOT_DONE_YET
    184
    185 -    def ebRender(self, ex, request):
    186          """errback intermédiaire pour catcher les ressources non autorisées"""
    187          if ex.type == ResourceAuthError:
    188              msg_err = ex.getErrorMessage()
    189              errpage = ErrorPage(http.UNAUTHORIZED,"Unauthorized", "erreur, autorisations insuffisantes : {0} !".format(msg_err))
    190              config.log.msg("tentative d'accès à une ressource interdite pour {0} : {1}".format(request.getUser(), msg_err))
    191              return errpage.render(request)
    192          else:
    193              self._ebRender(ex)
    194