2010-04-02 19 views
2

Je voudrais développer une interface web pour permettre aux utilisateurs d'un système Linux d'effectuer certaines tâches liées à leur compte. J'ai décidé d'écrire le backend du site en utilisant Python et mod_python sur Apache. Pour authentifier les utilisateurs, j'ai pensé que je pourrais utiliser python_pam pour interroger le service PAM. J'adapté le example livré avec le module et obtenu ceci:Utiliser pam_python dans un script avec mod_python

# out is the output stream used to print debug 
def auth(username, password, out): 
    def pam_conv(aut, query_list, user_data): 
     out.write("Query list: " + str(query_list) + "\n") 

     # List to store the responses to the different queries 
     resp = [] 

     for item in query_list: 
      query, qtype = item 

      # If PAM asks for an input, give the password 
      if qtype == PAM.PAM_PROMPT_ECHO_ON or qtype == PAM.PAM_PROMPT_ECHO_OFF: 
       resp.append((str(password), 0)) 

      elif qtype == PAM.PAM_PROMPT_ERROR_MSG or qtype == PAM.PAM_PROMPT_TEXT_INFO: 
       resp.append(('', 0)) 

     out.write("Our response: " + str(resp) + "\n") 
     return resp 

    # If username of password is undefined, fail 
    if username is None or password is None: 
     return False 

    service = 'login' 
    pam_ = PAM.pam() 
    pam_.start(service) 

    # Set the username 
    pam_.set_item(PAM.PAM_USER, str(username)) 

    # Set the conversation callback 
    pam_.set_item(PAM.PAM_CONV, pam_conv) 

    try: 
     pam_.authenticate() 
     pam_.acct_mgmt() 
    except PAM.error, resp: 
     out.write("Error: " + str(resp) + "\n") 
     return False 
    except: 
     return False 

    # If we get here, the authentication worked 
    return True 

Mon problème est que cette fonction ne se comporte pas le même si je l'utilise dans un script simple ou par mod_python. Pour illustrer cela, je l'ai écrit ces cas simples:

my_username = "markys" 
my_good_password = "lalala" 
my_bad_password = "lololo" 

def handler(req): 
req.content_type = "text/plain" 
req.write("1- " + str(auth(my_username,my_good_password,req) + "\n")) 
req.write("2- " + str(auth(my_username,my_bad_password,req) + "\n")) 
return apache.OK 

if __name__ == "__main__": 
print "1- " + str(auth(my_username,my_good_password,sys.__stdout__)) 
print "2- " + str(auth(my_username,my_bad_password,sys.__stdout__)) 

Le résultat du script est:

Query list: [('Password: ', 1)] 
Our response: [('lalala', 0)] 
1- True 
Query list: [('Password: ', 1)] 
Our response: [('lololo', 0)] 
Error: ('Authentication failure', 7) 
2- False 

mais le résultat de mod_python est:

Query list: [('Password: ', 1)] 
Our response: [('lalala', 0)] 
Error: ('Authentication failure', 7) 
1- False 
Query list: [('Password: ', 1)] 
Our response: [('lololo', 0)] 
Error: ('Authentication failure', 7) 
2- False 

Je ne comprends pas pourquoi la fonction auth ne renvoie pas la même valeur donnée pour les mêmes entrées. Une idée d'où je me suis trompé? Here est le script original, si cela peut vous aider.

Merci beaucoup!

EDIT: Très bien, j'ai trouvé l'erreur. Je courais le script en tant que root. mod_python exécutait le script en tant qu'utilisateur du serveur Web. Seule la racine a le droit de lire l'ombre. Je ne sais pas comment je vais contourner cela, mais au moins maintenant je sais quel est le problème!

Répondre

0

Il semble que vous deviez activer Apache pour utiliser l'authentification PAM. Jetez un oeil à ce site: http://www.debianhelp.co.uk/apachepam.htm

Vous pouvez jeter un oeil à ce site aussi: http://inming.net/?p=86

+0

Je pense que ce module permet d'utiliser l'authentification HTTP (la boîte de connexion popup) et valider les informations d'identification à l'aide de PAM et n'interfère pas avec Python. Je l'ai quand même essayé mais ça ne marchait pas mieux. – simark