Permalink
Browse files

Merge branch 'master' into 1347/client_component_check

  • Loading branch information...
fredreichbier committed Jan 2, 2019
2 parents db1119c + 42a210c commit 11291d2415ff955d532d2deeafd7fed3db1ea647
@@ -0,0 +1,29 @@
"""Add column used_login to usercache
Revision ID: cb6d7b7bae63
Revises: a63df077051a
Create Date: 2018-12-18 11:59:27.486883
"""

# revision identifiers, used by Alembic.
revision = 'cb6d7b7bae63'
down_revision = 'a63df077051a'

from alembic import op
import sqlalchemy as sa


def upgrade():
try:
op.add_column('usercache', sa.Column('used_login', sa.Unicode(length=64), nullable=True))
op.create_index(op.f('ix_usercache_used_login'), 'usercache', ['used_login'], unique=False)
except Exception as exx:
print('Adding of column "used_login" in table usercache failed: {!r}'.format(exx))
print('This is expected behavior if this column already exists.')


def downgrade():
op.drop_index(op.f('ix_usercache_used_login'), table_name='usercache')
op.drop_column('usercache', 'used_login')

@@ -405,12 +405,14 @@ def encrypt_enckey(encfile):
The result can be piped to a new enckey file.
"""
# TODO we just print out a string here and assume, the user pipes it into a file.
# Maybe we should write the file here so we know what is in there
password = getpass()
password2 = getpass(prompt='Confirm: ')
if password != password2:
import sys
sys.exit('Error: passwords do not match.')
with open(encfile, "r") as f:
with open(encfile, "rb") as f:
enckey = f.read()
res = DefaultSecurityModule.password_encrypt(enckey, password)
print(res)
@@ -49,7 +49,7 @@
g)
from .lib.utils import (send_result, get_all_params,
verify_auth_token)
from ..lib.crypto import geturandom, init_hsm
from privacyidea.lib.crypto import geturandom, init_hsm, hexlify_and_unicode
from ..lib.error import AuthError, ERROR
from ..lib.auth import verify_db_admin, db_admin_exist
import jwt
@@ -59,7 +59,7 @@
from privacyidea.lib.audit import getAudit
from privacyidea.lib.auth import check_webui_user, ROLE
from privacyidea.lib.user import User
from privacyidea.lib.user import split_user
from privacyidea.lib.user import split_user, log_used_user
from privacyidea.lib.policy import PolicyClass
from privacyidea.lib.realm import get_default_realm
from privacyidea.api.lib.postpolicy import postpolicy, get_webui_settings
@@ -179,10 +179,18 @@ def get_auth_token():
password = getParam(request.all_data, "password")
realm = getParam(request.all_data, "realm")
details = {}

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

if realm:
username = username + "@" + realm

g.audit_object.log({"user": username})
# 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", [])
@@ -194,9 +202,6 @@ def get_auth_token():
# "pi" = The admin or the user is authenticated against privacyIDEA
# "remote_user" = authenticated by webserver
authtype = "password"
if username is None:
raise AuthError(_("Authentication failure. Missing Username"),
id=ERROR.AUTHENTICATE_MISSING_USERNAME)
# Verify the password
admin_auth = False
user_auth = False
@@ -222,6 +227,9 @@ def get_auth_token():
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:
@@ -254,7 +262,13 @@ def get_auth_token():
superuser_realms)
if role == ROLE.ADMIN:
g.audit_object.log({"user": "",
"administrator": username})
"administrator": user_obj.login,
"realm": user_obj.realm,
"info": log_used_user(user_obj)})
else:
g.audit_object.log({"user": user_obj.login,
"realm": user_obj.realm,
"info": log_used_user(user_obj)})

if not admin_auth and not user_auth:
raise AuthError(_("Authentication failure. Wrong credentials"),
@@ -278,8 +292,7 @@ def get_auth_token():
g.client_ip)
else:
import os
import binascii
nonce = binascii.hexlify(os.urandom(20))
nonce = hexlify_and_unicode(os.urandom(20))
rights = []
menus = []

@@ -293,7 +306,7 @@ def get_auth_token():
"authtype": authtype,
"exp": datetime.utcnow() + validity,
"rights": rights},
secret, algorithm='HS256')
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)
@@ -3,6 +3,8 @@
# http://www.privacyidea.org
# (c) cornelius kölbel, privacyidea.org
#
# 2018-12-20 Cornelius Kölbel <cornelius.koelbel@netknights.it>
# Cleaning up the before_after method
# 2015-12-18 Cornelius Kölbel <cornelius.koelbel@netknights.it>
# Move before and after from api/token.py and system.py
# to this central location
@@ -85,19 +87,6 @@ def teardown_request(exc):
log.debug(u"End handling of request {!r}".format(request.full_path))


# NOTE: This can be commented in to debug SQL pooling issues
#@token_blueprint.before_app_request
#def log_pools():
# from privacyidea.lib.pooling import get_registry
# from privacyidea.models import db
# engines = {"flask-sqlalchemy": db.engine}
# if hasattr(get_registry(), '_engines'):
# engines.update(get_registry()._engines)
# log.info("We have {} engines".format(len(engines)))
# for name, engine in engines.iteritems():
# log.info("engine {}: {}".format(name, engine.pool.status()))


@token_blueprint.before_request
@audit_blueprint.before_request
@user_blueprint.before_request
@@ -141,8 +130,17 @@ def before_request():
# from the Form data or from JSON in the request body.
update_config_object()
request.all_data = get_all_params(request.values, request.data)
if g.logged_in_user.get("role") == "user":
# A user is calling this API. First thing we do is restricting the user parameter.
# ...to restrict token view, audit view or token actions.
request.all_data["user"] = g.logged_in_user.get("username")
request.all_data["realm"] = g.logged_in_user.get("realm")

try:
request.User = get_user_from_param(request.all_data)
# overwrite or set the resolver parameter in case of a logged in user
if g.logged_in_user.get("role") == "user":
request.all_data["resolver"] = request.User.resolver
except AttributeError:
# Some endpoints do not need users OR e.g. the setPolicy endpoint
# takes a list as the userobject
@@ -166,23 +164,21 @@ def before_request():
tokentype = get_token_type(serial)
else:
tokentype = None
realm = getParam(request.all_data, "realm")
user_loginname = ""
resolver = ""
if "token_blueprint" in request.endpoint:
# In case of token endpoint we evaluate the user in the request.
# Note: In policy-endpoint "user" is part of the policy configuration
# and will cause an exception
user = get_user_from_param(request.all_data)
user_loginname = user.login
realm = user.realm or realm
resolver = user.resolver

if request.User:
audit_username = request.User.login
audit_realm = request.User.realm
audit_resolver = request.User.resolver
else:
audit_realm = getParam(request.all_data, "realm")
audit_resolver = getParam(request.all_data, "resolver")
audit_username = getParam(request.all_data, "user")

g.audit_object.log({"success": False,
"serial": serial,
"user": user_loginname,
"realm": realm,
"resolver": resolver,
"user": audit_username,
"realm": audit_realm,
"resolver": audit_resolver,
"token_type": tokentype,
"client": g.client_ip,
"client_user_agent": request.user_agent.browser,
@@ -191,22 +187,7 @@ def before_request():
"action_detail": "",
"info": ""})

if g.logged_in_user.get("role") == "user":
# A user is calling this API
# In case the token API is called by the user and not by the admin we
# need to restrict the token view.
CurrentUser = get_user_from_param({"user":
g.logged_in_user.get(
"username"),
"realm": g.logged_in_user.get(
"realm")})
request.all_data["user"] = CurrentUser.login
request.all_data["resolver"] = CurrentUser.resolver
request.all_data["realm"] = CurrentUser.realm
g.audit_object.log({"user": CurrentUser.login,
"resolver": CurrentUser.resolver,
"realm": CurrentUser.realm})
else:
if g.logged_in_user.get("role") == "admin":
# An administrator is calling this API
g.audit_object.log({"administrator": g.logged_in_user.get("username")})
# TODO: Check is there are realm specific admin policies, so that the
@@ -249,7 +249,7 @@ def init():
# log.debug("setting tokenrealm %s" % res['realms'])
# tokenrealm = res['realms']

user = get_user_from_param(param)
user = request.User
tokenobject = init_token(param,
user,
tokenrealms=tokenrealms)
@@ -353,7 +353,7 @@ def list_api():
:rtype: json
"""
param = request.all_data
user = get_user_from_param(param, optional)
user = request.User
serial = getParam(param, "serial", optional)
page = int(getParam(param, "page", optional, default=1))
tokentype = getParam(param, "type", optional)
@@ -444,7 +444,7 @@ def unassign_api():
:return: In case of success it returns the number of unassigned tokens in "value".
:rtype: JSON object
"""
user = get_user_from_param(request.all_data, optional)
user = request.User
serial = getParam(request.all_data, "serial", optional)
g.audit_object.log({"serial": serial})

@@ -474,7 +474,7 @@ def revoke_api(serial=None):
tokens in "value".
:rtype: JSON object
"""
user = get_user_from_param(request.all_data, optional)
user = request.User
if not serial:
serial = getParam(request.all_data, "serial", optional)
g.audit_object.log({"serial": serial})
@@ -502,7 +502,7 @@ def enable_api(serial=None):
tokens in "value".
:rtype: json object
"""
user = get_user_from_param(request.all_data, optional)
user = request.User
if not serial:
serial = getParam(request.all_data, "serial", optional)
g.audit_object.log({"serial": serial})
@@ -532,7 +532,7 @@ def disable_api(serial=None):
tokens in "value".
:rtype: json object
"""
user = get_user_from_param(request.all_data, optional)
user = request.User
if not serial:
serial = getParam(request.all_data, "serial", optional)
g.audit_object.log({"serial": serial})
@@ -559,7 +559,7 @@ def delete_api(serial):
"""
# If the API is called by a user, we pass the User Object to the function
g.audit_object.log({"serial": serial})
user = get_user_from_param(request.all_data)
user = request.User
res = remove_token(serial, user=user)
g.audit_object.log({"success": True})
return send_result(res)
@@ -580,7 +580,7 @@ def reset_api(serial=None):
:return: In case of success it returns "value"=True
:rtype: json object
"""
user = get_user_from_param(request.all_data, optional)
user = request.User
if not serial:
serial = getParam(request.all_data, "serial", optional)
g.audit_object.log({"serial": serial})
@@ -605,7 +605,7 @@ def resync_api(serial=None):
:return: In case of success it returns "value"=True
:rtype: json object
"""
user = get_user_from_param(request.all_data, optional)
user = request.User
if not serial:
serial = getParam(request.all_data, "serial", required)
g.audit_object.log({"serial": serial})
@@ -647,7 +647,7 @@ def setpin_api(serial=None):
userpin = getParam(request.all_data, "userpin")
sopin = getParam(request.all_data, "sopin")
otppin = getParam(request.all_data, "otppin")
user = get_user_from_param(request.all_data)
user = request.User
encrypt_pin = getParam(request.all_data, "encryptpin")

res = 0
@@ -703,7 +703,7 @@ def set_api(serial=None):
if not serial:
serial = getParam(request.all_data, "serial", required)
g.audit_object.log({"serial": serial})
user = get_user_from_param(request.all_data)
user = request.User

description = getParam(request.all_data, "description")
count_window = getParam(request.all_data, "count_window")
@@ -974,7 +974,7 @@ def lost_api(serial=None):
"""
# check if a user is given, that the user matches the token owner.
g.audit_object.log({"serial": serial})
userobj = get_user_from_param(request.all_data)
userobj = request.User
if userobj:
toks = get_tokens(serial=serial, user=userobj)
if not toks:
Oops, something went wrong.

0 comments on commit 11291d2

Please sign in to comment.