mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2025-10-26 21:59:38 -07:00 
			
		
		
		
	* Move licenses to LICENSES/, run add-license.py, add LICENSES/MIT.txt. * Replace 'Copyright:' with 'Copyright' sed -i 's|Copyright:\(.*\)|Copyright\1|' $(rg -l 'Copyright:') Co-authored-by: Maxwell G <gotmax@e.email>
		
			
				
	
	
		
			179 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| # This code is part of Ansible, but is an independent component.
 | |
| # This particular file snippet, and this file snippet only, is BSD licensed.
 | |
| # Modules you write using this snippet, which is embedded dynamically by Ansible
 | |
| # still belong to the author of the module, and may assign their own license
 | |
| # to the complete work.
 | |
| 
 | |
| # Copyright (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
 | |
| #
 | |
| # Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
 | |
| # SPDX-License-Identifier: BSD-2-Clause
 | |
| 
 | |
| from __future__ import (absolute_import, division, print_function)
 | |
| __metaclass__ = type
 | |
| 
 | |
| from stringprep import (
 | |
|     in_table_a1,
 | |
|     in_table_b1,
 | |
|     in_table_c3,
 | |
|     in_table_c4,
 | |
|     in_table_c5,
 | |
|     in_table_c6,
 | |
|     in_table_c7,
 | |
|     in_table_c8,
 | |
|     in_table_c9,
 | |
|     in_table_c12,
 | |
|     in_table_c21_c22,
 | |
|     in_table_d1,
 | |
|     in_table_d2,
 | |
| )
 | |
| from unicodedata import normalize
 | |
| 
 | |
| from ansible.module_utils.six import text_type
 | |
| 
 | |
| 
 | |
| def is_unicode_str(string):
 | |
|     return True if isinstance(string, text_type) else False
 | |
| 
 | |
| 
 | |
| def mapping_profile(string):
 | |
|     """RFC4013 Mapping profile implementation."""
 | |
|     # Regarding RFC4013,
 | |
|     # This profile specifies:
 | |
|     #   -  non-ASCII space characters [StringPrep, C.1.2] that can be
 | |
|     #      mapped to SPACE (U+0020), and
 | |
|     #   -  the "commonly mapped to nothing" characters [StringPrep, B.1]
 | |
|     #      that can be mapped to nothing.
 | |
| 
 | |
|     tmp = []
 | |
|     for c in string:
 | |
|         # If not the "commonly mapped to nothing"
 | |
|         if not in_table_b1(c):
 | |
|             if in_table_c12(c):
 | |
|                 # map non-ASCII space characters
 | |
|                 # (that can be mapped) to Unicode space
 | |
|                 tmp.append(u' ')
 | |
|             else:
 | |
|                 tmp.append(c)
 | |
| 
 | |
|     return u"".join(tmp)
 | |
| 
 | |
| 
 | |
| def is_ral_string(string):
 | |
|     """RFC3454 Check bidirectional category of the string"""
 | |
|     # Regarding RFC3454,
 | |
|     # Table D.1 lists the characters that belong
 | |
|     # to Unicode bidirectional categories "R" and "AL".
 | |
|     # If a string contains any RandALCat character, a RandALCat
 | |
|     # character MUST be the first character of the string, and a
 | |
|     # RandALCat character MUST be the last character of the string.
 | |
|     if in_table_d1(string[0]):
 | |
|         if not in_table_d1(string[-1]):
 | |
|             raise ValueError('RFC3454: incorrect bidirectional RandALCat string.')
 | |
|         return True
 | |
|     return False
 | |
| 
 | |
| 
 | |
| def prohibited_output_profile(string):
 | |
|     """RFC4013 Prohibited output profile implementation."""
 | |
|     # Implements:
 | |
|     # RFC4013, 2.3. Prohibited Output.
 | |
|     # This profile specifies the following characters as prohibited input:
 | |
|     #   - Non-ASCII space characters [StringPrep, C.1.2]
 | |
|     #   - ASCII control characters [StringPrep, C.2.1]
 | |
|     #   - Non-ASCII control characters [StringPrep, C.2.2]
 | |
|     #   - Private Use characters [StringPrep, C.3]
 | |
|     #   - Non-character code points [StringPrep, C.4]
 | |
|     #   - Surrogate code points [StringPrep, C.5]
 | |
|     #   - Inappropriate for plain text characters [StringPrep, C.6]
 | |
|     #   - Inappropriate for canonical representation characters [StringPrep, C.7]
 | |
|     #   - Change display properties or deprecated characters [StringPrep, C.8]
 | |
|     #   - Tagging characters [StringPrep, C.9]
 | |
|     # RFC4013, 2.4. Bidirectional Characters.
 | |
|     # RFC4013, 2.5. Unassigned Code Points.
 | |
| 
 | |
|     # Determine how to handle bidirectional characters (RFC3454):
 | |
|     if is_ral_string(string):
 | |
|         # If a string contains any RandALCat characters,
 | |
|         # The string MUST NOT contain any LCat character:
 | |
|         is_prohibited_bidi_ch = in_table_d2
 | |
|         bidi_table = 'D.2'
 | |
|     else:
 | |
|         # Forbid RandALCat characters in LCat string:
 | |
|         is_prohibited_bidi_ch = in_table_d1
 | |
|         bidi_table = 'D.1'
 | |
| 
 | |
|     RFC = 'RFC4013'
 | |
|     for c in string:
 | |
|         # RFC4013 2.3. Prohibited Output:
 | |
|         if in_table_c12(c):
 | |
|             raise ValueError('%s: prohibited non-ASCII space characters '
 | |
|                              'that cannot be replaced (C.1.2).' % RFC)
 | |
|         if in_table_c21_c22(c):
 | |
|             raise ValueError('%s: prohibited control characters (C.2.1).' % RFC)
 | |
|         if in_table_c3(c):
 | |
|             raise ValueError('%s: prohibited private Use characters (C.3).' % RFC)
 | |
|         if in_table_c4(c):
 | |
|             raise ValueError('%s: prohibited non-character code points (C.4).' % RFC)
 | |
|         if in_table_c5(c):
 | |
|             raise ValueError('%s: prohibited surrogate code points (C.5).' % RFC)
 | |
|         if in_table_c6(c):
 | |
|             raise ValueError('%s: prohibited inappropriate for plain text '
 | |
|                              'characters (C.6).' % RFC)
 | |
|         if in_table_c7(c):
 | |
|             raise ValueError('%s: prohibited inappropriate for canonical '
 | |
|                              'representation characters (C.7).' % RFC)
 | |
|         if in_table_c8(c):
 | |
|             raise ValueError('%s: prohibited change display properties / '
 | |
|                              'deprecated characters (C.8).' % RFC)
 | |
|         if in_table_c9(c):
 | |
|             raise ValueError('%s: prohibited tagging characters (C.9).' % RFC)
 | |
| 
 | |
|         # RFC4013, 2.4. Bidirectional Characters:
 | |
|         if is_prohibited_bidi_ch(c):
 | |
|             raise ValueError('%s: prohibited bidi characters (%s).' % (RFC, bidi_table))
 | |
| 
 | |
|         # RFC4013, 2.5. Unassigned Code Points:
 | |
|         if in_table_a1(c):
 | |
|             raise ValueError('%s: prohibited unassigned code points (A.1).' % RFC)
 | |
| 
 | |
| 
 | |
| def saslprep(string):
 | |
|     """RFC4013 implementation.
 | |
|     Implements "SASLprep" profile (RFC4013) of the "stringprep" algorithm (RFC3454)
 | |
|     to prepare Unicode strings representing user names and passwords for comparison.
 | |
|     Regarding the RFC4013, the "SASLprep" profile is intended to be used by
 | |
|     Simple Authentication and Security Layer (SASL) mechanisms
 | |
|     (such as PLAIN, CRAM-MD5, and DIGEST-MD5), as well as other protocols
 | |
|     exchanging simple user names and/or passwords.
 | |
| 
 | |
|     Args:
 | |
|         string (unicode string): Unicode string to validate and prepare.
 | |
| 
 | |
|     Returns:
 | |
|         Prepared unicode string.
 | |
|     """
 | |
|     # RFC4013: "The algorithm assumes all strings are
 | |
|     # comprised of characters from the Unicode [Unicode] character set."
 | |
|     # Validate the string is a Unicode string
 | |
|     # (text_type is the string type if PY3 and unicode otherwise):
 | |
|     if not is_unicode_str(string):
 | |
|         raise TypeError('input must be of type %s, not %s' % (text_type, type(string)))
 | |
| 
 | |
|     # RFC4013: 2.1. Mapping.
 | |
|     string = mapping_profile(string)
 | |
| 
 | |
|     # RFC4013: 2.2. Normalization.
 | |
|     # "This profile specifies using Unicode normalization form KC."
 | |
|     string = normalize('NFKC', string)
 | |
|     if not string:
 | |
|         return u''
 | |
| 
 | |
|     # RFC4013: 2.3. Prohibited Output.
 | |
|     # RFC4013: 2.4. Bidirectional Characters.
 | |
|     # RFC4013: 2.5. Unassigned Code Points.
 | |
|     prohibited_output_profile(string)
 | |
| 
 | |
|     return string
 |