37 |
37 |
38 class LoginPasswordRetreiver(WebAuthInfoRetreiver): |
38 class LoginPasswordRetreiver(WebAuthInfoRetreiver): |
39 __regid__ = 'loginpwdauth' |
39 __regid__ = 'loginpwdauth' |
40 order = 10 |
40 order = 10 |
41 |
41 |
42 def __init__(self, vreg): |
|
43 self.anoninfo = vreg.config.anonymous_user() |
|
44 |
|
45 def authentication_information(self, req): |
42 def authentication_information(self, req): |
46 """retreive authentication information from the given request, raise |
43 """retreive authentication information from the given request, raise |
47 NoAuthInfo if expected information is not found. |
44 NoAuthInfo if expected information is not found. |
48 """ |
45 """ |
49 login, password = req.get_authorization() |
46 login, password = req.get_authorization() |
50 if not login: |
47 if not login: |
51 # No session and no login -> try anonymous |
48 raise NoAuthInfo() |
52 login, password = self.anoninfo |
|
53 if not login: # anonymous not authorized |
|
54 raise NoAuthInfo() |
|
55 return login, {'password': password} |
49 return login, {'password': password} |
56 |
50 |
57 |
51 |
58 class RepositoryAuthenticationManager(AbstractAuthenticationManager): |
52 class RepositoryAuthenticationManager(AbstractAuthenticationManager): |
59 """authenticate user associated to a request and check session validity""" |
53 """authenticate user associated to a request and check session validity""" |
63 self.repo = vreg.config.repository(vreg) |
57 self.repo = vreg.config.repository(vreg) |
64 self.log_queries = vreg.config['query-log-file'] |
58 self.log_queries = vreg.config['query-log-file'] |
65 self.authinforetreivers = sorted(vreg['webauth'].possible_objects(vreg), |
59 self.authinforetreivers = sorted(vreg['webauth'].possible_objects(vreg), |
66 key=lambda x: x.order) |
60 key=lambda x: x.order) |
67 assert self.authinforetreivers |
61 assert self.authinforetreivers |
|
62 self.anoninfo = vreg.config.anonymous_user() |
68 |
63 |
69 def validate_session(self, req, session): |
64 def validate_session(self, req, session): |
70 """check session validity, and return eventually hijacked session |
65 """check session validity, and return eventually hijacked session |
71 |
66 |
72 :raise InvalidSession: |
67 :raise InvalidSession: |
114 login, authinfo = retreiver.authentication_information(req) |
109 login, authinfo = retreiver.authentication_information(req) |
115 except NoAuthInfo: |
110 except NoAuthInfo: |
116 continue |
111 continue |
117 try: |
112 try: |
118 cnx = self._authenticate(req, login, authinfo) |
113 cnx = self._authenticate(req, login, authinfo) |
119 break |
|
120 except ExplicitLogin: |
114 except ExplicitLogin: |
121 continue # the next one may succeed |
115 continue # the next one may succeed |
|
116 for retreiver_ in self.authinforetreivers: |
|
117 retreiver_.authenticated(req, cnx, retreiver) |
|
118 break |
122 else: |
119 else: |
123 raise ExplicitLogin() |
120 # false if no authentication info found, eg this is not an |
124 for retreiver_ in self.authinforetreivers: |
121 # authentication failure |
125 retreiver_.authenticated(req, cnx, retreiver) |
122 if 'login' in locals(): |
|
123 req.set_message(req._('authentication failure')) |
|
124 cnx = self._open_anonymous_connection(req) |
126 return cnx |
125 return cnx |
127 |
126 |
128 def _authenticate(self, req, login, authinfo): |
127 def _authenticate(self, req, login, authinfo): |
129 # remove possibly cached cursor coming from closed connection |
|
130 cnxprops = ConnectionProperties(self.vreg.config.repo_method, |
128 cnxprops = ConnectionProperties(self.vreg.config.repo_method, |
131 close=False, log=self.log_queries) |
129 close=False, log=self.log_queries) |
132 try: |
130 try: |
133 cnx = repo_connect(self.repo, login, cnxprops=cnxprops, **authinfo) |
131 cnx = repo_connect(self.repo, login, cnxprops=cnxprops, **authinfo) |
134 except AuthenticationError: |
132 except AuthenticationError: |
135 req.set_message(req._('authentication failure')) |
133 raise ExplicitLogin() |
136 # restore an anonymous connection if possible |
134 self._init_cnx(cnx, login, authinfo) |
137 anonlogin, anonpassword = self.vreg.config.anonymous_user() |
|
138 if anonlogin and anonlogin != login: |
|
139 cnx = repo_connect(self.repo, anonlogin, password=anonpassword, |
|
140 cnxprops=cnxprops) |
|
141 self._init_cnx(cnx, anonlogin, {'password': anonpassword}) |
|
142 else: |
|
143 raise ExplicitLogin() |
|
144 else: |
|
145 self._init_cnx(cnx, login, authinfo) |
|
146 # associate the connection to the current request |
135 # associate the connection to the current request |
147 req.set_connection(cnx) |
136 req.set_connection(cnx) |
148 return cnx |
137 return cnx |
|
138 |
|
139 def _open_anonymous_connection(self, req): |
|
140 # restore an anonymous connection if possible |
|
141 login, password = self.anoninfo |
|
142 if login: |
|
143 return self._authenticate(req, login, {'password': password}) |
|
144 raise ExplicitLogin() |
149 |
145 |
150 def _init_cnx(self, cnx, login, authinfo): |
146 def _init_cnx(self, cnx, login, authinfo): |
151 # decorate connection |
147 # decorate connection |
152 if login == self.vreg.config.anonymous_user()[0]: |
148 if login == self.vreg.config.anonymous_user()[0]: |
153 cnx.anonymous_connection = True |
149 cnx.anonymous_connection = True |