; P?c'@sdZdZdkZdkZdZhdd<dd<dd <d d <d d <ddfd=d?fd=d@fd=dAfdBdCfdBdDfdBdEfdBdFfdGdHfdGdIfdGdJfdGdKfdLdMfdNdOfg&ZdPZedQjo eqndS(Rs ldaputil.passwd - client-side password setting (c) by Michael Stroeder This module is distributed under the terms of the GPL (GNU GENERAL PUBLIC LICENSE) Version 2 (see http://www.gnu.org/copyleft/gpl.html) Python compability note: This module only works with Python 1.6+ since all string parameters are assumed to be Unicode objects and string methods are used instead string module. s0.1.0Ns@./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZsshasuserPassword SHA-1ssshasuserPassword salted SHA-1smd5suserPassword MD5ssmd5suserPassword salted MD5scryptsuserPassword Unix cryptssuserPassword plain textssha1sauthPassword SHA-1sauthPassword MD5ucCs6x/|D]'}y ||=Wqtj oqXqWdS(sa Not for public use: Remove a list item ignoring ValueError: list.remove(x): x not in list N(srlsislsKeyError(slsrlsi((s./pylib/ldaputil/passwd.pys_remove_dict_items*s icCsg}|oHt|d}xkt|D]#}|i|ti d|q*Wn7x3t|D]%}|it ti ddqbWdi |SdS(s Create a random salt. saltLen Requested length of salt string. saltAlphabet If non-zero string it is assumed to contain all valid chars for the salt. If zero-length or None the salt returned is an arbitrary octet string. iiisN( ssalts saltAlphabetslenssaltAlphabetBouncesrangessaltLensisappendsrandoms randrangeschrsjoin(ssaltLens saltAlphabetssaltAlphabetBouncesissalt((s./pylib/ldaputil/passwd.pys_saltSs  % #sPasswordcBs_tZdZeddZdZdZdZedZeeedZ dZ RS( s/ Base class for plain-text LDAP passwords. sutf-8cCs||_||_d|_||_|tj oz|ii |it i d|i g}|o?|dd}|i|i |i|i ig|_qg|_n g|_dS(s| l LDAPObject instance to operate with. The application is responsible to bind with appropriate bind DN before(!) creating the Password instance. dn string object with DN of entry charset Character set for encoding passwords. Note that this might differ from the character set used for the normal directory strings. is(objectClass=*)iN(slsselfs_lsdns_dns _multiplescharsets_charsetsNonessearch_ssldaps SCOPE_BASEspasswordAttributeTypesresults entry_datasgetslowers_passwordAttributeValue(sselfslsdnscharsets entry_datasresult((s./pylib/ldaputil/passwd.pys__init__ns     '1 cCs||jSdS(s Compare testPassword with encoded password in singlePasswordValue. testPassword Plain text password for testing singlePasswordValue password to verify against N(s testPasswordssinglePasswordValue(sselfs testPasswordssinglePasswordValue((s./pylib/ldaputil/passwd.pys_compareSinglePasswordscCs`t|tjo|i|i}nx,|iD]!}|i||odSq3q3WdSdS(sE Return 1 if testPassword is in self._passwordAttributeValue iiN( stypes testPasswords _UnicodeTypesencodesselfs_charsets_passwordAttributeValuesps_compareSinglePassword(sselfs testPasswordsp((s./pylib/ldaputil/passwd.pyscomparePasswords  cCsJgi}|iD].}|i||i o||qq~SdS(sG Return list with all occurences of oldPassword being removed. N(sappends_[1]sselfs_passwordAttributeValuesps_compareSinglePasswords oldPasswordsstrip(sselfs oldPasswords_[1]sp((s./pylib/ldaputil/passwd.pys_delOldPasswordscCs1t|tjo|i|i}n|SdS(s7 encode plainPassword into plain text password N(stypes plainPasswords _UnicodeTypesencodesselfs_charset(sselfs plainPasswordsscheme((s./pylib/ldaputil/passwd.pysencodePasswordscCs|tj ot|tjo|it}n|io |tj o|i|}ng}|i ||}|i||i|||SdS(s% oldPassword Old password associated with entry. If a Unicode object is supplied it will be encoded with self._charset. newPassword New password for entry. If a Unicode object is supplied it will be encoded with charset before being transferred to the directory. scheme Hashing scheme to be used for encoding password. Default is plain text. charset This character set is used to encode passwords in case oldPassword and/or newPassword are Unicode objects. N(s oldPasswordsNonestypes _UnicodeTypesencodescharsetsselfs _multiples_delOldPasswordsnewPasswordValueListsencodePasswords newPasswordsschemesnewPasswordValuesappends_storePassword(sselfs oldPasswords newPasswordsschemesnewPasswordValueListsnewPasswordValue((s./pylib/ldaputil/passwd.pyschangePasswords! cCs,|ii|iti|i|fgdS(s%Replace the password value completelyN(sselfs_lsmodify_ss_dnsldaps MOD_REPLACEspasswordAttributeTypesnewPasswordValueList(sselfs oldPasswordsnewPasswordValueList((s./pylib/ldaputil/passwd.pys_storePasswords( s__name__s __module__s__doc__sNones__init__s_compareSinglePasswordscomparePasswords_delOldPasswordsencodePasswordschangePasswords_storePassword(((s./pylib/ldaputil/passwd.pysPasswordis  s UserPasswordcBsbtZdZdZhdd<ddtZdZdZdZeedZedZdZRS(s Class for LDAP password changing in unicodePwd attribute on Active Directory servers. (see "HOWTO: Change a Windows 2000 User's Password Through LDAP" on http://support.microsoft.com/support/kb/articles/q269/1/90.ASP) s unicodePwdicCs ti|||d|_dS(sH Like CharsetPassword.__init__() with one additional parameter. s utf-16-leN(sPasswords__init__sselfslsdns_charset(sselfslsdn((s./pylib/ldaputil/passwd.pys__init__scCsdti||SdS(s; Enclose Unicode password string in double-quotes. s"%s"N(sPasswordsencodePasswordsselfs plainPassword(sselfs plainPasswordsscheme((s./pylib/ldaputil/passwd.pysencodePasswordscCs|tjo,|ii|iti|i|fgnE|ii|i|iti |i|fti |i|dfgdS(sx Two different use-cases: If the application sets oldPassword to None it is assumed that an admin resets a user's password => A single replace operation is used to reset the unicodePwd attribute. If oldPassword is not None it is assumed it is assumed that the user changes his/her own password => a delete followed by an add operation is used. iN( s oldPasswordsNonesselfs_lsmodify_ss_dnsldaps MOD_REPLACEspasswordAttributeTypesnewPasswordValueLists MOD_DELETEsMOD_ADD(sselfs oldPasswordsnewPasswordValueList((s./pylib/ldaputil/passwd.pys_storePasswords  ( s__name__s __module__s__doc__spasswordAttributeTypes _multiplesNones__init__sencodePasswords_storePassword(((s./pylib/ldaputil/passwd.pys UnicodePwd}s  stest1s{MD5}WhBei51A4TKXgNYuoiZdig==s"{SMD5}i1GhUWtlHIva18fyzSVoSi6pLqk=s!{SHA}tESsBmE/yNY3lb6a0L6vVQEZNqw=s&{SSHA}uWg1PmLHZsZUqGOncZBiRTNXE3uHSyGCstest2s{MD5}rQI0gpIFuQMxlrqBj3qHKw==s"{SMD5}cavgPXL7OAX6Nkz4oxPCw0ff8/8=s!{SHA}EJ9LPFDXsN9ynSmbxvjp75Bmlx8=s&{SSHA}STa8xdUq+G6StaVHCjAKzy0rB9DZBIrystest3s{MD5}ith1e6qFZNwTbB4HUH9KmA==s"{SMD5}MSQjqRuAZYtVmF1te6hO2Yn7gFQ=s!{SHA}Pr+jAdxZGW8YWTxF5RkoeiMpdYk=s&{SSHA}BUTK//6laPB9HN4cjK31RzTnmwMYmHnGstest4s{MD5}hpheEF95uV1ryRj7Rex3Jw==s"{SMD5}5TWxU4fGloruSpD0u1IdxKd5ZZA=s!{SHA}H/KzcErt4E7stR5QymmO/VChN5s=s&{SSHA}4ckBH1ib1IgiISp3tvZf4bDXtk5xlUBystest5s{MD5}49cE81QrRKYh6+1w3A7+Ew==s"{SMD5}4NJzKqIX2sr8q3a4u0i92/4KPOY=s!{SHA}kR3cO4+aE7VJm2vEY4orTz9ovyM=s&{SSHA}kNTfeXHKb32yT4wUkN3AcpMCTHEx3Q2Qstest6s{MD5}TPrXB2Epli7nDDaDmh4+FQ==s"{SMD5}TesgPJdimK4miVwRcRQk/FZr7Uk=s!{SHA}pm3yYRILbCMRxu8LG6tOWDr8vMA=s&{SSHA}dIXzm4t40GfUXdHyBs//O3f09i/Ft3ikstest7s{MD5}sECD5T4kJiZZXiuOoyflJQ==s"{SMD5}TX6YHy6c0p1U9n6etx/irMv3cyE=s!{SHA}6jJDEy1lOzkCWpROcPPs33DuOZQ=s&{SSHA}zQ1xCPfNJgeDahwzzCLjM05cMJjaCULJstest8s{MD5}XkDQn6BSl4Gv0SVKQpE4Rw==s"{SMD5}6wNcr1crfhnTOmJj0oi4Ukc9/+o=s!{SHA}0D+dNBlDkwGebRLXyUKCfr1pREM=s&{SSHA}BnNwRej74F2NicyGggpTgWUajPenNvZastest9s{MD5}c5lptTJGsscnhQ27NJDt5g==s"{SMD5}mJUntKUUqtO+FgO7pIreIAHW4tA=s!{SHA}U9Ulg2zJbQiaWkIYtGT9pTL33r4=s&{SSHA}LdF62OhXywwvY6DMOCVkO25hHGG5fIAAsabcs!{SHA}qZk+NkcGgWq6PiVxeFDCbJzQ2J0=s8abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqs!{SHA}hJg+RBw70m66rkqh+VEp5eVGcPE=cCsRt}xBtD]:\}}|G|GH|i|| odG|G|GHqqWdS(Ns Test failed:(s UserPasswordsus rfc2307_testsspasswordsencoded_passwords_compareSinglePassword(spasswordsusencoded_password((s./pylib/ldaputil/passwd.pystests    s__main__(s__doc__s __version__srandomsldapsCRYPT_ALPHABETsAVAIL_USERPASSWORD_SCHEMESsAVAIL_AUTHPASSWORD_SCHEMESstypes _UnicodeTypes_remove_dict_itemssbase64s ImportErrorsseedsshasmd5scryptsNones_saltsPasswords UserPasswords AuthPasswords UnicodePwds __debug__s rfc2307_testsstests__name__(srandoms UnicodePwds UserPasswords_remove_dict_itemsscryptsbase64s _UnicodeTypesAVAIL_USERPASSWORD_SCHEMESsldapstestsPasswords AuthPasswordsAVAIL_AUTHPASSWORD_SCHEMESsmd5s __version__sCRYPT_ALPHABETsshas_salts rfc2307_tests((s./pylib/ldaputil/passwd.pys? sV<         s[F1].