HEX
Server: LiteSpeed
System: Linux shams.tasjeel.ae 5.14.0-611.5.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Nov 11 08:09:09 EST 2025 x86_64
User: infowars (1469)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: //lib/python3.9/site-packages/ipapython/__pycache__/ipaldap.cpython-39.opt-1.pyc
a

�N(i �@s`ddlZddlZddlZddlZddlmZddlmZddlmZddl	Z	ddl
Z
ddlZddlZddl
mZddlmZddlZddlZddlZddlmZmZddlZddlZddlmZmZmZdd	lmZdd
lm Z ddl!m"Z"m#Z#ddl$m%Z%m&Z&dd
l'm(Z(ddl)m*Z*ddl+m,Z,ej-�r0e.Z/e�0e1�Z2ej3�3id�Z4ej3�3id�Z5dZ6e7�Z8dZ9dZ:dZ;e7�Z<e7�Z=e7�Z>e%d�Z?ej@�r�eAed��r�ejBdejCd�dd�ZDdd�ZEd6dd�ZFGd d!�d!�ZGGd"d#�d#�ZHeH�ZIGd$d%�d%e,�ZJGd&d'�d'e,�ZKGd(d)�d)eK�ZLGd*d+�d+eK�ZMGd,d-�d-�ZNd7d0d1�ZOGd2d3�d3�ZPGd4d5�d5eN�ZQdS)8�N)�datetime)�Decimal)�deepcopy)�OrderedDict)�
serialization)�SimplePagedResultsControl�GetEffectiveRightsControl)�errors�x509�_)�LDAP_GENERALIZED_TIME_FORMAT)�paths)�
format_netloc�CIDict)�DN�RDN)�DNSName)�	Principal)�MutableMappingZGSSAPIz
GSS-SPNEGOF���)�cnzdirectory manager�LDAPBytesWarning�ignore)�action�categorycCsd�|�d��S)z/Convert Kerberos realm name to 389-DS server id�-�.)�join�split)�
realm_name�r"�5/usr/lib/python3.9/site-packages/ipapython/ipaldap.py�realm_to_serveridZsr$cCs"t|�}tj|f}dt�|�S)z(Get ldapi:// URI to 389-DS's Unix socket�ldapi://)r$r
ZSLAPD_INSTANCE_SOCKET_TEMPLATE�ldapurlZ
ldapUrlEscape)r!ZserveridZ
socketnamer"r"r#�realm_to_ldapi_uri_sr'cCs~t�|�}|�tjtj�|�d�sz|rNtj�|�s@t	t
j|��|�tj|�|�tj
d�|�tjtj�|�tjd�|S)a�Wrapper around ldap.initialize()

    The function undoes global and local ldap.conf settings that may cause
    issues or reduce security:

    * Canonization of SASL host names is disabled.
    * With cacertfile=None, the connection uses OpenSSL's default verify
      locations, also known as system-wide trust store.
    * Cert validation is enforced.
    * SSLv2 and SSLv3 are disabled.
    r%ir)�ldapZ
initialize�
set_option�OPT_X_SASL_NOCANONZOPT_ON�
startswith�os�path�isfile�IOError�errno�ENOENTZOPT_X_TLS_CACERTFILEZOPT_X_TLS_PROTOCOL_MINZOPT_X_TLS_REQUIRE_CERTZOPT_X_TLS_DEMANDZOPT_X_TLS_NEWCTX)�uri�
cacertfile�connr"r"r#�ldap_initializefs

	r5c@seZdZdZdd�ZdS)�
_ServerSchemaz?
    Properties of a schema retrieved from an LDAP server.
    cCs||_||_t��|_dS�N)�server�schema�timeZretrieve_timestamp)�selfr8r9r"r"r#�__init__�sz_ServerSchema.__init__N)�__name__�
__module__�__qualname__�__doc__r<r"r"r"r#r6�sr6c@s2eZdZdZdd�Zddd�Zdd�Zd	d
�ZdS)
�SchemaCachez:
    Cache the schema's from individual LDAP servers.
    cCs
i|_dSr7)�servers�r;r"r"r#r<�szSchemaCache.__init__FcCsH|r|�|�|j�|�}|durB|�||�}t||�}||j|<|jS)a
        Return schema belonging to a specific LDAP server.

        For performance reasons the schema is retrieved once and
        cached unless force_update is True. force_update flushes the
        existing schema for the server from the cache and reacquires
        it.
        N)�flushrB�get�_retrieve_schema_from_serverr6r9)r;�urlr4�force_updateZ
server_schemar9r"r"r#�
get_schema�s



zSchemaCache.get_schemacCs0t�d|�z|j|=Wnty*Yn0dS)Nzflushing %s from SchemaCache)�logger�debugrB�KeyError)r;rGr"r"r#rD�s
zSchemaCache.flushc
Cst�d||�z\z|jdtjddgd�d}Wn8tjyft�d�|jdtjddgd�d}Yn0Wn�tjy�tj|d	d
��Ynhtj	y�}zN|j
dd��}|j
d�dd
���}tj
d|d||fd��WYd}~n
d}~00tj�|d�S)a

        Retrieve the LDAP schema from the provided url and determine if
        User-Private Groups (upg) are configured.

        Bind using kerberos credentials. If in the context of the
        in-tree "lite" server then use the current ccache. If in the context of
        Apache then create a new ccache and bind using the Apache HTTP service
        principal.

        If a connection is provided then it the credentials bound to it are
        used. The connection is not closed when the request is done.
        z0retrieving schema for SchemaCache url=%s conn=%sz	cn=schema�attributetypes�
objectclasses)Zattrlistrz-cn=schema not found, fallback to cn=subschemazcn=subschemaz0LDAP Server Down, unable to retrieve LDAP schema�r2�error�desc�info�zuri=%sz&Unable to retrieve LDAP schema: %s: %s�rQrRNr)rJrKZsearch_sr(�
SCOPE_BASE�NO_SUCH_OBJECT�SERVER_DOWNr	�NetworkError�	LDAPError�args�striprE�
DatabaseErrorr9Z	SubSchema)r;rGr4Zschema_entry�erQrRr"r"r#rF�s8�
��

���


�z(SchemaCache._retrieve_schema_from_serverN)F)r=r>r?r@r<rIrDrFr"r"r"r#rA�s

rAcseZdZdZdZd:�fdd�	Zedd��Zedd��Zej	d	d��Zed
d��Z
edd
��Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd;d4d5�Zd6d7�Z d8d9�Z!�Z"S)<�	LDAPEntry)
�_conn�_dn�_names�_nice�_raw�_sync�	_not_list�	_orig_raw�	_raw_view�_single_value_viewNcstt|���t|t�r"|}|j}t|t�r6|}|j}|durBi}||_||_t�|_i|_i|_	i|_
t�|_i|_
d|_d|_t|t�r�t|j�|_t|j
�|_
|j|ur�t|j�|_t|j�|_t|j	�|_	t|j
�|_
n|j�|j�i}|j|fi|��dS)a�
        LDAPEntry constructor.

        Takes 1 to 3 positional arguments and an arbitrary number of keyword
        arguments. The 3 forms of positional arguments are:

          * LDAPEntry(entry) - create a shallow copy of an existing LDAPEntry.
          * LDAPEntry(dn, entry) - create a shallow copy of an existing
            LDAPEntry with a different DN.
          * LDAPEntry(conn, dn, mapping) - create a new LDAPEntry using the
            specified LDAPClient and DN and optionally initialize
            attributes from the specified mapping object.

        Keyword arguments can be used to override values of specific attributes.
        N)�superr^r<�
isinstancer_r`rrarbrcrd�setrerfrgrh�dictr4�raw�update)r;r_r`�_obj�kwargs��	__class__r"r#r<�s<



zLDAPEntry.__init__cCs|jSr7�r_rCr"r"r#r4,szLDAPEntry.conncCs|jSr7�r`rCr"r"r#�dn0szLDAPEntry.dncCs
||_dSr7rt)r;�valuer"r"r#ru4scCs|jdurt|�|_|jSr7)rg�RawLDAPEntryViewrCr"r"r#rm9s

z
LDAPEntry.rawcCs|jdurt|�|_|jSr7)rh�SingleValueLDAPEntryViewrCr"r"r#�single_value?s

zLDAPEntry.single_valuecCs:t|j�}|�dd�|j��D��dt|�j|j|fS)Ncss"|]\}}|dur||fVqdSr7r"��.0�k�vr"r"r#�	<genexpr>G�z%LDAPEntry.__repr__.<locals>.<genexpr>z
%s(%r, %r))rlrcrnrb�items�typer=r`)r;�datar"r"r#�__repr__Es
zLDAPEntry.__repr__cCst|�Sr7�r^rCr"r"r#�copyJszLDAPEntry.copycCs�|j|}|j|}|j�|ggf�\}}||kr>||kr>dSt|�t|�}t|�t|�}t|�t|�}t|�t|�}	|D]$}
|j�|
�}
|
|vr�q�|�|
�q�|	D]f}
z|j�|
|�}
Wn8t	y�}z t	dj
||jd���WYd}~n
d}~00|
|v�rq�|�|
�q�t||j
d�D]*}
|j�|
�}
|
|	v�r@�q"|�|
��q"t||j
d�D]l}
z|j�|
|�}
Wn:t	�y�}z t	dj
||jd���WYd}~n
d}~00|
|v�r��q\|�|
��q\t|�t|�f|j|<t|�dk�r�|j�|�dS)Nz{error} in LDAP entry '{dn}')rPru��keyr)rbrcrd�
setdefaultrkr_�encode�remove�decode�
ValueError�formatr`�sorted�index�appendr�lenre�discard)r;�name�nicermZ	nice_syncZraw_syncZ	nice_addsZ	nice_delsZraw_addsZraw_delsrvr]r"r"r#�
_sync_attrMsT

�

�
zLDAPEntry._sync_attrcCs6t|t�std|jj|f��t|t�r2|�d�}|S)Nz7attribute name must be unicode or str, got %s object %r�utf-8)rj�str�	TypeErrorrrr=�bytesr��r;r�r"r"r#�
_attr_name�s
��

zLDAPEntry._attr_namecCs�||jvr|j|S|jjdurxtjr2|�d�}n|}|jj�tjj|�}|durx|j	D]}tjrl|�
d�}||j|<qX||j|<t|j�D]*}|j�
|�|kr�|j�|�|j|<q�q�|S�Nr�)rar_r9�six�PY2r��get_objr(�
AttributeType�namesr��listrfrE�pop)r;r�Zencoded_nameZattrtype�altnameZoldnamer"r"r#�_add_attr_name�s(

�


zLDAPEntry._add_attr_namecCs�|�|�}|�|�}t|t�s@|dur,g}n|g}|j�|�n|j�|�|j�|�|ur~||j|<d|j	|<|j
�|d�|j	|dur�|�|�dSr7)
r�r�rjr�re�addr�rbrErcrdr�r��r;r�rvr"r"r#�	_set_nice�s




zLDAPEntry._set_nicecCs�|�|�}t|t�s*td||jj|f��t|�D]*\}}t|t�s2td|||jj|f��q2|�|�}|j	�
|�|ur�||j	|<d|j|<|j�
|d�|j|dur�|�|�dS)Nz'%s value must be list, got %s object %rz,%s[%d] value must be bytes, got %s object %r)r�rjr�r�rrr=�	enumerater�r�rcrErbrdr�r�)r;r�rv�i�itemr"r"r#�_set_raw�s&


�
��


zLDAPEntry._set_rawcCs|�||�dSr7)r�r�r"r"r#�__setitem__�szLDAPEntry.__setitem__cCs|�|�}|j|}|Sr7)r�rar�r"r"r#�_get_attr_name�s

zLDAPEntry._get_attr_namecCsb|�|�}|j|}|dur*g}|j|<|j|durB|�|�||jvr^|rZ|d}nd}|S)Nr)r�rbrcr�rer�r"r"r#�	_get_nice�s




zLDAPEntry._get_nicecCsF|�|�}|j|}|dur*g}|j|<|j|durB|�|�|Sr7)r�rcrbr�r�r"r"r#�_get_raw�s


zLDAPEntry._get_rawcCs
|�|�Sr7)r�r�r"r"r#�__getitem__�szLDAPEntry.__getitem__cCs`|�|�}t|j���D]\}}||kr|j|=q|j|=|j|=|j�|d�|j�	|�dSr7)
r�r�rar�rbrcrdr�rer�)r;r�r�Zkeynamer"r"r#�__delitem__�s

zLDAPEntry.__delitem__cCs6|j��|j��|j��|j��|j��dSr7)ra�clearrbrcrdrerCr"r"r#r�s




zLDAPEntry.clearcCs
t|j�Sr7)r�rbrCr"r"r#�__len__szLDAPEntry.__len__cCs
||jvSr7)rar�r"r"r#�__contains__szLDAPEntry.__contains__cCs||vSr7r"r�r"r"r#�has_keyszLDAPEntry.has_keycCst|t�stS||uSr7�rjr^�NotImplemented�r;�otherr"r"r#�__eq__s
zLDAPEntry.__eq__cCst|t�stS||uSr7r�r�r"r"r#�__ne__ s
zLDAPEntry.__ne__cCs |dur|}tt|j��|_dSr7)rrlrmrfr�r"r"r#�
reset_modlist%szLDAPEntry.reset_modlistcsg}t|�}|�|j�|D]�}|j�|g��|j�|g���rX�sX|�tj|df�q�st�rt|�tj|�f�q�fdd��D�}�fdd��D�}|r�|j	�
|�r�t|�dkr�tj
|d��|�tj||f�q|r�|�tj||f�|r|�tj||f�q|jdd�d�|S)	Ncsg|]}|�vr|�qSr"r"�r{rv)�oldr"r#�
<listcomp>=rz.LDAPEntry.generate_modlist.<locals>.<listcomp>csg|]}|�vr|�qSr"r"r�)�newr"r#r�>rr��attrcSs|d��dkS)NrrM��lower)�mr"r"r#�<lambda>Prz,LDAPEntry.generate_modlist.<locals>.<lambda>r�)rkrnrfrmrEr�r(Z
MOD_DELETEZMOD_REPLACEr4�get_attribute_single_valuer�r	ZOnlyOneValueAllowedZMOD_ADD�sort)r;�modlistr�r�ZaddsZdelsr")r�r�r#�generate_modlist+s0zLDAPEntry.generate_modlistcCs
t|j�Sr7)�iterrbrCr"r"r#�__iter__TszLDAPEntry.__iter__)NN)N)#r=r>r?�	__slots__�__hash__r<�propertyr4ru�setterrmryr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r��
__classcell__r"r"rqr#r^�sF;




5

)r^c@sHeZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dS)�
LDAPEntryView��_entrycCs
||_dSr7r��r;�entryr"r"r#r<[szLDAPEntryView.__init__cCs|j|=dSr7r�r�r"r"r#r�_szLDAPEntryView.__delitem__cCs|j��dSr7)r�r�rCr"r"r#r�bszLDAPEntryView.clearcCs
t|j�Sr7)r�r�rCr"r"r#r�eszLDAPEntryView.__iter__cCs
t|j�Sr7)r�r�rCr"r"r#r�hszLDAPEntryView.__len__cCs
||jvSr7r�r�r"r"r#r�kszLDAPEntryView.__contains__cCs||vSr7r"r�r"r"r#r�nszLDAPEntryView.has_keyN)r=r>r?r�r<r�r�r�r�r�r�r"r"r"r#r�Xsr�c@seZdZdd�Zdd�ZdS)rwcCs|j�|�Sr7)r�r�r�r"r"r#r�rszRawLDAPEntryView.__getitem__cCs|j�||�dSr7)r�r�r�r"r"r#r�uszRawLDAPEntryView.__setitem__N�r=r>r?r�r�r"r"r"r#rwqsrwc@seZdZdd�Zdd�ZdS)rxcCsL|j|}t|t�s|S|s dSt|�dkr4|dStd|t|�f��dS)Nrrz%s has %s values, one expected)r�rjr�r�r�r�r"r"r#r�ys

�z$SingleValueLDAPEntryView.__getitem__cCs$|durd|j|<n|g|j|<dSr7r�r�r"r"r#r��sz$SingleValueLDAPEntryView.__setitem__Nr�r"r"r"r#rxxs
rxc+@s�eZdZdZdZdZdZejZej	Z	ej
Z
eeeeeeee
eeeeeeee
e
e
e
e
e
e
e
e
e
ee
e
e
e
e
e
ee
e
eeee
e
eed�*Zee
e
e
e
e
eeeeeeejejejejeeeed��Zedddddddddddd��Zd	Zd
Zdgd
d�Zedd��Zeejdfdd��Zedd��Z dd�Z!dd�Z"e#dd��Z$e#dd��Z%dd�Z&dd �Z'd!d"�Z(d#d$�Z)d%d&�Z*d'd(�Z+d)d*�Z,d+d,�Z-e.j/dhd-d.��Z0e1d/d0��Z2e#d1d2��Z3did4d5�Z4d6d7�Z5d8d9�Z6d:d;�Z7d<d=�Z8djd>d?�Z9dkd@dA�Z:dldBdC�Z;dDdE�Z<dmdFdG�Z=dndIdJ�Z>dodKdL�Z?edpdMdN��Z@edqdOdP��ZAedrdQdR��ZBej
dddfdSdT�ZCdddej
ddddfdUdV�ZDdWdX�ZEdsdYdZ�ZFdtd[d\�ZGd]d^�ZHdud_d`�ZIdadb�ZJdcdd�ZKdedf�ZLdS)v�
LDAPClienta�LDAP backend class

    This class abstracts a LDAP connection, providing methods that work with
    LADPEntries.

    The purpose of this class is to provide a boundary between IPA and
    python-ldap. In IPA we use IPA defined types because they are
    richer and are designed to meet our needs. We also require that we
    consistently use those types without exception. On the other hand
    python-ldap uses different types. The goal is to be able to have
    IPA code call python-ldap methods using the types native to
    IPA. This class accomplishes that goal by exposing python-ldap
    methods which take IPA types, convert them to python-ldap types,
    call python-ldap, and then convert the results returned by
    python-ldap into IPA types.
    �|�&�!)*z1.3.6.1.4.1.1466.115.121.1.1z1.3.6.1.4.1.1466.115.121.1.4z1.3.6.1.4.1.1466.115.121.1.5z1.3.6.1.4.1.1466.115.121.1.7z1.3.6.1.4.1.1466.115.121.1.8z1.3.6.1.4.1.1466.115.121.1.9z1.3.6.1.4.1.1466.115.121.1.10z1.3.6.1.4.1.1466.115.121.1.12z1.3.6.1.4.1.1466.115.121.1.23z1.3.6.1.4.1.1466.115.121.1.24z1.3.6.1.4.1.1466.115.121.1.28z1.3.6.1.4.1.1466.115.121.1.40z1.3.6.1.4.1.1466.115.121.1.49z1.3.6.1.4.1.1466.115.121.1.51z1.3.6.1.4.1.5322.21.2.5z2.16.840.1.113730.3.8.3.3z2.16.840.1.113730.3.8.3.18z2.16.840.1.113730.3.8.3.5z2.16.840.1.113730.3.8.3.7z2.16.840.1.113730.3.8.3.20z2.16.840.1.113730.3.8.11.4z2.16.840.1.113730.3.8.11.21z2.16.840.1.113730.3.8.11.22z2.16.840.1.113730.3.8.7.1z2.16.840.1.113730.3.8.7.2z2.16.840.1.113719.1.301.4.6.1z2.16.840.1.113719.1.301.4.14.1z2.16.840.1.113719.1.301.4.17.1z2.16.840.1.113719.1.301.4.18.1z2.16.840.1.113719.1.301.4.26.1z2.16.840.1.113719.1.301.4.29.1z2.16.840.1.113719.1.301.4.36.1z2.16.840.1.113719.1.301.4.37.1z2.16.840.1.113719.1.301.4.40.1z2.16.840.1.113719.1.301.4.41.1z2.16.840.1.113719.1.301.4.45.1z2.16.840.1.113719.1.301.4.48.1z2.16.840.1.113719.1.301.4.49.1z2.16.840.1.113719.1.301.4.52.1z2.16.840.1.113719.1.301.4.53.1z2.16.840.1.113730.3.8.16.1.3z2.16.840.1.113730.3.8.16.1.4)ZmanagedtemplateZmanagedbaseZmemberindirectZmemberofindirectZoriginscope�idnsnameZidnssoamnameZidnssoarnameZdnszoneidnsnameZkrbcanonicalnameZkrbprincipalname�usercertificate�usercertificate;binaryZ
cACertificatezcACertificate;binaryZnsds5replicalastupdatestartZnsds5replicalastupdateendZnsds5replicalastinitstartZnsds5replicalastinitendT)znsslapd-ssl-check-hostnameznsslapd-lookthroughlimitznsslapd-idlistscanlimitznsslapd-anonlimitsdnznsslapd-minssf-exclude-rootdseznsslapd-enable-upgrade-hashznsslapd-db-locksz%nsslapd-logging-hr-timestamps-enabledznsslapd-ldapientrysearchbaseznsslapd-ldapidnmappingbaseznsslapd-sizelimit��rFNcCsT|dur||_||_||_||_||_||_||_d|_d|_|durP|�	�|_
dS)a�Create LDAPClient object.

        :param ldap_uri: The LDAP URI to connect to
        :param start_tls: Use STARTTLS
        :param force_schema_updates:
            If true, this object will always request a new schema from the
            server. If false, a cached schema will be reused if it exists.

            Generally, it should be true if the API context is 'installer' or
            'updates', but it must be given explicitly since the API object
            is not always available
        :param no_schema: If true, schema is never requested from the server.
        :param decode_attrs:
            If true, attributes are decoded to Python types according to their
            syntax.
        NF)�ldap_uri�
_start_tls�_force_schema_updates�
_no_schema�
_decode_attrs�_cacert�
_sasl_nocanon�_has_schema�_schema�_connectr_)r;r��	start_tls�force_schema_updates�	no_schema�decode_attrs�cacert�sasl_nocanonr"r"r#r<szLDAPClient.__init__cKst|�}||fddd�|��S)z;Create a LDAPI connection to local 389-DS instance
        FN�r�r�)r')�clsr!rpr2r"r"r#�
from_realm,szLDAPClient.from_realmcKs8|rdt|d�}ndt|d�}||f||d�|��S)a�Create LDAP or LDAPS connection to a remote 389-DS instance

        This constructor is opinionated and doesn't let you shoot yourself in
        the foot. It always creates a secure connection. By default it
        returns a LDAP connection to port 389 and performs STARTTLS using the
        default CA cert. With start_tls=False, it creates a LDAPS connection
        to port 636 instead.

        Note: Microsoft AD does not support SASL encryption and integrity
        verification with a TLS connection. For AD, use a plain connection
        with GSSAPI and a MIN_SSF >= 56. SASL GSSAPI and SASL GSS SPNEGO
        ensure data integrity and confidentiality with SSF > 1. Also see
        https://msdn.microsoft.com/en-us/library/cc223500.aspx
        �	ldap://%s��
ldaps://%si|r��r)r��hostnamer�r�rpr2r"r"r#�from_hostname_secure3szLDAPClient.from_hostname_securecKsdt|d�}||fi|��S)z�Create a plain LDAP connection with TLS/SSL

        Note: A plain TLS connection should only be used in combination with
        GSSAPI bind.
        r�r�r�)r�r�rpr2r"r"r#�from_hostname_plainJs	zLDAPClient.from_hostname_plaincCs|jSr7)r�rCr"r"r#�__str__VszLDAPClient.__str__cs(t|�}�fdd�|D�}�j�||�S)Ncs"g|]\}}}||��|�f�qSr"�r��r{�a�b�crCr"r#r�]rz'LDAPClient.modify_s.<locals>.<listcomp>)r�r4�modify_s)r;rur�r"rCr#rYszLDAPClient.modify_scCs|jSr7rsrCr"r"r#r4`szLDAPClient.conncCs |jr|j�dd�dSdSdS)Nz://rr)r�r rCr"r"r#�protocoldszLDAPClient.protocolc	Csj|jr
dS|jsdztj|j|j|jd�}Wntjt	fyFd}Yn0t
�|d|�t
�|dd�|jS)N)rHr�r�T)
r�r��schema_cacherIr�r4r�r	ZExecutionError�
IndexError�object�__setattr__r�)r;r9r"r"r#�_get_schemaks�

zLDAPClient._get_schemacCs t�|dd�t�|dd�dS)zr
        Force this instance to forget it's cached schema and reacquire
        it from the schema cache.
        r�Fr�N)rrrCr"r"r#�
_flush_schema}szLDAPClient._flush_schemacCs||js
tStjr$t|t�r$|�d�}||jvr8|j|S|��}|durx|�	t
jj|�}|durx|j
|jvrx|j|j
StSr�)r�r�r�r�rj�unicoder��_SYNTAX_OVERRIDErr�r(r9r�Zsyntax�_SYNTAX_MAPPING�r;�name_or_oidr9�objr"r"r#�get_attribute_type�s



zLDAPClient.get_attribute_typecCs|�|�tuS)zf
        Check the schema to see if the attribute uses DN syntax.

        Returns True/False
        )rr)r;r
r"r"r#�
has_dn_syntax�szLDAPClient.has_dn_syntaxcCs`tjrt|t�r|�d�}||jvr.|j|S|��}|dur\|�tj	j
|�}|dur\|jSdS)z�
        Check the schema to see if the attribute is single-valued.

        If the attribute is in the schema then returns True/False

        If there is a problem loading the schema or the attribute is
        not in the schema return None
        r�N)r�r�rjr	r��_SINGLE_VALUE_OVERRIDErr�r(r9r�ryrr"r"r#r��s	


z%LDAPClient.get_attribute_single_valuecs"t|t�r|rdSdS�nt|tttttf�r<t|��d�St|t	�rT|�
��d�St|t�rb|St|t�r~�fdd�|D�St|t
�r�t
�fdd�|D��St|t�r�t�fd	d�|��D��}|St|t�r�|�t��d�St|tj��r�|�tjj�S|d
u�r
d
Std|t|�f��d
S)zL
        Encode attribute value to LDAP representation (str/bytes).
        sTRUEsFALSEr��asciicsg|]}��|��qSr"r��r{r�rCr"r#r��rz%LDAPClient.encode.<locals>.<listcomp>c3s|]}��|�VqdSr7r�rrCr"r#r~�rz$LDAPClient.encode.<locals>.<genexpr>c3s |]\}}|��|�fVqdSr7r�rzrCr"r#r~�rNz:attempt to pass unsupported type to ldap, value=%s type=%s)rj�boolr	�intrrrr�r�rZto_textr�r��tuplerlr�r�strftimerr
�IPACertificate�public_bytes�Encoding�DERr�r�)r;�val�dctr"rCr#r��s0







zLDAPClient.encodecs�t|t��r����}z�|tur&|WS|tur:|�d�WS|turR|�d�dkWS|turnt�|�d�t�WS|t	ur�t	�
|�d��WS|ttfvr�||�d��WS|t
jur�t
�|�WS||�WSWn6t�y�d�||f}t�d|�t|��Yn0n�t|t��r ��fdd�|D�St|t��rDt��fdd�|D��St|t��rj�fd	d
�|��D�}|S|du�rxdStd|t|�f��dS)
zN
        Decode attribute value from LDAP representation (str/bytes).
        r�ZTRUEz6unable to convert the attribute %r value %r to type %s�%scsg|]}��|���qSr"�r�r�r�r;r"r#r�rz%LDAPClient.decode.<locals>.<listcomp>c3s|]}��|��VqdSr7rrr r"r#r~rz$LDAPClient.decode.<locals>.<genexpr>cs$i|]\}}|�d���||��qS)r�rrzrCr"r#�
<dictcomp>sz%LDAPClient.decode.<locals>.<dictcomp>Nz<attempt to pass unsupported type from ldap, value=%s type=%s)rjr�rr	r�rr�strptimerrZ	from_textrrr
rZload_der_x509_certificate�	ExceptionrJrPr�r�rrlr�r�r�)r;rr�Ztarget_type�msgrr"r r#r��sH

�

�
zLDAPClient.decodec
Cs�g}|D]v}|d}|d}|durBdjt|�d�}t�d|�qt|t|��}|��D]\}}	|	|j|<qX|��|�	|�qt
r�t�d|�|S)a�
        result is a python-ldap result tuple of the form (dn, attrs),
        where dn is a string containing the dn (distinguished name) of
        the entry, and attrs is a dictionary containing the attributes
        associated with the entry. The keys of attrs are strings, and
        the associated values are lists of strings.

        We convert the tuple to an LDAPEntry object.
        rrNzReferral entry ignored: {ref})�refrzldap.result: %s)r�r�rJrKr^rr�rmr�r��_debug_log_ldap)
r;�resultZ
ipa_resultZdn_tupleZoriginal_dnZoriginal_attrsZlog_msgZ	ipa_entryr��original_valuesr"r"r#�_convert_results$�zLDAPClient._convert_resultc
cs�d}z�z
dVWn~tjy,t���Yndtjy�}zJ|jdd��}|jd�dd���}|durxd||f}�WYd}~n
d}~00W�n\tjy�tj	|p�dd��Y�n8tj
y�t���Y�ntjy�tj|d	��Y�n�tj
�y4d
}|�|��r t���ntj||d��Y�n�tj�yVtj|d��Y�n�tj�y�tjd
||fd��Y�nrtj�y�tjd||fd��Y�nHtj�y�t���Y�n*tj�y�tj|d��Y�ntj�ytj|d��Y�n�tj�y*t���Y�n�tj�yHt���Y�n�tj�yft���Y�n�tj �y�tj!|d��Y�njtj"�y�tj#|d��Y�nHtj$�y�t�%��Y�n*tj&�y�tj'|j(|d��Y�ntj)�ytj|d��Yn�tj*�y"Yn�tj+�yDtj||d��Yn�tj,�yftj||d��Yn�tj-�y�tjd||fd��Yndtj�y�}zHd|v�r�tjdd��t.�/dt0|�j1t2|��tj||d��WYd}~n
d}~00dS)z0Context manager that handles LDAPErrors
        NrrQrRrSz%s arguments: %sz
no such entry��reason)�messagez:Another entry with the same attribute value already existsrT)rRz%s %sz%s: %sr�rOz%s (%s)ZNOT_ALLOWED_TO_DELEGATEz$KDC returned NOT_ALLOWED_TO_DELEGATEzUnhandled LDAPError: %s: %s)3r(ZTIMEOUTr	ZDatabaseTimeoutrYrZr[rErV�NotFoundZALREADY_EXISTSZDuplicateEntryZTYPE_OR_VALUE_EXISTSZCONSTRAINT_VIOLATIONr+r\ZINSUFFICIENT_ACCESSZACIErrorZINVALID_CREDENTIALSZINAPPROPRIATE_AUTHZNO_SUCH_ATTRIBUTEZMidairCollisionZINVALID_SYNTAXZ
InvalidSyntaxZOBJECT_CLASS_VIOLATIONZObjectclassViolation�ADMINLIMIT_EXCEEDED�AdminLimitExceeded�SIZELIMIT_EXCEEDED�SizeLimitExceeded�TIMELIMIT_EXCEEDED�TimeLimitExceededZNOT_ALLOWED_ON_RDNZNotAllowedOnRDNZFILTER_ERRORZBadSearchFilterZNOT_ALLOWED_ON_NONLEAFZNotAllowedOnNonLeafrWrXr�ZLOCAL_ERROR�SUCCESSZ
CONNECT_ERRORZUNWILLING_TO_PERFORMZAUTH_UNKNOWNrJrKr�r=r�)r;Zarg_descrQr]rRZ_msgr"r"r#�
error_handler@s�

�
��zLDAPClient.error_handlercCsJ|sdS|turt���n,|tur,t���n|tur>t���nt���dSr7)�TRUNCATED_ADMIN_LIMITr	r/�TRUNCATED_SIZE_LIMITr1�TRUNCATED_TIME_LIMITr3�LimitsExceeded)�	truncatedr"r"r#�handle_truncated_result�s


z"LDAPClient.handle_truncated_resultcCs|��S)z'schema associated with this LDAP server)rrCr"r"r#r9�szLDAPClient.schema�allcCs�|jdurdSg}|D]p}|j�tjj|�}|durn|dkrH||j7}q�|dkr\||j7}q�||j|j7}q|rtjtd�|d��qdd�t	t
|��D�S)N�must�mayzobjectclass %s not foundr*cSsg|]}t|����qSr")r	r��r{r�r"r"r#r��rz5LDAPClient.get_allowed_attributes.<locals>.<listcomp>)r9r�r(ZObjectClassr=r>r	r-rr�rk)r;rNZraise_on_unknownZ
attributesZallowed_attributes�ocrr"r"r#�get_allowed_attributes�s 

�z!LDAPClient.get_allowed_attributescCs|Sr7r"rCr"r"r#�	__enter__�szLDAPClient.__enter__cCs|��dSr7)�close)r;�exc_type�	exc_value�	tracebackr"r"r#�__exit__�szLDAPClient.__exit__cCs
d|_dS)z'
        Close the connection.
        NrsrCr"r"r#rC�szLDAPClient.closecCsj|���Nt|j|jd�}|js0|�tjtj�|j	rH|j
dkrH|��Wd�n1s\0Y|S)N)r3r()r5r5r�r�r�r)r(r*ZOPT_OFFr�rZstart_tls_s)r;r4r"r"r#r��s
&zLDAPClient._connectcCsx|jdkr |js |r |s td��|���<|��t|�}|�|�}|j�||||�Wd�n1sj0YdS)z0
        Perform simple bind operation.
        r(z)simple_bind over insecure LDAP connectionN)	rr�r�r5rr�r�r4Z
simple_bind_s)r;�bind_dnZ
bind_password�server_controls�client_controlsZ
insecure_bindr"r"r#�simple_bind�s��

�zLDAPClient.simple_bindcCsbt�t���j}|���6tj�|�}|�	�|j
�d|||�Wd�n1sT0YdS)zP
        Perform SASL bind operation using the SASL EXTERNAL mechanism.
        rSN)�pwd�getpwuidr,�geteuid�pw_namer5r(�saslZexternalrr4�sasl_interactive_bind_s)r;rIrJZ	user_name�auth_tokensr"r"r#�
external_bind�s
�zLDAPClient.external_bindcCsZ|���>|jdkrt}nt}|��|j�d|||�Wd�n1sL0YdS)zN
        Perform SASL bind operation using the SASL GSSAPI mechanism.
        �ldapirSN)r5r�SASL_GSS_SPNEGO�SASL_GSSAPIrr4rQ)r;rIrJrRr"r"r#�gssapi_bind�s

�zLDAPClient.gssapi_bindcCs>|���"|��|j��Wd�n1s00YdS)z+
        Perform unbind operation.
        N)r5rr4Zunbind_srCr"r"r#�unbind�s
zLDAPClient.unbindcCs2|durt�}t|ttf�r$|d}t||f|�S)z�
        Make distinguished name from attribute.

        Keyword arguments:
        parent_dn -- DN of the parent entry (default '')
        Nr)rrjr�r)r;r�rv�	parent_dnr"r"r#�make_dn_from_attrs
zLDAPClient.make_dn_from_attrrcCst|||f|�S)z�
        Make distinguished name from entry attributes.

        Keyword arguments:
        primary_key -- attribute from which to make RDN (default 'cn')
        parent_dn -- DN of the parent entry (default '')
        )r)r;�entry_attrsZprimary_keyrYr"r"r#�make_dnszLDAPClient.make_dncKst|||fi|��Sr7r�)r;r`rorpr"r"r#�
make_entry"szLDAPClient.make_entrycCs�dd�|D�}|r4||jkr4d|j|�||j�fSt|�dkrJd|}nd}|D]"}|�d�shd|}d	||f}qRt|�dkr�d
|}|S)z�
        Combine filters into one for ldap2.find_entries.

        Keyword arguments:
        rules -- see ldap2.make_filter
        cSsg|]}|r|�qSr"r")r{Zfxr"r"r#r�:rz.LDAPClient.combine_filters.<locals>.<listcomp>z(%s%s)rz(%srS�(z(%s)z%s%sz%s))�
MATCH_NONE�combine_filters�	MATCH_ANYr�r+)r��filters�rulesZflt�fr"r"r#r`/s�

zLDAPClient.combine_filtersc	s"t�ttf�r4�����fdd��D�}��||�S�du�rt�tj�rX��tjj	��t�t
�r�t����
d��d��fdd�tj�dt��d	�D���n6t�t�r���t��tj����nt���tj�����s�d
}�r�d|}�r�|d}|��|�jk�rd��fSd
��fSdS)a]
        Make filter for ldap2.find_entries from attribute.

        Keyword arguments:
        rules -- see ldap2.make_filter
        exact -- boolean, True - make filter as (attr=value)
                          False - make filter as (attr=*value*)
        leading_wildcard -- boolean:
            True - allow heading filter wildcard when exact=False
            False - forbid heading filter wildcard when exact=False
        trailing_wildcard -- boolean:
            True - allow trailing filter wildcard when exact=False
            False - forbid trailing filter wildcard when exact=False
        c	s g|]}�j�|���d��qS))�exact�leading_wildcard�trailing_wildcard)�make_filter_from_attr)r{r})r�r�rerfrgr"r#r�^s��z4LDAPClient.make_filter_from_attr.<locals>.<listcomp>Nr�\c3s|]}�||d�VqdS)rNr")r{r�)rvr"r#r~lsz3LDAPClient.make_filter_from_attr.<locals>.<genexpr>���rr�*z
(!(%s=%s))z(%s=%s)rS)rjr�rr`r
rrrrrr��binasciiZhexlifyr�rr�Zmoves�ranger�rrrr(�filterZescape_filter_charsr�r_)	r�r�rvrcrerfrg�flts�templater")r�r�rerfrgrvr#rhKs>�

�

�z LDAPClient.make_filter_from_attrc
Cs�||jkr|j}n|}g}|durP|��D]"\}	}
|�|�|	|
||||��q*n8|D]2}|�|d�}|durT|�|�||||||��qT|�||�S)a�
        Make filter for ldap2.find_entries from entry attributes.

        Keyword arguments:
        attrs_list -- list of attributes to use, all if None (default None)
        rules -- specifies how to determine a match (default ldap2.MATCH_ANY)
        exact -- boolean, True - make filter as (attr=value)
                          False - make filter as (attr=*value*)
        leading_wildcard -- boolean:
            True - allow heading filter wildcard when exact=False
            False - forbid heading filter wildcard when exact=False
        trailing_wildcard -- boolean:
            True - allow trailing filter wildcard when exact=False
            False - forbid trailing filter wildcard when exact=False

        rules can be one of the following:
        ldap2.MATCH_NONE - match entries that do not match any attribute
        ldap2.MATCH_ALL - match entries that match all attributes
        ldap2.MATCH_ANY - match entries that match any of attribute
        N)r_rar�r�rhrEr`)
r�r[�
attrs_listrcrerfrgZmake_filter_rulesror|r}r�rvr"r"r#�make_filter�s,
����zLDAPClient.make_filterc

Ksl|jf|||||d�|��\}}z|�|�Wn8tjyf}	zt�d|	||��WYd}	~	n
d}	~	00|S)a�Return a list of matching entries.

        :raises: errors.LimitsExceeded if the list is truncated by the server
        :raises: errors.NotFound if result set is empty
                                 or base_dn doesn't exist

        :param base_dn: dn of the entry at which to start the search
        :param scope: search scope, see LDAP docs (default ldap2.SCOPE_SUBTREE)
        :param filter: LDAP filter to apply
        :param attrs_list: ist of attributes to return, all if None (default)
        :param get_effective_rights: use GetEffectiveRights control
        :param kwargs: additional keyword arguments. See find_entries method
        for their description.
        )�base_dn�scopernrq�get_effective_rightsz2%s while getting entries (base DN: %s, filter: %s)N)�find_entriesr;r	r9rJrP)
r;rsrtrnrqrurp�entriesr:r]r"r"r#�get_entries�s��
�zLDAPClient.get_entriesc	Cs(|durt�}|sd}g}	d}
|dur,|j}|dkr8d}|durF|j}t|t�sXt|�}t|t�sjt|�}|r�dd�t|�D�}g}|r�|�|���d}|dkr�|nd	d
}
|
dkr�d}|�	���2t
jr�|�|�}|�|�}|r�|t
d|
|�g}n|p�d}z�|jjt|�||||||d�}|j�|d�}|\}}}}|tjk�rJ�ql|�|�}|�r |	�|d��q |�r�|D]}t|t
��rv|j}�q��qvd}W�n8tj�y�t}
Y�q�Y�ntj�y�t}
Y�q�Yn�tj�y�t}
Y�q�Yn�tj�y�}z�|�r�|�r�t
dd|�g}z"|jjt|�||||||d�Wn4tj�y~}zt�d|�WYd}~n
d}~00d}z|�Wn4tjtjtjf�y�d
}
YWYd}~�q�Yn0WYd}~n
d}~00|�r�|s�q�q�Wd�n1�s�0Y|	�s |
�s t j!dd��|	|
fS)a%
        Return a list of entries and indication of whether the results were
        truncated ([(dn, entry_attrs)], truncated) matching specified search
        parameters followed by truncated flag. If the truncated flag is True,
        search hit a server limit and its results are incomplete.

        Keyword arguments:
        :param attrs_list: list of attributes to return, all if None
                           (default None)
        :param base_dn: dn of the entry at which to start the search
                        (default '')
        :param scope: search scope, see LDAP docs (default ldap2.SCOPE_SUBTREE)
        :param time_limit: time limit in seconds (default unlimited)
        :param size_limit: size (number of entries returned) limit
                           (default unlimited)
        :param paged_search: search using paged results control
        :param get_effective_rights: use GetEffectiveRights control

        :raises: errors.NotFound if result set is empty
                                 or base_dn doesn't exist
        Nz(objectClass=*)Frr�cSsg|]}|���qSr"r�r?r"r"r#r��rz+LDAPClient.find_entries.<locals>.<listcomp>rSi�r)Zserverctrls�timeoutZ	sizelimitz!Error cancelling paged search: %sTzno matching entry foundr*)"r�
time_limit�
size_limitrjr�floatrkr��)_LDAPClient__get_effective_rights_controlr5r�r�r�rr4Z
search_extr�Zresult3r(ZRES_SEARCH_RESULTr)�cookier.r6r0r7r2r8rYZsearch_ext_srJZwarningr	�EmptyResult)r;rnrqrsrtrzr{Zpaged_searchru�resr:Zbase_sctrlsr~Z	page_sizeZsctrls�idr'ZobjtypeZres_listZ_res_idZ	res_ctrlsZctrlr]�e2r"r"r#rv�s�




��




�
�
�,
&zLDAPClient.find_entriescCs(|j��dd�}tdd�|��d��S)z8Construct a GetEffectiveRights control for current user.�NTzdn: {0}r�)r4Zwhoami_srr�r�)r;rHr"r"r#Z__get_effective_rights_controlUs�z)LDAPClient.__get_effective_rights_controlc	Cs^|durt�}||d|i}|j||jd�}|j|||d�}t|�dkrVtjt|�d��|dS)a
        Find entry (dn, entry_attrs) by attribute and object class.

        Keyword arguments:
        attrs_list - list of attributes to return, all if None (default None)
        base_dn - dn of the entry at which to start the search (default '')
        NZobjectClass)rc)rnrqr)�foundr)rrr�	MATCH_ALLrxr�r	ZSingleMatchExpected)	r;r�rvZobject_classrqrsZ	search_kwrnrwr"r"r#�find_entry_by_attr[s
�zLDAPClient.find_entry_by_attrc	Cs"|j||jd||||d�}|dS)z�
        Get entry (dn, entry_attrs) by dn.

        Keyword arguments:
        attrs_list - list of attributes to return, all if None (default None)
        N)rzr{rur)rxrU)r;rurqrzr{rurwr"r"r#�	get_entryss
�zLDAPClient.get_entrycCsrtdd�|j��D��}|���6|�|�}|j�t|j�t	|����Wd�n1s\0Y|�
�dS)zPCreate a new entry.

        This should be called as add_entry(entry).
        css|]\}}|r||fVqdSr7r"rzr"r"r#r~�rz'LDAPClient.add_entry.<locals>.<genexpr>N)rlrmr�r5r�r4Zadd_sr�rur�r�)r;r��attrsr"r"r#�	add_entry�s


:zLDAPClient.add_entrycCs�||krt���|d}|dd�|dd�kr6d}ntt|dd���}|���:|jjt|�t|�|t|�d�t�	d�Wd�n1s�0YdS)a�
        Move an entry (either to a new superior or/and changing relative distinguished name)

        Keyword arguments:
        dn: DN of the source entry
        new_dn: DN of the target entry
        del_old -- delete old RDN value (default True)

        :raises:
        errors.NotFound if source entry or target superior entry doesn't exist
        errors.EmptyModlist if source and target are identical
        rrN)ZnewsuperiorZdeloldg333333�?)
r	�EmptyModlistr�rr5r4Zrename_srr:�sleep)r;ru�new_dn�del_oldZnew_rdnZnew_superiorr"r"r#�
move_entry�s
�zLDAPClient.move_entrycsz|��}|st���t�d|�����6�fdd�|D�}�j�t|j	�|�Wd�n1sd0Y|�
�dS)zZUpdate entry's attributes.

        This should be called as update_entry(entry).
        zupdate_entry modlist %scs&g|]\}}}|t|���|�f�qSr")r�r�r�rCr"r#r��s�z+LDAPClient.update_entry.<locals>.<listcomp>N)r�r	r�rJrKr5r4rr�rur�)r;r�r�r"rCr#�update_entry�s

�2zLDAPClient.update_entrycCsRt|t�r|}n|j}|��� |j�t|��Wd�n1sD0YdS)z7Delete an entry given either the DN or the entry itselfN)rjrrur5r4Zdelete_sr��r;Zentry_or_dnrur"r"r#�delete_entry�s


zLDAPClient.delete_entrycCs2z|j|gd�Wntjy(YdS0dSdS)z?
        Test whether the given object exists in LDAP.
        )rqFTN)r�r	r-�r;rur"r"r#�entry_exists�s
zLDAPClient.entry_exists)FFFTNT)N)Fr<)NNF)NN)NN)N)rN)NN)r�)r�TTT)Nr�TTT)NN)NNNF)T)Mr=r>r?r@rar�r_r(rUZSCOPE_ONELEVELZ
SCOPE_SUBTREEr�rrrrrrrr
rr	r
rrzr{r<�classmethodr�r
Z
IPA_CA_CRTr�r�r�rr�r4rrrrrr�r�r�r)�
contextlib�contextmanagerr5�staticmethodr;r9rArBrGrCr�rKrSrWrXrZr\r]r`rhrrrxrvr}r�r�r�r�r�r�r�r"r"r"r#r��sH�9���
$
�


#*%O


�
�







�6�.�
 �
�
�


r�rSr�cCs||dur$|rd}n|dur d}nd}|dkr:dt||�S|dkrVdd�|�d��S|dkrldt||�Std	|��dS)
NrTZldapsr(r�z)ldapi://%%2fvar%%2frun%%2fslapd-%s.socketrrr�zProtocol %r not supported)rrr r�)�host�portr�rTZrealmrr"r"r#�get_ldap_uri�s�r�c@seZdZddd�ZdS)�
CacheEntryNFcCs||_||_||_||_dSr7)r�rq�	exceptionr<)r;r�rqr�rur<r"r"r#r<�szCacheEntry.__init__)NNNFF)r=r>r?r<r"r"r"r#r��s�r�c	s�eZdZdZd&�fdd�	Zedd	��Zed
d��Zedd
��Zdd�Z	gfdd�Z
d'dd�Zdd�Zdd�Z
dd�Z�fdd�Z�fdd�Z�fdd�Zd(�fd d!�	Z�fd"d#�Zd)�fd$d%�	Z�ZS)*�	LDAPCachez+A very basic LRU Cache using an OrderedDictFTN�dc	s�t�|_d|_d|_t�|dd�t�|dd�t�|d|oB|	dk�t�|d|
�t�|d|	�tt|��|||||||�dS)	NTF�
_cache_missesr�_cache_hits�
_enable_cache�_debug_cache�_cache_size)	r�cacher�r�rrrir�r<)r;r�r�r�r�r�r�r�Zenable_cacheZ
cache_sizeZdebug_cacherqr"r#r<�s
�
�zLDAPCache.__init__cCs|jSr7)r�rCr"r"r#�hitsz
LDAPCache.hitcCs|jSr7)r�rCr"r"r#�missszLDAPCache.misscCs|jSr7)r�rCr"r"r#�max_entriesszLDAPCache.max_entriescOs(|jr$|jr$tj|g|�Ri|��dSr7)r�r�rJrK)r;r$rZrpr"r"r#�emitszLDAPCache.emitcCszt|t|��}|s*|j�tt|j���n4|j��D](\}}|��|vrJq4t|�|j|��<q4tt|j��|_|�	�|Sr7)
r^rrmrnrrlr�r�rfr�)r;rur�r�Z	new_entryr�r(r"r"r#�
copy_entry"szLDAPCache.copy_entrycCs�hd�}|jsdS|�|�td�|vs@td�|vs@td�|vrDdS|rf|�d|�t|d�|j|<n,|�|�s�t|��|��|d�|j|<ndS|�d|||�|j�|�t	|j�|j
kr�|jjd	d
�\}}|�d|�dS)N>Zcospriorityr�r�r�z	cn=configzcn=kerberoszo=ipacazEXC: Caching exception %s�r�)r�rqr<zADD: %s: %s all=%sF)�lastzLRU: removed %s)r��remove_cache_entryrr�r�r��intersectionr��move_to_endr�r��popitem)r;rurq�get_allr�r�ZBANNED_ATTRSr"r"r#�add_cache_entry2s4	

�
�
�
�zLDAPCache.add_cache_entrycCs:|�d�t�|dt��t�|dd�t�|dd�dS)NZFINALr�r�rr�)�cache_statusrrrrCr"r"r#�clear_cachebs
zLDAPCache.clear_cachecCs |�d||j|jt|j��dS)Nz%s: Hits %d Misses %d Size %d)r�r�r�r�r�)r;r�r"r"r#r�hs�zLDAPCache.cache_statuscCs0|�d|�||jvr |j|=n|�d|�dS)NzDROP: %szDROP: not in cache %s)r�r�r�r"r"r#r�ls

zLDAPCache.remove_cache_entrycs*|�d�|�|j�tt|��|�dS)Nr�)r�r�rurir�r�r�rqr"r#r�vs
zLDAPCache.add_entrycs*|�d�|�|j�tt|��|�dS)Nr�)r�r�rurir�r�r�rqr"r#r�{s
zLDAPCache.update_entrycs>|�d�t|t�r|}n|j}|�|�tt|��|�dS)Nr�)r�rjrrur�rir�r�r�rqr"r#r��s


zLDAPCache.delete_entrycs6|�d�|�|�|�|�tt|��|||�dS)Nr�)r�r�rir�r�)r;rur�r�rqr"r#r��s


zLDAPCache.move_entrycs�|�d�t|t�st|�}|�d|�|D]R\}}}|��dvr,|D]6}t|ttf�sFt|�d��}|�d|�|�|�qFq,|�d|�|�|�tt|��	||�S)Nrz
modlist %s)�memberZipaallowedtoperform_write_keysZmanagedby_hostr�zmodify_s %s)
r�rjrr�rr�r�rir�r)r;rur�Z_opr�Zmod_dn�drqr"r#r�s


zLDAPCache.modify_sc

s�|jstt|��|||||�S|�d|�|j�|�}|rB|rBd}|r�|jr�|jd}t	�
|d|�|�d|j�|�d�|j�|�d|�|r�|�d|j�|s�dg}n|d	gkr�d
g}d}|r�|dgd	gfvr�|j
r�d}|�r"|j
�r"|�r"|jd}t	�
|d|�|�d�|�||j�S|�r�|�r�td
d�t|�D��}	tdd�|jD��}
|	�|
��r�|jd}t	�
|d|�|�d�|�||j|	�Sztt|��|||||�}Wnxtjtjf�y}zB|j||d�|jd}t	�
|d|�|�d|��WYd}~nbd}~0t�y*�YnF0|dgd	gfv�rBd}|j|tdd�|j��D��||�||�d�|jd}t	�
|d|�|�d�|S)NzCache lookup: %srr�zHIT: Re-raising %sZHITzRequested attrs_list %szCached attrs_list %srkrSruFTcss|]}|��VqdSr7r��r{r�r"r"r#r~�rz&LDAPCache.get_entry.<locals>.<genexpr>css|]}|��VqdSr7r�r�r"r"r#r~�rr�r�zMISS: %scss|]}|��VqdSr7r�)r{r|r"r"r#r~�r)rqr�r�ZMISS)r�rir�r�r�r�rEr�r�rrr�rqr<r�r�rk�issubsetr	r-rr�r�r#ra�keys)
r;rurqrzr{rur��hitsr�Z	req_attrsZcache_attrsr]�missesrqr"r#r��s�

�



���





�

�

zLDAPCache.get_entry)	FFFTNTTr�F)NFNN)T)NNNF)r=r>r?r@r<r�r�r�r�r�r�r�r�r�r�r�r�r�r�rr�r�r"r"rqr#r��s8�


�
0
�r�)N)rSr�NFNN)Rrlr0Zloggingr:rZdecimalrr�rr�r,rL�warnings�collectionsrZcryptography.hazmat.primitivesrr(Z	ldap.saslZldap.filterZ
ldap.controlsrrr&r�Zipalibr	r
rZipalib.constantsrZipaplatform.pathsr
Zipapython.ipautilrrZipapython.dnrrZipapython.dnsutilrZipapython.kerberosr�collections.abcrZPY3r�r	Z	getLoggerr=rJrPrVrUr&rZ_missingZ
AUTOBIND_AUTOZAUTOBIND_ENABLEDZAUTOBIND_DISABLEDr7r8r6Z	DIRMAN_DNr��hasattr�filterwarningsrr$r'r5r6rArr^r�rwrxr�r�r�r�r"r"r"r#�<module>s�
�
(NpW�