Merge branch 'fibre' of ssh://git.onelab.eu/git/myslice into fibre
[unfold.git] / auth / manifoldbackend.py
1 import time
2
3 # import ldap for LDAP authentication - Edelberto
4 import ldap
5
6 from django.contrib.auth.models import User
7
8 from manifoldapi.manifoldapi    import ManifoldAPI, ManifoldException, ManifoldResult
9 from manifold.core.query        import Query
10
11 # Name my backend 'ManifoldBackend'
12 class ManifoldBackend:
13
14
15     # Create an authentication method
16     # This is called by the standard Django login procedure
17     def authenticate(self, token=None):
18     
19         # LDAP local/global var
20         checkldap = None
21
22         if not token:
23             return None
24
25         try:
26             print "ManifoldBackend authenticate()"
27             # Mandatory fields in token
28             username = token['username']
29             request = token['request']
30
31             # usernameldap is optional - from LDAP user form. 
32             # If it is filled - See portal/homeview.py too
33             if 'usernameldap' in token:
34                 usernameldap = token['usernameldap']
35             else:
36                 usernameldap = None
37             password = token['password']
38             # if data are not from LDAP form then normal (local) login
39             if not usernameldap:
40                 print "not userldap ManifoldBackend authenticate()"
41                 auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password}
42                 api = ManifoldAPI(auth)
43                 sessions_result = api.forward(Query.create('local:session').to_dict())
44                 print "result"
45                 sessions = sessions_result.ok_value()
46                 print "ok"
47                 if not sessions:
48                     print "GetSession failed", sessions_result.error()
49                     return
50                 print "first", sessions
51                 session = sessions[0]
52
53                 # Change to session authentication
54                 api.auth = {'AuthMethod': 'session', 'session': session['session']}
55                 self.api = api
56
57                 # Get account details
58                 # the new API would expect Get('local:user') instead
59                 persons_result = api.forward(Query.get('local:user').to_dict())
60                 persons = persons_result.ok_value()
61                 if not persons:
62                     print "GetPersons failed",persons_result.error()
63                     return
64                 person = persons[0]
65                 print "PERSON=", person
66
67                 request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
68             ################################
69             # Edelberto LDAP authentication
70             # if data are from LDAP form, so
71             else:
72                 print "userldap ManifoldBackend authenticate()"
73             # XXX UGLY
74             # Needing to create an specific entries at settings.py (or myslice.ini) for these vars
75             ##################################################
76             # Edelberto - UFF - esilva@ic.uff.br
77             # v1 - ldap authentication module
78             # Note: focus on LDAP FIBRE-BR for DN
79             #       if uses other DN, configuration are needed
80             ###################################################
81             #Searching an LDAP Directory
82
83                 try:
84                     #uid = "debora@uff.br"
85
86                     # Receiving an email address, how can we split and mount it in DN format?
87                     #mail = "debora@uff.br"
88                     mail = usernameldap
89                     login = mail.split('@')[0]
90                     org = mail.split('@')[1]
91                     o = org.split('.')[0]
92                     dc = org.split('.')[1]
93                     '''
94                     print mail
95                     print login
96                     print org
97                     print o
98                     print dc
99                     '''
100
101                     # DN format to authenticate - IMPORTANT!
102                     #FIBRE-BR format
103                     uid = "uid="+mail+",ou=people,o="+o+",dc="+dc
104                     #uid = "uid=debora@uff.br,ou=people,o=uff,dc=br"
105                     # User password from LDAP form
106                     #userPassword = "fibre"
107                     userPassword = password
108
109                     # testing with:
110                     # wrong password for test
111                     #    userPassword = "fibre2"
112                     
113                     # Parameters to connect on LDAP
114                     ldap.set_option(ldap.OPT_REFERRALS, 0)
115                     # LDAP Server Address
116                     l = ldap.open("127.0.0.1")
117                     # LDAP version
118                     l.protocol_version = ldap.VERSION3
119
120                     #l.simple_bind(uid, userPassword)
121                     # l.bind_s is necessary to do the authentication with a normal LDAP user
122                     l.bind_s(uid, userPassword, ldap.AUTH_SIMPLE)
123                     #print l.bind_s(uid, userPassword, ldap.AUTH_SIMPLE)
124
125                     # DN base - Our root dc (dc=br)
126                     baseDN="dc="+dc
127                     searchScope = ldap.SCOPE_SUBTREE
128                     retrieveAttributes = None
129                     # User only can see its credentials. He search only his attributes
130                     searchFilter = "uid="+mail
131
132                     # Getting all attributes
133                     try:
134                         ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes)
135                         result_set = []
136                         # while exist attributes, save them in a list!
137                         while 1:
138                         #   print l.result(ldap_result_id, 0)
139                             result_type, result_data = l.result(ldap_result_id, 0)
140                             if (result_data == []):
141                             #print ("User %s don't allowed to bind in LDAP", uid)
142                                 break
143                             else:
144                                 ## Appendng to a list
145                                 if result_type == ldap.RES_SEARCH_ENTRY:
146                                     result_set.append(result_data)
147                                     #    print result_set
148                     except ldap.LDAPError, e:
149                         print e
150
151                     # Matching if the user is really who his say
152                     #checkldap = None
153                     if l.compare_s(uid, 'uid', mail):
154                         # DEBUG
155                         checkldap = True
156                         print "match"
157
158                 # Now, based on default Manifold Auth
159                         auth = {'AuthMethod': 'password', 'Username': usernameldap, 'AuthString': password}
160                         api = ManifoldAPI(auth)
161                         sessions_result = api.forward(Query.create('local:session').to_dict())
162                         print "result"
163                         sessions = sessions_result.ok_value()
164                         print "ok"
165                         if not sessions:
166                             print "GetSession failed", sessions_result.error()
167                             return
168                         print "first", sessions
169                         session = sessions[0]
170
171                         # Change to session authentication
172                         api.auth = {'AuthMethod': 'session', 'session': session['session']}
173                         self.api = api
174
175                         # Get account details
176                         # the new API would expect Get('local:user') instead
177                         persons_result = api.forward(Query.get('local:user').to_dict())
178                         persons = persons_result.ok_value()
179                         if not persons:
180                             print "GetPersons failed",persons_result.error()
181                             return
182                         person = persons[0]
183                         print "PERSON=", person
184
185                         request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': session['expires']}
186
187                     else:
188                         print "no match. User doesnt allowed"
189                         checkldap = False
190
191                 except ldap.LDAPError, e:
192                     print "E: LDAP Search user", e                      
193         # end of LDAP
194        
195         # Follow the same of Manifold 
196         except ManifoldException, e:
197             print "ManifoldBackend.authenticate caught ManifoldException, returning corresponding ManifoldResult"
198             return e.manifold_result
199         except Exception, e:
200             print "E: manifoldbackend", e
201             import traceback
202             traceback.print_exc()
203             return None
204     
205         if not usernameldap:
206             try:
207                 # Check if the user exists in Django's local database
208                user = User.objects.get(username=username)
209             except User.DoesNotExist:
210                 # Create a user in Django's local database
211                 user = User.objects.create_user(username, usernamep, 'passworddoesntmatter')
212                 user.email = person['email']
213         else:
214             if checkldap:
215                 try:
216                     # Check if the user exists in Django's local database
217                     user = User.objects.get(username=usernameldap)
218                 except User.DoesNotExist:
219                     # Create a user in Django's local database
220                     user = User.objects.create_user(username, usernameldap, 'passworddoesntmatter')
221                     user.email = person['email']
222
223         if 'firstname' in person:
224             user.first_name = person['firstname']
225         if 'lastname' in person:
226             user.last_name = person['lastname']
227
228         return user
229     # Required for your backend to work properly - unchanged in most scenarios
230     def get_user(self, user_id):
231         try:
232             return User.objects.get(pk=user_id)
233         except User.DoesNotExist:
234             return None
235
236