Show More
@@ -676,6 +676,16 b' web::' | |||||
676 | must be present in this list (separated by whitespace or ","). |
|
676 | must be present in this list (separated by whitespace or ","). | |
677 | The contents of the allow_push list are examined after the |
|
677 | The contents of the allow_push list are examined after the | |
678 | deny_push list. |
|
678 | deny_push list. | |
|
679 | allow_read;; | |||
|
680 | If the user has not already been denied repository access due to the | |||
|
681 | contents of deny_read, this list determines whether to grant repository | |||
|
682 | access to the user. If this list is not empty, and the user is | |||
|
683 | unauthenticated or not present in the list (separated by whitespace or ","), | |||
|
684 | then access is denied for the user. If the list is empty or not set, then | |||
|
685 | access is permitted to all users by default. Setting allow_read to the | |||
|
686 | special value "*" is equivalent to it not being set (i.e. access is | |||
|
687 | permitted to all users). The contents of the allow_read list are examined | |||
|
688 | after the deny_read list. | |||
679 | allowzip;; |
|
689 | allowzip;; | |
680 | (DEPRECATED) Whether to allow .zip downloading of repo revisions. |
|
690 | (DEPRECATED) Whether to allow .zip downloading of repo revisions. | |
681 | Default is false. This feature creates temporary files. |
|
691 | Default is false. This feature creates temporary files. | |
@@ -693,6 +703,18 b' web::' | |||||
693 | and any authenticated user name present in this list (separated by |
|
703 | and any authenticated user name present in this list (separated by | |
694 | whitespace or ",") is also denied. The contents of the deny_push |
|
704 | whitespace or ",") is also denied. The contents of the deny_push | |
695 | list are examined before the allow_push list. |
|
705 | list are examined before the allow_push list. | |
|
706 | deny_read;; | |||
|
707 | Whether to deny reading/viewing of the repository. If this list is not | |||
|
708 | empty, unauthenticated users are all denied, and any authenticated user name | |||
|
709 | present in this list (separated by whitespace or ",") is also denied access | |||
|
710 | to the repository. If set to the special value "*", all remote users are | |||
|
711 | denied access (rarely needed ;). If deny_read is empty or not set, the | |||
|
712 | determination of repository access depends on the presence and content of | |||
|
713 | the allow_read list (see description). If both deny_read and allow_read are | |||
|
714 | empty or not set, then access is permitted to all users by default. If the | |||
|
715 | repository is being served via hgwebdir, denied users will not be able to | |||
|
716 | see it in the list of repositories. The contents of the deny_read list have | |||
|
717 | priority over (are examined before) the contents of the allow_read list. | |||
696 | description;; |
|
718 | description;; | |
697 | Textual description of the repository's purpose or contents. |
|
719 | Textual description of the repository's purpose or contents. | |
698 | Default is "unknown". |
|
720 | Default is "unknown". |
@@ -161,11 +161,13 b' class hgweb(object):' | |||||
161 | # process the web interface request |
|
161 | # process the web interface request | |
162 |
|
162 | |||
163 | try: |
|
163 | try: | |
164 |
|
||||
165 | tmpl = self.templater(req) |
|
164 | tmpl = self.templater(req) | |
166 | ctype = tmpl('mimetype', encoding=self.encoding) |
|
165 | ctype = tmpl('mimetype', encoding=self.encoding) | |
167 | ctype = templater.stringify(ctype) |
|
166 | ctype = templater.stringify(ctype) | |
168 |
|
167 | |||
|
168 | # check allow_read / deny_read config options | |||
|
169 | self.check_perm(req, None) | |||
|
170 | ||||
169 | if cmd == '': |
|
171 | if cmd == '': | |
170 | req.form['cmd'] = [tmpl.cache['default']] |
|
172 | req.form['cmd'] = [tmpl.cache['default']] | |
171 | cmd = req.form['cmd'][0] |
|
173 | cmd = req.form['cmd'][0] | |
@@ -278,11 +280,24 b' class hgweb(object):' | |||||
278 |
|
280 | |||
279 | def check_perm(self, req, op): |
|
281 | def check_perm(self, req, op): | |
280 | '''Check permission for operation based on request data (including |
|
282 | '''Check permission for operation based on request data (including | |
281 |
authentication info. Return |
|
283 | authentication info). Return if op allowed, else raise an ErrorResponse | |
|
284 | exception.''' | |||
|
285 | ||||
|
286 | user = req.env.get('REMOTE_USER') | |||
|
287 | ||||
|
288 | deny_read = self.configlist('web', 'deny_read') | |||
|
289 | if deny_read and (not user or deny_read == ['*'] or user in deny_read): | |||
|
290 | raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized') | |||
|
291 | ||||
|
292 | allow_read = self.configlist('web', 'allow_read') | |||
|
293 | result = (not allow_read) or (allow_read == ['*']) or (user in allow_read) | |||
|
294 | if not result: | |||
|
295 | raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized') | |||
282 |
|
296 | |||
283 | if op == 'pull' and not self.allowpull: |
|
297 | if op == 'pull' and not self.allowpull: | |
284 | raise ErrorResponse(HTTP_OK, '') |
|
298 | raise ErrorResponse(HTTP_OK, '') | |
285 | elif op == 'pull': |
|
299 | # op is None when checking allow/deny_read permissions for a web-browser request | |
|
300 | elif op == 'pull' or op is None: | |||
286 | return |
|
301 | return | |
287 |
|
302 | |||
288 | # enforce that you can only push using POST requests |
|
303 | # enforce that you can only push using POST requests | |
@@ -296,8 +311,6 b' class hgweb(object):' | |||||
296 | if self.configbool('web', 'push_ssl', True) and scheme != 'https': |
|
311 | if self.configbool('web', 'push_ssl', True) and scheme != 'https': | |
297 | raise ErrorResponse(HTTP_OK, 'ssl required') |
|
312 | raise ErrorResponse(HTTP_OK, 'ssl required') | |
298 |
|
313 | |||
299 | user = req.env.get('REMOTE_USER') |
|
|||
300 |
|
||||
301 | deny = self.configlist('web', 'deny_push') |
|
314 | deny = self.configlist('web', 'deny_push') | |
302 | if deny and (not user or deny == ['*'] or user in deny): |
|
315 | if deny and (not user or deny == ['*'] or user in deny): | |
303 | raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized') |
|
316 | raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized') |
@@ -72,6 +72,28 b' class hgwebdir(object):' | |||||
72 | req = wsgirequest(env, respond) |
|
72 | req = wsgirequest(env, respond) | |
73 | return self.run_wsgi(req) |
|
73 | return self.run_wsgi(req) | |
74 |
|
74 | |||
|
75 | def read_allowed(self, ui, req): | |||
|
76 | """Check allow_read and deny_read config options of a repo's ui object | |||
|
77 | to determine user permissions. By default, with neither option set (or | |||
|
78 | both empty), allow all users to read the repo. There are two ways a | |||
|
79 | user can be denied read access: (1) deny_read is not empty, and the | |||
|
80 | user is unauthenticated or deny_read contains user (or *), and (2) | |||
|
81 | allow_read is not empty and the user is not in allow_read. Return True | |||
|
82 | if user is allowed to read the repo, else return False.""" | |||
|
83 | ||||
|
84 | user = req.env.get('REMOTE_USER') | |||
|
85 | ||||
|
86 | deny_read = ui.configlist('web', 'deny_read', default=None, untrusted=True) | |||
|
87 | if deny_read and (not user or deny_read == ['*'] or user in deny_read): | |||
|
88 | return False | |||
|
89 | ||||
|
90 | allow_read = ui.configlist('web', 'allow_read', default=None, untrusted=True) | |||
|
91 | # by default, allow reading if no allow_read option has been set | |||
|
92 | if (not allow_read) or (allow_read == ['*']) or (user in allow_read): | |||
|
93 | return True | |||
|
94 | ||||
|
95 | return False | |||
|
96 | ||||
75 | def run_wsgi(self, req): |
|
97 | def run_wsgi(self, req): | |
76 |
|
98 | |||
77 | try: |
|
99 | try: | |
@@ -175,6 +197,9 b' class hgwebdir(object):' | |||||
175 | if u.configbool("web", "hidden", untrusted=True): |
|
197 | if u.configbool("web", "hidden", untrusted=True): | |
176 | continue |
|
198 | continue | |
177 |
|
199 | |||
|
200 | if not self.read_allowed(u, req): | |||
|
201 | continue | |||
|
202 | ||||
178 | parts = [name] |
|
203 | parts = [name] | |
179 | if 'PATH_INFO' in req.env: |
|
204 | if 'PATH_INFO' in req.env: | |
180 | parts.insert(0, req.env['PATH_INFO'].rstrip('/')) |
|
205 | parts.insert(0, req.env['PATH_INFO'].rstrip('/')) |
General Comments 0
You need to be logged in to leave comments.
Login now