##// END OF EJS Templates
hgweb: centralize permission checks for protocol commands...
Dirkjan Ochtman -
r6779:d3147b4e default
parent child Browse files
Show More
@@ -16,6 +16,13 b' from common import HTTP_OK, HTTP_BAD_REQ'
16 16 from request import wsgirequest
17 17 import webcommands, protocol, webutil
18 18
19 perms = {
20 'changegroup': 'pull',
21 'changegroupsubset': 'pull',
22 'unbundle': 'push',
23 'stream_out': 'pull',
24 }
25
19 26 class hgweb(object):
20 27 def __init__(self, repo, name=None):
21 28 if isinstance(repo, str):
@@ -95,6 +102,8 b' class hgweb(object):'
95 102
96 103 cmd = req.form.get('cmd', [''])[0]
97 104 if cmd and cmd in protocol.__all__:
105 if cmd in perms and not self.check_perm(req, perms[cmd]):
106 return
98 107 method = getattr(protocol, cmd)
99 108 method(self, req)
100 109 return
@@ -343,16 +352,39 b' class hgweb(object):'
343 352 'zip': ('application/zip', 'zip', '.zip', None),
344 353 }
345 354
346 def check_perm(self, req, op, default):
347 '''check permission for operation based on user auth.
348 return true if op allowed, else false.
349 default is policy to use if no config given.'''
355 def check_perm(self, req, op):
356 '''Check permission for operation based on request data (including
357 authentication info. Return true if op allowed, else false.'''
358
359 def error(status, message):
360 req.respond(status, protocol.HGTYPE)
361 req.write('0\n%s\n' % message)
362
363 if op == 'pull':
364 return self.allowpull
365
366 # enforce that you can only push using POST requests
367 if req.env['REQUEST_METHOD'] != 'POST':
368 error('405 Method Not Allowed', 'push requires POST request')
369 return False
370
371 # require ssl by default for pushing, auth info cannot be sniffed
372 # and replayed
373 scheme = req.env.get('wsgi.url_scheme')
374 if self.configbool('web', 'push_ssl', True) and scheme != 'https':
375 error(HTTP_OK, 'ssl required')
376 return False
350 377
351 378 user = req.env.get('REMOTE_USER')
352 379
353 deny = self.configlist('web', 'deny_' + op)
380 deny = self.configlist('web', 'deny_push')
354 381 if deny and (not user or deny == ['*'] or user in deny):
382 error('401 Unauthorized', 'push not authorized')
355 383 return False
356 384
357 allow = self.configlist('web', 'allow_' + op)
358 return (allow and (allow == ['*'] or user in allow)) or default
385 allow = self.configlist('web', 'allow_push')
386 result = allow and (allow == ['*'] or user in allow)
387 if not result:
388 error('401 Unauthorized', 'push not authorized')
389
390 return result
@@ -62,8 +62,6 b' def between(web, req):'
62 62 def changegroup(web, req):
63 63 req.respond(HTTP_OK, HGTYPE)
64 64 nodes = []
65 if not web.allowpull:
66 return
67 65
68 66 if 'roots' in req.form:
69 67 nodes = map(bin, req.form['roots'][0].split(" "))
@@ -82,8 +80,6 b' def changegroupsubset(web, req):'
82 80 req.respond(HTTP_OK, HGTYPE)
83 81 bases = []
84 82 heads = []
85 if not web.allowpull:
86 return
87 83
88 84 if 'bases' in req.form:
89 85 bases = [bin(x) for x in req.form['bases'][0].split(' ')]
@@ -120,28 +116,7 b' def unbundle(web, req):'
120 116 req.write('0\n')
121 117 req.write(response)
122 118
123 # enforce that you can only unbundle with POST requests
124 if req.env['REQUEST_METHOD'] != 'POST':
125 headers = {'status': '405 Method Not Allowed'}
126 bail('unbundle requires POST request\n', headers)
127 return
128
129 # require ssl by default, auth info cannot be sniffed and
130 # replayed
131 ssl_req = web.configbool('web', 'push_ssl', True)
132 if ssl_req:
133 if req.env.get('wsgi.url_scheme') != 'https':
134 bail('ssl required\n')
135 return
136 proto = 'https'
137 else:
138 proto = 'http'
139
140 # do not allow push unless explicitly allowed
141 if not web.check_perm(req, 'push', False):
142 bail('push not authorized\n', headers={'status': '401 Unauthorized'})
143 return
144
119 proto = req.env.get('wsgi.url_scheme') or 'http'
145 120 their_heads = req.form['heads'][0].split(' ')
146 121
147 122 def check_heads():
@@ -224,7 +199,5 b' def unbundle(web, req):'
224 199 os.unlink(tempname)
225 200
226 201 def stream_out(web, req):
227 if not web.allowpull:
228 return
229 202 req.respond(HTTP_OK, HGTYPE)
230 203 streamclone.stream_out(web.repo, req, untrusted=True)
1 NO CONTENT: modified file, binary diff hidden
General Comments 0
You need to be logged in to leave comments. Login now