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