Show More
@@ -323,12 +323,32 b' related options for the diff command.' | |||||
323 | ``auth`` |
|
323 | ``auth`` | |
324 | -------- |
|
324 | -------- | |
325 |
|
325 | |||
326 |
Authentication credentials |
|
326 | Authentication credentials and other authentication-like configuration | |
327 | allows you to store usernames and passwords for use when logging |
|
327 | for HTTP connections. This section allows you to store usernames and | |
328 | *into* HTTP servers. See :hg:`help config.web` if |
|
328 | passwords for use when logging *into* HTTP servers. See | |
329 |
you want to configure *who* can login to |
|
329 | :hg:`help config.web` if you want to configure *who* can login to | |
330 |
|
330 | your HTTP server. | ||
331 | Each line has the following format:: |
|
331 | ||
|
332 | The following options apply to all hosts. | |||
|
333 | ||||
|
334 | ``cookiefile`` | |||
|
335 | Path to a file containing HTTP cookie lines. Cookies matching a | |||
|
336 | host will be sent automatically. | |||
|
337 | ||||
|
338 | The file format uses the Mozilla cookies.txt format, which defines cookies | |||
|
339 | on their own lines. Each line contains 7 fields delimited by the tab | |||
|
340 | character (domain, is_domain_cookie, path, is_secure, expires, name, | |||
|
341 | value). For more info, do an Internet search for "Netscape cookies.txt | |||
|
342 | format." | |||
|
343 | ||||
|
344 | Note: the cookies parser does not handle port numbers on domains. You | |||
|
345 | will need to remove ports from the domain for the cookie to be recognized. | |||
|
346 | This could result in a cookie being disclosed to an unwanted server. | |||
|
347 | ||||
|
348 | The cookies file is read-only. | |||
|
349 | ||||
|
350 | Other options in this section are grouped by name and have the following | |||
|
351 | format:: | |||
332 |
|
352 | |||
333 | <name>.<argument> = <value> |
|
353 | <name>.<argument> = <value> | |
334 |
|
354 |
@@ -417,6 +417,35 b' class httpbasicauthhandler(urlreq.httpba' | |||||
417 | else: |
|
417 | else: | |
418 | return None |
|
418 | return None | |
419 |
|
419 | |||
|
420 | class cookiehandler(urlreq.basehandler): | |||
|
421 | def __init__(self, ui): | |||
|
422 | self.cookiejar = None | |||
|
423 | ||||
|
424 | cookiefile = ui.config('auth', 'cookiefile') | |||
|
425 | if not cookiefile: | |||
|
426 | return | |||
|
427 | ||||
|
428 | cookiefile = util.expandpath(cookiefile) | |||
|
429 | try: | |||
|
430 | cookiejar = util.cookielib.MozillaCookieJar(cookiefile) | |||
|
431 | cookiejar.load() | |||
|
432 | self.cookiejar = cookiejar | |||
|
433 | except util.cookielib.LoadError as e: | |||
|
434 | ui.warn(_('(error loading cookie file %s: %s; continuing without ' | |||
|
435 | 'cookies)\n') % (cookiefile, str(e))) | |||
|
436 | ||||
|
437 | def http_request(self, request): | |||
|
438 | if self.cookiejar: | |||
|
439 | self.cookiejar.add_cookie_header(request) | |||
|
440 | ||||
|
441 | return request | |||
|
442 | ||||
|
443 | def https_request(self, request): | |||
|
444 | if self.cookiejar: | |||
|
445 | self.cookiejar.add_cookie_header(request) | |||
|
446 | ||||
|
447 | return request | |||
|
448 | ||||
420 | handlerfuncs = [] |
|
449 | handlerfuncs = [] | |
421 |
|
450 | |||
422 | def opener(ui, authinfo=None): |
|
451 | def opener(ui, authinfo=None): | |
@@ -450,6 +479,7 b' def opener(ui, authinfo=None):' | |||||
450 | handlers.extend((httpbasicauthhandler(passmgr), |
|
479 | handlers.extend((httpbasicauthhandler(passmgr), | |
451 | httpdigestauthhandler(passmgr))) |
|
480 | httpdigestauthhandler(passmgr))) | |
452 | handlers.extend([h(ui, passmgr) for h in handlerfuncs]) |
|
481 | handlers.extend([h(ui, passmgr) for h in handlerfuncs]) | |
|
482 | handlers.append(cookiehandler(ui)) | |||
453 | opener = urlreq.buildopener(*handlers) |
|
483 | opener = urlreq.buildopener(*handlers) | |
454 |
|
484 | |||
455 | # The user agent should should *NOT* be used by servers for e.g. |
|
485 | # The user agent should should *NOT* be used by servers for e.g. |
@@ -1,4 +1,4 b'' | |||||
1 | #require serve |
|
1 | #require killdaemons serve | |
2 |
|
2 | |||
3 | $ hg init test |
|
3 | $ hg init test | |
4 | $ cd test |
|
4 | $ cd test | |
@@ -333,3 +333,64 b' check abort error reporting while pullin' | |||||
333 | abort: pull failed on remote |
|
333 | abort: pull failed on remote | |
334 | [255] |
|
334 | [255] | |
335 | $ cat error.log |
|
335 | $ cat error.log | |
|
336 | ||||
|
337 | corrupt cookies file should yield a warning | |||
|
338 | ||||
|
339 | $ cat > $TESTTMP/cookies.txt << EOF | |||
|
340 | > bad format | |||
|
341 | > EOF | |||
|
342 | ||||
|
343 | $ hg --config auth.cookiefile=$TESTTMP/cookies.txt id http://localhost:$HGPORT/ | |||
|
344 | (error loading cookie file $TESTTMP/cookies.txt: '$TESTTMP/cookies.txt' does not look like a Netscape format cookies file; continuing without cookies) | |||
|
345 | 56f9bc90cce6 | |||
|
346 | ||||
|
347 | $ killdaemons.py | |||
|
348 | ||||
|
349 | Create dummy authentication handler that looks for cookies. It doesn't do anything | |||
|
350 | useful. It just raises an HTTP 500 with details about the Cookie request header. | |||
|
351 | We raise HTTP 500 because its message is printed in the abort message. | |||
|
352 | ||||
|
353 | $ cat > cookieauth.py << EOF | |||
|
354 | > from mercurial import util | |||
|
355 | > from mercurial.hgweb import common | |||
|
356 | > def perform_authentication(hgweb, req, op): | |||
|
357 | > cookie = req.env.get('HTTP_COOKIE') | |||
|
358 | > if not cookie: | |||
|
359 | > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, 'no-cookie') | |||
|
360 | > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, 'Cookie: %s' % cookie) | |||
|
361 | > def extsetup(): | |||
|
362 | > common.permhooks.insert(0, perform_authentication) | |||
|
363 | > EOF | |||
|
364 | ||||
|
365 | $ hg serve --config extensions.cookieauth=cookieauth.py -R test -p $HGPORT -d --pid-file=pid | |||
|
366 | $ cat pid > $DAEMON_PIDS | |||
|
367 | ||||
|
368 | Request without cookie sent should fail due to lack of cookie | |||
|
369 | ||||
|
370 | $ hg id http://localhost:$HGPORT | |||
|
371 | abort: HTTP Error 500: no-cookie | |||
|
372 | [255] | |||
|
373 | ||||
|
374 | Populate a cookies file | |||
|
375 | ||||
|
376 | $ cat > cookies.txt << EOF | |||
|
377 | > # HTTP Cookie File | |||
|
378 | > # Expiration is 2030-01-01 at midnight | |||
|
379 | > .example.com TRUE / FALSE 1893456000 hgkey examplevalue | |||
|
380 | > EOF | |||
|
381 | ||||
|
382 | Should not send a cookie for another domain | |||
|
383 | ||||
|
384 | $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/ | |||
|
385 | abort: HTTP Error 500: no-cookie | |||
|
386 | [255] | |||
|
387 | ||||
|
388 | Add a cookie entry for our test server and verify it is sent | |||
|
389 | ||||
|
390 | $ cat >> cookies.txt << EOF | |||
|
391 | > localhost.local FALSE / FALSE 1893456000 hgkey localhostvalue | |||
|
392 | > EOF | |||
|
393 | ||||
|
394 | $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/ | |||
|
395 | abort: HTTP Error 500: Cookie: hgkey=localhostvalue | |||
|
396 | [255] |
General Comments 0
You need to be logged in to leave comments.
Login now