Пример #1
0
 def test_01_create_realm(self):
     rid = save_resolver({"resolver": self.resolvername1,
                            "type": "passwdresolver",
                            "fileName": "/etc/passwd"})
     self.assertTrue(rid > 0, rid)
     
     rid = save_resolver({"resolver": self.resolvername2,
                            "type": "passwdresolver",
                            "fileName": "/etc/secrets"})
     self.assertTrue(rid > 0, rid)
     
     (added, failed) = set_realm(self.realm1,
                                 [self.resolvername1,
                                  self.resolvername2])
     self.assertTrue(len(failed) == 0)
     self.assertTrue(len(added) == 2)
     
     # test the realms
     realms = get_realms()
     self.assertTrue(self.realm1 in realms, realms)
     self.assertTrue(realms.get("realm1").get("default"), realms)
     
     # try to create realm with invalid name
     self.assertRaises(Exception, set_realm, "#####")
     
     # update the resolver list:
     (added, failed) = set_realm(self.realm1,
                                 [self.resolvername1,
                                  "non exiting"])
     self.assertTrue(len(failed) == 1)
     self.assertTrue(len(added) == 1)
     
     self.assertTrue(realm_is_defined(self.realm1))
     self.assertTrue(realm_is_defined("non exist") is False)
Пример #2
0
def split_user(username):
    """
    Split the username of the form user@realm into the username and the realm
    splitting [email protected]@realm is also possible and will
    return (myemail@emailprovider, realm).

    If for a user@domain the "domain" does not exist as realm, the name is
    not split, since it might be the user@domain in the default realm
    
    We can also split realm\\user to (user, realm)
    
    :param username: the username to split
    :type username: string
    :return: username and realm
    :rtype: tuple
    """
    from privacyidea.lib.realm import realm_is_defined
    user = username.strip()
    realm = ""

    l = user.split('@')
    if len(l) >= 2:
        if realm_is_defined(l[-1]):
            # split the last only if the last part is really a realm
            (user, realm) = user.rsplit('@', 1)
    else:
        l = user.split('\\')
        if len(l) >= 2:
            (realm, user) = user.rsplit('\\', 1)

    return user, realm
Пример #3
0
def split_user(username):
    """
    Split the username of the form user@realm into the username and the realm
    splitting [email protected]@realm is also possible and will
    return ([email protected], realm).

    If for a user@domain the "domain" does not exist as realm, the name is
    not split, since it might be the user@domain in the default realm
    
    We can also split realm\\user to (user, realm)
    
    :param username: the username to split
    :type username: string
    :return: username and realm
    :rtype: tuple
    """
    from privacyidea.lib.realm import realm_is_defined
    user = username.strip()
    realm = ""

    l = user.split('@')
    if len(l) >= 2:
        if realm_is_defined(l[-1]):
            # split the last only if the last part is really a realm
            (user, realm) = user.rsplit('@', 1)
    else:
        l = user.split('\\')
        if len(l) >= 2:
            (realm, user) = user.rsplit('\\', 1)

    return user, realm
Пример #4
0
    def test_01_create_realm(self):
        rid = save_resolver({
            "resolver": self.resolvername1,
            "type": "passwdresolver",
            "fileName": "/etc/passwd"
        })
        self.assertTrue(rid > 0, rid)

        rid = save_resolver({
            "resolver": self.resolvername2,
            "type": "passwdresolver",
            "fileName": "/etc/secrets"
        })
        self.assertTrue(rid > 0, rid)

        (added, failed) = set_realm(self.realm1,
                                    [self.resolvername1, self.resolvername2])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 2)

        (added, failed) = set_realm(self.realm_dot,
                                    [self.resolvername1, self.resolvername2])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 2)

        # test the realms
        realms = get_realms()
        self.assertTrue(self.realm1 in realms, realms)
        self.assertTrue(realms.get("realm1").get("default"), realms)
        self.assertTrue(self.realm_dot in realms, realms)

        # delete dot realm
        delete_realm(self.realm_dot)

        # try to create realm with invalid name
        self.assertRaises(Exception, set_realm, "#####")

        # update the resolver list:
        (added, failed) = set_realm(self.realm1,
                                    [self.resolvername1, "non exiting"])
        self.assertTrue(len(failed) == 1)
        self.assertTrue(len(added) == 1)

        self.assertTrue(realm_is_defined(self.realm1))
        self.assertTrue(realm_is_defined("non exist") is False)
Пример #5
0
def get_auth_token():
    """
    This call verifies the credentials of the user and issues an
    authentication token, that is used for the later API calls. The
    authentication token has a validity, that is usually 1 hour.

    :jsonparam username: The username of the user who wants to authenticate to
        the API.
    :jsonparam password: The password/credentials of the user who wants to
        authenticate to the API.
    :jsonparam realm: The realm where the user will be searched.

    :return: A json response with an authentication token, that needs to be
        used in any further request.

    :status 200: in case of success
    :status 401: if authentication fails

    **Example Authentication Request**:

    .. sourcecode:: http

       POST /auth HTTP/1.1
       Host: example.com
       Accept: application/json

       username=admin
       password=topsecret

    **Example Authentication Response**:

    .. sourcecode:: http

       HTTP/1.0 200 OK
       Content-Length: 354
       Content-Type: application/json

       {
            "id": 1,
            "jsonrpc": "2.0",
            "result": {
                "status": true,
                "value": {
                    "token": "eyJhbGciOiJIUz....jdpn9kIjuGRnGejmbFbM"
                }
            },
            "version": "privacyIDEA unknown"
       }

    **Response for failed authentication**:

    .. sourcecode:: http

       HTTP/1.1 401 UNAUTHORIZED
       Content-Type: application/json
       Content-Length: 203

       {
          "id": 1,
          "jsonrpc": "2.0",
          "result": {
            "error": {
              "code": -401,
              "message": "missing Authorization header"
            },
            "status": false
          },
          "version": "privacyIDEA unknown",
          "config": {
            "logout_time": 30
          }
       }

    """
    validity = timedelta(hours=1)
    username = getParam(request.all_data, "username")
    password = getParam(request.all_data, "password")
    realm_param = getParam(request.all_data, "realm")
    details = {}
    realm = ''

    # the realm parameter has precedence! Check if it exists
    if realm_param and not realm_is_defined(realm_param):
        raise AuthError(_("Authentication failure. Unknown realm: {0!s}.".format(realm_param)),
                        id=ERROR.AUTHENTICATE_WRONG_CREDENTIALS)

    if username is None:
        raise AuthError(_("Authentication failure. Missing Username"),
                        id=ERROR.AUTHENTICATE_MISSING_USERNAME)

    loginname, realm = split_user(username)

    # overwrite the split realm if we have a realm parameter
    if realm_param:
        realm = realm_param

    # and finally check if there is a realm
    realm = realm or get_default_realm()

    # Failsafe to have the user attempt in the log, whatever happens
    # This can be overwritten later
    g.audit_object.log({"user": username,
                        "realm": realm})

    secret = current_app.secret_key
    superuser_realms = current_app.config.get("SUPERUSER_REALM", [])
    # This is the default role for the logged in user.
    # The role privileges may be risen to "admin"
    role = ROLE.USER
    # The way the user authenticated. This could be
    # "password" = The admin user DB or the user store
    # "pi" = The admin or the user is authenticated against privacyIDEA
    # "remote_user" = authenticated by webserver
    authtype = "password"
    # Verify the password
    admin_auth = False
    user_auth = False

    user_obj = User()

    # Check if the remote user is allowed
    if (request.remote_user == username) and is_remote_user_allowed(request):
        # Authenticated by the Web Server
        # Check if the username exists
        # 1. in local admins
        # 2. in a realm
        # 2a. is an admin realm
        authtype = "remote_user "
        if db_admin_exist(username):
            role = ROLE.ADMIN
            admin_auth = True
            g.audit_object.log({"success": True,
                                "user": "",
                                "administrator": username,
                                "info": "internal admin"})
        else:
            # check, if the user exists
            user_obj = User(loginname, realm)
            g.audit_object.log({"user": user_obj.login,
                                "realm": user_obj.realm,
                                "info": log_used_user(user_obj)})
            if user_obj.exist():
                user_auth = True
                if user_obj.realm in superuser_realms:
                    role = ROLE.ADMIN
                    admin_auth = True

    elif verify_db_admin(username, password):
        role = ROLE.ADMIN
        admin_auth = True
        # This admin is not in the default realm!
        realm = ""
        g.audit_object.log({"success": True,
                            "user": "",
                            "administrator": username,
                            "info": "internal admin"})

    else:
        # The user could not be identified against the admin database,
        # so we do the rest of the check
        options = {"g": g,
                   "clientip": g.client_ip}
        for key, value in request.all_data.items():
            if value and key not in ["g", "clientip"]:
                options[key] = value
        user_obj = User(loginname, realm)
        user_auth, role, details = check_webui_user(user_obj,
                                                    password,
                                                    options=options,
                                                    superuser_realms=
                                                    superuser_realms)
        details = details or {}
        if role == ROLE.ADMIN:
            g.audit_object.log({"user": "",
                                "administrator": user_obj.login,
                                "realm": user_obj.realm,
                                "resolver": user_obj.resolver,
                                "serial": details.get('serial', None),
                                "info": u"{0!s}|loginmode={1!s}".format(log_used_user(user_obj),
                                                                        details.get("loginmode"))})
        else:
            g.audit_object.log({"user": user_obj.login,
                                "realm": user_obj.realm,
                                "resolver": user_obj.resolver,
                                "serial": details.get('serial', None),
                                "info": u"{0!s}|loginmode={1!s}".format(log_used_user(user_obj),
                                        details.get("loginmode"))})

    if not admin_auth and not user_auth:
        raise AuthError(_("Authentication failure. Wrong credentials"),
                        id=ERROR.AUTHENTICATE_WRONG_CREDENTIALS,
                        details=details or {})
    else:
        g.audit_object.log({"success": True})
        request.User = user_obj

    # If the HSM is not ready, we need to create the nonce in another way!
    hsm = init_hsm()
    if hsm.is_ready:
        nonce = geturandom(hex=True)
        # Add the role to the JWT, so that we can verify it internally
        # Add the authtype to the JWT, so that we could use it for access
        # definitions
        rights = g.policy_object.ui_get_rights(role, realm, loginname,
                                               g.client_ip)
        menus = g.policy_object.ui_get_main_menus({"username": loginname,
                                                   "role": role,
                                                   "realm": realm},
                                                  g.client_ip)
    else:
        import os
        nonce = hexlify_and_unicode(os.urandom(20))
        rights = []
        menus = []

    # What is the log level?
    log_level = current_app.config.get("PI_LOGLEVEL", 30)

    token = jwt.encode({"username": loginname,
                        "realm": realm,
                        "nonce": nonce,
                        "role": role,
                        "authtype": authtype,
                        "exp": datetime.utcnow() + validity,
                        "rights": rights},
                       secret, algorithm='HS256').decode('utf8')

    # Add the role to the response, so that the WebUI can make decisions
    # based on this (only show selfservice, not the admin part)
    return send_result({"token": token,
                        "role": role,
                        "username": loginname,
                        "realm": realm,
                        "log_level": log_level,
                        "rights": rights,
                        "menus": menus},
                       details=details)