a fWcE@sdZddlmZddlZeeZddlZddlm Z ddl m Z m Z ddl mZddlmZddlmZdd lmZmZmZdd lmZdd lmZmZmZmZd d gZeZ dZ!dZ"dZ#dZ$dZ%GdddeZ&e'Z(ddZ)e)Z*ddZ+e+Z,Gdd d e&Z-Gdd d e&Z.dS)z(passlib.apache - apache password support)with_statementN)warn)excregistry) CryptContext)ExpectedStringError)htdigest) render_bytesto_bytesis_ascii_codec)deprecated_method) join_bytesunicodeBytesIOPY3 HtpasswdFile HtdigestFile:#s: skippedrecordc@seZdZdZdZdZdZdZdZdZ dZ e ddZ e ddZ ddddd efd d Zd d ZeddZejddZeddZddZd2ddZddZddZddZddZdd Zd3d!d"Zd#d$Zd%d&Zd'd(Zd)d*Z d+d,Z!d4d.d/Z"d0d1Z#dS)5 _CommonFilez0common framework for HtpasswdFile & HtdigestFileNFcKs,d|vrtd|fi|}|||S)zcreate new object from raw string. :type data: unicode or bytes :arg data: database to load, as single string. :param \*\*kwds: all other keywords are the same as in the class constructor pathz$'path' not accepted by from_string()) TypeError load_string)clsdatakwdsselfr2/usr/lib/python3.9/site-packages/passlib/apache.py from_stringKs  z_CommonFile.from_stringcKs|fi|}|||S)zcreate new object from file, without binding object to file. :type path: str :arg path: local filepath to load from :param \*\*kwds: all other keywords are the same as in the class constructor )load)rrrrrrr from_path\s  z_CommonFile.from_pathTutf-8cCs|stdtddd}d}nt|s,td||_||_||_||_d|_|s`tdtddd }|rr|sr| n i|_ g|_ dS) Nz``encoding=None`` is deprecated as of Passlib 1.6, and will cause a ValueError in Passlib 1.8, use ``return_unicode=False`` instead. stacklevelr$Fz'encoding must be 7-bit ascii compatiblerzp``autoload=False`` is deprecated as of Passlib 1.6, and will be removed in Passlib 1.8, use ``new=True`` insteadT) rDeprecationWarningr ValueErrorencodingreturn_unicodeautosave_path_mtimer"_records_source)rrnewZautoloadr,r*r+rrr __init__ns, z_CommonFile.__init__cCsTd}|jr|d7}|jr&|d|j7}|jdkr>|d|j7}d|jjt||fS)Nz autosave=Truez path=%rr$z encoding=%rz <%s 0x%0x%s>)r,r-r* __class____name__id)rtailrrr __repr__s z_CommonFile.__repr__cCs|jSN)r-rrrr rsz_CommonFile.pathcCs||jkrd|_||_dS)Nr)r-r.rvaluerrr rs cCs|jS)z7modify time when last loaded (if bound to a local file))r.r:rrr mtimesz_CommonFile.mtimecCs<|jstd||jr0|jtj|jkr0dS|dS)zBReload from ``self.path`` only if file has changed since last loadz%r is not bound to a local fileFT)r- RuntimeErrorr.osrgetmtimer"r:rrr load_if_changeds  z_CommonFile.load_if_changedcCs|durDt|d }d|_||Wdq1s80Yn|sltdt|jjdtdd|S|j rt|j d*}t j |j |_||Wdq1s0Ynt d|jjd S) aLoad state from local file. If no path is specified, attempts to load from ``self.path``. :type path: str :arg path: local file to load from :type force: bool :param force: if ``force=False``, only load from ``self.path`` if file has changed since last load. .. deprecated:: 1.6 This keyword will be removed in Passlib 1.8; Applications should use :meth:`load_if_changed` instead. Nrbrz%(name)s.load(force=False) is deprecated as of Passlib 1.6,and will be removed in Passlib 1.8; use %(name)s.load_if_changed() instead.)namer%r&z2%s().path is not set, an explicit path is requiredT)openr. _load_linesrdictr4r5r(rAr-r?rr@r>)rrforcefhrrr r"s& * *z_CommonFile.loadcCs&t||jd}d|_|t|dS)z@Load state from unicode or bytes string, replacing current staterrN)r r*r.rEr)rrrrr rsz_CommonFile.load_stringc Cs|j}i}g}d}t|D]\}}|}|r8|trB||7}q|||d\} } | |vrttd| ||7}q|r|t|fd}| || <|t | fq| r|t|f||_ ||_ dS)zload from sequence of listsz1username occurs multiple times in source file: %rN) _parse_record enumeratelstrip startswith_BHASHlogZwarningappend_SKIPPED_RECORDrstripr/r0) rlinesparserecordssourceridxlinetmpkeyr<rrr rEs.z_CommonFile._load_linescCs tddS)z)parse line of file into (key, value) pair!should be implemented in subclassNNotImplementedError)rrlinenorrr rK sz_CommonFile._parse_recordcCs.|j}||v}|||<|s*|jt|f|S)z helper for setting record which takes care of inserting source line if needed; :returns: bool if key already present )r/r0rQrS)rr\r<rWexistingrrr _set_records z_CommonFile._set_recordcCs|jr|jr|dS)z0subclass helper to call save() after any changesN)r,r-saver:rrr _autosave!s z_CommonFile._autosavecCsz|durBt|d}||Wdqv1s60Yn4|jrf||jtj|j|_nt d|j j dS)zhSave current state to file. If no path is specified, attempts to save to ``self.path``. Nwbz%%s().path is not set, cannot autosave) rD writelines _iter_linesr-rcr?rr@r.r>r4r5)rrrHrrr rc&s . z_CommonFile.savecCs t|S)z)Export current state as a string of bytes)r rgr:rrr to_string4sz_CommonFile.to_stringccsv|j}t|}|jD]J\}}|tkr,|Vq|tks8J||vrBq||||V||q|rrJd|fdS)z#iterator yielding lines of databasez'failed to write all records: missing=%rN)r/setr0rRrS_render_recordremove)rrWpendingactionZcontentrrr rg@s  z_CommonFile._iter_linescCs tddS)z,given key/value pair, encode as line of filer]Nr^)rr\r<rrr rj[sz_CommonFile._render_recordcCs ||dS)z)user-specific wrapper for _encode_field()user _encode_fieldrrnrrr _encode_userbsz_CommonFile._encode_usercCs ||dS)z*realm-specific wrapper for _encode_field()realmrorrsrrr _encode_realmfsz_CommonFile._encode_realmfieldcCsnt|tr||j}nt|ts,t||t|dkrHtd||ftdd|Drjtd||f|S)a+convert field to internal representation. internal representation is always bytes. byte strings are left as-is, unicode strings encoding using file's default encoding (or ``utf-8`` if no encoding has been specified). :raises UnicodeEncodeError: if unicode value cannot be encoded using default encoding. :raises ValueError: if resulting byte string contains a forbidden character, or is too long (>255 bytes). :returns: encoded identifer as bytes z%%s must be at most 255 characters: %rcss|]}|tvVqdSr9)_INVALID_FIELD_CHARS).0crrr rIz,_CommonFile._encode_field..z"%s contains invalid characters: %r) isinstancerencoder*bytesrlenr)any)rr<Zparamrrr rpjs    z_CommonFile._encode_fieldcCs,t|tsJd|jr$||jS|SdS)aWdecode field from internal representation to format returns by users() method, etc. :raises UnicodeDecodeError: if unicode value cannot be decoded using default encoding. (usually indicates wrong encoding set for file). :returns: field as unicode or bytes, as appropriate. zexpected value to be bytesN)r|r~r+decoder*r;rrr _decode_fields  z_CommonFile._decode_field)NT)N)rv)$r5 __module__ __qualname____doc__r*r+r-r.r,r/r0 classmethodr!r#rr2r8propertyrsetterr=rAr"rrErKrbrdrcrhrgrjrrrurprrrrr r,sJ   #     $*   rcCsd}dD]}t|r|}q qtdr.dnd}t|sLtgdt|pTdd|p`|p`d|pfd|plddd}|j|d|dd |S) N)bcrypt sha256_cryptr)portable_apache_24host_apache_24linux_apache_24portablehost apr_md5_cryptr)rportable_apache_22rZhost_apache_22rZlinux_apache_22rr)rr)rZhas_os_crypt_supportZ has_backend_warn_no_bcryptclearupdaterF)Z host_bestrCrdefaultsrrr _init_default_schemess,  rcCsPgd}|t|dddg|}tt||jd}t|tdddS)N)rrZ sha512_cryptZ des_cryptrZ ldap_sha1Z plaintextr)r\rZ2y)schemesdefaultZ bcrypt__ident)extendrZget_supported_os_crypt_schemessortedriindexrhtpasswd_defaults)rZ preferredrrr _init_htpasswd_contextsrcseZdZdZddeffdd ZddZddZd d Zd d Z e d dddddZ ddZ ddZ e d dddddZddZddZe d ddddd ZZS)!raclass for reading & writing Htpasswd files. The class constructor accepts the following arguments: :type path: filepath :param path: Specifies path to htpasswd file, use to implicitly load from and save to. This class has two modes of operation: 1. It can be "bound" to a local file by passing a ``path`` to the class constructor. In this case it will load the contents of the file when created, and the :meth:`load` and :meth:`save` methods will automatically load from and save to that file if they are called without arguments. 2. Alternately, it can exist as an independant object, in which case :meth:`load` and :meth:`save` will require an explicit path to be provided whenever they are called. As well, ``autosave`` behavior will not be available. This feature is new in Passlib 1.6, and is the default if no ``path`` value is provided to the constructor. This is also exposed as a readonly instance attribute. :type new: bool :param new: Normally, if *path* is specified, :class:`HtpasswdFile` will immediately load the contents of the file. However, when creating a new htpasswd file, applications can set ``new=True`` so that the existing file (if any) will not be loaded. .. versionadded:: 1.6 This feature was previously enabled by setting ``autoload=False``. That alias has been deprecated, and will be removed in Passlib 1.8 :type autosave: bool :param autosave: Normally, any changes made to an :class:`HtpasswdFile` instance will not be saved until :meth:`save` is explicitly called. However, if ``autosave=True`` is specified, any changes made will be saved to disk immediately (assuming *path* has been set). This is also exposed as a writeable instance attribute. :type encoding: str :param encoding: Optionally specify character encoding used to read/write file and hash passwords. Defaults to ``utf-8``, though ``latin-1`` is the only other commonly encountered encoding. This is also exposed as a readonly instance attribute. :type default_scheme: str :param default_scheme: Optionally specify default scheme to use when encoding new passwords. This can be any of the schemes with builtin Apache support, OR natively supported by the host OS's :func:`crypt.crypt` function. * Builtin schemes include ``"bcrypt"`` (apache 2.4+), ``"apr_md5_crypt"`, and ``"des_crypt"``. * Schemes commonly supported by Unix hosts include ``"bcrypt"``, ``"sha256_crypt"``, and ``"des_crypt"``. In order to not have to sort out what you should use, passlib offers a number of aliases, that will resolve to the most appropriate scheme based on your needs: * ``"portable"``, ``"portable_apache_24"`` -- pick scheme that's portable across hosts running apache >= 2.4. **This will be the default as of Passlib 2.0**. * ``"portable_apache_22"`` -- pick scheme that's portable across hosts running apache >= 2.4. **This is the default up to Passlib 1.9**. * ``"host"``, ``"host_apache_24"`` -- pick strongest scheme supported by apache >= 2.4 and/or host OS. * ``"host_apache_22"`` -- pick strongest scheme supported by apache >= 2.2 and/or host OS. .. versionadded:: 1.6 This keyword was previously named ``default``. That alias has been deprecated, and will be removed in Passlib 1.8. .. versionchanged:: 1.6.3 Added support for ``"bcrypt"``, ``"sha256_crypt"``, and ``"portable"`` alias. .. versionchanged:: 1.7 Added apache 2.4 semantics, and additional aliases. :type context: :class:`~passlib.context.CryptContext` :param context: :class:`!CryptContext` instance used to create and verify the hashes found in the htpasswd file. The default value is a pre-built context which supports all of the hashes officially allowed in an htpasswd file. This is also exposed as a readonly instance attribute. .. warning:: This option may be used to add support for non-standard hash formats to an htpasswd file. However, the resulting file will probably not be usable by another application, and particularly not by Apache. :param autoload: Set to ``False`` to prevent the constructor from automatically loaded the file from disk. .. deprecated:: 1.6 This has been replaced by the *new* keyword. Instead of setting ``autoload=False``, you should use ``new=True``. Support for this keyword will be removed in Passlib 1.8. :param default: Change the default algorithm used to hash new passwords. .. deprecated:: 1.6 This has been renamed to *default_scheme* for clarity. Support for this alias will be removed in Passlib 1.8. Loading & Saving ================ .. automethod:: load .. automethod:: load_if_changed .. automethod:: load_string .. automethod:: save .. automethod:: to_string Inspection ================ .. automethod:: users .. automethod:: check_password .. automethod:: get_hash Modification ================ .. automethod:: set_password .. automethod:: delete Alternate Constructors ====================== .. automethod:: from_string Attributes ========== .. attribute:: path Path to local file that will be used as the default for all :meth:`load` and :meth:`save` operations. May be written to, initialized by the *path* constructor keyword. .. attribute:: autosave Writeable flag indicating whether changes will be automatically written to *path*. Errors ====== :raises ValueError: All of the methods in this class will raise a :exc:`ValueError` if any user name contains a forbidden character (one of ``:\r\n\t\x00``), or is longer than 255 characters. Nc svd|vr tdtdd|d}|rT|tvrrIz&HtpasswdFile.users..)r/r:rr:r usersszHtpasswdFile.userscCs|j|}|||S)aSet password for user; adds user if needed. :returns: * ``True`` if existing user was updated. * ``False`` if user account was added. .. versionchanged:: 1.6 This method was previously called ``update``, it was renamed to prevent ambiguity with the dictionary method. The old alias is deprecated, and will be removed in Passlib 1.8. )rrset_hash)rrnpasswordrrrr set_passwords zHtpasswdFile.set_password1.61.8rZ deprecatedZremovedZ replacementcCs |||Szset password for userrrrnrrrr r szHtpasswdFile.updatecCs,z|j||WSty&YdS0dS)aReturn hash stored for user, or ``None`` if user not found. .. versionchanged:: 1.6 This method was previously named ``find``, it was renamed for clarity. The old name is deprecated, and will be removed in Passlib 1.8. N)r/rrKeyErrorrqrrr get_hashs zHtpasswdFile.get_hashcCs<trt|tr||j}||}|||}||S)z semi-private helper which allows writing a hash directly; adds user if needed. .. warning:: does not (currently) do any validation of the hash string .. versionadded:: 1.7 )rr|strr}r*rrrbrd)rrnrrarrr rs    zHtpasswdFile.set_hashrcCs ||Szreturn hash for userrrqrrr find1szHtpasswdFile.findcCs4z|j||=Wnty&YdS0|dS)zDelete user's entry. :returns: * ``True`` if user deleted. * ``False`` if user not found. FT)r/rrrrdrqrrr delete8s  zHtpasswdFile.deletecCsz||}|j|}|dur"dSt|tr8||j}|j||\}}|rv|durv||jvsdJ||j|<| |S)aM Verify password for specified user. If algorithm marked as deprecated by CryptContext, will automatically be re-hashed. :returns: * ``None`` if user not found. * ``False`` if user found, but password does not match. * ``True`` if user found and password matches. .. versionchanged:: 1.6 This method was previously called ``verify``, it was renamed to prevent ambiguity with the :class:`!CryptContext` method. The old alias is deprecated, and will be removed in Passlib 1.8. N) rrr/rr|rr}r*rZverify_and_updaterd)rrnrrokZnew_hashrrr check_passwordFs      zHtpasswdFile.check_passwordrcCs |||Szverify password for userrrrrr verifyeszHtpasswdFile.verify)r5rrrhtpasswd_contextr2rKrjrrr rrrrrrr __classcell__rrrr rs.9   cseZdZdZdZd+fdd ZddZddZd d Zd d Z d dZ ddZ d,ddZ de fddZeddddddZd-ddZde fddZeddddd d!Zd.d"d#Zd$d%Zde fd&d'Zeddd(dd)d*ZZS)/raclass for reading & writing Htdigest files. The class constructor accepts the following arguments: :type path: filepath :param path: Specifies path to htdigest file, use to implicitly load from and save to. This class has two modes of operation: 1. It can be "bound" to a local file by passing a ``path`` to the class constructor. In this case it will load the contents of the file when created, and the :meth:`load` and :meth:`save` methods will automatically load from and save to that file if they are called without arguments. 2. Alternately, it can exist as an independant object, in which case :meth:`load` and :meth:`save` will require an explicit path to be provided whenever they are called. As well, ``autosave`` behavior will not be available. This feature is new in Passlib 1.6, and is the default if no ``path`` value is provided to the constructor. This is also exposed as a readonly instance attribute. :type default_realm: str :param default_realm: If ``default_realm`` is set, all the :class:`HtdigestFile` methods that require a realm will use this value if one is not provided explicitly. If unset, they will raise an error stating that an explicit realm is required. This is also exposed as a writeable instance attribute. .. versionadded:: 1.6 :type new: bool :param new: Normally, if *path* is specified, :class:`HtdigestFile` will immediately load the contents of the file. However, when creating a new htpasswd file, applications can set ``new=True`` so that the existing file (if any) will not be loaded. .. versionadded:: 1.6 This feature was previously enabled by setting ``autoload=False``. That alias has been deprecated, and will be removed in Passlib 1.8 :type autosave: bool :param autosave: Normally, any changes made to an :class:`HtdigestFile` instance will not be saved until :meth:`save` is explicitly called. However, if ``autosave=True`` is specified, any changes made will be saved to disk immediately (assuming *path* has been set). This is also exposed as a writeable instance attribute. :type encoding: str :param encoding: Optionally specify character encoding used to read/write file and hash passwords. Defaults to ``utf-8``, though ``latin-1`` is the only other commonly encountered encoding. This is also exposed as a readonly instance attribute. :param autoload: Set to ``False`` to prevent the constructor from automatically loaded the file from disk. .. deprecated:: 1.6 This has been replaced by the *new* keyword. Instead of setting ``autoload=False``, you should use ``new=True``. Support for this keyword will be removed in Passlib 1.8. Loading & Saving ================ .. automethod:: load .. automethod:: load_if_changed .. automethod:: load_string .. automethod:: save .. automethod:: to_string Inspection ========== .. automethod:: realms .. automethod:: users .. automethod:: check_password(user[, realm], password) .. automethod:: get_hash Modification ============ .. automethod:: set_password(user[, realm], password) .. automethod:: delete .. automethod:: delete_realm Alternate Constructors ====================== .. automethod:: from_string Attributes ========== .. attribute:: default_realm The default realm that will be used if one is not provided to methods that require it. By default this is ``None``, in which case an explicit realm must be provided for every method call. Can be written to. .. attribute:: path Path to local file that will be used as the default for all :meth:`load` and :meth:`save` operations. May be written to, initialized by the *path* constructor keyword. .. attribute:: autosave Writeable flag indicating whether changes will be automatically written to *path*. Errors ====== :raises ValueError: All of the methods in this class will raise a :exc:`ValueError` if any user name or realm contains a forbidden character (one of ``:\r\n\t\x00``), or is longer than 255 characters. Nc s"||_tt|j|fi|dSr9) default_realmrrr2)rrrrrrr r2szHtdigestFile.__init__cCs<|t}t|dkr&td||\}}}||f|fS)Nrz/malformed htdigest file (error reading line %d)r)rrr`rrnrsrrrr rK s  zHtdigestFile._parse_recordcCs|\}}td|||S)Nz %s:%s:%s r)rr\rrnrsrrr rjszHtdigestFile._render_recordcCs"|dur|j}|durtd|S)NzGyou must specify a realm explicitly, or set the default_realm attribute)rrrtrrr _require_realms zHtdigestFile._require_realmcCs||}||dS)Nrs)rrprtrrr rus zHtdigestFile._encode_realmcCs||||fSr9)rrrurrnrsrrr _encode_key#szHtdigestFile._encode_keycs&tddjD}fdd|DS)z%Return list of all realms in databasecss|]}|dVqdS)rJNrryr\rrr r{,rIz&HtdigestFile.realms..csg|]}|qSrr)ryrsr:rr r-rIz'HtdigestFile.realms..)rir/)rrealmsrr:r r*szHtdigestFile.realmscs fddjDS)zReturn list of all users in specified realm. * uses ``self.default_realm`` if no realm explicitly provided. * returns empty list if realm not found. cs&g|]}|dkr|dqS)rJrrrrsrrr r6s z&HtdigestFile.users..)rur/rtrrr r/s zHtdigestFile.userscCs>|turd|}}||}tj||||jd}||||S)aSet password for user; adds user & realm if needed. If ``self.default_realm`` has been set, this may be called with the syntax ``set_password(user, password)``, otherwise it must be called with all three arguments: ``set_password(user, realm, password)``. :returns: * ``True`` if existing user was updated * ``False`` if user account added. Nr*)_UNSETrrrr*rrrnrsrrrrr rQs   zHtdigestFile.set_passwordrrrrcCs||||Srrrrnrsrrrr rdszHtdigestFile.updatecCs8|||}|j|}|dur$dStr4||j}|S)aReturn :class:`~passlib.hash.htdigest` hash stored for user. * uses ``self.default_realm`` if no realm explicitly provided. * returns ``None`` if user or realm not found. .. versionchanged:: 1.6 This method was previously named ``find``, it was renamed for clarity. The old name is deprecated, and will be removed in Passlib 1.8. N)rr/rrrr*)rrnrsr\rrrr rjs   zHtdigestFile.get_hashcCsP|turd|}}tr,t|tr,||j}|||}|||}||S)a semi-private helper which allows writing a hash directly; adds user & realm if needed. If ``self.default_realm`` has been set, this may be called with the syntax ``set_hash(user, hash)``, otherwise it must be called with all three arguments: ``set_hash(user, realm, hash)``. .. warning:: does not (currently) do any validation of the hash string .. versionadded:: 1.7 N) rrr|rr}r*rrbrd)rrnrsrr\rarrr r}s    zHtdigestFile.set_hashrcCs |||Srrrrrr rszHtdigestFile.findcCs:|||}z |j|=Wnty,YdS0|dS)zDelete user's entry for specified realm. if realm is not specified, uses ``self.default_realm``. :returns: * ``True`` if user deleted, * ``False`` if user not found in realm. FT)rr/rrd)rrnrsr\rrr rs   zHtdigestFile.deletecsB||j}fdd|D}|D] }||=q&|t|S)zDelete all users for specified realm. if realm is not specified, uses ``self.default_realm``. :returns: number of users deleted (0 if realm not found) csg|]}|dkr|qS)rJrrrsrr rrIz-HtdigestFile.delete_realm..)rur/rdr)rrsrWkeysr\rrr delete_realms zHtdigestFile.delete_realmcCsX|turd|}}||}||}|j||f}|durBdStj|||||jdS)aVerify password for specified user + realm. If ``self.default_realm`` has been set, this may be called with the syntax ``check_password(user, password)``, otherwise it must be called with all three arguments: ``check_password(user, realm, password)``. :returns: * ``None`` if user or realm not found. * ``False`` if user found, but password does not match. * ``True`` if user found and password matches. .. versionchanged:: 1.6 This method was previously called ``verify``, it was renamed to prevent ambiguity with the :class:`!CryptContext` method. The old alias is deprecated, and will be removed in Passlib 1.8. Nr)rrrrur/rrrr*rrrr rs    zHtdigestFile.check_passwordrcCs||||Srrrrrr rszHtdigestFile.verify)NN)N)N)N)r5rrrrr2rKrjrrurrrrrr rrrrrrrrrrrrr rrs: "    )/rZ __future__rZloggingZ getLoggerr5rPr?warningsrZpasslibrrZpasslib.contextrZ passlib.excrZ passlib.hashrZ passlib.utilsr r r Zpasslib.utils.decorr Zpasslib.utils.compatr rrr__all__objectrrrOrxrRrSrrirrrrrrrrrrr sB      )-c