Esempio n. 1
0
 def complete(self):
     """
     Check to see if SASL negotiation has completed successfully, including
     a mutual authentication check if the chosen mechanism supports that and
     mutual authentication was requested via the `mutual_auth` parameter
     for the `SASLClient` constructor.
     """
     if not self._chosen_mech:
         raise SASLError("A mechanism has not been chosen yet")
     return self._chosen_mech.complete
Esempio n. 2
0
    def _fetch_properties(self, *properties):
        """
        Ensure this mechanism has the needed properties. If they haven't
        been set yet, the registered callback function will be called for
        each property to retrieve a value.
        """
        needed = [p for p in properties if getattr(self, p, None) is None]
        if needed and not self.sasl.callback:
            raise SASLError('The following properties are required, but a '
                            'callback has not been set: %s' % ', '.join(needed))

        for prop in needed:
            setattr(self, prop, self.sasl.callback(prop))
Esempio n. 3
0
    def choose_mechanism(self,
                         mechanism_choices,
                         allow_anonymous=True,
                         allow_plaintext=True,
                         allow_active=True,
                         allow_dictionary=True):
        """
        Choose a mechanism from a list of mechanisms based on security
        scores for mechanisms and required properties of the mechanism.

        If `allow_anonymous` is ``False``, mechanisms that allow anonymous
        authentication will not be considered.

        If `allow_plaintext` is ``False``, mechanisms that transmit
        sensitive information in plaintext (and are thus susceptible to
        passive listening attacks) will not be considered.

        If `allow_active` is ``False``, mechanisms that are susceptible
        to active non-dictionary attacks (MITM, injection) will not be
        considered.

        If `allow_dictionary` is ``False, mechanisms that are susceptible
        to passive dictionary attacks will not be considered.
        """
        candidates = [
            mech_mod.mechanisms[choice] for choice in mechanism_choices
            if choice in mech_mod.mechanisms
        ]

        if not allow_anonymous:
            candidates = [m for m in candidates if not m.allows_anonymous]
        if not allow_plaintext:
            candidates = [m for m in candidates if not m.uses_plaintext]
        if not allow_active:
            candidates = [m for m in candidates if m.active_safe]
        if not allow_dictionary:
            candidates = [m for m in candidates if m.dictionary_safe]

        if not candidates:
            raise SASLError("None of the mechanisms listed meet all "
                            "required properties")

        # Pick the best mechanism based on its security score
        mech_class = max(candidates, key=lambda mech: mech.score)
        self.mechanism = mech_class.name
        self._chosen_mech = mech_class(self, **self._mech_props)
Esempio n. 4
0
 def wrapped(self, *args, **kwargs):
     if not self._chosen_mech:
         raise SASLError("A mechanism has not been chosen yet")
     return f(self, *args, **kwargs)