示例#1
0
    def test_43_encryptpin(self):
        serial = "ENC01"
        # encrypt pin on init
        init_token({
            "serial": serial,
            "genkey": 1,
            "pin": "Hallo",
            "encryptpin": True
        })
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # set a hashed pin
        set_pin(serial, "test", encrypt_pin=False)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertTrue(tokenobj.token.pin_hash[0:2] != "@@")

        # set an encrypted PIN
        set_pin(serial, "test", encrypt_pin=True)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # assign the token with a PIN
        assign_token(serial,
                     User(login="******", realm=self.realm1),
                     pin="WellWell",
                     encrypt_pin=True)
        # check if pinhash starts with "@@" to indicate the encryption
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")
示例#2
0
    def test_43_encryptpin(self):
        serial = "ENC01"
        # encrypt pin on init
        init_token({"serial": serial,
                    "genkey": 1,
                    "pin": "Hallo",
                    "encryptpin": True})
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # set a hashed pin
        set_pin(serial, "test", encrypt_pin=False)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertTrue(tokenobj.token.pin_hash[0:2] != "@@")

        # set an encrypted PIN
        set_pin(serial, "test", encrypt_pin=True)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # assign the token with a PIN
        assign_token(serial, User(login="******", realm=self.realm1),
                     pin="WellWell", encrypt_pin=True)
        # check if pinhash starts with "@@" to indicate the encryption
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")
示例#3
0
def setpin(serial):
    app = create_app(config_name="production",
                     config_file="/etc/privacyidea/pi.cfg",
                     silent=True)

    with app.app_context():
        # Set global values
        set_pin(serial, PIN)
示例#4
0
 def setUp(self):
     self.setUp_user_realms()
     # New token for the user "selfservice"
     Token("hotp1", "hotp", otpkey=self.otpkey, userid=1004, resolver=self.resolvername1,
           realm=self.realm1).save()
     # Define HOTP token to be challenge response
     set_policy(name="pol_cr", scope=SCOPE.AUTH, action="{0!s}=hotp".format(ACTION.CHALLENGERESPONSE))
     set_policy(name="webuilog", scope=SCOPE.WEBUI, action="{0!s}=privacyIDEA".format(ACTION.LOGINMODE))
     from privacyidea.lib.token import set_pin
     set_pin("hotp1", "pin")
示例#5
0
    def test_37_challenge(self):
        # We create a challenge by first sending the PIN of the HOTP token
        # then we answer the challenge by sending the OTP.

        num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # The correct PIN will create a challenge
        r, reply = check_serial_pass("hotptoken", "hotppin")
        self.assertTrue(r is False, r)
        num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # check that the challenge is created
        self.assertTrue(num1 + 1 == num2, (num1, num2))
        self.assertTrue(type(reply) == dict, reply)
        transaction_id = reply.get("transaction_id", "")
        self.assertTrue(len(transaction_id) > 10, reply)

        # Challenge Response, with the transaction id
        r, reply = check_serial_pass("hotptoken", "436521",
                                     {"transaction_id": transaction_id})
        self.assertTrue(r)
        self.assertTrue(
            reply.get("message") == "Found matching challenge", reply)

        # create two tokens with the same OTP Key and the same PIN, so
        # this token will create the same challenge
        # creating a challenge will not work!
        tokenobject = init_token({
            "serial": "CHALL001",
            "type": "hotp",
            "otpkey": self.otpkey
        })
        tokenobject = init_token({
            "serial": "CHALL002",
            "type": "hotp",
            "otpkey": self.otpkey
        })
        user = User("cornelius", realm=self.realm1)
        assign_token("CHALL001", user)
        assign_token("CHALL002", user)
        set_pin("CHALL001", "challpin")
        set_pin("CHALL002", "challpin")
        r, reply = check_user_pass(user, "challpin")
        self.assertFalse(r)
        self.assertTrue(
            "Multiple tokens to create a challenge found"
            in reply.get("message"), reply)
        remove_token("CHALL001")
        remove_token("CHALL002")
示例#6
0
    def test_37_challenge(self):
        # We create a challenge by first sending the PIN of the HOTP token
        # then we answer the challenge by sending the OTP.

        num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # The correct PIN will create a challenge
        r, reply = check_serial_pass("hotptoken", "hotppin")
        self.assertTrue(r is False, r)
        num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # check that the challenge is created
        self.assertTrue(num1 + 1 == num2, (num1, num2))
        self.assertTrue(type(reply) == dict, reply)
        transaction_id = reply.get("transaction_id","")
        self.assertTrue(len(transaction_id) > 10, reply)

        # Challenge Response, with the transaction id
        r, reply = check_serial_pass("hotptoken", "436521",
                                     {"transaction_id": transaction_id})
        self.assertTrue(r)
        self.assertTrue(reply.get("message") == "Found matching challenge",
                        reply)

        # create two tokens with the same OTP Key and the same PIN, so
        # this token will create the same challenge
        # creating a challenge will not work!
        tokenobject = init_token({"serial": "CHALL001", "type": "hotp",
                                  "otpkey": self.otpkey})
        tokenobject = init_token({"serial": "CHALL002", "type": "hotp",
                                  "otpkey": self.otpkey})
        user = User("cornelius", realm=self.realm1)
        assign_token("CHALL001", user)
        assign_token("CHALL002", user)
        set_pin("CHALL001", "challpin")
        set_pin("CHALL002", "challpin")
        r, reply = check_user_pass(user, "challpin")
        self.assertFalse(r)
        self.assertTrue("Multiple tokens to create a challenge found"
                        in reply.get("message"), reply)
        remove_token("CHALL001")
        remove_token("CHALL002")
示例#7
0
    def test_31_copy_token_pin(self):
        serial1 = "tcopy1"
        tobject1 = init_token({"serial": serial1, "genkey": 1})
        r = set_pin(serial1, "secret")
        self.assertTrue(r)
        serial2 = "tcopy2"
        tobject2 = init_token({"serial": serial2, "genkey": 1})
        r = copy_token_pin(serial1, serial2)
        self.assertTrue(r)

        # Now compare the pinhash
        self.assertTrue(tobject1.token.pin_hash == tobject2.token.pin_hash,
                        "%s <> %s" % (tobject1.token.pin_hash,
                                      tobject2.token.pin_hash))

        remove_token(serial1)
        remove_token(serial2)
示例#8
0
    def test_31_copy_token_pin(self):
        serial1 = "tcopy1"
        tobject1 = init_token({"serial": serial1, "genkey": 1})
        r = set_pin(serial1, "secret")
        self.assertTrue(r)
        serial2 = "tcopy2"
        tobject2 = init_token({"serial": serial2, "genkey": 1})
        r = copy_token_pin(serial1, serial2)
        self.assertTrue(r)

        # Now compare the pinhash
        self.assertTrue(
            tobject1.token.pin_hash == tobject2.token.pin_hash,
            "%s <> %s" % (tobject1.token.pin_hash, tobject2.token.pin_hash))

        remove_token(serial1)
        remove_token(serial2)
示例#9
0
 def test_20_pin_token_so_user(self):
     serial = "pins"
     tokenobject = init_token({"serial": serial,
                               "otpkey": "1234567890123456"})
     # user parameter is wrong
     self.assertRaises(ParameterError, set_pin, serial, None, "1234")
     # user and serial is missing
     self.assertRaises(ParameterError, set_pin)
     # now set the pin
     self.assertTrue(set_pin(serial, "1234") == 1)
     self.assertTrue(tokenobject.token.check_pin("1234"))
     self.assertTrue(tokenobject.token.user_pin == "")
     self.assertTrue(set_pin_user(serial, "1234") == 1)
     self.assertTrue(tokenobject.token.user_pin != "")
     self.assertTrue(tokenobject.token.so_pin == "")
     self.assertTrue(set_pin_so(serial, "1234") == 1)
     self.assertTrue(tokenobject.token.so_pin != "")
     remove_token(serial)
示例#10
0
 def test_20_pin_token_so_user(self):
     serial = "pins"
     tokenobject = init_token({
         "serial": serial,
         "otpkey": "1234567890123456"
     })
     # user parameter is wrong
     self.assertRaises(ParameterError, set_pin, serial, None, "1234")
     # user and serial is missing
     self.assertRaises(ParameterError, set_pin)
     # now set the pin
     self.assertTrue(set_pin(serial, "1234") == 1)
     self.assertTrue(tokenobject.token.check_pin("1234"))
     self.assertTrue(tokenobject.token.user_pin == "")
     self.assertTrue(set_pin_user(serial, "1234") == 1)
     self.assertTrue(tokenobject.token.user_pin != "")
     self.assertTrue(tokenobject.token.so_pin == "")
     self.assertTrue(set_pin_so(serial, "1234") == 1)
     self.assertTrue(tokenobject.token.so_pin != "")
     remove_token(serial)
示例#11
0
    def test_34_check_token_list(self):
        # We can not authenticate with an unknown type
        # Such a token will not be returned by get_tokens...
        db_token = Token("serial72", tokentype="unknown")
        db_token.save()

        # set a matching OTP PIN for our hotp token
        set_pin("hotptoken", "hotppin40")
        tokenobject_list = get_tokens()

        # the HOTP token has the correct PIN but wrong otp value
        # The failcounter is increased
        hotp_tokenobject = get_tokens(serial="hotptoken")[0]
        hotp_tokenobject.set_pin("hotppin")
        hotp_tokenobject.save()
        old_failcount = hotp_tokenobject.token.failcount
        res, reply = check_token_list(tokenobject_list, "hotppin40123456")
        self.assertFalse(res)
        failcount = hotp_tokenobject.token.failcount
        self.assertTrue(failcount == old_failcount + 1, (old_failcount,
                                                         failcount))

        # if there is no token with at least a correct pin, we increase all
        # failcounters
        hotp_tokenobject = get_tokens(serial="hotptoken")[0]
        old_failcount = hotp_tokenobject.token.failcount
        res, reply = check_token_list(tokenobject_list, "everythingiswrong")
        self.assertFalse(res)
        failcount = hotp_tokenobject.token.failcount
        self.assertTrue(failcount == old_failcount + 1, (old_failcount,
                                                         failcount))

        # Now we do some successful auth with the HOTP token
        tokenobject_list = get_tokens(serial="hotptoken")
        """                        Truncated
           Count    Hexadecimal    Decimal        HOTP
           0        4c93cf18       1284755224     755224
           1        41397eea       1094287082     287082
           2         82fef30        137359152     359152
           3        66ef7655       1726969429     969429
           4        61c5938a       1640338314     338314
           5        33c083d4        868254676     254676
           6        7256c032       1918287922     287922
           7         4e5b397         82162583     162583
           8        2823443f        673399871     399871
           9        2679dc69        645520489     520489
           10                                     403154
           11                                     481090
           12                                     868912
           13                                     736127
        """
        hotp_tokenobject = tokenobject_list[0]
        old_counter = hotp_tokenobject.token.count
        res, reply = check_token_list(tokenobject_list, "hotppin399871")
        self.assertTrue(res)
        # check if the counter increased
        self.assertTrue(old_counter < hotp_tokenobject.token.count,
                        (old_counter, hotp_tokenobject.token.count))
        # but was it also increased in the database?
        tokenobject_list_new = get_tokens(serial="hotptoken")
        hotp_tokenobject_new = tokenobject_list_new[0]
        self.assertTrue(old_counter < hotp_tokenobject_new.token.count,
                        (old_counter, hotp_tokenobject.token.count))

        # False authentication
        old_failcount = hotp_tokenobject.token.failcount
        res, reply = check_token_list(tokenobject_list, "hotppin000000")
        self.assertFalse(res)
        # check the failcounter increased
        self.assertTrue(old_failcount + 1 == hotp_tokenobject.token.failcount)
        # Successful auth. The failcount needs to be resetted
        res, reply = check_token_list(tokenobject_list, "hotppin520489")
        self.assertTrue(res)
        self.assertTrue(hotp_tokenobject.token.failcount == 0)

        # Now we disable the hotp_tokenobject. If the token is disabled,
        # we must not be able to authenticate anymore with this very token.
        # But if the OTP value is valid, the counter is increased, anyway!
        old_counter = hotp_tokenobject.token.count
        hotp_tokenobject.enable(False)
        res, reply = check_token_list(tokenobject_list, "hotppin403154")
        self.assertFalse(res)
        self.assertTrue("Token is disabled" in reply.get("message"))
        self.assertEqual(old_counter + 1, hotp_tokenobject.token.count)
        # enable the token again
        hotp_tokenobject.enable(True)
示例#12
0
    def do(self, action, options=None):
        """
        This method executes the defined action in the given event.

        :param action:
        :param options: Contains the flask parameters g, request, response
            and the handler_def configuration
        :type options: dict
        :return:
        """
        ret = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        content = self._get_response_content(response)
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial") or \
                 g.audit_object.audit_data.get("serial")

        if action.lower() in [ACTION_TYPE.SET_TOKENREALM,
                              ACTION_TYPE.SET_DESCRIPTION,
                              ACTION_TYPE.DELETE, ACTION_TYPE.DISABLE,
                              ACTION_TYPE.ENABLE, ACTION_TYPE.UNASSIGN,
                              ACTION_TYPE.SET_VALIDITY,
                              ACTION_TYPE.SET_COUNTWINDOW,
                              ACTION_TYPE.SET_TOKENINFO,
                              ACTION_TYPE.SET_FAILCOUNTER,
                              ACTION_TYPE.CHANGE_FAILCOUNTER,
                              ACTION_TYPE.SET_RANDOM_PIN,
                              ACTION_TYPE.DELETE_TOKENINFO]:
            if serial:
                log.info("{0!s} for token {1!s}".format(action, serial))
                if action.lower() == ACTION_TYPE.SET_TOKENREALM:
                    realm = handler_options.get("realm")
                    only_realm = is_true(handler_options.get("only_realm"))
                    # Set the realm..
                    log.info("Setting realm of token {0!s} to {1!s}".format(
                        serial, realm))
                    # Add the token realm
                    set_realms(serial, [realm], add=not only_realm)
                elif action.lower() == ACTION_TYPE.SET_RANDOM_PIN:
                    # If for any reason we have no value, we default to 6
                    length = int(handler_options.get("length") or 6)
                    pin = generate_password(size=length)
                    if set_pin(serial, pin):
                        content.setdefault("detail", {})["pin"] = pin
                        options.get("response").data = json.dumps(content)
                elif action.lower() == ACTION_TYPE.DELETE:
                    remove_token(serial=serial)
                elif action.lower() == ACTION_TYPE.DISABLE:
                    enable_token(serial, enable=False)
                elif action.lower() == ACTION_TYPE.ENABLE:
                    enable_token(serial, enable=True)
                elif action.lower() == ACTION_TYPE.UNASSIGN:
                    unassign_token(serial)
                elif action.lower() == ACTION_TYPE.SET_DESCRIPTION:
                    description = handler_options.get("description") or ""
                    description, td = parse_time_offset_from_now(description)
                    s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                        AUTH_DATE_FORMAT)
                    set_description(serial,
                                    description.format(
                                        current_time=s_now,
                                        now=s_now,
                                        client_ip=g.client_ip,
                                        ua_browser=request.user_agent.browser,
                                        ua_string=request.user_agent.string))
                elif action.lower() == ACTION_TYPE.SET_COUNTWINDOW:
                    set_count_window(serial,
                                     int(handler_options.get("count window",
                                                             50)))
                elif action.lower() == ACTION_TYPE.SET_TOKENINFO:
                    tokeninfo = handler_options.get("value") or ""
                    tokeninfo, td = parse_time_offset_from_now(tokeninfo)
                    s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                        AUTH_DATE_FORMAT)
                    try:
                        username = request.User.loginname
                        realm = request.User.realm
                    except Exception:
                        username = "******"
                        realm = "N/A"
                    add_tokeninfo(serial, handler_options.get("key"),
                                  tokeninfo.format(
                                      current_time=s_now,
                                      now=s_now,
                                      client_ip=g.client_ip,
                                      username=username,
                                      realm=realm,
                                      ua_browser=request.user_agent.browser,
                                      ua_string=request.user_agent.string))
                elif action.lower() == ACTION_TYPE.DELETE_TOKENINFO:
                    delete_tokeninfo(serial, handler_options.get("key"))
                elif action.lower() == ACTION_TYPE.SET_VALIDITY:
                    start_date = handler_options.get(VALIDITY.START)
                    end_date = handler_options.get(VALIDITY.END)
                    if start_date:
                         d = parse_date(start_date)
                         set_validity_period_start(serial, None,
                                                   d.strftime(DATE_FORMAT))
                    if end_date:
                        d = parse_date(end_date)
                        set_validity_period_end(serial, None,
                                                d.strftime(DATE_FORMAT))
                elif action.lower() == ACTION_TYPE.SET_FAILCOUNTER:
                    try:
                        set_failcounter(serial,
                                        int(handler_options.get("fail counter")))
                    except Exception as exx:
                        log.warning("Misconfiguration: Failed to set fail "
                                    "counter!")
                elif action.lower() == ACTION_TYPE.CHANGE_FAILCOUNTER:
                    try:
                        token_obj = get_one_token(serial=serial)
                        token_obj.set_failcount(
                            token_obj.token.failcount + int(handler_options.get("change fail counter")))
                    except Exception as exx:
                        log.warning("Misconfiguration: Failed to increase or decrease fail "
                                    "counter!")
            else:
                log.info("Action {0!s} requires serial number. But no serial "
                         "number could be found in request.")

        if action.lower() == ACTION_TYPE.INIT:
            log.info("Initializing new token")
            init_param = {"type": handler_options.get("tokentype"),
                          "genkey": 1,
                          "realm": handler_options.get("realm", "")}
            user = None
            if is_true(handler_options.get("user")):
                user = self._get_tokenowner(request)
                tokentype = handler_options.get("tokentype")
                # Some tokentypes need additional parameters
                if handler_options.get("additional_params"):
                    add_params = yaml.safe_load(handler_options.get("additional_params"))
                    if type(add_params) == dict:
                        init_param.update(add_params)

                if tokentype == "sms":
                    if handler_options.get("dynamic_phone"):
                        init_param["dynamic_phone"] = 1
                    else:
                        init_param['phone'] = user.get_user_phone(
                            phone_type='mobile', index=0)
                        if not init_param['phone']:
                            log.warning("Enrolling SMS token. But the user "
                                        "{0!r} has no mobile number!".format(user))
                    if handler_options.get("sms_identifier"):
                        init_param["sms.identifier"] = handler_options.get("sms_identifier")
                elif tokentype == "email":
                    if handler_options.get("dynamic_email"):
                        init_param["dynamic_email"] = 1
                    else:
                        init_param['email'] = user.info.get("email", "")
                        if not init_param['email']:
                            log.warning("Enrolling EMail token. But the user {0!s}"
                                        "has no email address!".format(user))
                    if handler_options.get("smtp_identifier"):
                        init_param["email.identifier"] = handler_options.get("smtp_identifier")
                elif tokentype == "motp":
                    init_param['motppin'] = handler_options.get("motppin")

            t = init_token(param=init_param, user=user)
            log.info("New token {0!s} enrolled.".format(t.token.serial))

        return ret
示例#13
0
    def test_34_check_token_list(self):
        # We can not authenticate with an unknown type
        # Such a token will not be returned by get_tokens...
        db_token = Token("serial72", tokentype="unknown")
        db_token.save()

        # set a matching OTP PIN for our hotp token
        set_pin("hotptoken", "hotppin40")
        tokenobject_list = get_tokens()

        # the HOTP token has the correct PIN but wrong otp value
        # The failcounter is increased
        hotp_tokenobject = get_tokens(serial="hotptoken")[0]
        hotp_tokenobject.set_pin("hotppin")
        hotp_tokenobject.save()
        old_failcount = hotp_tokenobject.token.failcount
        res, reply = check_token_list(tokenobject_list, "hotppin40123456")
        self.assertFalse(res)
        failcount = hotp_tokenobject.token.failcount
        self.assertTrue(failcount == old_failcount + 1,
                        (old_failcount, failcount))

        # if there is no token with at least a correct pin, we increase all
        # failcounters
        hotp_tokenobject = get_tokens(serial="hotptoken")[0]
        old_failcount = hotp_tokenobject.token.failcount
        res, reply = check_token_list(tokenobject_list, "everythingiswrong")
        self.assertFalse(res)
        failcount = hotp_tokenobject.token.failcount
        self.assertTrue(failcount == old_failcount + 1,
                        (old_failcount, failcount))

        # Now we do some successful auth with the HOTP token
        tokenobject_list = get_tokens(serial="hotptoken")
        """                        Truncated
           Count    Hexadecimal    Decimal        HOTP
           0        4c93cf18       1284755224     755224
           1        41397eea       1094287082     287082
           2         82fef30        137359152     359152
           3        66ef7655       1726969429     969429
           4        61c5938a       1640338314     338314
           5        33c083d4        868254676     254676
           6        7256c032       1918287922     287922
           7         4e5b397         82162583     162583
           8        2823443f        673399871     399871
           9        2679dc69        645520489     520489
           10                                     403154
           11                                     481090
           12                                     868912
           13                                     736127
        """
        hotp_tokenobject = tokenobject_list[0]
        old_counter = hotp_tokenobject.token.count
        res, reply = check_token_list(tokenobject_list, "hotppin399871")
        self.assertTrue(res)
        # check if the counter increased
        self.assertTrue(old_counter < hotp_tokenobject.token.count,
                        (old_counter, hotp_tokenobject.token.count))
        # but was it also increased in the database?
        tokenobject_list_new = get_tokens(serial="hotptoken")
        hotp_tokenobject_new = tokenobject_list_new[0]
        self.assertTrue(old_counter < hotp_tokenobject_new.token.count,
                        (old_counter, hotp_tokenobject.token.count))

        # False authentication
        old_failcount = hotp_tokenobject.token.failcount
        res, reply = check_token_list(tokenobject_list, "hotppin000000")
        self.assertFalse(res)
        # check the failcounter increased
        self.assertTrue(old_failcount + 1 == hotp_tokenobject.token.failcount)
        # Successful auth. The failcount needs to be resetted
        res, reply = check_token_list(tokenobject_list, "hotppin520489")
        self.assertTrue(res)
        self.assertTrue(hotp_tokenobject.token.failcount == 0)

        # Now we disable the hotp_tokenobject. If the token is disabled,
        # we must not be able to authenticate anymore with this very token.
        # But if the OTP value is valid, the counter is increased, anyway!
        old_counter = hotp_tokenobject.token.count
        hotp_tokenobject.enable(False)
        res, reply = check_token_list(tokenobject_list, "hotppin403154")
        self.assertFalse(res)
        self.assertTrue("Token is disabled" in reply.get("message"))
        self.assertEqual(old_counter + 1, hotp_tokenobject.token.count)
        # enable the token again
        hotp_tokenobject.enable(True)