Example #1
0
 def test_02_updateserver(self):
     r = add_privacyideaserver(identifier="myserver",
                               url="https://pi/pi",
                               tls=False)
     self.assertTrue(r > 0)
     server = get_privacyideaserver("myserver")
     self.assertEqual(server.config.url, "https://pi/pi")
     self.assertFalse(server.config.tls)
     r = add_privacyideaserver(identifier="myserver",
                               url="https://pi/",
                               tls=True,
                               description="Hallo")
     self.assertTrue(r > 0)
     server = get_privacyideaserver("myserver")
     self.assertEqual(server.config.url, "https://pi/")
     self.assertEqual(server.config.tls, True)
     self.assertEqual(server.config.description, "Hallo")
Example #2
0
    def update(self, param):
        """
        second phase of the init process - updates parameters

        :param param: the request parameters
        :return: - nothing -
        """
        # if another OTP length would be specified in /admin/init this would
        # be overwritten by the parent class, which is ok.
        self.set_otplen(6)
        TokenClass.update(self, param)

        remote_server_id = getParam(param, "remote.server_id", optional)

        if remote_server_id is not None:
            if get_privacyideaserver(id=remote_server_id):
                self.add_tokeninfo("remote.server_id", remote_server_id)
        else:
            remoteServer = getParam(param, "remote.server", required)
            self.add_tokeninfo("remote.server", remoteServer)
            log.warning(
                "Using remote.server for remote tokens is deprecated. Use remote.server_id!"
            )

        val = getParam(param, "remote.local_checkpin", optional) or 0
        self.add_tokeninfo("remote.local_checkpin", val)

        for key in [
                "remote.serial", "remote.user", "remote.path", "remote.realm",
                "remote.resolver"
        ]:
            val = getParam(param, key, optional)
            if val is not None:
                self.add_tokeninfo(key, val)

        self.add_tokeninfo("tokenkind", TOKENKIND.VIRTUAL)
    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:
        """
        g = options.get("g")
        request = options.get("request")
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})

        if action == ACTION_TYPE.FORWARD:
            server_def = handler_options.get("privacyIDEA")
            pi_server = get_privacyideaserver(server_def)

            # the new url is the configured server url and the original path
            url = pi_server.config.url + request.path
            # We use the original method
            method = request.method
            tls = pi_server.config.tls
            # We also transfer the original payload
            data = request.all_data
            if handler_options.get("forward_client_ip"):
                data["client"] = g.client_ip
            if handler_options.get("realm"):
                data["realm"] = handler_options.get("realm")
            if handler_options.get("resolver"):
                data["resolver"] = handler_options.get("resolver")

            log.info(u"Sending {0} request to {1!r}".format(method, url))
            requestor = None
            params = None
            headers = {}

            # We need to pass an authorization header if we forward administrative requests
            if handler_options.get("forward_authorization_token"):
                auth_token = request.headers.get('PI-Authorization')
                if not auth_token:
                    auth_token = request.headers.get('Authorization')
                headers["PI-Authorization"] = auth_token

            if method.upper() == "GET":
                params = data
                data = None
                requestor = requests.get
            elif method.upper() == "POST":
                requestor = requests.post
            elif method.upper() == "DELETE":
                requestor = requests.delete

            if requestor:
                r = requestor(url, params=params, data=data,
                              headers=headers, verify=tls)
                # convert requests Response to werkzeug Response
                response_dict = json.loads(r.text)
                if "detail" in response_dict:
                    if response_dict.get("detail") is None:
                        # In case of exceptions we may not have a detail
                        response_dict["detail"] = {"origin": url}
                    else:
                        response_dict.get("detail")["origin"] = url
                # We will modify the response!
                # We can not use flask.jsonify(response_dict) here, since we
                # would work outside of application context!
                options["response"] = Response()
                options["response"].status_code = r.status_code
                options["response"].content_type = "application/json"
                options["response"].data = json.dumps(response_dict)
            else:
                log.warning(u"Unsupported method: {0!r}".format(method))

        return True
Example #4
0
    def check_otp(self, otpval, counter=None, window=None, options=None):
        """
        run the http request against the remote host

        :param otpval: the OTP value
        :param counter: The counter for counter based otp values
        :type counter: int
        :param window: a counter window
        :type counter: int
        :param options: additional token specific options
        :type options: dict
        :return: counter of the matching OTP value.
        :rtype: int
        """
        otp_count = -1
        pi_server_obj = None
        remoteServer = None

        remote_server_id = self.get_tokeninfo("remote.server_id")
        if remote_server_id:
            pi_server_obj = get_privacyideaserver(id=int(remote_server_id))
        else:
            # Deprecated
            remoteServer = self.get_tokeninfo("remote.server") or ""
            log.warning(
                "Using remote.server for remote tokens is deprecated. Use remote.server_id!"
            )
            ssl_verify = get_from_config("remote.verify_ssl_certificate",
                                         False,
                                         return_bool=True) or False
            # in preparation of the ability to relocate privacyidea urls,
            # we introduce the remote url path
            remotePath = self.get_tokeninfo("remote.path") or ""
            remotePath = remotePath.strip()
            remotePath = remotePath or "/validate/check"

        remoteSerial = self.get_tokeninfo("remote.serial") or ""
        remoteUser = self.get_tokeninfo("remote.user") or ""
        remoteRealm = self.get_tokeninfo("remote.realm") or ""
        remoteResolver = self.get_tokeninfo("remote.resolver") or ""

        # here we also need to check for remote.user and so on....
        log.debug("checking OTP len:%r remotely on server: %r,"
                  " serial: %r, user: %r" %
                  (len(otpval), remoteServer, remoteSerial, remoteUser))
        params = {}

        if remoteSerial:
            params['serial'] = remoteSerial
        elif remoteUser:
            params['user'] = remoteUser
            params['realm'] = remoteRealm
            params['resolver'] = remoteResolver
        else:
            log.warning("The remote token does neither contain a "
                        "remote.serial nor a remote.user.")
            return otp_count

        try:
            if remoteServer:
                # Deprecated
                params['pass'] = otpval
                request_url = "{0!s}{1!s}".format(remoteServer, remotePath)
                r = requests.post(request_url, data=params, verify=ssl_verify)
            elif pi_server_obj:
                r = pi_server_obj.validate_check(remoteUser,
                                                 otpval,
                                                 serial=remoteSerial,
                                                 realm=remoteRealm,
                                                 resolver=remoteResolver)

            if r.status_code == requests.codes.ok:
                response = r.json()
                result = response.get("result")
                if result.get("value"):
                    otp_count = 1
                    # Add the serial of the used remote token in the tokeninfo parameters
                    self.add_tokeninfo(
                        "last_matching_remote_serial",
                        response.get("detail", {}).get("serial"))

        except Exception as exx:  # pragma: no cover
            log.error("Error getting response from "
                      "remote Server (%r): %r" % (request_url, exx))
            log.debug("{0!s}".format(traceback.format_exc()))

        return otp_count
Example #5
0
    def test_04_privacyidea_request(self):
        responses.add(responses.POST,
                      "https://privacyidea/pi/validate/check",
                      body="""{
            "jsonrpc": "2.0",
            "signature": "8714492288983608958721372435263469282038130269793819687538718333085851022315074567013564786433032592569773009757668260857150988825993253128403096686276017572870299270974318705442428477018018734211619614135162719525545735285162164985627482472020309913143284756699606758573589339750891246114721488327919685939018812698986042837837048205963507243718362073386749929275433723467277740468538209437683755941724140343215877868596281187733952567488886126455218397004400817126119660003078762499546137083926344365458736163867631154552432520453852071998486914168310985851091111203094188983006153929089352703802214328258347608348",
            "detail": null,
            "version": "privacyIDEA 2.20.dev2",
            "result": {
              "status": true,
              "value": true},
            "time": 1503561105.028947,
            "id": 1
                }""",
                      content_type="application/json")

        responses.add(responses.POST,
                      "https://privacyidea/pi2/validate/check",
                      body="""{
        "jsonrpc": "2.0",
        "signature": "8714492288983608958721372435263469282038130269793819687538718333085851022315074567013564786433032592569773009757668260857150988825993253128403096686276017572870299270974318705442428477018018734211619614135162719525545735285162164985627482472020309913143284756699606758573589339750891246114721488327919685939018812698986042837837048205963507243718362073386749929275433723467277740468538209437683755941724140343215877868596281187733952567488886126455218397004400817126119660003078762499546137083926344365458736163867631154552432520453852071998486914168310985851091111203094188983006153929089352703802214328258347608348",
        "detail": null,
        "version": "privacyIDEA 2.20.dev2",
        "result": {
          "status": false},
        "time": 1503561105.028947,
        "id": 1
        }""",
                      content_type="application/json",
                      status=404)

        responses.add(responses.POST,
                      "https://privacyidea/pi3/validate/check",
                      body="""{
                "jsonrpc": "2.0",
                "signature": "8714492288983608958721372435263469282038130269793819687538718333085851022315074567013564786433032592569773009757668260857150988825993253128403096686276017572870299270974318705442428477018018734211619614135162719525545735285162164985627482472020309913143284756699606758573589339750891246114721488327919685939018812698986042837837048205963507243718362073386749929275433723467277740468538209437683755941724140343215877868596281187733952567488886126455218397004400817126119660003078762499546137083926344365458736163867631154552432520453852071998486914168310985851091111203094188983006153929089352703802214328258347608348",
                "detail": null,
                "version": "privacyIDEA 2.20.dev2",
                "result": {
                  "status": true,
                  "value": false},
                "time": 1503561105.028947,
                "id": 1
                }""",
                      content_type="application/json",
                      status=404)

        # successful authentication
        r = add_privacyideaserver(identifier="pi",
                                  url="https://privacyidea/pi",
                                  tls=False)
        self.assertTrue(r > 0)
        pi = get_privacyideaserver("pi")
        r = PrivacyIDEAServer.request(pi.config, "user", "password")
        self.assertTrue(r)

        # failed  authentication 404
        r = add_privacyideaserver(identifier="pi2",
                                  url="https://privacyidea/pi2",
                                  tls=False)
        self.assertTrue(r > 0)
        pi = get_privacyideaserver("pi2")
        r = PrivacyIDEAServer.request(pi.config, "user", "password")
        self.assertFalse(r)

        # failed  authentication value=false
        r = add_privacyideaserver(identifier="pi3",
                                  url="https://privacyidea/pi3",
                                  tls=False)
        self.assertTrue(r > 0)
        pi = get_privacyideaserver("pi3")
        r = PrivacyIDEAServer.request(pi.config, "user", "password")
        self.assertFalse(r)