Exemplo n.º 1
0
 def test_03_hash(self):
     import os
     val = os.urandom(16)
     seed = os.urandom(16)
     h1 = hash(val, seed)
     self.assertEqual(h1, hash(val, seed))
     seed2 = os.urandom(16)
     self.assertNotEqual(h1, hash(val, seed2))
Exemplo n.º 2
0
 def test_03_hash(self):
     import os
     val = os.urandom(16)
     seed = os.urandom(16)
     h1 = hash(val, seed)
     self.assertEqual(h1, hash(val, seed))
     seed2 = os.urandom(16)
     self.assertNotEqual(h1, hash(val, seed2))
Exemplo n.º 3
0
    def check_otp(self, anOtpVal, counter=None, window=None, options=None):
        """
        check if the given OTP value is valid for this token.

        :param anOtpVal: the to be verified otpvalue
        :type anOtpVal: string
        :param counter: the counter state, that should be verified
        :type counter: int
        :param window: the counter +window, which should be checked
        :type window: int
        :param options: the dict, which could contain token specific info
        :type options: dict
        :return: the counter state or -1
        :rtype: int
        """
        res = -1
        tans = self.get_tokeninfo()
        for tankey, tanvalue in tans.items():
            if tankey.startswith("tan.tan"):
                salt, tan = tanvalue.split(":")
                if tan == hash(anOtpVal, salt):
                    self.del_tokeninfo(tankey)
                    return 1

        return res
Exemplo n.º 4
0
 def update(self, param, reset_failcount=True):
     if "tans" in param:
         # init tokens with tans
         tans = param.get("tans").split()
         tan_dict = {k: v for k, v in enumerate(tans)}
         # Avoid to generate TANs in the superclass PaperToken, since we get the tans from params
         param["papertoken_count"] = 0
         # Determine the otplen from the TANs
         if len(tans) > 0:
             param["otplen"] = len(tans[0])
         PaperTokenClass.update(self,
                                param,
                                reset_failcount=reset_failcount)
     else:
         # Init token without tans, so we create tans in the superclass PaperToken
         param["papertoken_count"] = param.get(
             "tantoken_count") or DEFAULT_COUNT
         PaperTokenClass.update(self,
                                param,
                                reset_failcount=reset_failcount)
         # After this creation, the init_details contain the complete list of the TANs
         tan_dict = self.init_details.get("otps", {})
     for tankey, tanvalue in tan_dict.items():
         # Get a 4 byte salt from the crypto module
         salt = geturandom(SALT_LENGTH, hex=True)
         # Now we add all TANs to the tokeninfo of this token.
         hashed_tan = hash(tanvalue, salt)
         self.add_tokeninfo("tan.tan{0!s}".format(tankey),
                            "{0}:{1}".format(salt, hashed_tan))
Exemplo n.º 5
0
    def check_otp(self, anOtpVal, counter=None, window=None, options=None):
        """
        check if the given OTP value is valid for this token.

        :param anOtpVal: the to be verified otpvalue
        :type anOtpVal: string
        :param counter: the counter state, that should be verified
        :type counter: int
        :param window: the counter +window, which should be checked
        :type window: int
        :param options: the dict, which could contain token specific info
        :type options: dict
        :return: the counter state or -1
        :rtype: int
        """
        res = -1
        tans = self.get_tokeninfo()
        for tankey, tanvalue in tans.items():
            if tankey.startswith("tan.tan"):
                salt, tan = tanvalue.split(":")
                if tan == binascii.hexlify(hash(anOtpVal,salt)):
                    self.del_tokeninfo(tankey)
                    return 1

        return res
Exemplo n.º 6
0
    def getHashedPin(self, pin):
        # TODO: we could log the PIN here.
        log.debug('getHashedPin()')

        ## calculate a hash from a pin
        # Fix for working with MS SQL servers
        # MS SQL servers sometimes return a '<space>' when the column is empty: ''
        seed_str = self._fix_spaces(self.privacyIDEASeed)
        seed = binascii.unhexlify(seed_str)
        hPin = hash(pin, seed)
        log.debug("hPin: %s, pin: %s, seed: %s" % (binascii.hexlify(hPin), pin, self.privacyIDEASeed))
        return binascii.hexlify(hPin)
Exemplo n.º 7
0
    def test_05_old_hashes(self):
        from privacyidea.lib.crypto import hash
        # Test that old hashes do not break the code
        r = cleanup(100000000)
        # Add an entry with an old password hash
        AuthCache("grandpa", self.realm, self.resolver, hash("old password", seed=""),
                  first_auth=datetime.datetime.utcnow() - datetime.timedelta(
                      minutes=10),
                  last_auth=datetime.datetime.utcnow() - datetime.timedelta(
                      minutes=2)).save()

        r = verify_in_cache("grandpa", self.realm, self.resolver, "old password")
        self.assertFalse(r)
Exemplo n.º 8
0
 def update(self, param, reset_failcount=True):
     if "tans" in param:
         # init tokens with tans
         tans = param.get("tans").split()
         tan_dict = {k: v for k, v in enumerate(tans)}
         # Avoid to generate TANs in the superclass PaperToken, since we get the tans from params
         param["papertoken_count"] = 0
         # Determine the otplen from the TANs
         if len(tans) > 0:
             param["otplen"] = len(tans[0])
         PaperTokenClass.update(self, param, reset_failcount=reset_failcount)
     else:
         # Init token without tans, so we create tans in the superclass PaperToken
         param["papertoken_count"] = param.get("tantoken_count") or DEFAULT_COUNT
         PaperTokenClass.update(self, param, reset_failcount=reset_failcount)
         # After this creation, the init_details contain the complete list of the TANs
         tan_dict = self.init_details.get("otps", {})
     for tankey, tanvalue in tan_dict.items():
         # Get a 4 byte salt from the crypto module
         salt = geturandom(SALT_LENGTH, hex=True)
         # Now we add all TANs to the tokeninfo of this token.
         hashed_tan = binascii.hexlify(hash(tanvalue, salt))
         self.add_tokeninfo("tan.tan{0!s}".format(tankey),
                            "{0}:{1}".format(salt, hashed_tan))
Exemplo n.º 9
0
 def setHashedPin(self, pin):
     log.debug('setHashedPin()')
     seed = geturandom(16)
     self.privacyIDEASeed = unicode(binascii.hexlify(seed))
     self.privacyIDEAPinHash = unicode(binascii.hexlify(hash(pin, seed)))
     return self.privacyIDEAPinHash
Exemplo n.º 10
0
def _hash_password(password):
    return hash(password, seed="")
def generic_challenge_response_reset_pin(wrapped_function, *args, **kwds):
    """
    Check if the authentication was successful, but if the token needs to reset
    its PIN.

    Conditions: To do so we check for "next_pin_change" in the tokeninfo data. This
    is however easily done using token.is_pin_change().

    Policies: A policy defines, if this PIN reset functionality should be active
    at all. scope=AUTH, action=CHANGE_PIN_VIA_VALIDATE

    args are:
    :param tokenobject_list: The list of all the tokens of the user, that will be checked
    :param passw: The password presented in the authentication. We need this for the PIN reset.

    kwds are:
    :param options: options dictionary containing g
    :param user: The user_obj
    """

    # Before we call the wrapped function, we need to check, if we have a generic challenge
    # for the given transaction_id and if the token serial matches a given token
    options = kwds.get("options") or {}
    user_obj = kwds.get("user")
    transaction_id = options.get("transaction_id") or options.get("state")
    if transaction_id:
        challenges = get_challenges(transaction_id=transaction_id, challenge=CHALLENGE_TYPE.PIN_RESET)
        if len(challenges) == 1:
            challenge = challenges[0]
            # check if challenge matches a token and if it is valid
            token_obj = next(t for t in args[0] if t.token.serial == challenge.serial)
            if token_obj:
                # Then either verify the PIN or set the PIN the first time. The
                # PIN from the 1st response is stored in challenge.data
                if challenge.data:
                    hashedpin = challenge.data[SEED_LENGTH + 1:]
                    seed = challenge.data[0:SEED_LENGTH]
                    # Verify the password
                    if hash(args[1], seed) == hashedpin:
                        g = options.get("g")
                        challenge.set_otp_status(True)
                        token_obj.challenge_janitor()
                        # Success, set new PIN and return success
                        token_obj.set_pin(args[1])
                        pinpol = Match.token(g, scope=SCOPE.ENROLL, action=ACTION.CHANGE_PIN_EVERY,
                                             token_obj=token_obj).action_values(unique=True)
                        # Set a new next_pin_change
                        if pinpol:
                            # Set a new next pin change
                            token_obj.set_next_pin_change(diff=list(pinpol)[0])
                        else:
                            # Obviously the admin removed the policy for changing pins,
                            # so we will not require to change the PIN again
                            token_obj.del_tokeninfo("next_pin_change")
                        return True, {"message": "PIN successfully set.",
                                      "serial": token_obj.token.serial}
                    else:
                        return False, {"serial": token_obj.token.serial,
                                       "message": "PINs do not match"}
                else:
                    # The PIN is presented the first time.
                    # Verify if the PIN adheres to the PIN policies. This is always in the normal user context
                    g = options.get("g")
                    g.logged_in_user = {"role": SCOPE.USER}
                    if user_obj:
                        # check_pin below originally works for logged in users, since only logged in users
                        # are allowed to change the pin. So we need to construct a logged_in_user object, otherwise
                        # check_pin would fail.
                        g.logged_in_user["username"] = user_obj.login
                        g.logged_in_user["realm"] = user_obj.realm
                    check_pin(g, args[1], token_obj.token.tokentype, user_obj)
                    # We need to ask for a 2nd time
                    challenge.set_otp_status(True)
                    seed = get_rand_digit_str(SEED_LENGTH)
                    reply_dict = _create_pin_reset_challenge(token_obj, _("Please enter the new PIN again"),
                                                             "{0!s}:{1!s}".format(seed, hash(args[1], seed)))
                    return False, reply_dict

    success, reply_dict = wrapped_function(*args, **kwds)

    # After a successful authentication, we might start the PIN change process
    if success and reply_dict.get("pin_change"):
        g = options.get("g")
        # Determine the realm by the serial
        serial = reply_dict.get("serial")
        # The tokenlist can contain more than one token. So we get the matching token object
        token_obj = next(t for t in args[0] if t.token.serial == serial)
        if g and Match.token(g, scope=SCOPE.AUTH, action=ACTION.CHANGE_PIN_VIA_VALIDATE, token_obj=token_obj).any():
            reply_dict = _create_pin_reset_challenge(token_obj, _("Please enter a new PIN"))
            return False, reply_dict

    return success, reply_dict
Exemplo n.º 12
0
def _hash_password(password):
    return hash(password, seed="")