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