Xc@s:dZddlmZddlZddlZejeZddlZddl Z ddl m Z ddl j Z ddljZddl mZmZmZddlmZddlmZddlmZmZmZmZmZmZmZmZmZm Z m!Z!dd l"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dd l*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m0Z0m3Z3m4Z4m5Z5dd l6m7Z7m8Z8d d ddddddddddddgZ9e$Z:e#Z;e%Z<e'Z=e(Z>dZ?ddZ@dZAdZBe-dZCe-d ZDd!ZEd"ZFeCeGd#ZHeCd$eGeGd%ZId$eGd&eGd'ZJe-dd(ZKe-dd$d)ZLd&d*ZMdeGd&eNd+ZOd,efd-YZPd.ePfd/YZQdePfd0YZRdeRfd1YZSd2eRfd3YZTdeRfd4YZUdeRfd5YZVdeRfd6YZWdeRfd7YZXdeXfd8YZYdeRfd9YZZd:eRfd;YZ[e j\Z]d<efd=YZ^d>e^fd?YZ_de^eRfd@YZ`deafdAYZbdS(BsRpasslib.handler - code for implementing handlers, and global registry for handlersi(twith_statementN(twarn(tMissingBackendErrortPasslibConfigWarningtPasslibHashWarning(t PasswordHash(tget_crypt_handler( tconsteqt getrandstrt getrandbytestrngt to_native_strtis_crypt_handlert to_unicodetMAX_PASSWORD_SIZEtaccepts_keywordtas_booltupdate_mixin_classes(t BASE64_CHARSt HASH64_CHARStPADDED_BASE64_CHARSt HEX_CHARStUPPER_HEX_CHARStLOWER_HEX_CHARStALL_BYTE_VALUES( tjoin_byte_valuestirangetutnative_string_typest uascii_to_strt join_unicodetunicodet str_to_uasciiRtunicode_or_bytes_typestPY2t int_types(t classpropertytdeprecated_methodt parse_mc2t parse_mc3t render_mc2t render_mc3tGenericHandlert StaticHandlertHasUserContexttHasRawChecksumt HasManyIdentstHasSaltt HasRawSaltt HasRoundstHasManyBackendst PrefixWrappercCs@|r8|r8ddl}t||jt|dSdSdS(shelper for bitsize() methodsiNii(tmathtinttlogtlen(tcounttcharsR4((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_bitsizeJs   icCstj}| }zix^|rv|jjdd}|jdsS|jd r`td|S|d7}|j}qW|SWd~XdS(si try to guess stacklevel for application warning. looks for first frame not part of passlib. t__name__tspasslib.tests.spasslib.iN(tinspectt currentframet f_globalstgett startswithtmaxtf_back(tstarttframeR8tname((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytguess_app_stacklevelRs     cCs-tdtd|jtdtddS(Nspassing settings to %(handler)s.hash() is deprecated, and won't be supported in Passlib 2.0; use '%(handler)s.using(**settings).hash(secret)' insteadthandlert stackleveli(RtdictRFtDeprecationWarningRG(RHtkwds((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytwarn_hash_settings_deprecationdscs2t|jtfdtDS(s helper to extract settings kwds from mix of context & settings kwds. pops settings keys from kwds, returns them as a dict. c3s0|]&}|kr|j|fVqdS(N(tpop(t.0tkey(t context_keysRL(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys os(tsett context_kwdsRJtlist(RHRL((RQRLs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytextract_settings_kwdsist$t0cCsLt|ts$tj|dnt|tkrHtjtndS(s%ensure secret has correct type & sizetsecretN(t isinstanceR!texctExpectedStringErrorR7RtPasswordSizeError(RX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytvalidate_secretwscCsjt|tr|St|trTy|jdSWqftk rP|jdSXntj|ddS(s+convert hash to unicode for identify methodsutf-8slatin-1thashN(RYRtbytestdecodetUnicodeDecodeErrorRZR[(R^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytto_unicode_for_identify~s cCst|dd}|j|s3tj|n|t|j|}t|dkrz|\}}||pvdfSt|dkr|ddfStj|dS(sparse hash using 2-part modular crypt format. this expects a hash of the format :samp:`{prefix}{salt}[${checksum}]`, such as md5_crypt, and parses it into salt / checksum portions. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param handler: handler class to pass to error constructors. :returns: a ``(salt, chk | None)`` tuple. tasciiR^iiiN(R RARZtInvalidHashErrorR7tsplittNonetMalformedHashError(R^tprefixtsepRHtpartstsalttchk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR&s i c Cs%t|dd}|j|s3tj|n|t|j|}t|dkrp|\}}} n6t|dkr|\}}d} ntj||jtr|tkrtj |n?|rt ||}n'|dkr tj|dn|}||| p!dfS(srparse hash using 3-part modular crypt format. this expects a hash of the format :samp:`{prefix}[{rounds}]${salt}[${checksum}]`, such as sha1_crypt, and parses it into rounds / salt / checksum portions. tries to convert the rounds to an integer, and throws error if it has zero-padding. :arg hash: the hash to parse (bytes or unicode) :arg prefix: the identifying prefix (unicode) :param sep: field separator (unicode, defaults to ``$``). :param rounds_base: the numeric base the rounds are encoded in (defaults to base 10). :param default_rounds: the default rounds value to return if the rounds field was omitted. if this is ``None`` (the default), the rounds field is *required*. :param handler: handler class to pass to error constructors. :returns: a ``(rounds : int, salt, chk | None)`` tuple. RcR^iisempty rounds fieldN( R RARZRdR7ReRfRgt_UZEROtZeroPaddedRoundsErrorR5( R^RhRit rounds_basetdefault_roundsRHRjtroundsRkRl((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR's$   tvaluecCst|jtr4|tkr4tj|d|n<|rGt||S|dkrltj|d|n|SdS(s helper to parse an integer config field :arg source: unicode source string :param base: numeric base :param default: optional default if source is empty :param param: name of variable, for error msgs :param handler: handler class, for error msgs szero-padded %s fieldsempty %s fieldN(RARmRZRgR5Rf(tsourcetbasetdefaulttparamRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt parse_ints   cCs7|r||||g}n ||g}tt|S(sformat hash using 2-part modular crypt format; inverse of parse_mc2() returns native string with format :samp:`{ident}{salt}[${checksum}]`, such as used by md5_crypt. :arg ident: identifier prefix (unicode) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :returns: config or hash (native str) (RR(tidentRktchecksumRiRj((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR( s cCs|dkrtd}n+|dkr:td|}n t|}|rg||||||g}n||||g}tt|S(s.format hash using 3-part modular crypt format; inverse of parse_mc3() returns native string with format :samp:`{ident}[{rounds}$]{salt}[${checksum}]`, such as used by sha1_crypt. :arg ident: identifier prefix (unicode) :arg rounds: rounds field (int or None) :arg salt: encoded salt (unicode) :arg checksum: encoded checksum (unicode or None) :param sep: separator char (unicode, defaults to ``$``) :param rounds_base: base to encode rounds value (defaults to base 10) :returns: config or hash (native str) R<is%xN(RfRRRR(RxRqRkRyRiRoRj((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR)!s   cCstS(s assert helper that quickly validates default value. designed to get out of the way and reduce overhead when asserts are stripped. (tTrue(RHRutnormRv((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytvalidate_default_valueBscCst|ts'tj|d|n||krzd|j|||f}|rkt|tj|}qzt|n|r||krd|j|||f}|rt|tj|}qt|n|S(s helper to normalize and validate an integer value (e.g. rounds, salt_size) :arg value: value provided to constructor :arg default: default value if none provided. if set to ``None``, value is required. :arg param: name of parameter (xxx: move to first arg?) :param min: minimum value (defaults to 1) :param max: maximum value (default ``None`` means no maximum) :returns: validated value tintegers+%s: %s (%d) is too low, must be at least %ds0%s: %s (%d) is too large, cannot be more than %d(RYR#RZtExpectedTypeErrorRFRRt ValueError(RHRrtminRBRvtrelaxedtmsg((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt norm_integerKs    tMinimalHandlercBs&eZdZeZeedZRS(s helper class for implementing hash handlers. provides nothing besides a base implementation of the .using() subclass constructor. cCsD|j}|jsd|}nt||ftd|jdtS(Nst __module__t _configured(R;RttypeRJRRz(tclsRRF((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytusings   (R;Rt__doc__tFalseRt classmethodR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRrst TruncateMixincBs;eZdZeZeZeddZedZ RS(s PasswordHash mixin which provides a method that will check if secret would be truncated, and can be configured to throw an error. .. warning:: Hashers using this mixin will generally need to override the default PasswordHash.truncate_error policy of "True", and will similarly want to override .truncate_verify_reject as well. TODO: This should be done explicitly, but for now this mixin sets these flags implicitly. cKsUtt|j|}|dk rQt|dd}|dk rQ||_qQn|S(NRvttruncate_error(tsuperRRRfRR(RRRLtsubcls((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   cCs4|jr0t||jkr0tj|ndS(s make sure secret won't be truncated. NOTE: this should only be called for .hash(), not for .verify(), which should honor the .truncate_verify_reject policy. N(RR7t truncate_sizeRZtPasswordTruncateError(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_check_truncate_policysN( R;RRRRttruncate_verify_rejectRRfRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs cBsseZdZdZdZdZdZdZdZ e Z dZ de dZ e dZedZedZdZedZdZedZed Zed d d d edZed d d d edZeddZddZdZdZedZ e!e"ddZ#ee$e dZ%edZ&RS(s4helper class for implementing hash handlers. GenericHandler-derived classes will have (at least) the following constructor options, though others may be added by mixins and by the class itself: :param checksum: this should contain the digest portion of a parsed hash (mainly provided when the constructor is called by :meth:`from_string()`). defaults to ``None``. :param use_defaults: If ``False`` (the default), a :exc:`TypeError` should be thrown if any settings required by the handler were not explicitly provided. If ``True``, the handler should attempt to provide a default for any missing values. This means generate missing salts, fill in default cost parameters, etc. This is typically only set to ``True`` when the constructor is called by :meth:`hash`, allowing user-provided values to be handled in a more permissive manner. :param relaxed: If ``False`` (the default), a :exc:`ValueError` should be thrown if any settings are out of bounds or otherwise invalid. If ``True``, they should be corrected if possible, and a warning issue. If not possible, only then should an error be raised. (e.g. under ``relaxed=True``, rounds values will be clamped to min/max rounds). This is mainly used when parsing the config strings of certain hashes, whose specifications implementations to be tolerant of incorrect values in salt strings. Class Attributes ================ .. attribute:: ident [optional] If this attribute is filled in, the default :meth:`identify` method will use it as a identifying prefix that can be used to recognize instances of this handler's hash. Filling this out is recommended for speed. This should be a unicode str. .. attribute:: _hash_regex [optional] If this attribute is filled in, the default :meth:`identify` method will use it to recognize instances of the hash. If :attr:`ident` is specified, this will be ignored. This should be a unique regex object. .. attribute:: checksum_size [optional] Specifies the number of characters that should be expected in the checksum string. If omitted, no check will be performed. .. attribute:: checksum_chars [optional] A string listing all the characters allowed in the checksum string. If omitted, no check will be performed. This should be a unicode str. .. attribute:: _stub_checksum Placeholder checksum that will be used by genconfig() in lieu of actually generating a hash for the empty string. This should be a string of the same datatype as :attr:`checksum`. Instance Attributes =================== .. attribute:: checksum The checksum string provided to the constructor (after passing it through :meth:`_norm_checksum`). Required Subclass Methods ========================= The following methods must be provided by handler subclass: .. automethod:: from_string .. automethod:: to_string .. automethod:: _calc_checksum Default Methods =============== The following methods have default implementations that should work for most cases, though they may be overridden if the hash subclass needs to: .. automethod:: _norm_checksum .. automethod:: genconfig .. automethod:: genhash .. automethod:: identify .. automethod:: hash .. automethod:: verify cKsD||_tt|j||dk r@|j||_ndS(N(t use_defaultsRR*t__init__Rft_norm_checksumRy(tselfRyRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRLs  cs|j}|r9t|tstj|ddqn[t|tst|tr||r|tdt|jd}qtj|ddn|j }|rt ||krtj |d|n|s|j rt fd|Drtd|jfqn|S( sovalidates checksum keyword against class requirements, returns normalized version of checksum. R_Rys%checksum should be unicode, not bytesRcRtrawc3s|]}|kVqdS(N((ROtc(tcs(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys tss!invalid characters in %s checksum(t_checksum_is_bytesRYR_RZR~RRRR`t checksum_sizeR7tChecksumSizeErrortchecksum_charstanyRRF(RRyRRtcc((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRUs"    "cCst|}|stS|j}|dk r8|j|S|j}|dk r`|j|dk Sy|j|tSWnt k rtSXdS(N( RbRRxRfRAt _hash_regextmatcht from_stringRzR(RR^Rxtpat((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytidentify|s        cKstd|fdS(sV return parsed instance from hash/configuration string :param \*\*context: context keywords to pass to constructor (if applicable). :raises ValueError: if hash is incorrectly formatted :returns: hash parsed into components, for formatting / calculating checksum. s%s must implement from_string()N(tNotImplementedError(RR^tcontext((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCstd|jfdS(srender instance to hash or configuration string :returns: hash string with salt & digest included. should return native string type (ascii-bytes under python 2, unicode under python 3) s%s must implement from_string()N(Rt __class__(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt to_strings cCs|jr;|jrd|jS|jr;|jd|jSnt|tr|j}|jp_d|_z|jdSWd||_Xn|jdS(si placeholder used by default .genconfig() so it can avoid expense of calculating digest. tiiR<N(RRRRYR1Rqt min_roundst_calc_checksum(Rtorig((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_stub_checksums      cCstd|jfdS(sgiven secret; calcuate and return encoded checksum portion of hash string, taking config from object state calc checksum implementations may assume secret is always either unicode or bytes, checks are performed by verify/etc. s"%s must implement _calc_checksum()N(RR(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKs||rDt||}|rDt|||j|j||Snt||dt|}|j||_|jS(NR( RURMRR^R]RzRRyR(RRXRLtsettingsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^s  cKsYt||j||}|j}|dkrCtj|nt|j||S(N(R]RRyRfRZtMissingDigestErrorRR(RRXR^RRRl((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytverifys    t deprecateds1.7tremoveds2.0cKsSt||}|r+|j|j|S|dt|}|j|_|jS(NR(RURt genconfigRzRRyR(RRLRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  cKsS|dkrtdnt||j||}|j||_|jS(Nsconfig must be string(Rft TypeErrorR]RRRyR(RRXtconfigRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytgenhash s   cKs"|j|}|jd||S(NRX(Rt_calc_needs_update(RR^RXRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt needs_updatescCstS(s; internal helper for :meth:`needs_update`. (R(RRX((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR"st salt_sizeRRkRycsfdjDS(Nc3s$|]}|jkr|VqdS(N(t_unparsed_settings(RORP(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys 3s(t setting_kwds(R((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_parsed_settings1st*cCs|dkrdSt|trGddlm}||jd}nt|tset|}nt|}td|d}|| |||S(s*default method to obscure sensitive fieldsi(t ab64_encodeRciiN( RfRYR_tpasslib.utils.binaryRR`RR7R(RrtcharRtsizetclip((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _sanitize7s  csj|ttfdjD}|rbjdk rbj|d]sRyN( RtobjectRJRRyRfRzRt_unsafe_settings(RR^RytsanitizeRLRP((RRRs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt parsehashEs %   cKszytt|j|}Wntk r5i}nX|jrEtn|j}|jrv|rvt|j||dt k r}t |dkrt dfqnXt dt t|S( s{given secret; calcuate and return encoded checksum portion of hash string, taking config from object state cstdfdS(Ns"%s must implement _calc_checksum()(R(RRX(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytinnerst_wrapperRRc3s$|]}|t|fVqdS(N(R(ROtk(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys ssconfig must be strings"%s must implement _calc_checksum()s%r should be updated to implement StaticHandler._calc_checksum() instead of StaticHandler.genhash(), support for the latter style will be removed in Passlib 1.8N(Rt_StaticHandler__cc_compat_hackRfRR;RJRRSRRtstrRRRKR (RRXt wrapper_clsRRR^terr((RRs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs$    +(N( R;RRRRRRRRRRfRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR+{s  tHasEncodingContextcBs&eZdZdZdZddZRS(s?helper for classes which require knowledge of the encoding usedtencodingsutf-8cKs,tt|j||p"|j|_dS(N(RRRtdefault_encodingR(RRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs(sencodingN(R;RRRSRRfR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscBskeZdZd Zd dZed dZed dZe dddded d Z RS( s7helper for classes which require a user context keywordtusercKs#tt|j|||_dS(N(RR,RR(RRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKstt|j|d||S(NR(RR,R^(RRXRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^scKs"tt|j||d||S(NR(RR,R(RRXR^RR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRsRs1.7Rs2.0cKs"tt|j||d||S(NR(RR,R(RRXRRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs(suserN( R;RRRSRfRRR^RR%R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR,s cBseZdZeZRS(sqmixin for classes which work with decoded checksum bytes .. todo:: document this class's usage (R;RRRzR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR-scBsteZdZdZdZdZdZedddZ ddZ edZ edZ edZ RS(s mixin for hashes which use multiple prefix identifiers For the hashes which may use multiple identifier prefixes, this mixin adds an ``ident`` keyword to constructor. Any value provided is passed through the :meth:`norm_idents` method, which takes care of validating the identifier, as well as allowing aliases for easier specification of the identifiers by the user. .. todo:: document this class's usage Class Methods ============= .. todo:: document using() and needs_update() options cKsv|dk r0|dk r'tdn|}ntt|j|}|dk rr|d|dtj|_n|S(s4 This mixin adds support for the following :meth:`~passlib.ifc.PasswordHash.using` keywords: :param default_ident: default identifier that will be used by resulting customized hasher. :param ident: supported as alternate alias for **default_ident**. s2'default_ident' and 'ident' are mutually exclusiveRxRN(RfRRR.RRzRxt default_ident(RRRxRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR>s    cKsbtt|j||dk r4|j|}n!|jrI|j}n td||_dS(Nsno ident specified( RR.RRft _norm_identRRRRx(RRxRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR\s    cCst|tr!|jd}n|j}||kr:|S|j}|r~y||}Wntk rjq~X||kr~|Sntd|fdS(sD helper which normalizes & validates 'ident' value. Rcsinvalid ident: %rN(RYR_R`t ident_valuest ident_aliasestKeyErrorR(RRxtivtiaRr((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRis     cCst|}|j|jS(N(RbRAR(RR^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs cCs\t|dd}x4|jD])}|j|r||t|fSqWtj|dS(sDextract ident prefix from hash, helper for subclasses' from_string()RcR^N(R RRAR7RZRd(RR^Rx((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _parse_idents N(R;RRRfRRRRxRRRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR.s   cBseZdZdZdZdZedZedZ e Z dZ dZ eddddZededZddZd Zee d Zed Zed Zedd ZRS(s2 mixin for validating salts. This :class:`GenericHandler` mixin adds a ``salt`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_salt` method, which takes care of validating salt length and content, as well as generating new salts if one it not provided. :param salt: optional salt string :param salt_size: optional size of salt (only used if no salt provided); defaults to :attr:`default_salt_size`. Class Attributes ================ In order for :meth:`!_norm_salt` to do its job, the following attributes should be provided by the handler subclass: .. attribute:: min_salt_size The minimum number of characters allowed in a salt string. An :exc:`ValueError` will be throw if the provided salt is too small. Defaults to ``0``. .. attribute:: max_salt_size The maximum number of characters allowed in a salt string. By default an :exc:`ValueError` will be throw if the provided salt is too large; but if ``relaxed=True``, it will be clipped and a warning issued instead. Defaults to ``None``, for no maximum. .. attribute:: default_salt_size [required] If no salt is provided, this should specify the size of the salt that will be generated by :meth:`_generate_salt`. By default this will fall back to :attr:`max_salt_size`. .. attribute:: salt_chars A string containing all the characters which are allowed in the salt string. An :exc:`ValueError` will be throw if any other characters are encountered. May be set to ``None`` to skip this check (but see in :attr:`default_salt_chars`). .. attribute:: default_salt_chars [required] This attribute controls the set of characters use to generate *new* salt strings. By default, it mirrors :attr:`salt_chars`. If :attr:`!salt_chars` is ``None``, this attribute must be specified in order to generate new salts. Aside from that purpose, the main use of this attribute is for hashes which wish to generate salts from a restricted subset of :attr:`!salt_chars`; such as accepting all characters, but only using a-z. Instance Attributes =================== .. attribute:: salt This instance attribute will be filled in with the salt provided to the constructor (as adapted by :meth:`_norm_salt`) Subclassable Methods ==================== .. automethod:: _norm_salt .. automethod:: _generate_salt icCs|jS(s/default salt size (defaults to *max_salt_size*)(t max_salt_size(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytdefault_salt_sizescCs|jS(sDcharset used to generate new salt strings (defaults to *salt_chars*)(t salt_chars(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytdefault_salt_charssR9c s|dk r0|dk r'tdn|}ntt|j|}|jd}|dk rt|trt|}n|j |ddd||_ ndk r|j d|t fd|_ n|S(NsB'salt_size' and 'default_salt_size' aliases are mutually exclusiveRRvRcsS(N(((Rk(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt&s(RfRRR/RR@RYRR5t_clip_to_valid_salt_sizeRt _norm_saltRt_generate_salt(RRRRkRLRR((Rks:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s       RcCs|j}|j}||krl||krhd|j|||f}|rYt|tqht|n|S||krd|j|||f}|rt|t|}qt|n|r||krd|j|||f}|rt|t|}qt|n|S(s internal helper -- clip salt size value to handler's absolute limits (min_salt_size / max_salt_size) :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :returns: clipped rounds value s%s: %s (%d) must be exactly %ds$%s: %s (%r) below min_salt_size (%d)s$%s: %s (%r) above max_salt_size (%d)(t min_salt_sizeRRFRRR(RRRvRtmntmxR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR+s,         cKsett|j||dk r4|j|}n$|jrL|j}n td||_dS(Nsno salt specified( RR/RRft _parse_saltRRRRk(RRkRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR_s    cCs |j|S(N(R(RRk((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRksc s|jr3t|tstj|ddqnt|tst|trots]|ro|jd}qtj|ddn|jd k rt fd|Drt d|j n|j }|r/t||kr/d|j ||jkr dnd ||jf}t |n|j}|rt||krd |j ||krkdnd ||jf}|rt|t|j||}qt |n|S( sThelper to normalize & validate user-provided salt string :arg salt: salt string :raises TypeError: If salt not correct type. :raises ValueError: * if salt contains chars that aren't in :attr:`salt_chars`. * if salt contains less than :attr:`min_salt_size` characters. * if ``relaxed=False`` and salt has more than :attr:`max_salt_size` characters (if ``relaxed=True``, the salt is truncated and a warning is issued instead). :returns: normalized salt R_RkRcRc3s|]}|kVqdS(N((ROR(tsc(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys ssinvalid characters in %s salts%salt too small (%s requires %s %d %s)texactlys>=s%salt too large (%s requires %s %d %s)s<=N(t_salt_is_bytesRYR_RZR~RR"R`RRfRRRFRR7Rt _salt_unitRRt_truncate_salt(RRkRRRR((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRns0  (  (  % cCs|| S(N((RkR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCstt|j|jS(sU helper method for _init_salt(); generates a new random salt string. (RR RR(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscKsJtt|j|}|dkr0|j}nt||j|d<|S(s8[experimental method] return info about bitsizes of hashRkN(RR/RRfRR:R(RRRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs   N(R;RRRRfRRR$RRRRRRkRRRzRRRRRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR/s.E3 9cBs/eZdZeZeZdZedZ RS(smixin for classes which use decoded salt parameter A variant of :class:`!HasSalt` which takes in decoded bytes instead of an encoded string. .. todo:: document this class's usage R_cCstt|jS(N(R R R(R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs( R;RRRRRzRRRR(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR0s c BseZdZdZdZdZdZdZdZ dZ dZ dZ e dddddddd Ze d Ze d Zdd Zd Ze eddZe dZdZe dddZRS(s3mixin for validating rounds parameter This :class:`GenericHandler` mixin adds a ``rounds`` keyword to the class constuctor; any value provided is passed through the :meth:`_norm_rounds` method, which takes care of validating the number of rounds. :param rounds: optional number of rounds hash should use Class Attributes ================ In order for :meth:`!_norm_rounds` to do its job, the following attributes must be provided by the handler subclass: .. attribute:: min_rounds The minimum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is too small. Defaults to ``0``. .. attribute:: max_rounds The maximum number of rounds allowed. A :exc:`ValueError` will be thrown if the rounds value is larger than this. Defaults to ``None`` which indicates no limit to the rounds value. .. attribute:: default_rounds If no rounds value is provided to constructor, this value will be used. If this is not specified, a rounds value *must* be specified by the application. .. attribute:: rounds_cost [required] The ``rounds`` parameter typically encodes a cpu-time cost for calculating a hash. This should be set to ``"linear"`` (the default) or ``"log2"``, depending on how the rounds value relates to the actual amount of time that will be required. Class Methods ============= .. todo:: document using() and needs_update() options Instance Attributes =================== .. attribute:: rounds This instance attribute will be filled in with the rounds value provided to the constructor (as adapted by :meth:`_norm_rounds`) Subclassable Methods ==================== .. automethod:: _norm_rounds itlineartmin_desired_roundstmax_desired_roundsRt max_roundsRpt vary_roundsc Ks|dk r0|dk r'tdn|}n|dk r`|dk rWtdn|}n|dk r|dkr|}n|dkr|}n|dkr|}qntt|j|} |jd} |dkrt} |j}nBt} t |t rt |}n| j |ddd| | _|dkrM|j }nt |t rkt |}n|r||krd| j||f} | rt| qt| t|}n| j |ddd| | _ |dk rt |t rt |}n|r7||kr7td| j||fn1|rh||krhtd | j||fn| j |dd d| | _n| jdk r| j| j| _n|dk rt |t r|jd rt|d d }qd|kr t|}qt |}n|dkrCtd| j|fnXt |tr}|dkrtd| j|fqnt |t stdn|rtdtn|| _n| S(NsD'min_rounds' and 'min_desired_rounds' aliases are mutually exclusivesD'max_rounds' and 'max_desired_rounds' aliases are mutually exclusiveRRvRs9%s: max_desired_rounds (%r) below min_desired_rounds (%r)Rs5%s: default_rounds (%r) below min_desired_rounds (%r)s5%s: default_rounds (%r) above max_desired_rounds (%r)Rpt%ig{Gz?t.is%s: vary_rounds (%r) below 0is%s: vary_rounds (%r) above 1.0s vary_rounds must be int or floats\The 'vary_rounds' option is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0(RfRRR1RR@RRRzRYRR5t _norm_roundsRRFRRRRpt_clip_to_desired_roundstendswithtfloatR( RRRRpRRRRqRLRRtexplicit_min_roundsR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR6s                               cCsB|jp d}||kr|S|j}|r>||kr>|S|S(s| helper for :meth:`_generate_rounds` -- clips rounds value to desired min/max set by class (if any) i(RR(RRqtmndtmxd((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  cCs|j}d}t|trY|jdkrFd|>}d}nt||}n|||t}|||t}|j||j|fS(s helper for :meth:`_generate_rounds` -- returns range for vary rounds generation. :returns: (lower, upper) limits suitable for random.randint() cSs|S(N((Rrtupper((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytlinear_to_nativestlog2icSsO|dkrdS|r,ttj|dSttjtj|dSdS(Nii(R5R4R6tceil(RrR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs  (RRYRt rounds_costR5RRzR(RRpRRtlowerR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt_calc_vary_rounds_ranges    cKsett|j||dk r4|j|}n$|jrL|j}n td||_dS(Nsno rounds specified( RR1RRft _parse_roundsRt_generate_roundsRRq(RRqRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRs    cCs |j|S(N(R(RRq((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR sRqc Cs%t|||j|jd|d|S(s helper for normalizing rounds value. :arg rounds: an integer cost parameter. :param relaxed: if ``True`` (the default), issues PasslibHashWarning is rounds are outside allowed range. if ``False``, raises a ValueError instead. :param param: optional name of parameter to insert into error/warning messages. :raises TypeError: * if ``use_defaults=False`` and no rounds is specified * if rounds is not an integer. :raises ValueError: * if rounds is ``None`` and class does not specify a value for :attr:`default_rounds`. * if ``relaxed=False`` and rounds is outside bounds of :attr:`min_rounds` and :attr:`max_rounds` (if ``relaxed=True``, the rounds value will be clamped, and a warning issued). :returns: normalized rounds value RvR(RRR(RRqRRv((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRscCst|j}|dkr.td|jfn|jrp|j|\}}||krptj||}qpn|S(s internal helper for :meth:`_norm_rounds` -- returns default rounds value, incorporating vary_rounds, and any other limitations hash may place on rounds parameter. s,%s rounds value must be specified explicitlyN(RpRfRRFRR R trandint(RRqR R((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s    cKsZ|j}|r"|j|kr"tS|j}|rD|j|krDtStt|j|S(sR mark hash as needing update if rounds is outside desired bounds. (RRqRzRRR1R(RRLRR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR)s  g?cKstt|j|}|jdkr{ddl}|dkrK|j}ntdtd|j ||d|d` handlers; such as :class:`~passlib.hash.ldap_md5_crypt` which wraps :class:`~passlib.hash.md5_crypt` and adds a ``{CRYPT}`` prefix. usage:: myhandler = PrefixWrapper("myhandler", "md5_crypt", prefix="$mh$", orig_prefix="$1$") :param name: name to assign to handler :param wrapped: handler object or name of registered handler :param prefix: identifying prefix to prepend to all hashes :param orig_prefix: prefix to strip (defaults to ''). :param lazy: if True and wrapped handler is specified by name, don't look it up until needed. R<cCs@||_t|tr*|jd}n||_t|trT|jd}n||_|ro||_nt|dr|j|n||_ |s|j n|dk r<|t kr|r|}qt dnt|tr|jd}n|t| |t| kr0t dn||_ndS(NRcRFsno prefix specifiedsident must agree with prefix(RFRYR_R`Rht orig_prefixRthasattrt _set_wrappedt _wrapped_namet _get_wrappedRfRzRR7t_ident(RRFtwrappedRhRAtlazytdocRx((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s0          cCsBd|jkr5|jr5td|jftjn||_dS(NRxskPrefixWrapper: 'orig_prefix' option may not work correctly for handlers which have multiple identifiers: %r(RRARRFRZtPasslibRuntimeWarningt_wrapped_handler(RRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRC scCs8|j}|dkr4t|j}|j|n|S(N(RKRfRRDRC(RRH((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRE s   cCsp|j}|tkrld}|js`|j}t|dd}|dk r`|j|}q`n||_n|S(NRx(RFRRfRARGRt _wrap_hash(RRrRGRx((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRx s      cswj}|tkrsd}jsgj}t|dd}|rgtfd|D}qgn|_n|S(NRc3s|]}j|VqdS(N(RL(RORx(R(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys s(t _ident_valuesRRfRARGRttuple(RRrRGtidents((Rs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR s    " RRSRpRRR RRRRRRRRRRRRt is_disabledRRRRcCs{t|jp|jg}|jr;|jd|jn|jr[|jd|jndj|}d|j|fS(Ns prefix=%rsorig_prefix=%rs, sPrefixWrapper(%r, %s)(treprRDRKRhR/RAtjoinRF(Rtargs((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt__repr__ s  csXtt|j}|j|j|j|jfd|jDt|S(Nc3s$|]}t|r|VqdS(N(RB(ROtattr(RG(s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pys  s(RRtdirRtupdateR,RGt _proxy_attrsRT(Rtattrs((RGs:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt__dir__ s  cCs6||jkrt|j|Std|fdS(sFproxy most attributes from wrapped class (e.g. rounds, salt size, etc)smissing attribute: %rN(RXRRGR(RRU((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt __getattr__ scCsZ||jkrG|jrG|j}t||rGt|||dSntj|||S(N(RXt _derived_fromRGRBtsetattrRt __setattr__(RRURrRG((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^ s  cCs?|j}|j|s*tj|n|j|t|S(s4given hash belonging to wrapper, return orig version(RhRARZRdRAR7(RR^Rh((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyt _unwrap_hash+ s cCsot|tr!|jd}n|j}|j|sNtj|jn|j|t |}t |S(s0given orig hash; return one belonging to wrapperRc( RYR_R`RARARZRdRGRhR7R(RR^RARG((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRL4 s cKsp|jj|}t|j|d|jd|j}||_x*|jD]}t||t ||qIW|S(NRhRA( RGRR3RFRhRAR\t_using_clone_attrsR]R(RRLRtwrapperRU((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRC s $ cKs"|j|}|jj||S(N(R_RGR(RR^RL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRN scCsAt|}|j|js"tS|j|}|jj|S(N(RbRARhRR_RGR(RR^((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRR s  Rs1.7Rs2.0cKs:|jj|}|dkr-tdn|j|S(Ns+.genconfig() must return a string, not None(RGRRfR?RL(RRLR((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRY s cKsO|dk r0t|dd}|j|}n|j|jj|||S(NRcs config/hash(RfR R_RLRGR(RRXRRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR` s t replacements.hash()cKs|j||S(N(R^(RRXRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pytencrypth scKs|j|jj||S(N(RLRGR^(RRXRL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR^l scKs7t|dd}|j|}|jj|||S(NRcR^(R R_RGR(RRXR^RL((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyRo s(N(s setting_kwdss context_kwdssdefault_roundss min_roundss max_roundss rounds_costsmin_desired_roundssmax_desired_roundss vary_roundssdefault_salt_sizes min_salt_sizes max_salt_sizes salt_charssdefault_salt_charssbackendss has_backends get_backends set_backendRPs truncate_sizestruncate_errorstruncate_verify_rejects_salt_is_bytes(#R;RRR`RRRfRRDRKRCRERRGRFRxRMRRXRTRZR[R^R_RLR\RRRR%RRRcR^R(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyR3 sJ      $ (cRt __future__RR=tloggingt getLoggerR;R6R4t threadingtwarningsRt passlib.excRZt passlib.ifctifcRRRRtpasslib.registryRt passlib.utilsRRR R R R R RRRRRRRRRRRRtpasslib.utils.compatRRRRRRRR R!R"R#tpasslib.utils.decorR$R%t__all__t H64_CHARSt B64_CHARStPADDED_B64_CHARSt UC_HEX_CHARSt LC_HEX_CHARSR:RGRMRUt_UDOLLARRmR]RbRfR&R'RwR(R)R|RRRRR*R+RR,R-R.R/R0R1RtRLockRRR)R2RR3(((s:/usr/lib/python2.7/site-packages/passlib/utils/handlers.pyts    L4R        J! &!*Z '&xH N|