Projet

Général

Profil

0001-misc-limit-cancel-URL-to-relatable-URLs-43276.patch

Frédéric Péters, 25 mai 2020 18:13

Télécharger (4,62 ko)

Voir les différences:

Subject: [PATCH] misc: limit cancel URL to relatable URLs (#43276)

 tests/test_form_pages.py | 41 ++++++++++++++++++++++++++++++++++++++++
 wcs/forms/root.py        |  2 ++
 wcs/qommon/publisher.py  | 19 +++++++++++++++++++
 3 files changed, 62 insertions(+)
tests/test_form_pages.py
428 428
    assert resp.form
429 429

  
430 430

  
431
def test_form_cancelurl(pub):
432
    formdef = create_formdef()
433
    formdef.data_class().wipe()
434

  
435
    # path
436
    resp = get_app(pub).get('/test/?cancelurl=/plop/')
437
    resp = resp.form.submit('cancel')
438
    assert resp.location == 'http://example.net/plop/'
439

  
440
    # full URL
441
    resp = get_app(pub).get('/test/?cancelurl=http://example.net/plop/')
442
    resp = resp.form.submit('cancel')
443
    assert resp.location == 'http://example.net/plop/'
444

  
445
    # remote site
446
    get_app(pub).get('/test/?cancelurl=http://example.org/plop/', status=400)
447

  
448
    pub.site_options.add_section('api-secrets')
449
    pub.site_options.set('api-secrets', 'example.org', 'xyz')
450
    pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w'))
451
    resp = get_app(pub).get('/test/?cancelurl=http://example.org/plop/')
452
    resp = resp.form.submit('cancel')
453
    assert resp.location == 'http://example.org/plop/'
454

  
455
    pub.site_options.remove_section('api-secrets')
456
    if not pub.site_options.has_section('options'):
457
        pub.site_options.add_section('options')
458
    pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w'))
459
    get_app(pub).get('/test/?cancelurl=http://example.org/plop/', status=400)
460

  
461
    pub.site_options.set('options', 'relatable-hosts', 'example.com')
462
    pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w'))
463
    get_app(pub).get('/test/?cancelurl=http://example.org/plop/', status=400)
464

  
465
    pub.site_options.set('options', 'relatable-hosts', 'example.com, example.org')
466
    pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w'))
467
    resp = get_app(pub).get('/test/?cancelurl=http://example.org/plop/')
468
    resp = resp.form.submit('cancel')
469
    assert resp.location == 'http://example.org/plop/'
470

  
471

  
431 472
def test_form_submit(pub):
432 473
    formdef = create_formdef()
433 474
    formdef.data_class().wipe()
wcs/forms/root.py
328 328

  
329 329
        if page == self.pages[0] and 'cancelurl' in get_request().form:
330 330
            cancelurl = get_request().form['cancelurl']
331
            if not get_publisher().is_relatable_url(cancelurl):
332
                raise errors.RequestError('invalid cancel URL')
331 333
            form_data['__cancelurl'] = cancelurl
332 334
            session.add_magictoken(magictoken, form_data)
333 335

  
wcs/qommon/publisher.py
37 37
import sys
38 38
import time
39 39
import traceback
40
import urllib.parse
40 41

  
41 42
import linecache
42 43
import xml.etree.ElementTree as ET
......
386 387
        defaults = {
387 388
            'options': {
388 389
                'unused-files-behaviour': 'remove',
390
                'relatable-hosts': '',
389 391
            },
390 392
        }
391 393
        if self.site_options is None:
......
956 958
        d['manager_homepage_title'] = d.get('portal_agent_title')
957 959
        return d
958 960

  
961
    def is_relatable_url(self, url):
962
        parsed_url = urllib.parse.urlparse(url)
963
        if not parsed_url.netloc:
964
            return True
965
        if parsed_url.netloc == urllib.parse.urlparse(self.get_frontoffice_url()).netloc:
966
            return True
967
        if parsed_url.netloc == urllib.parse.urlparse(self.get_backoffice_url()).netloc:
968
            return True
969
        if parsed_url.netloc in [x.strip() for x in self.get_site_option('relatable-hosts').split(',')]:
970
            return True
971
        try:
972
            if parsed_url.netloc in self.site_options.options('api-secrets'):
973
                return True
974
        except ConfigParser.NoSectionError:
975
            pass
976
        return False
977

  
959 978
    extra_sources = []
960 979
    @classmethod
961 980
    def register_extra_source(cls, source):
962
-