#NEWLINE# def validate_mechanism( self , mech ) : #NEWLINE# #INDENT# "Parse and validate a mechanism.\n    Returns mech,m,arg,cidrlength,result\n\n    Examples:\n    >>> q = query(s='strong-bad@email.example.com.',\n    ...           h='mx.example.org', i='192.0.2.3')\n    >>> q.validate_mechanism('A')\n    ('A', 'a', 'email.example.com', 32, 'pass')\n\n    >>> q = query(s='strong-bad@email.example.com',\n    ...           h='mx.example.org', i='192.0.2.3')\n    >>> q.validate_mechanism('A//64')\n    ('A//64', 'a', 'email.example.com', 32, 'pass')\n\n    >>> q.validate_mechanism('A/24//64')\n    ('A/24//64', 'a', 'email.example.com', 24, 'pass')\n    \n    >>> q.validate_mechanism('?mx:%{d}/27')\n    ('?mx:%{d}/27', 'mx', 'email.example.com', 27, 'neutral')\n\n    >>> try: q.validate_mechanism('ip4:1.2.3.4/247')\n    ... except PermError as x: print(x)\n    Invalid IP4 CIDR length: ip4:1.2.3.4/247\n    \n    >>> try: q.validate_mechanism('ip4:1.2.3.4/33')\n    ... except PermError as x: print(x)\n    Invalid IP4 CIDR length: ip4:1.2.3.4/33\n\n    >>> try: q.validate_mechanism('a:example.com:8080')\n    ... except PermError as x: print(x)\n    Invalid domain found (use FQDN): example.com:8080\n    \n    >>> try: q.validate_mechanism('ip4:1.2.3.444/24')\n    ... except PermError as x: print(x)\n    Invalid IP4 address: ip4:1.2.3.444/24\n    \n    >>> try: q.validate_mechanism('ip4:1.2.03.4/24')\n    ... except PermError as x: print(x)\n    Invalid IP4 address: ip4:1.2.03.4/24\n    \n    >>> try: q.validate_mechanism('-all:3030')\n    ... except PermError as x: print(x)\n    Invalid all mechanism format - only qualifier allowed with all: -all:3030\n\n    >>> q.validate_mechanism('-mx:%%%_/.Clara.de/27')\n    ('-mx:%%%_/.Clara.de/27', 'mx', '% /.Clara.de', 27, 'fail')\n\n    >>> q.validate_mechanism('~exists:%{i}.%{s1}.100/86400.rate.%{d}')\n    ('~exists:%{i}.%{s1}.100/86400.rate.%{d}', 'exists', '192.0.2.3.com.100/86400.rate.email.example.com', 32, 'softfail')\n\n    >>> q.validate_mechanism('a:mail.example.com.')\n    ('a:mail.example.com.', 'a', 'mail.example.com', 32, 'pass')\n\n    >>> try: q.validate_mechanism('a:mail.example.com,')\n    ... except PermError as x: print(x)\n    Do not separate mechnisms with commas: a:mail.example.com,\n\n    >>> q = query(s='strong-bad@email.example.com',\n    ...           h='mx.example.org', i='2001:db8:1234::face:b007')    \n    >>> q.validate_mechanism('A//64')\n    ('A//64', 'a', 'email.example.com', 64, 'pass')\n\n    >>> q.validate_mechanism('A/16')\n    ('A/16', 'a', 'email.example.com', 128, 'pass')\n\n    >>> q.validate_mechanism('A/16//48')\n    ('A/16//48', 'a', 'email.example.com', 48, 'pass')\n\n    " #NEWLINE# if mech . endswith ( ',' ) : #NEWLINE# #INDENT# self . note_error ( 'Do not separate mechnisms with commas' , mech ) #NEWLINE# mech = mech [ : ( - 1 ) ] #NEWLINE# #UNINDENT# ( m , arg , cidrlength , cidr6length ) = parse_mechanism ( mech , self . d ) #NEWLINE# if m : #NEWLINE# #INDENT# result = RESULTS . get ( m [ 0 ] ) #NEWLINE# if result : #NEWLINE# #INDENT# m = m [ 1 : ] #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# result = 'pass' #NEWLINE# #UNINDENT# #UNINDENT# if ( m in COMMON_MISTAKES ) : #NEWLINE# #INDENT# self . note_error ( 'Unknown mechanism found' , mech ) #NEWLINE# m = COMMON_MISTAKES [ m ] #NEWLINE# #UNINDENT# if ( ( m == 'a' ) and RE_IP4 . match ( arg ) ) : #NEWLINE# #INDENT# x = self . note_error ( 'Use the ip4 mechanism for ip4 addresses' , mech ) #NEWLINE# m = 'ip4' #NEWLINE# #UNINDENT# if ( m in ( 'a' , 'mx' ) ) : #NEWLINE# #INDENT# if ( cidrlength is None ) : #NEWLINE# #INDENT# cidrlength = 32 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( cidrlength > 32 ) : #NEWLINE# #INDENT# raise PermError ( 'Invalid IP4 CIDR length' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# if ( cidr6length is None ) : #NEWLINE# #INDENT# cidr6length = 128 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( cidr6length > 128 ) : #NEWLINE# #INDENT# raise PermError ( 'Invalid IP6 CIDR length' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# if ( self . v == 'ip6' ) : #NEWLINE# #INDENT# cidrlength = cidr6length #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( m == 'ip4' ) or RE_IP4 . match ( m ) ) : #NEWLINE# #INDENT# if ( m != 'ip4' ) : #NEWLINE# #INDENT# self . note_error ( 'Missing IP4' , mech ) #NEWLINE# ( m , arg ) = ( 'ip4' , m ) #NEWLINE# #UNINDENT# if ( cidr6length is not None ) : #NEWLINE# #INDENT# raise PermError ( 'Dual CIDR not allowed' , mech ) #NEWLINE# #UNINDENT# if ( cidrlength is None ) : #NEWLINE# #INDENT# cidrlength = 32 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( cidrlength > 32 ) : #NEWLINE# #INDENT# raise PermError ( 'Invalid IP4 CIDR length' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# if ( not RE_IP4 . match ( arg ) ) : #NEWLINE# #INDENT# raise PermError ( 'Invalid IP4 address' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( m == 'ip6' ) : #NEWLINE# #INDENT# if ( cidr6length is not None ) : #NEWLINE# #INDENT# raise PermError ( 'Dual CIDR not allowed' , mech ) #NEWLINE# #UNINDENT# if ( cidrlength is None ) : #NEWLINE# #INDENT# cidrlength = 128 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( cidrlength > 128 ) : #NEWLINE# #INDENT# raise PermError ( 'Invalid IP6 CIDR length' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# if ( not RE_IP6 . match ( arg ) ) : #NEWLINE# #INDENT# raise PermError ( 'Invalid IP6 address' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( cidrlength is not None ) or ( cidr6length is not None ) ) : #NEWLINE# #INDENT# if ( m in ALL_MECHANISMS ) : #NEWLINE# #INDENT# raise PermError ( 'CIDR not allowed' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# cidrlength = self . cidrmax #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# if ( m in ( 'a' , 'mx' , 'ptr' , 'exists' , 'include' ) ) : #NEWLINE# #INDENT# if ( ( m == 'exists' ) and ( not arg ) ) : #NEWLINE# #INDENT# raise PermError ( 'implicit exists not allowed' , mech ) #NEWLINE# #UNINDENT# arg = self . expand_domain ( arg ) #NEWLINE# if ( not arg ) : #NEWLINE# #INDENT# raise PermError ( 'empty domain:' , mech ) #NEWLINE# #UNINDENT# if ( m == 'include' ) : #NEWLINE# #INDENT# if ( arg == m . d ) : #NEWLINE# #INDENT# if ( mech != 'include' ) : #NEWLINE# #INDENT# raise PermError ( 'include has trivial recursion' , mech ) #NEWLINE# #UNINDENT# raise PermError ( 'include mechanism missing domain' , mech ) #NEWLINE# #UNINDENT# #UNINDENT# return ( mech , m , arg , cidrlength , result ) #NEWLINE# #UNINDENT# if ( ( m == 'all' ) and mech . count ( ':' ) ) : #NEWLINE# #INDENT# self . note_error ( 'Invalid all mechanism format - only qualifier allowed with all' , mech ) #NEWLINE# #UNINDENT# if ( m in ALL_MECHANISMS ) : #NEWLINE# #INDENT# return ( mech , m , arg , cidrlength , result ) #NEWLINE# #UNINDENT# if ( m [ 1 : ] in ALL_MECHANISMS ) : #NEWLINE# #INDENT# x = self . note_error ( 'Unknown qualifier, RFC 4408 para 4.6.1, found in' , mech ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# x = self . note_error ( 'Unknown mechanism found' , mech ) #NEWLINE# #UNINDENT# return ( mech , m , arg , cidrlength , x )