import CS ipa-4.9.13-8.module_el8+981+726db82c
This commit is contained in:
parent
7ee38917e2
commit
42c4963dff
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/freeipa-4.9.12.tar.gz
|
SOURCES/freeipa-4.9.13.tar.gz
|
||||||
|
@ -1 +1 @@
|
|||||||
ea6c8a209748b4ad8d07da556f705a366b3dd6c1 SOURCES/freeipa-4.9.12.tar.gz
|
da1bb0220894d8dc06afb98dcf087fea38076a79 SOURCES/freeipa-4.9.13.tar.gz
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
From 06b4c61b4484efe2093501caf21b03f1fc14093b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Date: Thu, 19 Oct 2023 12:47:03 +0200
|
||||||
|
Subject: [PATCH] group-add-member fails with an external member
|
||||||
|
|
||||||
|
The command ipa group-add-member --external aduser@addomain.test
|
||||||
|
fails with an internal error when used with samba 4.19.
|
||||||
|
|
||||||
|
The command internally calls samba.security.dom_sid(sid) which
|
||||||
|
used to raise a TypeError but now raises a ValueError
|
||||||
|
(commit 9abdd67 on https://github.com/samba-team/samba).
|
||||||
|
|
||||||
|
IPA source code needs to handle properly both exception types.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9466
|
||||||
|
|
||||||
|
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
---
|
||||||
|
ipaserver/dcerpc.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
|
||||||
|
index c1db2f9a499..ee0a229d1f0 100644
|
||||||
|
--- a/ipaserver/dcerpc.py
|
||||||
|
+++ b/ipaserver/dcerpc.py
|
||||||
|
@@ -303,7 +303,7 @@ def get_domain_by_sid(self, sid, exact_match=False):
|
||||||
|
# Parse sid string to see if it is really in a SID format
|
||||||
|
try:
|
||||||
|
test_sid = security.dom_sid(sid)
|
||||||
|
- except TypeError:
|
||||||
|
+ except (TypeError, ValueError):
|
||||||
|
raise errors.ValidationError(name='sid',
|
||||||
|
error=_('SID is not valid'))
|
||||||
|
|
||||||
|
From aa3397378acf1a03fc8bbe34b9fae33e84588b34 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Date: Fri, 20 Oct 2023 10:20:57 +0200
|
||||||
|
Subject: [PATCH] Handle samba changes in samba.security.dom_sid()
|
||||||
|
|
||||||
|
samba.security.dom_sid() in 4.19 now raises ValueError instead of
|
||||||
|
TypeError. Fix the expected exception.
|
||||||
|
|
||||||
|
Related: https://pagure.io/freeipa/issue/9466
|
||||||
|
|
||||||
|
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
---
|
||||||
|
ipaserver/dcerpc.py | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
|
||||||
|
index ee0a229d1f0..3e4c71d9976 100644
|
||||||
|
--- a/ipaserver/dcerpc.py
|
||||||
|
+++ b/ipaserver/dcerpc.py
|
||||||
|
@@ -97,7 +97,7 @@
|
||||||
|
def is_sid_valid(sid):
|
||||||
|
try:
|
||||||
|
security.dom_sid(sid)
|
||||||
|
- except TypeError:
|
||||||
|
+ except (TypeError, ValueError):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
@@ -457,7 +457,7 @@ def get_trusted_domain_object_sid(self, object_name,
|
||||||
|
try:
|
||||||
|
test_sid = security.dom_sid(sid)
|
||||||
|
return unicode(test_sid)
|
||||||
|
- except TypeError:
|
||||||
|
+ except (TypeError, ValueError):
|
||||||
|
raise errors.ValidationError(name=_('trusted domain object'),
|
||||||
|
error=_('Trusted domain did not '
|
||||||
|
'return a valid SID for '
|
@ -1,261 +0,0 @@
|
|||||||
From f42a106e84c1fd609350da2540289ce945a7ecbd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Thu, 11 May 2023 10:53:58 +0200
|
|
||||||
Subject: [PATCH] user or group name: explain the supported format
|
|
||||||
|
|
||||||
The commands ipa user-add or ipa group-add validate the
|
|
||||||
format of the user/group name and display the following
|
|
||||||
message when it does not conform to the expectations:
|
|
||||||
invalid 'login': may only include letters, numbers, _, -, . and $
|
|
||||||
|
|
||||||
The format is more complex, for instance '1234567' is an invalid
|
|
||||||
user name but the failure is inconsistent with the error message.
|
|
||||||
Modify the error message to point to ipa help user/group and add
|
|
||||||
more details in the help message.
|
|
||||||
|
|
||||||
Same change for idoverrideuser and idoverridegroup:
|
|
||||||
The user/group name must follow these rules:
|
|
||||||
- cannot contain only numbers
|
|
||||||
- must start with a letter, a number, _ or .
|
|
||||||
- may contain letters, numbers, _, ., or -
|
|
||||||
- may end with a letter, a number, _, ., - or $
|
|
||||||
|
|
||||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2150217
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
|
||||||
Reviewed-By: Alexander Bokovoy <abbra@users.noreply.github.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
---
|
|
||||||
ipalib/constants.py | 5 +++++
|
|
||||||
ipaserver/plugins/baseuser.py | 2 +-
|
|
||||||
ipaserver/plugins/group.py | 10 ++++++++--
|
|
||||||
ipaserver/plugins/idviews.py | 5 +++--
|
|
||||||
ipaserver/plugins/stageuser.py | 6 ++++++
|
|
||||||
ipaserver/plugins/user.py | 6 ++++++
|
|
||||||
ipatests/test_xmlrpc/test_group_plugin.py | 5 +++--
|
|
||||||
ipatests/test_xmlrpc/test_stageuser_plugin.py | 3 ++-
|
|
||||||
ipatests/test_xmlrpc/test_user_plugin.py | 7 ++++---
|
|
||||||
9 files changed, 38 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ipalib/constants.py b/ipalib/constants.py
|
|
||||||
index 4b759a573..104419bc2 100644
|
|
||||||
--- a/ipalib/constants.py
|
|
||||||
+++ b/ipalib/constants.py
|
|
||||||
@@ -319,6 +319,11 @@ MAXHOSTFQDNLEN = 253
|
|
||||||
PATTERN_GROUPUSER_NAME = (
|
|
||||||
'(?!^[0-9]+$)^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$'
|
|
||||||
)
|
|
||||||
+ERRMSG_GROUPUSER_NAME = (
|
|
||||||
+ 'may only include letters, numbers, _, -, . and $'
|
|
||||||
+ ', refer to \'ipa help {}\' for complete format '
|
|
||||||
+ 'description'
|
|
||||||
+)
|
|
||||||
|
|
||||||
# Kerberos Anonymous principal name
|
|
||||||
ANON_USER = 'WELLKNOWN/ANONYMOUS'
|
|
||||||
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
|
|
||||||
index 684a65242..bae6c54ff 100644
|
|
||||||
--- a/ipaserver/plugins/baseuser.py
|
|
||||||
+++ b/ipaserver/plugins/baseuser.py
|
|
||||||
@@ -211,7 +211,7 @@ class baseuser(LDAPObject):
|
|
||||||
takes_params = (
|
|
||||||
Str('uid',
|
|
||||||
pattern=constants.PATTERN_GROUPUSER_NAME,
|
|
||||||
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
|
|
||||||
+ pattern_errmsg=constants.ERRMSG_GROUPUSER_NAME.format('user'),
|
|
||||||
maxlength=255,
|
|
||||||
cli_name='login',
|
|
||||||
label=_('User login'),
|
|
||||||
diff --git a/ipaserver/plugins/group.py b/ipaserver/plugins/group.py
|
|
||||||
index afdad93c1..0333ed622 100644
|
|
||||||
--- a/ipaserver/plugins/group.py
|
|
||||||
+++ b/ipaserver/plugins/group.py
|
|
||||||
@@ -24,7 +24,7 @@ import logging
|
|
||||||
|
|
||||||
from ipalib import api
|
|
||||||
from ipalib import Int, Str, Flag
|
|
||||||
-from ipalib.constants import PATTERN_GROUPUSER_NAME
|
|
||||||
+from ipalib.constants import PATTERN_GROUPUSER_NAME, ERRMSG_GROUPUSER_NAME
|
|
||||||
from ipalib.plugable import Registry
|
|
||||||
from .baseldap import (
|
|
||||||
add_external_post_callback,
|
|
||||||
@@ -70,6 +70,12 @@ converted to non-POSIX groups.
|
|
||||||
|
|
||||||
Every group must have a description.
|
|
||||||
|
|
||||||
+The group name must follow these rules:
|
|
||||||
+- cannot contain only numbers
|
|
||||||
+- must start with a letter, a number, _ or .
|
|
||||||
+- may contain letters, numbers, _, ., or -
|
|
||||||
+- may end with a letter, a number, _, ., - or $
|
|
||||||
+
|
|
||||||
POSIX groups must have a Group ID (GID) number. Changing a GID is
|
|
||||||
supported but can have an impact on your file permissions. It is not necessary
|
|
||||||
to supply a GID when creating a group. IPA will generate one automatically
|
|
||||||
@@ -330,7 +336,7 @@ class group(LDAPObject):
|
|
||||||
takes_params = (
|
|
||||||
Str('cn',
|
|
||||||
pattern=PATTERN_GROUPUSER_NAME,
|
|
||||||
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
|
|
||||||
+ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('group'),
|
|
||||||
maxlength=255,
|
|
||||||
cli_name='group_name',
|
|
||||||
label=_('Group name'),
|
|
||||||
diff --git a/ipaserver/plugins/idviews.py b/ipaserver/plugins/idviews.py
|
|
||||||
index 4f4b3a2f7..6a16884cf 100644
|
|
||||||
--- a/ipaserver/plugins/idviews.py
|
|
||||||
+++ b/ipaserver/plugins/idviews.py
|
|
||||||
@@ -37,6 +37,7 @@ from ipalib.constants import (
|
|
||||||
IPA_ANCHOR_PREFIX,
|
|
||||||
SID_ANCHOR_PREFIX,
|
|
||||||
PATTERN_GROUPUSER_NAME,
|
|
||||||
+ ERRMSG_GROUPUSER_NAME
|
|
||||||
)
|
|
||||||
from ipalib.plugable import Registry
|
|
||||||
from ipalib.util import (normalize_sshpubkey, validate_sshpubkey,
|
|
||||||
@@ -1025,7 +1026,7 @@ class idoverrideuser(baseidoverride):
|
|
||||||
takes_params = baseidoverride.takes_params + (
|
|
||||||
Str('uid?',
|
|
||||||
pattern=PATTERN_GROUPUSER_NAME,
|
|
||||||
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
|
|
||||||
+ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('user'),
|
|
||||||
maxlength=255,
|
|
||||||
cli_name='login',
|
|
||||||
label=_('User login'),
|
|
||||||
@@ -1128,7 +1129,7 @@ class idoverridegroup(baseidoverride):
|
|
||||||
takes_params = baseidoverride.takes_params + (
|
|
||||||
Str('cn?',
|
|
||||||
pattern=PATTERN_GROUPUSER_NAME,
|
|
||||||
- pattern_errmsg='may only include letters, numbers, _, -, . and $',
|
|
||||||
+ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('group'),
|
|
||||||
maxlength=255,
|
|
||||||
cli_name='group_name',
|
|
||||||
label=_('Group name'),
|
|
||||||
diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py
|
|
||||||
index 760dff7ab..51438a83a 100644
|
|
||||||
--- a/ipaserver/plugins/stageuser.py
|
|
||||||
+++ b/ipaserver/plugins/stageuser.py
|
|
||||||
@@ -94,6 +94,12 @@ usernames that start with a digit or usernames that exceed a certain length
|
|
||||||
may cause problems for some UNIX systems.
|
|
||||||
Use 'ipa config-mod' to change the username format allowed by IPA tools.
|
|
||||||
|
|
||||||
+The user name must follow these rules:
|
|
||||||
+- cannot contain only numbers
|
|
||||||
+- must start with a letter, a number, _ or .
|
|
||||||
+- may contain letters, numbers, _, ., or -
|
|
||||||
+- may end with a letter, a number, _, ., - or $
|
|
||||||
+
|
|
||||||
|
|
||||||
EXAMPLES:
|
|
||||||
|
|
||||||
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
|
|
||||||
index fa8a67d3d..643b44f14 100644
|
|
||||||
--- a/ipaserver/plugins/user.py
|
|
||||||
+++ b/ipaserver/plugins/user.py
|
|
||||||
@@ -88,6 +88,12 @@ usernames that start with a digit or usernames that exceed a certain length
|
|
||||||
may cause problems for some UNIX systems.
|
|
||||||
Use 'ipa config-mod' to change the username format allowed by IPA tools.
|
|
||||||
|
|
||||||
+The user name must follow these rules:
|
|
||||||
+- cannot contain only numbers
|
|
||||||
+- must start with a letter, a number, _ or .
|
|
||||||
+- may contain letters, numbers, _, ., or -
|
|
||||||
+- may end with a letter, a number, _, ., - or $
|
|
||||||
+
|
|
||||||
Disabling a user account prevents that user from obtaining new Kerberos
|
|
||||||
credentials. It does not invalidate any credentials that have already
|
|
||||||
been issued.
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_group_plugin.py b/ipatests/test_xmlrpc/test_group_plugin.py
|
|
||||||
index f9a0e2cfe..27bc21fbc 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_group_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_group_plugin.py
|
|
||||||
@@ -25,6 +25,7 @@ Test the `ipaserver/plugins/group.py` module.
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from ipalib import errors
|
|
||||||
+from ipalib.constants import ERRMSG_GROUPUSER_NAME
|
|
||||||
from ipatests.test_xmlrpc import objectclasses
|
|
||||||
from ipatests.test_xmlrpc.xmlrpc_test import (
|
|
||||||
fuzzy_digits, fuzzy_uuid, fuzzy_set_ci,
|
|
||||||
@@ -169,7 +170,7 @@ class TestGroup(XMLRPC_test):
|
|
||||||
)
|
|
||||||
with raises_exact(errors.ValidationError(
|
|
||||||
name='group_name',
|
|
||||||
- error=u'may only include letters, numbers, _, -, . and $')):
|
|
||||||
+ error=ERRMSG_GROUPUSER_NAME.format('group'))):
|
|
||||||
command()
|
|
||||||
|
|
||||||
def test_create_with_name_starting_with_numeric(self):
|
|
||||||
@@ -188,7 +189,7 @@ class TestGroup(XMLRPC_test):
|
|
||||||
)
|
|
||||||
with raises_exact(errors.ValidationError(
|
|
||||||
name='group_name',
|
|
||||||
- error=u'may only include letters, numbers, _, -, . and $',
|
|
||||||
+ error=ERRMSG_GROUPUSER_NAME.format('group'),
|
|
||||||
)):
|
|
||||||
testgroup.create()
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py
|
|
||||||
index fd146876c..bd877aa94 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py
|
|
||||||
@@ -12,6 +12,7 @@ import six
|
|
||||||
|
|
||||||
from collections import OrderedDict
|
|
||||||
from ipalib import api, errors
|
|
||||||
+from ipalib.constants import ERRMSG_GROUPUSER_NAME
|
|
||||||
from ipaplatform.constants import constants as platformconstants
|
|
||||||
|
|
||||||
from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test, raises_exact
|
|
||||||
@@ -357,7 +358,7 @@ class TestCreateInvalidAttributes(XMLRPC_test):
|
|
||||||
command = invalid.make_create_command()
|
|
||||||
with raises_exact(errors.ValidationError(
|
|
||||||
name='login',
|
|
||||||
- error=u"may only include letters, numbers, _, -, . and $")):
|
|
||||||
+ error=ERRMSG_GROUPUSER_NAME.format('user'))):
|
|
||||||
command()
|
|
||||||
|
|
||||||
def test_create_long_uid(self):
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
index c156a8793..eadfe6a65 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
@@ -31,6 +31,7 @@ import ldap
|
|
||||||
import re
|
|
||||||
|
|
||||||
from ipalib import api, errors
|
|
||||||
+from ipalib.constants import ERRMSG_GROUPUSER_NAME
|
|
||||||
from ipaplatform.constants import constants as platformconstants
|
|
||||||
from ipapython import ipautil
|
|
||||||
from ipatests.test_xmlrpc import objectclasses
|
|
||||||
@@ -502,7 +503,7 @@ class TestUpdate(XMLRPC_test):
|
|
||||||
)
|
|
||||||
with raises_exact(errors.ValidationError(
|
|
||||||
name='rename',
|
|
||||||
- error=u'may only include letters, numbers, _, -, . and $')):
|
|
||||||
+ error=ERRMSG_GROUPUSER_NAME.format('user'))):
|
|
||||||
command()
|
|
||||||
|
|
||||||
def test_add_radius_username(self, user):
|
|
||||||
@@ -556,7 +557,7 @@ class TestCreate(XMLRPC_test):
|
|
||||||
command = testuser.make_create_command()
|
|
||||||
with raises_exact(errors.ValidationError(
|
|
||||||
name=u'login',
|
|
||||||
- error=u'may only include letters, numbers, _, -, . and $')):
|
|
||||||
+ error=ERRMSG_GROUPUSER_NAME.format('user'))):
|
|
||||||
command()
|
|
||||||
|
|
||||||
def test_create_with_too_long_login(self):
|
|
||||||
@@ -730,7 +731,7 @@ class TestCreate(XMLRPC_test):
|
|
||||||
)
|
|
||||||
with raises_exact(errors.ValidationError(
|
|
||||||
name=u'login',
|
|
||||||
- error=u'may only include letters, numbers, _, -, . and $',
|
|
||||||
+ error=ERRMSG_GROUPUSER_NAME.format('user'),
|
|
||||||
)):
|
|
||||||
testuser.create()
|
|
||||||
|
|
||||||
--
|
|
||||||
2.40.1
|
|
||||||
|
|
121
SOURCES/0002-Check-the-HTTP-Referer-header-on-all-requests.patch
Normal file
121
SOURCES/0002-Check-the-HTTP-Referer-header-on-all-requests.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
From ae006b436cfb4ccee5972cf1db0a309fcd80e669 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Fri, 6 Oct 2023 20:16:29 +0000
|
||||||
|
Subject: [PATCH] Check the HTTP Referer header on all requests
|
||||||
|
|
||||||
|
The referer was only checked in WSGIExecutioner classes:
|
||||||
|
|
||||||
|
- jsonserver
|
||||||
|
- KerberosWSGIExecutioner
|
||||||
|
- xmlserver
|
||||||
|
- jsonserver_kerb
|
||||||
|
|
||||||
|
This left /i18n_messages, /session/login_kerberos,
|
||||||
|
/session/login_x509, /session/login_password,
|
||||||
|
/session/change_password and /session/sync_token unprotected
|
||||||
|
against CSRF attacks.
|
||||||
|
|
||||||
|
CVE-2023-5455
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
---
|
||||||
|
ipaserver/rpcserver.py | 34 +++++++++++++++++++++++++++++++---
|
||||||
|
1 file changed, 31 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
|
||||||
|
index 4e8a08b66..3555014ca 100644
|
||||||
|
--- a/ipaserver/rpcserver.py
|
||||||
|
+++ b/ipaserver/rpcserver.py
|
||||||
|
@@ -156,6 +156,19 @@ _success_template = """<html>
|
||||||
|
</html>"""
|
||||||
|
|
||||||
|
class HTTP_Status(plugable.Plugin):
|
||||||
|
+ def check_referer(self, environ):
|
||||||
|
+ if "HTTP_REFERER" not in environ:
|
||||||
|
+ logger.error("Rejecting request with missing Referer")
|
||||||
|
+ return False
|
||||||
|
+ if (not environ["HTTP_REFERER"].startswith(
|
||||||
|
+ "https://%s/ipa" % self.api.env.host)
|
||||||
|
+ and not self.env.in_tree):
|
||||||
|
+ logger.error("Rejecting request with bad Referer %s",
|
||||||
|
+ environ["HTTP_REFERER"])
|
||||||
|
+ return False
|
||||||
|
+ logger.debug("Valid Referer %s", environ["HTTP_REFERER"])
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
def not_found(self, environ, start_response, url, message):
|
||||||
|
"""
|
||||||
|
Return a 404 Not Found error.
|
||||||
|
@@ -331,9 +344,6 @@ class wsgi_dispatch(Executioner, HTTP_Status):
|
||||||
|
self.__apps[key] = app
|
||||||
|
|
||||||
|
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-
|
||||||
|
class WSGIExecutioner(Executioner):
|
||||||
|
"""
|
||||||
|
Base class for execution backends with a WSGI application interface.
|
||||||
|
@@ -897,6 +907,9 @@ class jsonserver_session(jsonserver, KerberosSession):
|
||||||
|
|
||||||
|
logger.debug('WSGI jsonserver_session.__call__:')
|
||||||
|
|
||||||
|
+ if not self.check_referer(environ):
|
||||||
|
+ return self.bad_request(environ, start_response, 'denied')
|
||||||
|
+
|
||||||
|
# Redirect to login if no Kerberos credentials
|
||||||
|
ccache_name = self.get_environ_creds(environ)
|
||||||
|
if ccache_name is None:
|
||||||
|
@@ -949,6 +962,9 @@ class KerberosLogin(Backend, KerberosSession):
|
||||||
|
def __call__(self, environ, start_response):
|
||||||
|
logger.debug('WSGI KerberosLogin.__call__:')
|
||||||
|
|
||||||
|
+ if not self.check_referer(environ):
|
||||||
|
+ return self.bad_request(environ, start_response, 'denied')
|
||||||
|
+
|
||||||
|
# Redirect to login if no Kerberos credentials
|
||||||
|
user_ccache_name = self.get_environ_creds(environ)
|
||||||
|
if user_ccache_name is None:
|
||||||
|
@@ -967,6 +983,9 @@ class login_x509(KerberosLogin):
|
||||||
|
def __call__(self, environ, start_response):
|
||||||
|
logger.debug('WSGI login_x509.__call__:')
|
||||||
|
|
||||||
|
+ if not self.check_referer(environ):
|
||||||
|
+ return self.bad_request(environ, start_response, 'denied')
|
||||||
|
+
|
||||||
|
if 'KRB5CCNAME' not in environ:
|
||||||
|
return self.unauthorized(
|
||||||
|
environ, start_response, 'KRB5CCNAME not set',
|
||||||
|
@@ -1015,6 +1034,9 @@ class login_password(Backend, KerberosSession):
|
||||||
|
|
||||||
|
logger.debug('WSGI login_password.__call__:')
|
||||||
|
|
||||||
|
+ if not self.check_referer(environ):
|
||||||
|
+ return self.bad_request(environ, start_response, 'denied')
|
||||||
|
+
|
||||||
|
# Get the user and password parameters from the request
|
||||||
|
content_type = environ.get('CONTENT_TYPE', '').lower()
|
||||||
|
if not content_type.startswith('application/x-www-form-urlencoded'):
|
||||||
|
@@ -1147,6 +1169,9 @@ class change_password(Backend, HTTP_Status):
|
||||||
|
def __call__(self, environ, start_response):
|
||||||
|
logger.info('WSGI change_password.__call__:')
|
||||||
|
|
||||||
|
+ if not self.check_referer(environ):
|
||||||
|
+ return self.bad_request(environ, start_response, 'denied')
|
||||||
|
+
|
||||||
|
# Get the user and password parameters from the request
|
||||||
|
content_type = environ.get('CONTENT_TYPE', '').lower()
|
||||||
|
if not content_type.startswith('application/x-www-form-urlencoded'):
|
||||||
|
@@ -1364,6 +1389,9 @@ class xmlserver_session(xmlserver, KerberosSession):
|
||||||
|
|
||||||
|
logger.debug('WSGI xmlserver_session.__call__:')
|
||||||
|
|
||||||
|
+ if not self.check_referer(environ):
|
||||||
|
+ return self.bad_request(environ, start_response, 'denied')
|
||||||
|
+
|
||||||
|
ccache_name = environ.get('KRB5CCNAME')
|
||||||
|
|
||||||
|
# Redirect to /ipa/xml if no Kerberos credentials
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -1,242 +0,0 @@
|
|||||||
From 9fe30f21c987bdccf80ef5f6d645fdc59b393bdb Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Date: Jun 16 2023 19:09:52 +0000
|
|
||||||
Subject: Revert "Use the OpenSSL certificate parser in cert-find"
|
|
||||||
|
|
||||||
|
|
||||||
This reverts commit 191880bc9f77c3e8a3cecc82e6eea33ab5ad03e4.
|
|
||||||
|
|
||||||
The problem isn't with python-cryptography, it is with the
|
|
||||||
IPACertificate class which does way more work on a certificate
|
|
||||||
than is necessary in cert-find.
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/9331
|
|
||||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/freeipa.spec.in b/freeipa.spec.in
|
|
||||||
index f3380b4..2b18963 100755
|
|
||||||
--- a/freeipa.spec.in
|
|
||||||
+++ b/freeipa.spec.in
|
|
||||||
@@ -390,7 +390,6 @@ BuildRequires: python3-pylint
|
|
||||||
BuildRequires: python3-pytest-multihost
|
|
||||||
BuildRequires: python3-pytest-sourceorder
|
|
||||||
BuildRequires: python3-qrcode-core >= 5.0.0
|
|
||||||
-BuildRequires: python3-pyOpenSSL
|
|
||||||
BuildRequires: python3-samba
|
|
||||||
BuildRequires: python3-six
|
|
||||||
BuildRequires: python3-sss
|
|
||||||
@@ -862,7 +861,6 @@ Requires: python3-netifaces >= 0.10.4
|
|
||||||
Requires: python3-pyasn1 >= 0.3.2-2
|
|
||||||
Requires: python3-pyasn1-modules >= 0.3.2-2
|
|
||||||
Requires: python3-pyusb
|
|
||||||
-Requires: python3-pyOpenSSL
|
|
||||||
Requires: python3-qrcode-core >= 5.0.0
|
|
||||||
Requires: python3-requests
|
|
||||||
Requires: python3-six
|
|
||||||
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
|
|
||||||
index cec3d93..88c6b62 100644
|
|
||||||
--- a/ipaserver/plugins/cert.py
|
|
||||||
+++ b/ipaserver/plugins/cert.py
|
|
||||||
@@ -30,7 +30,6 @@ import cryptography.x509
|
|
||||||
from cryptography.hazmat.primitives import hashes, serialization
|
|
||||||
from dns import resolver, reversename
|
|
||||||
import six
|
|
||||||
-import sys
|
|
||||||
|
|
||||||
from ipalib import Command, Str, Int, Flag, StrEnum
|
|
||||||
from ipalib import api
|
|
||||||
@@ -1623,19 +1622,7 @@ class cert_find(Search, CertMethod):
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_cert_key(self, cert):
|
|
||||||
- # for cert-find with a certificate value
|
|
||||||
- if isinstance(cert, x509.IPACertificate):
|
|
||||||
- return (DN(cert.issuer), cert.serial_number)
|
|
||||||
-
|
|
||||||
- issuer = []
|
|
||||||
- for oid, value in cert.get_issuer().get_components():
|
|
||||||
- issuer.append(
|
|
||||||
- '{}={}'.format(oid.decode('utf-8'), value.decode('utf-8'))
|
|
||||||
- )
|
|
||||||
- issuer = ','.join(issuer)
|
|
||||||
- # Use this to flip from OpenSSL reverse to X500 ordering
|
|
||||||
- issuer = DN(issuer).x500_text()
|
|
||||||
- return (DN(issuer), cert.get_serial_number())
|
|
||||||
+ return (DN(cert.issuer), cert.serial_number)
|
|
||||||
|
|
||||||
def _cert_search(self, pkey_only, **options):
|
|
||||||
result = collections.OrderedDict()
|
|
||||||
@@ -1755,11 +1742,6 @@ class cert_find(Search, CertMethod):
|
|
||||||
return result, False, complete
|
|
||||||
|
|
||||||
def _ldap_search(self, all, pkey_only, no_members, **options):
|
|
||||||
- # defer import of the OpenSSL module to not affect the requests
|
|
||||||
- # module which will use pyopenssl if this is available.
|
|
||||||
- if sys.modules.get('OpenSSL.SSL', False) is None:
|
|
||||||
- del sys.modules["OpenSSL.SSL"]
|
|
||||||
- import OpenSSL.crypto
|
|
||||||
ldap = self.api.Backend.ldap2
|
|
||||||
|
|
||||||
filters = []
|
|
||||||
@@ -1818,14 +1800,12 @@ class cert_find(Search, CertMethod):
|
|
||||||
ca_enabled = getattr(context, 'ca_enabled')
|
|
||||||
for entry in entries:
|
|
||||||
for attr in ('usercertificate', 'usercertificate;binary'):
|
|
||||||
- for der in entry.raw.get(attr, []):
|
|
||||||
- cert = OpenSSL.crypto.load_certificate(
|
|
||||||
- OpenSSL.crypto.FILETYPE_ASN1, der)
|
|
||||||
+ for cert in entry.get(attr, []):
|
|
||||||
cert_key = self._get_cert_key(cert)
|
|
||||||
try:
|
|
||||||
obj = result[cert_key]
|
|
||||||
except KeyError:
|
|
||||||
- obj = {'serial_number': cert.get_serial_number()}
|
|
||||||
+ obj = {'serial_number': cert.serial_number}
|
|
||||||
if not pkey_only and (all or not ca_enabled):
|
|
||||||
# Retrieving certificate details is now deferred
|
|
||||||
# until after all certificates are collected.
|
|
||||||
|
|
||||||
From 3b1dbcdba2994bf57908f530913998e9ab888e4c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Date: Jun 16 2023 19:09:52 +0000
|
|
||||||
Subject: Revert "cert_find: fix call with --all"
|
|
||||||
|
|
||||||
|
|
||||||
This reverts commit 1f30cc65276a532e7288217f216b72a2b0628c8f.
|
|
||||||
|
|
||||||
The problem isn't with python-cryptography, it is with the
|
|
||||||
IPACertificate class which does way more work on a certificate
|
|
||||||
than is necessary in cert-find.
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/9331
|
|
||||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
|
|
||||||
index 88c6b62..ba37525 100644
|
|
||||||
--- a/ipaserver/plugins/cert.py
|
|
||||||
+++ b/ipaserver/plugins/cert.py
|
|
||||||
@@ -1812,7 +1812,6 @@ class cert_find(Search, CertMethod):
|
|
||||||
# For the case of CA-less we need to keep
|
|
||||||
# the certificate because getting it again later
|
|
||||||
# would require unnecessary LDAP searches.
|
|
||||||
- cert = cert.to_cryptography()
|
|
||||||
obj['certificate'] = (
|
|
||||||
base64.b64encode(
|
|
||||||
cert.public_bytes(x509.Encoding.DER))
|
|
||||||
|
|
||||||
From d00fd3398c32beb2c3e72f4878c87f9d2c0e833d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Date: Jun 16 2023 19:09:52 +0000
|
|
||||||
Subject: Use the python-cryptography parser directly in cert-find
|
|
||||||
|
|
||||||
|
|
||||||
cert-find is a rather complex beast because it not only
|
|
||||||
looks for certificates in the optional CA but within the
|
|
||||||
IPA LDAP database as well. It has a process to deduplicate
|
|
||||||
the certificates since any PKI issued certificates will
|
|
||||||
also be associated with an IPA record.
|
|
||||||
|
|
||||||
In order to obtain the data to deduplicate the certificates
|
|
||||||
the cert from LDAP must be parser for issuer and serial number.
|
|
||||||
ipaldap has automation to determine the datatype of an
|
|
||||||
attribute and will use the ipalib.x509 IPACertificate class to
|
|
||||||
decode a certificate automatically if you access
|
|
||||||
entry['usercertificate'].
|
|
||||||
|
|
||||||
The downside is that this is comparatively slow. Here is the
|
|
||||||
parse time in microseconds:
|
|
||||||
|
|
||||||
cryptography 0.0081
|
|
||||||
OpenSSL.crypto 0.2271
|
|
||||||
ipalib.x509 2.6814
|
|
||||||
|
|
||||||
Since only issuer and subject are required there is no need to
|
|
||||||
make the expensive IPACertificate call.
|
|
||||||
|
|
||||||
The IPACertificate parsing time is fine if you're parsing one
|
|
||||||
certificate but if the LDAP search returns a lot of certificates,
|
|
||||||
say in the thousands, then those microseconds add up quickly.
|
|
||||||
In testing it took ~17 seconds to parse 5k certificates (excluding
|
|
||||||
transmission overhead, etc).
|
|
||||||
|
|
||||||
cert-find when there are a lot of certificates has been
|
|
||||||
historically slow. It isn't related to the CA which returns
|
|
||||||
large sets (well, 5k anyway) in a second or two. It was the
|
|
||||||
LDAP comparision adding tens of seconds to the runtime.
|
|
||||||
|
|
||||||
When searching with the default sizelimit of 100 the time is
|
|
||||||
~10s without this patch. With it the time is 1.5s.
|
|
||||||
|
|
||||||
CLI times from before and after searching for all certs:
|
|
||||||
|
|
||||||
original:
|
|
||||||
|
|
||||||
-------------------------------
|
|
||||||
Number of entries returned 5038
|
|
||||||
-------------------------------
|
|
||||||
real 0m15.507s
|
|
||||||
user 0m0.828s
|
|
||||||
sys 0m0.241s
|
|
||||||
|
|
||||||
using cryptography:
|
|
||||||
|
|
||||||
real 0m4.037s
|
|
||||||
user 0m0.816s
|
|
||||||
sys 0m0.193s
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9331
|
|
||||||
|
|
||||||
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
|
|
||||||
index ba37525..619be83 100644
|
|
||||||
--- a/ipaserver/plugins/cert.py
|
|
||||||
+++ b/ipaserver/plugins/cert.py
|
|
||||||
@@ -1800,7 +1800,8 @@ class cert_find(Search, CertMethod):
|
|
||||||
ca_enabled = getattr(context, 'ca_enabled')
|
|
||||||
for entry in entries:
|
|
||||||
for attr in ('usercertificate', 'usercertificate;binary'):
|
|
||||||
- for cert in entry.get(attr, []):
|
|
||||||
+ for der in entry.raw.get(attr, []):
|
|
||||||
+ cert = cryptography.x509.load_der_x509_certificate(der)
|
|
||||||
cert_key = self._get_cert_key(cert)
|
|
||||||
try:
|
|
||||||
obj = result[cert_key]
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_cert_plugin.py b/ipatests/test_xmlrpc/test_cert_plugin.py
|
|
||||||
index 433cebc..583c67f 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_cert_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_cert_plugin.py
|
|
||||||
@@ -254,6 +254,16 @@ class test_cert(BaseCert):
|
|
||||||
result = _emails_are_valid(email_addrs, [])
|
|
||||||
assert not result
|
|
||||||
|
|
||||||
+ def test_00012_cert_find_all(self):
|
|
||||||
+ """
|
|
||||||
+ Test that cert-find --all returns successfully.
|
|
||||||
+
|
|
||||||
+ We don't know how many we'll get but there should be at least 10
|
|
||||||
+ by default.
|
|
||||||
+ """
|
|
||||||
+ res = api.Command['cert_find'](all=True)
|
|
||||||
+ assert 'count' in res and res['count'] >= 10
|
|
||||||
+
|
|
||||||
def test_99999_cleanup(self):
|
|
||||||
"""
|
|
||||||
Clean up cert test data
|
|
||||||
@@ -283,7 +293,7 @@ class test_cert_find(XMLRPC_test):
|
|
||||||
|
|
||||||
short = api.env.host.split('.', maxsplit=1)[0]
|
|
||||||
|
|
||||||
- def test_0001_find_all(self):
|
|
||||||
+ def test_0001_find_all_certs(self):
|
|
||||||
"""
|
|
||||||
Search for all certificates.
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,359 @@
|
|||||||
|
From f1f8b16def3e809f5773bb8aa40aefb21699347b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Thu, 12 Oct 2023 20:34:01 +0000
|
||||||
|
Subject: [PATCH] Integration tests for verifying Referer header in the UI
|
||||||
|
|
||||||
|
Validate that the change_password and login_password endpoints
|
||||||
|
verify the HTTP Referer header. There is some overlap in the
|
||||||
|
tests: belt and suspenders.
|
||||||
|
|
||||||
|
All endpoints except session/login_x509 are covered, sometimes
|
||||||
|
having to rely on expected bad results (see the i18n endpoint).
|
||||||
|
|
||||||
|
session/login_x509 is not tested yet as it requires significant
|
||||||
|
additional setup in order to associate a user certificate with
|
||||||
|
a user entry, etc.
|
||||||
|
|
||||||
|
This can be manually verified by modifying /etc/httpd/conf.d/ipa.conf
|
||||||
|
and adding:
|
||||||
|
|
||||||
|
Satisfy Any
|
||||||
|
Require all granted
|
||||||
|
|
||||||
|
Then comment out Auth and SSLVerify, etc. and restart httpd.
|
||||||
|
|
||||||
|
With a valid Referer will fail with a 401 and log that there is no
|
||||||
|
KRB5CCNAME. This comes after the referer check.
|
||||||
|
|
||||||
|
With an invalid Referer it will fail with a 400 Bad Request as
|
||||||
|
expected.
|
||||||
|
|
||||||
|
CVE-2023-5455
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
---
|
||||||
|
ipatests/test_ipaserver/httptest.py | 7 +-
|
||||||
|
ipatests/test_ipaserver/test_changepw.py | 12 +-
|
||||||
|
.../test_ipaserver/test_login_password.py | 88 ++++++++++++
|
||||||
|
ipatests/test_ipaserver/test_referer.py | 136 ++++++++++++++++++
|
||||||
|
ipatests/util.py | 4 +-
|
||||||
|
5 files changed, 242 insertions(+), 5 deletions(-)
|
||||||
|
create mode 100644 ipatests/test_ipaserver/test_login_password.py
|
||||||
|
create mode 100644 ipatests/test_ipaserver/test_referer.py
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_ipaserver/httptest.py b/ipatests/test_ipaserver/httptest.py
|
||||||
|
index 6cd034a71..8924798fc 100644
|
||||||
|
--- a/ipatests/test_ipaserver/httptest.py
|
||||||
|
+++ b/ipatests/test_ipaserver/httptest.py
|
||||||
|
@@ -36,7 +36,7 @@ class Unauthorized_HTTP_test:
|
||||||
|
content_type = 'application/x-www-form-urlencoded'
|
||||||
|
accept_language = 'en-us'
|
||||||
|
|
||||||
|
- def send_request(self, method='POST', params=None):
|
||||||
|
+ def send_request(self, method='POST', params=None, host=None):
|
||||||
|
"""
|
||||||
|
Send a request to HTTP server
|
||||||
|
|
||||||
|
@@ -45,7 +45,10 @@ class Unauthorized_HTTP_test:
|
||||||
|
if params is not None:
|
||||||
|
if self.content_type == 'application/x-www-form-urlencoded':
|
||||||
|
params = urllib.parse.urlencode(params, True)
|
||||||
|
- url = 'https://' + self.host + self.app_uri
|
||||||
|
+ if host:
|
||||||
|
+ url = 'https://' + host + self.app_uri
|
||||||
|
+ else:
|
||||||
|
+ url = 'https://' + self.host + self.app_uri
|
||||||
|
|
||||||
|
headers = {'Content-Type': self.content_type,
|
||||||
|
'Accept-Language': self.accept_language,
|
||||||
|
diff --git a/ipatests/test_ipaserver/test_changepw.py b/ipatests/test_ipaserver/test_changepw.py
|
||||||
|
index c3a47ab26..df38ddb3d 100644
|
||||||
|
--- a/ipatests/test_ipaserver/test_changepw.py
|
||||||
|
+++ b/ipatests/test_ipaserver/test_changepw.py
|
||||||
|
@@ -53,10 +53,11 @@ class test_changepw(XMLRPC_test, Unauthorized_HTTP_test):
|
||||||
|
|
||||||
|
request.addfinalizer(fin)
|
||||||
|
|
||||||
|
- def _changepw(self, user, old_password, new_password):
|
||||||
|
+ def _changepw(self, user, old_password, new_password, host=None):
|
||||||
|
return self.send_request(params={'user': str(user),
|
||||||
|
'old_password' : str(old_password),
|
||||||
|
'new_password' : str(new_password)},
|
||||||
|
+ host=host
|
||||||
|
)
|
||||||
|
|
||||||
|
def _checkpw(self, user, password):
|
||||||
|
@@ -89,6 +90,15 @@ class test_changepw(XMLRPC_test, Unauthorized_HTTP_test):
|
||||||
|
# make sure that password is NOT changed
|
||||||
|
self._checkpw(testuser, old_password)
|
||||||
|
|
||||||
|
+ def test_invalid_referer(self):
|
||||||
|
+ response = self._changepw(testuser, old_password, new_password,
|
||||||
|
+ 'attacker.test')
|
||||||
|
+
|
||||||
|
+ assert_equal(response.status, 400)
|
||||||
|
+
|
||||||
|
+ # make sure that password is NOT changed
|
||||||
|
+ self._checkpw(testuser, old_password)
|
||||||
|
+
|
||||||
|
def test_pwpolicy_error(self):
|
||||||
|
response = self._changepw(testuser, old_password, '1')
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_ipaserver/test_login_password.py b/ipatests/test_ipaserver/test_login_password.py
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..9425cb797
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/ipatests/test_ipaserver/test_login_password.py
|
||||||
|
@@ -0,0 +1,88 @@
|
||||||
|
+# Copyright (C) 2023 Red Hat
|
||||||
|
+# see file 'COPYING' for use and warranty information
|
||||||
|
+#
|
||||||
|
+# This program is free software; you can redistribute it and/or modify
|
||||||
|
+# it under the terms of the GNU General Public License as published by
|
||||||
|
+# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+# (at your option) any later version.
|
||||||
|
+#
|
||||||
|
+# This program is distributed in the hope that it will be useful,
|
||||||
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+# GNU General Public License for more details.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU General Public License
|
||||||
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+import os
|
||||||
|
+import pytest
|
||||||
|
+import uuid
|
||||||
|
+
|
||||||
|
+from ipatests.test_ipaserver.httptest import Unauthorized_HTTP_test
|
||||||
|
+from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
|
||||||
|
+from ipatests.util import assert_equal
|
||||||
|
+from ipalib import api, errors
|
||||||
|
+from ipapython.ipautil import run
|
||||||
|
+
|
||||||
|
+testuser = u'tuser'
|
||||||
|
+password = u'password'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.tier1
|
||||||
|
+class test_login_password(XMLRPC_test, Unauthorized_HTTP_test):
|
||||||
|
+ app_uri = '/ipa/session/login_password'
|
||||||
|
+
|
||||||
|
+ @pytest.fixture(autouse=True)
|
||||||
|
+ def login_setup(self, request):
|
||||||
|
+ ccache = os.path.join('/tmp', str(uuid.uuid4()))
|
||||||
|
+ try:
|
||||||
|
+ api.Command['user_add'](uid=testuser, givenname=u'Test', sn=u'User')
|
||||||
|
+ api.Command['passwd'](testuser, password=password)
|
||||||
|
+ run(['kinit', testuser], stdin='{0}\n{0}\n{0}\n'.format(password),
|
||||||
|
+ env={"KRB5CCNAME": ccache})
|
||||||
|
+ except errors.ExecutionError as e:
|
||||||
|
+ pytest.skip(
|
||||||
|
+ 'Cannot set up test user: %s' % e
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ def fin():
|
||||||
|
+ try:
|
||||||
|
+ api.Command['user_del']([testuser])
|
||||||
|
+ except errors.NotFound:
|
||||||
|
+ pass
|
||||||
|
+ os.unlink(ccache)
|
||||||
|
+
|
||||||
|
+ request.addfinalizer(fin)
|
||||||
|
+
|
||||||
|
+ def _login(self, user, password, host=None):
|
||||||
|
+ return self.send_request(params={'user': str(user),
|
||||||
|
+ 'password' : str(password)},
|
||||||
|
+ host=host)
|
||||||
|
+
|
||||||
|
+ def test_bad_options(self):
|
||||||
|
+ for params in (
|
||||||
|
+ None, # no params
|
||||||
|
+ {"user": "foo"}, # missing options
|
||||||
|
+ {"user": "foo", "password": ""}, # empty option
|
||||||
|
+ ):
|
||||||
|
+ response = self.send_request(params=params)
|
||||||
|
+ assert_equal(response.status, 400)
|
||||||
|
+ assert_equal(response.reason, 'Bad Request')
|
||||||
|
+
|
||||||
|
+ def test_invalid_auth(self):
|
||||||
|
+ response = self._login(testuser, 'wrongpassword')
|
||||||
|
+
|
||||||
|
+ assert_equal(response.status, 401)
|
||||||
|
+ assert_equal(response.getheader('X-IPA-Rejection-Reason'),
|
||||||
|
+ 'invalid-password')
|
||||||
|
+
|
||||||
|
+ def test_invalid_referer(self):
|
||||||
|
+ response = self._login(testuser, password, 'attacker.test')
|
||||||
|
+
|
||||||
|
+ assert_equal(response.status, 400)
|
||||||
|
+
|
||||||
|
+ def test_success(self):
|
||||||
|
+ response = self._login(testuser, password)
|
||||||
|
+
|
||||||
|
+ assert_equal(response.status, 200)
|
||||||
|
+ assert response.getheader('X-IPA-Rejection-Reason') is None
|
||||||
|
diff --git a/ipatests/test_ipaserver/test_referer.py b/ipatests/test_ipaserver/test_referer.py
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..4eade8bba
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/ipatests/test_ipaserver/test_referer.py
|
||||||
|
@@ -0,0 +1,136 @@
|
||||||
|
+# Copyright (C) 2023 Red Hat
|
||||||
|
+# see file 'COPYING' for use and warranty information
|
||||||
|
+#
|
||||||
|
+# This program is free software; you can redistribute it and/or modify
|
||||||
|
+# it under the terms of the GNU General Public License as published by
|
||||||
|
+# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+# (at your option) any later version.
|
||||||
|
+#
|
||||||
|
+# This program is distributed in the hope that it will be useful,
|
||||||
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+# GNU General Public License for more details.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU General Public License
|
||||||
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+import os
|
||||||
|
+import pytest
|
||||||
|
+import uuid
|
||||||
|
+
|
||||||
|
+from ipatests.test_ipaserver.httptest import Unauthorized_HTTP_test
|
||||||
|
+from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
|
||||||
|
+from ipatests.util import assert_equal
|
||||||
|
+from ipalib import api, errors
|
||||||
|
+from ipapython.ipautil import run
|
||||||
|
+
|
||||||
|
+testuser = u'tuser'
|
||||||
|
+password = u'password'
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.tier1
|
||||||
|
+class test_referer(XMLRPC_test, Unauthorized_HTTP_test):
|
||||||
|
+
|
||||||
|
+ @pytest.fixture(autouse=True)
|
||||||
|
+ def login_setup(self, request):
|
||||||
|
+ ccache = os.path.join('/tmp', str(uuid.uuid4()))
|
||||||
|
+ tokenid = None
|
||||||
|
+ try:
|
||||||
|
+ api.Command['user_add'](uid=testuser, givenname=u'Test', sn=u'User')
|
||||||
|
+ api.Command['passwd'](testuser, password=password)
|
||||||
|
+ run(['kinit', testuser], stdin='{0}\n{0}\n{0}\n'.format(password),
|
||||||
|
+ env={"KRB5CCNAME": ccache})
|
||||||
|
+ result = api.Command["otptoken_add"](
|
||||||
|
+ type='HOTP', description='testotp',
|
||||||
|
+ ipatokenotpalgorithm='sha512', ipatokenowner=testuser,
|
||||||
|
+ ipatokenotpdigits='6')
|
||||||
|
+ tokenid = result['result']['ipatokenuniqueid'][0]
|
||||||
|
+ except errors.ExecutionError as e:
|
||||||
|
+ pytest.skip(
|
||||||
|
+ 'Cannot set up test user: %s' % e
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ def fin():
|
||||||
|
+ try:
|
||||||
|
+ api.Command['user_del']([testuser])
|
||||||
|
+ api.Command['otptoken_del']([tokenid])
|
||||||
|
+ except errors.NotFound:
|
||||||
|
+ pass
|
||||||
|
+ os.unlink(ccache)
|
||||||
|
+
|
||||||
|
+ request.addfinalizer(fin)
|
||||||
|
+
|
||||||
|
+ def _request(self, params={}, host=None):
|
||||||
|
+ # implicit is that self.app_uri is set to the appropriate value
|
||||||
|
+ return self.send_request(params=params, host=host)
|
||||||
|
+
|
||||||
|
+ def test_login_password_valid(self):
|
||||||
|
+ """Valid authentication of a user"""
|
||||||
|
+ self.app_uri = "/ipa/session/login_password"
|
||||||
|
+ response = self._request(
|
||||||
|
+ params={'user': 'tuser', 'password': password})
|
||||||
|
+ assert_equal(response.status, 200, self.app_uri)
|
||||||
|
+
|
||||||
|
+ def test_change_password_valid(self):
|
||||||
|
+ """This actually changes the user password"""
|
||||||
|
+ self.app_uri = "/ipa/session/change_password"
|
||||||
|
+ response = self._request(
|
||||||
|
+ params={'user': 'tuser',
|
||||||
|
+ 'old_password': password,
|
||||||
|
+ 'new_password': 'new_password'}
|
||||||
|
+ )
|
||||||
|
+ assert_equal(response.status, 200, self.app_uri)
|
||||||
|
+
|
||||||
|
+ def test_sync_token_valid(self):
|
||||||
|
+ """We aren't testing that sync works, just that we can get there"""
|
||||||
|
+ self.app_uri = "/ipa/session/sync_token"
|
||||||
|
+ response = self._request(
|
||||||
|
+ params={'user': 'tuser',
|
||||||
|
+ 'first_code': '1234',
|
||||||
|
+ 'second_code': '5678',
|
||||||
|
+ 'password': 'password'})
|
||||||
|
+ assert_equal(response.status, 200, self.app_uri)
|
||||||
|
+
|
||||||
|
+ def test_i18n_messages_valid(self):
|
||||||
|
+ # i18n_messages requires a valid JSON request and we send
|
||||||
|
+ # nothing. If we get a 500 error then it got past the
|
||||||
|
+ # referer check.
|
||||||
|
+ self.app_uri = "/ipa/i18n_messages"
|
||||||
|
+ response = self._request()
|
||||||
|
+ assert_equal(response.status, 500, self.app_uri)
|
||||||
|
+
|
||||||
|
+ # /ipa/session/login_x509 is not tested yet as it requires
|
||||||
|
+ # significant additional setup.
|
||||||
|
+ # This can be manually verified by adding
|
||||||
|
+ # Satisfy Any and Require all granted to the configuration
|
||||||
|
+ # section and comment out all Auth directives. The request
|
||||||
|
+ # will fail and log that there is no KRB5CCNAME which comes
|
||||||
|
+ # after the referer check.
|
||||||
|
+
|
||||||
|
+ def test_endpoints_auth_required(self):
|
||||||
|
+ """Test endpoints that require pre-authorization which will
|
||||||
|
+ fail before we even get to the Referer check
|
||||||
|
+ """
|
||||||
|
+ self.endpoints = {
|
||||||
|
+ "/ipa/xml",
|
||||||
|
+ "/ipa/session/login_kerberos",
|
||||||
|
+ "/ipa/session/json",
|
||||||
|
+ "/ipa/session/xml"
|
||||||
|
+ }
|
||||||
|
+ for self.app_uri in self.endpoints:
|
||||||
|
+ response = self._request(host="attacker.test")
|
||||||
|
+
|
||||||
|
+ # referer is checked after auth
|
||||||
|
+ assert_equal(response.status, 401, self.app_uri)
|
||||||
|
+
|
||||||
|
+ def notest_endpoints_invalid(self):
|
||||||
|
+ """Pass in a bad Referer, expect a 400 Bad Request"""
|
||||||
|
+ self.endpoints = {
|
||||||
|
+ "/ipa/session/login_password",
|
||||||
|
+ "/ipa/session/change_password",
|
||||||
|
+ "/ipa/session/sync_token",
|
||||||
|
+ }
|
||||||
|
+ for self.app_uri in self.endpoints:
|
||||||
|
+ response = self._request(host="attacker.test")
|
||||||
|
+
|
||||||
|
+ assert_equal(response.status, 400, self.app_uri)
|
||||||
|
diff --git a/ipatests/util.py b/ipatests/util.py
|
||||||
|
index 5c0152b90..c69d98790 100644
|
||||||
|
--- a/ipatests/util.py
|
||||||
|
+++ b/ipatests/util.py
|
||||||
|
@@ -163,12 +163,12 @@ class ExceptionNotRaised(Exception):
|
||||||
|
return self.msg % self.expected.__name__
|
||||||
|
|
||||||
|
|
||||||
|
-def assert_equal(val1, val2):
|
||||||
|
+def assert_equal(val1, val2, msg=''):
|
||||||
|
"""
|
||||||
|
Assert ``val1`` and ``val2`` are the same type and of equal value.
|
||||||
|
"""
|
||||||
|
assert type(val1) is type(val2), '%r != %r' % (val1, val2)
|
||||||
|
- assert val1 == val2, '%r != %r' % (val1, val2)
|
||||||
|
+ assert val1 == val2, '%r != %r %r' % (val1, val2, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assert_not_equal(val1, val2):
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -1,87 +0,0 @@
|
|||||||
From 86c1426b2d376a390e87b074d3e10d85fa124abf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Jun 21 2023 17:02:48 +0000
|
|
||||||
Subject: Upgrade: add PKI drop-in file if missing
|
|
||||||
|
|
||||||
|
|
||||||
During the installation of IPA server, the installer adds a drop-in
|
|
||||||
file in /etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf
|
|
||||||
that ensures the CA is reachable before the start command returns.
|
|
||||||
If the file is missing (for instance because the server was installed
|
|
||||||
with an old version before this drop-in was created), the upgrade
|
|
||||||
should add the file.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9381
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
|
|
||||||
index dd22ac2..e4dc7ae 100644
|
|
||||||
--- a/ipaserver/install/server/upgrade.py
|
|
||||||
+++ b/ipaserver/install/server/upgrade.py
|
|
||||||
@@ -1737,6 +1737,10 @@ def upgrade_configuration():
|
|
||||||
os.path.join(paths.USR_SHARE_IPA_DIR,
|
|
||||||
"ipa-kdc-proxy.conf.template"))
|
|
||||||
if ca.is_configured():
|
|
||||||
+ # Ensure that the drop-in file is present
|
|
||||||
+ if not os.path.isfile(paths.SYSTEMD_PKI_TOMCAT_IPA_CONF):
|
|
||||||
+ ca.add_ipa_wait()
|
|
||||||
+
|
|
||||||
# Handle upgrade of AJP connector configuration
|
|
||||||
rewrite = ca.secure_ajp_connector()
|
|
||||||
if ca.ajp_secret:
|
|
||||||
|
|
||||||
From 356ec5cbfe0876686239f938bdf54892dc30571e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Jun 21 2023 17:02:48 +0000
|
|
||||||
Subject: Integration test: add a test for upgrade and PKI drop-in file
|
|
||||||
|
|
||||||
|
|
||||||
Add an upgrade test with the following scenario:
|
|
||||||
- remove PKI drop-in file (to simulate an upgrade from an old
|
|
||||||
version)
|
|
||||||
- remove caECServerCertWithSCT profile from LDAP
|
|
||||||
- launch the ipa-server-upgrade command
|
|
||||||
- check that the upgrade added the file
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/9381
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py
|
|
||||||
index 9203503..182e3b5 100644
|
|
||||||
--- a/ipatests/test_integration/test_upgrade.py
|
|
||||||
+++ b/ipatests/test_integration/test_upgrade.py
|
|
||||||
@@ -455,3 +455,25 @@ class TestUpgrade(IntegrationTest):
|
|
||||||
assert 'tXTRecord' in location_krb_rec
|
|
||||||
assert len(location_krb_rec['tXTRecord']) == 1
|
|
||||||
assert location_krb_rec['tXTRecord'][0] == f'"{realm}"'
|
|
||||||
+
|
|
||||||
+ def test_pki_dropin_file(self):
|
|
||||||
+ """Test that upgrade adds the drop-in file if missing
|
|
||||||
+
|
|
||||||
+ Test for ticket 9381
|
|
||||||
+ Simulate an update from a version that didn't provide
|
|
||||||
+ /etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf,
|
|
||||||
+ remove one of the certificate profiles from LDAP and check that upgrade
|
|
||||||
+ completes successfully and adds the missing file.
|
|
||||||
+ When the drop-in file is missing, the upgrade tries to login to
|
|
||||||
+ PKI in order to migrate the profile and fails because PKI failed to
|
|
||||||
+ start.
|
|
||||||
+ """
|
|
||||||
+ self.master.run_command(["rm", "-f", paths.SYSTEMD_PKI_TOMCAT_IPA_CONF])
|
|
||||||
+ ldif = textwrap.dedent("""
|
|
||||||
+ dn: cn=caECServerCertWithSCT,ou=certificateProfiles,ou=ca,o=ipaca
|
|
||||||
+ changetype: delete
|
|
||||||
+ """)
|
|
||||||
+ tasks.ldapmodify_dm(self.master, ldif)
|
|
||||||
+ self.master.run_command(['ipa-server-upgrade'])
|
|
||||||
+ assert self.master.transport.file_exists(
|
|
||||||
+ paths.SYSTEMD_PKI_TOMCAT_IPA_CONF)
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
|||||||
From d29b47512a39ada02fb371521994576cd9815a6c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Mon, 19 Jun 2023 10:36:29 +0200
|
|
||||||
Subject: [PATCH] Upgrade: fix replica agreement
|
|
||||||
|
|
||||||
The upgrade checks the replication agreements to ensure that
|
|
||||||
some attributes are excluded from replication. The agreements
|
|
||||||
are stored in entries like
|
|
||||||
cn=serverToreplica,cn=replica,cn=_suffix_,cn=mapping tree,cn=config
|
|
||||||
but those entries are managed by the replication topology plugin
|
|
||||||
and should not be updated directly. The consequence is that the update
|
|
||||||
of the attributes fails and ipa-server-update prints an error message:
|
|
||||||
|
|
||||||
Error caught updating nsDS5ReplicatedAttributeList: Server is unwilling
|
|
||||||
to perform: Entry and attributes are managed by topology plugin.No direct
|
|
||||||
modifications allowed.
|
|
||||||
Error caught updating nsDS5ReplicatedAttributeListTotal: Server is
|
|
||||||
unwilling to perform: Entry and attributes are managed by topology
|
|
||||||
plugin.No direct modifications allowed.
|
|
||||||
|
|
||||||
The upgrade continues but the replication is not excluding
|
|
||||||
passwordgraceusertime.
|
|
||||||
|
|
||||||
Instead of editing the agreements, perform the modifications on
|
|
||||||
the topology segments.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9385
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
---
|
|
||||||
.../install/plugins/fix_replica_agreements.py | 80 +++++++++----------
|
|
||||||
1 file changed, 38 insertions(+), 42 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ipaserver/install/plugins/fix_replica_agreements.py b/ipaserver/install/plugins/fix_replica_agreements.py
|
|
||||||
index c0cdd3eb1..d963753d0 100644
|
|
||||||
--- a/ipaserver/install/plugins/fix_replica_agreements.py
|
|
||||||
+++ b/ipaserver/install/plugins/fix_replica_agreements.py
|
|
||||||
@@ -22,6 +22,7 @@ import logging
|
|
||||||
from ipaserver.install import replication
|
|
||||||
from ipalib import Registry
|
|
||||||
from ipalib import Updater
|
|
||||||
+from ipalib import errors
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
@@ -41,35 +42,42 @@ class update_replica_attribute_lists(Updater):
|
|
||||||
def execute(self, **options):
|
|
||||||
# We need an LDAPClient connection to the backend
|
|
||||||
logger.debug("Start replication agreement exclude list update task")
|
|
||||||
- conn = self.api.Backend.ldap2
|
|
||||||
|
|
||||||
- repl = replication.ReplicationManager(self.api.env.realm,
|
|
||||||
- self.api.env.host,
|
|
||||||
- None, conn=conn)
|
|
||||||
-
|
|
||||||
- # We need to update only IPA replica agreements, not winsync
|
|
||||||
- ipa_replicas = repl.find_ipa_replication_agreements()
|
|
||||||
-
|
|
||||||
- logger.debug("Found %d agreement(s)", len(ipa_replicas))
|
|
||||||
-
|
|
||||||
- for replica in ipa_replicas:
|
|
||||||
- for desc in replica.get('description', []):
|
|
||||||
- logger.debug('%s', desc)
|
|
||||||
-
|
|
||||||
- self._update_attr(repl, replica,
|
|
||||||
- 'nsDS5ReplicatedAttributeList',
|
|
||||||
- replication.EXCLUDES, template=EXCLUDE_TEMPLATE)
|
|
||||||
- self._update_attr(repl, replica,
|
|
||||||
- 'nsDS5ReplicatedAttributeListTotal',
|
|
||||||
- replication.TOTAL_EXCLUDES, template=EXCLUDE_TEMPLATE)
|
|
||||||
- self._update_attr(repl, replica,
|
|
||||||
- 'nsds5ReplicaStripAttrs', replication.STRIP_ATTRS)
|
|
||||||
+ # Find suffixes
|
|
||||||
+ suffixes = self.api.Command.topologysuffix_find()['result']
|
|
||||||
+ for suffix in suffixes:
|
|
||||||
+ suffix_name = suffix['cn'][0]
|
|
||||||
+ # Find segments
|
|
||||||
+ sgmts = self.api.Command.topologysegment_find(
|
|
||||||
+ suffix_name, all=True)['result']
|
|
||||||
+ for segment in sgmts:
|
|
||||||
+ updates = {}
|
|
||||||
+ updates = self._update_attr(
|
|
||||||
+ segment, updates,
|
|
||||||
+ 'nsds5replicatedattributelist',
|
|
||||||
+ replication.EXCLUDES, template=EXCLUDE_TEMPLATE)
|
|
||||||
+ updates = self._update_attr(
|
|
||||||
+ segment, updates,
|
|
||||||
+ 'nsds5replicatedattributelisttotal',
|
|
||||||
+ replication.TOTAL_EXCLUDES, template=EXCLUDE_TEMPLATE)
|
|
||||||
+ updates = self._update_attr(
|
|
||||||
+ segment, updates,
|
|
||||||
+ 'nsds5replicastripattrs', replication.STRIP_ATTRS)
|
|
||||||
+ if updates:
|
|
||||||
+ try:
|
|
||||||
+ self.api.Command.topologysegment_mod(
|
|
||||||
+ suffix_name, segment['cn'][0],
|
|
||||||
+ **updates)
|
|
||||||
+ except errors.EmptyModlist:
|
|
||||||
+ # No update done
|
|
||||||
+ logger.debug("No update required for the segment %s",
|
|
||||||
+ segment['cn'][0])
|
|
||||||
|
|
||||||
logger.debug("Done updating agreements")
|
|
||||||
|
|
||||||
return False, [] # No restart, no updates
|
|
||||||
|
|
||||||
- def _update_attr(self, repl, replica, attribute, values, template='%s'):
|
|
||||||
+ def _update_attr(self, segment, updates, attribute, values, template='%s'):
|
|
||||||
"""Add or update an attribute of a replication agreement
|
|
||||||
|
|
||||||
If the attribute doesn't already exist, it is added and set to
|
|
||||||
@@ -77,27 +85,21 @@ class update_replica_attribute_lists(Updater):
|
|
||||||
If the attribute does exist, `values` missing from it are just
|
|
||||||
appended to the end, also space-separated.
|
|
||||||
|
|
||||||
- :param repl: Replication manager
|
|
||||||
- :param replica: Replica agreement
|
|
||||||
+ :param: updates: dict containing the updates
|
|
||||||
+ :param segment: dict containing segment information
|
|
||||||
:param attribute: Attribute to add or update
|
|
||||||
:param values: List of values the attribute should hold
|
|
||||||
:param template: Template to use when adding attribute
|
|
||||||
"""
|
|
||||||
- attrlist = replica.single_value.get(attribute)
|
|
||||||
+ attrlist = segment.get(attribute)
|
|
||||||
if attrlist is None:
|
|
||||||
logger.debug("Adding %s", attribute)
|
|
||||||
|
|
||||||
# Need to add it altogether
|
|
||||||
- replica[attribute] = [template % " ".join(values)]
|
|
||||||
-
|
|
||||||
- try:
|
|
||||||
- repl.conn.update_entry(replica)
|
|
||||||
- logger.debug("Updated")
|
|
||||||
- except Exception as e:
|
|
||||||
- logger.error("Error caught updating replica: %s", str(e))
|
|
||||||
+ updates[attribute] = template % " ".join(values)
|
|
||||||
|
|
||||||
else:
|
|
||||||
- attrlist_normalized = attrlist.lower().split()
|
|
||||||
+ attrlist_normalized = attrlist[0].lower().split()
|
|
||||||
missing = [a for a in values
|
|
||||||
if a.lower() not in attrlist_normalized]
|
|
||||||
|
|
||||||
@@ -105,14 +107,8 @@ class update_replica_attribute_lists(Updater):
|
|
||||||
logger.debug("%s needs updating (missing: %s)", attribute,
|
|
||||||
', '.join(missing))
|
|
||||||
|
|
||||||
- replica[attribute] = [
|
|
||||||
- '%s %s' % (attrlist, ' '.join(missing))]
|
|
||||||
+ updates[attribute] = '%s %s' % (attrlist[0], ' '.join(missing))
|
|
||||||
|
|
||||||
- try:
|
|
||||||
- repl.conn.update_entry(replica)
|
|
||||||
- logger.debug("Updated %s", attribute)
|
|
||||||
- except Exception as e:
|
|
||||||
- logger.error("Error caught updating %s: %s",
|
|
||||||
- attribute, str(e))
|
|
||||||
else:
|
|
||||||
logger.debug("%s: No update necessary", attribute)
|
|
||||||
+ return updates
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
||||||
From 93d97b59600c15e5028ee39b0e98450544165158 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Mon, 19 Jun 2023 10:36:59 +0200
|
|
||||||
Subject: [PATCH] Integration tests: add a test to ipa-server-upgrade
|
|
||||||
|
|
||||||
Add an integration test ensuring that the upgrade
|
|
||||||
properly updates the attributes to be excluded from
|
|
||||||
replication.
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/9385
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
---
|
|
||||||
.../test_simple_replication.py | 30 +++++++++++++++++++
|
|
||||||
1 file changed, 30 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_simple_replication.py b/ipatests/test_integration/test_simple_replication.py
|
|
||||||
index 17092a499..d1e65ef7c 100644
|
|
||||||
--- a/ipatests/test_integration/test_simple_replication.py
|
|
||||||
+++ b/ipatests/test_integration/test_simple_replication.py
|
|
||||||
@@ -23,8 +23,10 @@ import pytest
|
|
||||||
|
|
||||||
from ipaplatform.paths import paths
|
|
||||||
from ipapython.dn import DN
|
|
||||||
+from ipaserver.install.replication import EXCLUDES
|
|
||||||
from ipatests.pytest_ipa.integration import tasks
|
|
||||||
from ipatests.test_integration.base import IntegrationTest
|
|
||||||
+from ipatests.test_integration.test_topology import find_segment
|
|
||||||
|
|
||||||
|
|
||||||
def check_replication(source_host, dest_host, login):
|
|
||||||
@@ -104,6 +106,34 @@ class TestSimpleReplication(IntegrationTest):
|
|
||||||
[paths.IPA_CUSTODIA_CHECK, self.master.hostname]
|
|
||||||
)
|
|
||||||
|
|
||||||
+ def test_fix_agreements(self):
|
|
||||||
+ """Test that upgrade fixes the list of attributes excluded from repl
|
|
||||||
+
|
|
||||||
+ Test for ticket 9385
|
|
||||||
+ """
|
|
||||||
+ # Prepare the server by removing some values from
|
|
||||||
+ # from the nsDS5ReplicatedAttributeList
|
|
||||||
+ segment = find_segment(self.master, self.replicas[0], "domain")
|
|
||||||
+ self.master.run_command([
|
|
||||||
+ "ipa", "topologysegment-mod", "domain", segment,
|
|
||||||
+ "--replattrs",
|
|
||||||
+ "(objectclass=*) $ EXCLUDE memberof idnssoaserial entryusn"])
|
|
||||||
+ # Run the upgrade
|
|
||||||
+ result = self.master.run_command(["ipa-server-upgrade"])
|
|
||||||
+ # Ensure that the upgrade updated the attribute without error
|
|
||||||
+ errmsg = "Error caught updating nsDS5ReplicatedAttributeList"
|
|
||||||
+ assert errmsg not in result.stdout_text
|
|
||||||
+ # Check the updated value
|
|
||||||
+ suffix = DN(self.master.domain.basedn)
|
|
||||||
+ dn = DN(('cn', str(suffix)), ('cn', 'mapping tree'), ('cn', 'config'))
|
|
||||||
+ result = tasks.ldapsearch_dm(self.master, str(dn),
|
|
||||||
+ ["nsDS5ReplicatedAttributeList"])
|
|
||||||
+ output = result.stdout_text.lower()
|
|
||||||
+
|
|
||||||
+ template = 'nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE %s'
|
|
||||||
+ expected_value = template % " ".join(EXCLUDES)
|
|
||||||
+ assert expected_value.lower() in output
|
|
||||||
+
|
|
||||||
def test_replica_removal(self):
|
|
||||||
"""Test replica removal"""
|
|
||||||
result = self.master.run_command(['ipa-replica-manage', 'list'])
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
265
SOURCES/0004-ipa-kdb-Detect-and-block-Bronze-Bit-attacks.patch
Normal file
265
SOURCES/0004-ipa-kdb-Detect-and-block-Bronze-Bit-attacks.patch
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
From 013be398bced31f567ef01ac2471cb7529789b4a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Mon, 9 Oct 2023 15:47:03 +0200
|
||||||
|
Subject: [PATCH] ipa-kdb: Detect and block Bronze-Bit attacks
|
||||||
|
|
||||||
|
The C8S/RHEL8 version of FreeIPA is vulnerable to the Bronze-Bit attack
|
||||||
|
because it does not implement PAC ticket signature to protect the
|
||||||
|
"forwardable" flag. However, it does implement the PAC extended KDC
|
||||||
|
signature, which protects against PAC spoofing.
|
||||||
|
|
||||||
|
Based on information available in the PAC and the
|
||||||
|
"ok-to-auth-as-delegate" attribute in the database. It is possible to
|
||||||
|
detect and reject requests where the "forwardable" flag was flipped by
|
||||||
|
the attacker in the evidence ticket.
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb.h | 13 +++
|
||||||
|
daemons/ipa-kdb/ipa_kdb_kdcpolicy.c | 6 +
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac.c | 173 ++++++++++++++++++++++++++++
|
||||||
|
ipaserver/install/server/install.py | 8 ++
|
||||||
|
4 files changed, 200 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
index 7aa5be494..02b2cb631 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
@@ -367,6 +367,19 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
const char *test_realm, size_t size,
|
||||||
|
char **trusted_realm);
|
||||||
|
|
||||||
|
+/* Try to detect a Bronze-Bit attack based on the content of the request and
|
||||||
|
+ * data from the KDB.
|
||||||
|
+ *
|
||||||
|
+ * context krb5 context
|
||||||
|
+ * request KDB request
|
||||||
|
+ * detected Set to "true" if a bronze bit attack is detected and the
|
||||||
|
+ * pointer is not NULL. Remains unset otherwise.
|
||||||
|
+ * status If the call fails and the pointer is not NULL, set it with a
|
||||||
|
+ * message describing the cause of the failure. */
|
||||||
|
+krb5_error_code
|
||||||
|
+ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
+ bool *detected, const char **status);
|
||||||
|
+
|
||||||
|
/* DELEGATION CHECKS */
|
||||||
|
|
||||||
|
krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
index f2804c9b2..1032dff0b 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
@@ -185,6 +185,12 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||||
|
const char **status, krb5_deltat *lifetime_out,
|
||||||
|
krb5_deltat *renew_lifetime_out)
|
||||||
|
{
|
||||||
|
+ krb5_error_code kerr;
|
||||||
|
+
|
||||||
|
+ kerr = ipadb_check_for_bronze_bit_attack(context, request, NULL, status);
|
||||||
|
+ if (kerr)
|
||||||
|
+ return KRB5KDC_ERR_POLICY;
|
||||||
|
+
|
||||||
|
*status = NULL;
|
||||||
|
*lifetime_out = 0;
|
||||||
|
*renew_lifetime_out = 0;
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index 83cb9914d..b4e22d431 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -3298,3 +3298,176 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
|
||||||
|
return KRB5_KDB_NOENTRY;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+krb5_error_code
|
||||||
|
+ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
+ bool *detected, const char **status)
|
||||||
|
+{
|
||||||
|
+ krb5_error_code kerr;
|
||||||
|
+ const char *st = NULL;
|
||||||
|
+ size_t i, j;
|
||||||
|
+ krb5_ticket *evidence_tkt;
|
||||||
|
+ krb5_authdata **authdata, **ifrel = NULL;
|
||||||
|
+ krb5_pac pac = NULL;
|
||||||
|
+ TALLOC_CTX *tmpctx = NULL;
|
||||||
|
+ krb5_data fullsign = { 0, 0, NULL }, linfo_blob = { 0, 0, NULL };
|
||||||
|
+ DATA_BLOB linfo_data;
|
||||||
|
+ struct PAC_LOGON_INFO_CTR linfo;
|
||||||
|
+ enum ndr_err_code ndr_err;
|
||||||
|
+ struct dom_sid asserted_identity_sid;
|
||||||
|
+ bool evtkt_is_s4u2self = false;
|
||||||
|
+ krb5_db_entry *proxy_entry = NULL;
|
||||||
|
+
|
||||||
|
+ /* If no additional ticket, this is not a constrained delegateion request.
|
||||||
|
+ * Skip checks. */
|
||||||
|
+ if (!(request->kdc_options & KDC_OPT_CNAME_IN_ADDL_TKT)) {
|
||||||
|
+ kerr = 0;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ evidence_tkt = request->second_ticket[0];
|
||||||
|
+
|
||||||
|
+ /* No need to check the Forwardable flag. If it was not set, this request
|
||||||
|
+ * would have failed earlier. */
|
||||||
|
+
|
||||||
|
+ /* We only support general constrained delegation (not RBCD), which is not
|
||||||
|
+ * available for cross-realms. */
|
||||||
|
+ if (!krb5_realm_compare(context, evidence_tkt->server, request->server)) {
|
||||||
|
+ st = "S4U2PROXY_NOT_SUPPORTED_FOR_CROSS_REALMS";
|
||||||
|
+ kerr = ENOTSUP;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ authdata = evidence_tkt->enc_part2->authorization_data;
|
||||||
|
+
|
||||||
|
+ /* Search for the PAC. */
|
||||||
|
+ for (i = 0; authdata != NULL && authdata[i] != NULL; i++) {
|
||||||
|
+ if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ kerr = krb5_decode_authdata_container(context,
|
||||||
|
+ KRB5_AUTHDATA_IF_RELEVANT,
|
||||||
|
+ authdata[i], &ifrel);
|
||||||
|
+ if (kerr) {
|
||||||
|
+ st = "S4U2PROXY_CANNOT_DECODE_EVIDENCE_TKT_AUTHDATA";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (j = 0; ifrel[j] != NULL; j++) {
|
||||||
|
+ if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (ifrel[j] != NULL)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ krb5_free_authdata(context, ifrel);
|
||||||
|
+ ifrel = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ifrel == NULL) {
|
||||||
|
+ st = "S4U2PROXY_EVIDENCE_TKT_WITHOUT_PAC";
|
||||||
|
+ kerr = ENOENT;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Parse the PAC. */
|
||||||
|
+ kerr = krb5_pac_parse(context, ifrel[j]->contents, ifrel[j]->length, &pac);
|
||||||
|
+ if (kerr) {
|
||||||
|
+ st = "S4U2PROXY_CANNOT_DECODE_EVICENCE_TKT_PAC";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Check that the PAC extanded KDC signature is present. If it is, it was
|
||||||
|
+ * already tested.
|
||||||
|
+ * If absent, the context of the PAC cannot be trusted. */
|
||||||
|
+ kerr = krb5_pac_get_buffer(context, pac, KRB5_PAC_FULL_CHECKSUM, &fullsign);
|
||||||
|
+ if (kerr) {
|
||||||
|
+ st = "S4U2PROXY_MISSING_EXTENDED_KDC_SIGN_IN_EVIDENCE_TKT_PAC";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Get the PAC Logon Info. */
|
||||||
|
+ kerr = krb5_pac_get_buffer(context, pac, KRB5_PAC_LOGON_INFO, &linfo_blob);
|
||||||
|
+ if (kerr) {
|
||||||
|
+ st = "S4U2PROXY_NO_PAC_LOGON_INFO_IN_EVIDENCE_TKT";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Parse the PAC Logon Info. */
|
||||||
|
+ tmpctx = talloc_new(NULL);
|
||||||
|
+ if (!tmpctx) {
|
||||||
|
+ st = "OUT_OF_MEMORY";
|
||||||
|
+ kerr = ENOMEM;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ linfo_data.length = linfo_blob.length;
|
||||||
|
+ linfo_data.data = (uint8_t *)linfo_blob.data;
|
||||||
|
+ ndr_err = ndr_pull_union_blob(&linfo_data, tmpctx, &linfo,
|
||||||
|
+ PAC_TYPE_LOGON_INFO,
|
||||||
|
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
|
||||||
|
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
|
+ st = "S4U2PROXY_CANNOT_PARSE_ENVIDENCE_TKT_PAC_LOGON_INFO";
|
||||||
|
+ kerr = EINVAL;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Check that the extra SIDs array is not empty. */
|
||||||
|
+ if (linfo.info->info3.sidcount == 0) {
|
||||||
|
+ st = "S4U2PROXY_NO_EXTRA_SID";
|
||||||
|
+ kerr = ENOENT;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Search for the S-1-18-2 domain SID, which indicates the ticket was
|
||||||
|
+ * obtained using S4U2Self */
|
||||||
|
+ kerr = ipadb_string_to_sid("S-1-18-2", &asserted_identity_sid);
|
||||||
|
+ if (kerr) {
|
||||||
|
+ st = "S4U2PROXY_CANNOT_CREATE_ASSERTED_IDENTITY_SID";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < linfo.info->info3.sidcount; i++) {
|
||||||
|
+ if (dom_sid_check(&asserted_identity_sid,
|
||||||
|
+ linfo.info->info3.sids[0].sid, true)) {
|
||||||
|
+ evtkt_is_s4u2self = true;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If the ticket was obtained using S4U2Self, the proxy principal entry must
|
||||||
|
+ * have the "ok_to_auth_as_delegate" attribute set to true. */
|
||||||
|
+ if (evtkt_is_s4u2self) {
|
||||||
|
+ kerr = ipadb_get_principal(context, evidence_tkt->server, 0,
|
||||||
|
+ &proxy_entry);
|
||||||
|
+ if (kerr) {
|
||||||
|
+ st = "S4U2PROXY_CANNOT_FIND_PROXY_PRINCIPAL";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!(proxy_entry->attributes & KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)) {
|
||||||
|
+ /* This evidence ticket cannot be forwardable given the privileges
|
||||||
|
+ * of the proxy principal.
|
||||||
|
+ * This is a Bronze Bit attack. */
|
||||||
|
+ if (detected)
|
||||||
|
+ *detected = true;
|
||||||
|
+ st = "S4U2PROXY_BRONZE_BIT_ATTACK_DETECTED";
|
||||||
|
+ kerr = EBADE;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kerr = 0;
|
||||||
|
+
|
||||||
|
+end:
|
||||||
|
+ if (st && status)
|
||||||
|
+ *status = st;
|
||||||
|
+
|
||||||
|
+ krb5_free_authdata(context, ifrel);
|
||||||
|
+ krb5_pac_free(context, pac);
|
||||||
|
+ krb5_free_data_contents(context, &linfo_blob);
|
||||||
|
+ krb5_free_data_contents(context, &fullsign);
|
||||||
|
+ talloc_free(tmpctx);
|
||||||
|
+ ipadb_free_principal(context, proxy_entry);
|
||||||
|
+ return kerr;
|
||||||
|
+}
|
||||||
|
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
|
||||||
|
index 4e4076410..bfbb83bcb 100644
|
||||||
|
--- a/ipaserver/install/server/install.py
|
||||||
|
+++ b/ipaserver/install/server/install.py
|
||||||
|
@@ -981,6 +981,14 @@ def install(installer):
|
||||||
|
# Set the admin user kerberos password
|
||||||
|
ds.change_admin_password(admin_password)
|
||||||
|
|
||||||
|
+ # Force KDC to refresh the cached value of ipaKrbAuthzData by restarting.
|
||||||
|
+ # ipaKrbAuthzData has to be set with "MS-PAC" to trigger PAC generation,
|
||||||
|
+ # which is required to handle S4U2Proxy with the Bronze-Bit fix.
|
||||||
|
+ # Not doing so would cause API malfunction for around a minute, which is
|
||||||
|
+ # long enough to cause the hereafter client installation to fail.
|
||||||
|
+ service.print_msg("Restarting the KDC")
|
||||||
|
+ krb.restart()
|
||||||
|
+
|
||||||
|
# Call client install script
|
||||||
|
service.print_msg("Configuring client side components")
|
||||||
|
try:
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -0,0 +1,212 @@
|
|||||||
|
From 3add9ba03a0af913d03b1f5ecaa8e48e46a93f91 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Jan 15 2024 13:42:08 +0000
|
||||||
|
Subject: Server affinity: Retain user-requested remote server
|
||||||
|
|
||||||
|
|
||||||
|
We want to avoid splitting a replica server installation between
|
||||||
|
two hosts where possible so if a CA or KRA is requested then
|
||||||
|
we only try to install against a remote server that also provides
|
||||||
|
those capabilities. This avoids race conditions.
|
||||||
|
|
||||||
|
If a CA or KRA is not requested and the user has provided a
|
||||||
|
server to install against then use that instead of overriding it.
|
||||||
|
|
||||||
|
Extend the logic of picking the remote Custodia mode
|
||||||
|
(KRA, CA, *MASTER*) to include considering whether the
|
||||||
|
CA and KRA services are requested. If the service(s) are
|
||||||
|
not requested the the associated hostname may not be
|
||||||
|
reliable.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9491
|
||||||
|
Related: https://pagure.io/freeipa/issue/9289
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
|
||||||
|
index 27fbdef..8096b6a 100644
|
||||||
|
--- a/ipaserver/install/server/replicainstall.py
|
||||||
|
+++ b/ipaserver/install/server/replicainstall.py
|
||||||
|
@@ -782,6 +782,7 @@ def promotion_check_host_principal_auth_ind(conn, hostdn):
|
||||||
|
|
||||||
|
|
||||||
|
def remote_connection(config):
|
||||||
|
+ logger.debug("Creating LDAP connection to %s", config.master_host_name)
|
||||||
|
ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name)
|
||||||
|
xmlrpc_uri = 'https://{}/ipa/xml'.format(
|
||||||
|
ipautil.format_netloc(config.master_host_name))
|
||||||
|
@@ -1087,7 +1088,7 @@ def promote_check(installer):
|
||||||
|
'CA', conn, preferred_cas
|
||||||
|
)
|
||||||
|
if ca_host is not None:
|
||||||
|
- if config.master_host_name != ca_host:
|
||||||
|
+ if options.setup_ca and config.master_host_name != ca_host:
|
||||||
|
conn.disconnect()
|
||||||
|
del remote_api
|
||||||
|
config.master_host_name = ca_host
|
||||||
|
@@ -1096,8 +1097,7 @@ def promote_check(installer):
|
||||||
|
conn = remote_api.Backend.ldap2
|
||||||
|
conn.connect(ccache=installer._ccache)
|
||||||
|
config.ca_host_name = ca_host
|
||||||
|
- config.master_host_name = ca_host
|
||||||
|
- ca_enabled = True
|
||||||
|
+ ca_enabled = True # There is a CA somewhere in the topology
|
||||||
|
if options.dirsrv_cert_files:
|
||||||
|
logger.error("Certificates could not be provided when "
|
||||||
|
"CA is present on some master.")
|
||||||
|
@@ -1135,7 +1135,7 @@ def promote_check(installer):
|
||||||
|
'KRA', conn, preferred_kras
|
||||||
|
)
|
||||||
|
if kra_host is not None:
|
||||||
|
- if config.master_host_name != kra_host:
|
||||||
|
+ if options.setup_kra and config.master_host_name != kra_host:
|
||||||
|
conn.disconnect()
|
||||||
|
del remote_api
|
||||||
|
config.master_host_name = kra_host
|
||||||
|
@@ -1143,10 +1143,9 @@ def promote_check(installer):
|
||||||
|
installer._remote_api = remote_api
|
||||||
|
conn = remote_api.Backend.ldap2
|
||||||
|
conn.connect(ccache=installer._ccache)
|
||||||
|
- config.kra_host_name = kra_host
|
||||||
|
- config.ca_host_name = kra_host
|
||||||
|
- config.master_host_name = kra_host
|
||||||
|
- kra_enabled = True
|
||||||
|
+ config.kra_host_name = kra_host
|
||||||
|
+ config.ca_host_name = kra_host
|
||||||
|
+ kra_enabled = True # There is a KRA somewhere in the topology
|
||||||
|
if options.setup_kra and options.server and \
|
||||||
|
kra_host != options.server:
|
||||||
|
# Installer was provided with a specific master
|
||||||
|
@@ -1372,10 +1371,10 @@ def install(installer):
|
||||||
|
otpd.create_instance('OTPD', config.host_name,
|
||||||
|
ipautil.realm_to_suffix(config.realm_name))
|
||||||
|
|
||||||
|
- if kra_enabled:
|
||||||
|
+ if options.setup_kra and kra_enabled:
|
||||||
|
# A KRA peer always provides a CA, too.
|
||||||
|
mode = custodiainstance.CustodiaModes.KRA_PEER
|
||||||
|
- elif ca_enabled:
|
||||||
|
+ elif options.setup_ca and ca_enabled:
|
||||||
|
mode = custodiainstance.CustodiaModes.CA_PEER
|
||||||
|
else:
|
||||||
|
mode = custodiainstance.CustodiaModes.MASTER_PEER
|
||||||
|
|
||||||
|
From 701339d4fed539713eb1a13495992879f56a6daa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Jan 18 2024 14:53:28 +0000
|
||||||
|
Subject: Server affinity: Don't rely just on [ca|kra]_enabled for installs
|
||||||
|
|
||||||
|
|
||||||
|
ca_enable and kra_enabled are intended to be used to identify that
|
||||||
|
a CA or KRA is available in the topology. It was also being used
|
||||||
|
to determine whether a CA or KRA service is desired on a replica
|
||||||
|
install, rather than options.setup_[ca|kra]
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9510
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
|
||||||
|
index 8096b6a..191913d 100644
|
||||||
|
--- a/ipaserver/install/server/replicainstall.py
|
||||||
|
+++ b/ipaserver/install/server/replicainstall.py
|
||||||
|
@@ -1143,7 +1143,8 @@ def promote_check(installer):
|
||||||
|
installer._remote_api = remote_api
|
||||||
|
conn = remote_api.Backend.ldap2
|
||||||
|
conn.connect(ccache=installer._ccache)
|
||||||
|
- config.kra_host_name = kra_host
|
||||||
|
+ config.kra_host_name = kra_host
|
||||||
|
+ if options.setup_kra: # only reset ca_host if KRA is requested
|
||||||
|
config.ca_host_name = kra_host
|
||||||
|
kra_enabled = True # There is a KRA somewhere in the topology
|
||||||
|
if options.setup_kra and options.server and \
|
||||||
|
@@ -1381,7 +1382,7 @@ def install(installer):
|
||||||
|
custodia = custodiainstance.get_custodia_instance(config, mode)
|
||||||
|
custodia.create_instance()
|
||||||
|
|
||||||
|
- if ca_enabled:
|
||||||
|
+ if options.setup_ca and ca_enabled:
|
||||||
|
options.realm_name = config.realm_name
|
||||||
|
options.domain_name = config.domain_name
|
||||||
|
options.host_name = config.host_name
|
||||||
|
@@ -1397,7 +1398,7 @@ def install(installer):
|
||||||
|
service.print_msg("Finalize replication settings")
|
||||||
|
ds.finalize_replica_config()
|
||||||
|
|
||||||
|
- if kra_enabled:
|
||||||
|
+ if options.setup_kra and kra_enabled:
|
||||||
|
kra.install(api, config, options, custodia=custodia)
|
||||||
|
|
||||||
|
service.print_msg("Restarting the KDC")
|
||||||
|
|
||||||
|
From e6014a5c1996528b255480b67fe2937203bff81b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Jan 23 2024 15:32:58 +0000
|
||||||
|
Subject: Server affinity: call ca.install() if there is a CA in the topology
|
||||||
|
|
||||||
|
|
||||||
|
This should not have been gated on options.setup_ca because we need
|
||||||
|
the RA agent on all servers if there is a CA in the topology otherwise
|
||||||
|
the non-CA servers won't be able to communicate with the CA.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9510
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
|
||||||
|
index c93ae1f..187f803 100644
|
||||||
|
--- a/ipaserver/install/ca.py
|
||||||
|
+++ b/ipaserver/install/ca.py
|
||||||
|
@@ -387,9 +387,10 @@ def install_step_0(standalone, replica_config, options, custodia):
|
||||||
|
promote = False
|
||||||
|
else:
|
||||||
|
cafile = os.path.join(replica_config.dir, 'cacert.p12')
|
||||||
|
- custodia.get_ca_keys(
|
||||||
|
- cafile,
|
||||||
|
- replica_config.dirman_password)
|
||||||
|
+ if replica_config.setup_ca:
|
||||||
|
+ custodia.get_ca_keys(
|
||||||
|
+ cafile,
|
||||||
|
+ replica_config.dirman_password)
|
||||||
|
|
||||||
|
ca_signing_algorithm = None
|
||||||
|
ca_type = None
|
||||||
|
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
|
||||||
|
index f8d4733..4c1c07c 100644
|
||||||
|
--- a/ipaserver/install/server/replicainstall.py
|
||||||
|
+++ b/ipaserver/install/server/replicainstall.py
|
||||||
|
@@ -1359,11 +1359,13 @@ def install(installer):
|
||||||
|
custodia = custodiainstance.get_custodia_instance(config, mode)
|
||||||
|
custodia.create_instance()
|
||||||
|
|
||||||
|
- if options.setup_ca and ca_enabled:
|
||||||
|
+ if ca_enabled:
|
||||||
|
options.realm_name = config.realm_name
|
||||||
|
options.domain_name = config.domain_name
|
||||||
|
options.host_name = config.host_name
|
||||||
|
options.dm_password = config.dirman_password
|
||||||
|
+ # Always call ca.install() if there is a CA in the topology
|
||||||
|
+ # to ensure the RA agent is present.
|
||||||
|
ca.install(False, config, options, custodia=custodia)
|
||||||
|
|
||||||
|
# configure PKINIT now that all required services are in place
|
||||||
|
@@ -1375,7 +1377,8 @@ def install(installer):
|
||||||
|
service.print_msg("Finalize replication settings")
|
||||||
|
ds.finalize_replica_config()
|
||||||
|
|
||||||
|
- if options.setup_kra and kra_enabled:
|
||||||
|
+ if kra_enabled:
|
||||||
|
+ # The KRA installer checks for itself the status of setup_kra
|
||||||
|
kra.install(api, config, options, custodia=custodia)
|
||||||
|
|
||||||
|
service.print_msg("Restarting the KDC")
|
||||||
|
|
@ -1,52 +0,0 @@
|
|||||||
From a7e167154b889f75463ccc9cd91a75c1afb22da9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Jun 28 2023 19:43:16 +0000
|
|
||||||
Subject: OTP: fix data type to avoid endianness issue
|
|
||||||
|
|
||||||
|
|
||||||
When 389-ds process an OTP authentication, the ipa-pwd-extop
|
|
||||||
plugin reads a buffer to extract the authentication type.
|
|
||||||
The type is stored in an int but the data is a ber_tag_t.
|
|
||||||
|
|
||||||
On big endian machines the type cast does not cause any issue
|
|
||||||
but on s390x the buffer that should return 128 is seen as 0.
|
|
||||||
|
|
||||||
As a consequence, the plugin considers that the method is not
|
|
||||||
LDAP_AUTH_SIMPLE and exits early, without processing the OTP.
|
|
||||||
|
|
||||||
The fix is simple and consists in using the right type
|
|
||||||
(ber_tag_t is an unsigned long).
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9402
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
|
|
||||||
index 9375941..4562652 100644
|
|
||||||
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
|
|
||||||
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
|
|
||||||
@@ -1433,7 +1433,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
|
||||||
Slapi_DN *target_sdn = NULL;
|
|
||||||
Slapi_DN *sdn = NULL;
|
|
||||||
const char *dn = NULL;
|
|
||||||
- int method = 0;
|
|
||||||
+ ber_tag_t method = 0;
|
|
||||||
bool syncreq;
|
|
||||||
bool otpreq;
|
|
||||||
int ret = 0;
|
|
||||||
@@ -1454,8 +1454,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We're only interested in simple authentication. */
|
|
||||||
- if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0)
|
|
||||||
+ if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0) {
|
|
||||||
+ LOG("Not handled (not simple bind or NULL dn/credentials)\n");
|
|
||||||
return 0;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* Retrieve the user's entry. */
|
|
||||||
sdn = slapi_sdn_dup(target_sdn);
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
|||||||
From 7a94acca6a9efb546f1cf59f63fcb89f98944ea5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Thu, 25 May 2023 08:16:33 +0200
|
|
||||||
Subject: [PATCH] ACME tests: fix issue_and_expire_acme_cert method
|
|
||||||
|
|
||||||
The fixture issue_and_expire_acme_cert is changing the date
|
|
||||||
on master and client. It also resets the admin password as
|
|
||||||
it gets expired after the date change.
|
|
||||||
Currently the code is resetting the password by performing
|
|
||||||
kinit on the client, which leaves the master with an expired
|
|
||||||
ticket in its cache. Reset the password on the master instead
|
|
||||||
in order to have a valid ticket for the next operations.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9383
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Mohammad Rizwan <myusuf@redhat.com>
|
|
||||||
---
|
|
||||||
ipatests/test_integration/test_acme.py | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
|
|
||||||
index c73f441fc..c69e810da 100644
|
|
||||||
--- a/ipatests/test_integration/test_acme.py
|
|
||||||
+++ b/ipatests/test_integration/test_acme.py
|
|
||||||
@@ -583,20 +583,20 @@ class TestACMERenew(IntegrationTest):
|
|
||||||
tasks.kdestroy_all(host)
|
|
||||||
tasks.move_date(host, 'stop', '+90days')
|
|
||||||
|
|
||||||
- tasks.get_kdcinfo(host)
|
|
||||||
+ tasks.get_kdcinfo(self.master)
|
|
||||||
# Note raiseonerr=False:
|
|
||||||
# the assert is located after kdcinfo retrieval.
|
|
||||||
# run kinit command repeatedly until sssd gets settle
|
|
||||||
# after date change
|
|
||||||
tasks.run_repeatedly(
|
|
||||||
- host, "KRB5_TRACE=/dev/stdout kinit admin",
|
|
||||||
+ self.master, "KRB5_TRACE=/dev/stdout kinit admin",
|
|
||||||
stdin_text='{0}\n{0}\n{0}\n'.format(
|
|
||||||
- self.clients[0].config.admin_password
|
|
||||||
+ self.master.config.admin_password
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# Retrieve kdc.$REALM after the password change, just in case SSSD
|
|
||||||
# domain status flipped to online during the password change.
|
|
||||||
- tasks.get_kdcinfo(host)
|
|
||||||
+ tasks.get_kdcinfo(self.master)
|
|
||||||
|
|
||||||
yield
|
|
||||||
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
||||||
From 998bafee86a870ad1ea4d6bccf12f0fae64c398c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Wed, 31 May 2023 11:50:14 +0200
|
|
||||||
Subject: [PATCH] ipatest: remove xfail from test_smb
|
|
||||||
|
|
||||||
test_smb is now successful because the windows server version
|
|
||||||
has been updated to windows-server-2022 with
|
|
||||||
- KB5012170
|
|
||||||
- KB5025230
|
|
||||||
- KB5022507
|
|
||||||
- servicing stack 10.0.20348.1663
|
|
||||||
in freeipa-pr-ci commit 3ba4151.
|
|
||||||
|
|
||||||
Remove the xfail.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9124
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Mohammad Rizwan <myusuf@redhat.com>
|
|
||||||
---
|
|
||||||
ipatests/test_integration/test_smb.py | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py
|
|
||||||
index 30f8d5901..eb3981bdd 100644
|
|
||||||
--- a/ipatests/test_integration/test_smb.py
|
|
||||||
+++ b/ipatests/test_integration/test_smb.py
|
|
||||||
@@ -349,7 +349,6 @@ class TestSMB(IntegrationTest):
|
|
||||||
@pytest.mark.skipif(
|
|
||||||
osinfo.id == 'fedora' and osinfo.version_number <= (31,),
|
|
||||||
reason='Test requires krb 1.18')
|
|
||||||
- @pytest.mark.xfail(reason="Pagure ticket 9124", strict=True)
|
|
||||||
def test_smb_service_s4u2self(self):
|
|
||||||
"""Test S4U2Self operation by IPA service
|
|
||||||
against both AD and IPA users
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
||||||
From 1b51fa4cb07380d1102891233e85a7940f804c72 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Anuja More <amore@redhat.com>
|
|
||||||
Date: Thu, 11 May 2023 12:50:10 +0530
|
|
||||||
Subject: [PATCH] ipatests: Check that SSSD_PUBCONF_KRB5_INCLUDE_D_DIR is not
|
|
||||||
included in krb5.conf
|
|
||||||
|
|
||||||
SSSD already provides a config snippet which includes
|
|
||||||
SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, and having both breaks Java.
|
|
||||||
Test checks that krb5.conf does not include
|
|
||||||
SSSD_PUBCONF_KRB5_INCLUDE_D_DIR.
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/9267
|
|
||||||
|
|
||||||
Signed-off-by: Anuja More <amore@redhat.com>
|
|
||||||
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
---
|
|
||||||
.../test_integration/test_installation_client.py | 15 +++++++++++++++
|
|
||||||
1 file changed, 15 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_installation_client.py b/ipatests/test_integration/test_installation_client.py
|
|
||||||
index 014b0f6ab..56e1593bf 100644
|
|
||||||
--- a/ipatests/test_integration/test_installation_client.py
|
|
||||||
+++ b/ipatests/test_integration/test_installation_client.py
|
|
||||||
@@ -76,6 +76,21 @@ class TestInstallClient(IntegrationTest):
|
|
||||||
result = self.clients[0].run_command(['cat', '/etc/ssh/ssh_config'])
|
|
||||||
assert 'HostKeyAlgorithms' not in result.stdout_text
|
|
||||||
|
|
||||||
+ def test_client_install_with_krb5(self):
|
|
||||||
+ """Test that SSSD_PUBCONF_KRB5_INCLUDE_D_DIR is not added in krb5.conf
|
|
||||||
+
|
|
||||||
+ SSSD already provides a config snippet which includes
|
|
||||||
+ SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, and having both breaks Java.
|
|
||||||
+ Test checks that krb5.conf does not include
|
|
||||||
+ SSSD_PUBCONF_KRB5_INCLUDE_D_DIR.
|
|
||||||
+
|
|
||||||
+ related: https://pagure.io/freeipa/issue/9267
|
|
||||||
+ """
|
|
||||||
+ krb5_cfg = self.master.get_file_contents(paths.KRB5_CONF)
|
|
||||||
+ assert 'includedir {dir}'.format(
|
|
||||||
+ dir=paths.SSSD_PUBCONF_KRB5_INCLUDE_D_DIR
|
|
||||||
+ ).encode() not in krb5_cfg
|
|
||||||
+
|
|
||||||
|
|
||||||
class TestClientInstallBind(IntegrationTest):
|
|
||||||
"""
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
||||||
From f599e2d67bad5945e4dcf99fdd584f01f1e20d1e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Tue, 6 Jun 2023 09:04:48 +0200
|
|
||||||
Subject: [PATCH] webuitests: close notification which hides Add button
|
|
||||||
|
|
||||||
The webui test test_service.py::test_service::test_arbitrary_certificates
|
|
||||||
randomly fails.
|
|
||||||
The test is creating a new service then navigates to the Service page
|
|
||||||
and clicks on the Add Certificate button.
|
|
||||||
The notification area may still be present and hide the button, with
|
|
||||||
the message "Service successfully added".
|
|
||||||
Close all notifications before navigating to the Service page.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9389
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
|
|
||||||
---
|
|
||||||
ipatests/test_webui/test_service.py | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_webui/test_service.py b/ipatests/test_webui/test_service.py
|
|
||||||
index f1d9a9d62..e2976d73a 100644
|
|
||||||
--- a/ipatests/test_webui/test_service.py
|
|
||||||
+++ b/ipatests/test_webui/test_service.py
|
|
||||||
@@ -296,6 +296,7 @@ class test_service(sevice_tasks):
|
|
||||||
cert_widget_sel = "div.certificate-widget"
|
|
||||||
|
|
||||||
self.add_record(ENTITY, data)
|
|
||||||
+ self.close_notifications()
|
|
||||||
self.navigate_to_record(pkey)
|
|
||||||
|
|
||||||
# check whether certificate section is present
|
|
||||||
--
|
|
||||||
2.41.0
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
|||||||
|
From 3842116185de6ae8714f30b57bd75c7eddde53d8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Jan 15 2024 13:50:10 +0000
|
||||||
|
Subject: host: update System: Manage Host Keytab permission
|
||||||
|
|
||||||
|
|
||||||
|
Since commit 5c0e7a5fb420377dcc06a956695afdcb35196444, a new extended
|
||||||
|
operation to get a keytab is supposed to be used. This keytab
|
||||||
|
setting/retrieval extended operation checks access rights of the bound
|
||||||
|
DN to write to a virtual attribute 'ipaProtectedOperation;write_keys'.
|
||||||
|
|
||||||
|
If the write isn't allowed, the operation is rejected and ipa-getkeytab
|
||||||
|
tool falls back to an older code that generates the keytab on the client
|
||||||
|
and forcibly sets to the LDAP entry. For the latter, a check is done to
|
||||||
|
make sure the bound DN is allowed to write to 'krbPrincipalKey' attribute.
|
||||||
|
|
||||||
|
This fallback should never happen for newer deployments. When enrollemnt
|
||||||
|
operation is delegated to non-administrative user with the help of 'Host
|
||||||
|
Enrollment' role, a host can be pre-created or created at enrollment
|
||||||
|
time, if this non-administrative user has 'Host Administrators' role. In
|
||||||
|
the latter case a system permission 'System: Manage Host Keytab' grants
|
||||||
|
write access to 'krbPrincipalKey' attribute but lacks any access to the
|
||||||
|
virtual attributes expected by the new extended operation.
|
||||||
|
|
||||||
|
There is a second virtual attribute, 'ipaProtectedOperation;read_keys',
|
||||||
|
that allows to retrieve existing keys for a host. However, during
|
||||||
|
initial enrollment we do not allow to retrieve and reuse existing
|
||||||
|
Kerberos key: while 'ipa-getkeytab -r' would give ability to retrieve
|
||||||
|
the existing key, 'ipa-join' has no way to trigger that operation.
|
||||||
|
Hence, permission 'System: Manage Host Keytab' will not grant the right
|
||||||
|
to read the Kerberos key via extended operation used by 'ipa-getkeytab
|
||||||
|
-r'. Such operation can be done later by utilizing 'ipa
|
||||||
|
service/host-allow-retrieve-keytab' commands.
|
||||||
|
|
||||||
|
Fix 'System: Manage Host Keytab' permission and extend a permission test
|
||||||
|
to see that we do not fallback to the old extended operation.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9496
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ACI.txt b/ACI.txt
|
||||||
|
index e6d6e3d..236bb43 100644
|
||||||
|
--- a/ACI.txt
|
||||||
|
+++ b/ACI.txt
|
||||||
|
@@ -147,7 +147,7 @@ aci: (targetattr = "usercertificate")(targetfilter = "(objectclass=ipahost)")(ve
|
||||||
|
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||||
|
aci: (targetattr = "userpassword")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Enrollment Password";allow (write) groupdn = "ldap:///cn=System: Manage Host Enrollment Password,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||||
|
-aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(&(!(memberOf=cn=ipaservers,cn=hostgroups,cn=accounts,dc=ipa,dc=example))(objectclass=ipahost))")(version 3.0;acl "permission:System: Manage Host Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
+aci: (targetattr = "ipaprotectedoperation;write_keys || krblastpwdchange || krbprincipalkey")(targetfilter = "(&(!(memberOf=cn=ipaservers,cn=hostgroups,cn=accounts,dc=ipa,dc=example))(objectclass=ipahost))")(version 3.0;acl "permission:System: Manage Host Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||||
|
aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys || ipaallowedtoperform;write_keys || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Keytab Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Host Keytab Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=computers,cn=accounts,dc=ipa,dc=example
|
||||||
|
diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py
|
||||||
|
index 3ef510e..b02c8b5 100644
|
||||||
|
--- a/ipaserver/plugins/host.py
|
||||||
|
+++ b/ipaserver/plugins/host.py
|
||||||
|
@@ -409,7 +409,8 @@ class host(LDAPObject):
|
||||||
|
api.env.container_hostgroup,
|
||||||
|
api.env.basedn),
|
||||||
|
],
|
||||||
|
- 'ipapermdefaultattr': {'krblastpwdchange', 'krbprincipalkey'},
|
||||||
|
+ 'ipapermdefaultattr': {'krblastpwdchange', 'krbprincipalkey',
|
||||||
|
+ 'ipaprotectedoperation;write_keys'},
|
||||||
|
'replaces': [
|
||||||
|
'(targetattr = "krbprincipalkey || krblastpwdchange")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Manage host keytab";allow (write) groupdn = "ldap:///cn=Manage host keytab,cn=permissions,cn=pbac,$SUFFIX";)',
|
||||||
|
],
|
||||||
|
diff --git a/ipatests/test_integration/test_user_permissions.py b/ipatests/test_integration/test_user_permissions.py
|
||||||
|
index 3333a4f..cd1096f 100644
|
||||||
|
--- a/ipatests/test_integration/test_user_permissions.py
|
||||||
|
+++ b/ipatests/test_integration/test_user_permissions.py
|
||||||
|
@@ -277,6 +277,9 @@ class TestInstallClientNoAdmin(IntegrationTest):
|
||||||
|
self.master.run_command(['ipa', 'privilege-add-permission',
|
||||||
|
'--permissions', 'System: Add Hosts',
|
||||||
|
'Add Hosts'])
|
||||||
|
+ self.master.run_command(['ipa', 'privilege-add-permission',
|
||||||
|
+ '--permissions', 'System: Manage Host Keytab',
|
||||||
|
+ 'Add Hosts'])
|
||||||
|
|
||||||
|
self.master.run_command(['ipa', 'role-add-privilege', 'useradmin',
|
||||||
|
'--privileges', 'Host Enrollment'])
|
||||||
|
@@ -301,6 +304,10 @@ class TestInstallClientNoAdmin(IntegrationTest):
|
||||||
|
encoding='utf-8')
|
||||||
|
assert msg in install_log
|
||||||
|
|
||||||
|
+ # Make sure we do not fallback to an old keytab retrieval method anymore
|
||||||
|
+ msg = "Retrying with pre-4.0 keytab retrieval method..."
|
||||||
|
+ assert msg not in install_log
|
||||||
|
+
|
||||||
|
# check that user is able to request a host cert, too
|
||||||
|
result = tasks.run_certutil(client, ['-L'], paths.IPA_NSSDB_DIR)
|
||||||
|
assert 'Local IPA host' in result.stdout_text
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From 2f17319df6147832dceff7c06154363f8d58b194 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Jan 18 2024 09:07:31 +0000
|
||||||
|
Subject: adtrustinstance: make sure NetBIOS name defaults are set properly
|
||||||
|
|
||||||
|
|
||||||
|
Some tools may pass None as NetBIOS name if not put explicitly by a
|
||||||
|
user. This meant to use default NetBIOS name generator based on the
|
||||||
|
domain (realm) name. However, this wasn't done properly, so None is
|
||||||
|
passed later to python-ldap and it rejects such LDAP entry.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9514
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
|
||||||
|
index bf0cc3b..bb5b61a 100644
|
||||||
|
--- a/ipaserver/install/adtrustinstance.py
|
||||||
|
+++ b/ipaserver/install/adtrustinstance.py
|
||||||
|
@@ -189,6 +189,8 @@ class ADTRUSTInstance(service.Service):
|
||||||
|
self.fqdn = self.fqdn or api.env.host
|
||||||
|
self.host_netbios_name = make_netbios_name(self.fqdn)
|
||||||
|
self.realm = self.realm or api.env.realm
|
||||||
|
+ if not self.netbios_name:
|
||||||
|
+ self.netbios_name = make_netbios_name(self.realm)
|
||||||
|
|
||||||
|
self.suffix = ipautil.realm_to_suffix(self.realm)
|
||||||
|
self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % \
|
||||||
|
|
@ -1,85 +0,0 @@
|
|||||||
From b5793c854035a122ed4c66f917cc427e5024e46a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Julien Rische <jrische@redhat.com>
|
|
||||||
Date: Aug 02 2023 11:52:30 +0000
|
|
||||||
Subject: ipa-kdb: fix error handling of is_master_host()
|
|
||||||
|
|
||||||
|
|
||||||
Adding proper error handling to the is_master_host() function to allow
|
|
||||||
it to make the difference between the absence of a master host object
|
|
||||||
and a connection failure. This will keep the krb5kdc daemon from
|
|
||||||
continuing to run with a NULL LDAP context.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9422
|
|
||||||
|
|
||||||
Signed-off-by: Julien Rische <jrische@redhat.com>
|
|
||||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
|
||||||
index 8da7543..83cb991 100644
|
|
||||||
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
|
||||||
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
|
||||||
@@ -401,27 +401,29 @@ static krb5_error_code ipadb_add_asserted_identity(struct ipadb_context *ipactx,
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static bool is_master_host(struct ipadb_context *ipactx, const char *fqdn)
|
|
||||||
+static krb5_error_code
|
|
||||||
+is_master_host(struct ipadb_context *ipactx, const char *fqdn, bool *result)
|
|
||||||
{
|
|
||||||
- int ret;
|
|
||||||
+ int err;
|
|
||||||
char *master_host_base = NULL;
|
|
||||||
- LDAPMessage *result = NULL;
|
|
||||||
- krb5_error_code err;
|
|
||||||
+ LDAPMessage *ldap_res = NULL;
|
|
||||||
|
|
||||||
- ret = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s",
|
|
||||||
+ err = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s",
|
|
||||||
fqdn, ipactx->base);
|
|
||||||
- if (ret == -1) {
|
|
||||||
- return false;
|
|
||||||
- }
|
|
||||||
+ if (err == -1)
|
|
||||||
+ return ENOMEM;
|
|
||||||
+
|
|
||||||
err = ipadb_simple_search(ipactx, master_host_base, LDAP_SCOPE_BASE,
|
|
||||||
- NULL, NULL, &result);
|
|
||||||
+ NULL, NULL, &ldap_res);
|
|
||||||
free(master_host_base);
|
|
||||||
- ldap_msgfree(result);
|
|
||||||
- if (err == 0) {
|
|
||||||
- return true;
|
|
||||||
- }
|
|
||||||
+ ldap_msgfree(ldap_res);
|
|
||||||
+ if (err != KRB5_KDB_NOENTRY && err != 0)
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ if (result)
|
|
||||||
+ *result = err != KRB5_KDB_NOENTRY;
|
|
||||||
|
|
||||||
- return false;
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
|
||||||
@@ -692,9 +694,14 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
|
||||||
if ((is_host || is_service)) {
|
|
||||||
/* it is either host or service, so get the hostname first */
|
|
||||||
char *sep = strchr(info3->base.account_name.string, '/');
|
|
||||||
- bool is_master = is_master_host(
|
|
||||||
- ipactx,
|
|
||||||
- sep ? sep + 1 : info3->base.account_name.string);
|
|
||||||
+ bool is_master;
|
|
||||||
+
|
|
||||||
+ ret = is_master_host(ipactx,
|
|
||||||
+ sep ? sep + 1 : info3->base.account_name.string,
|
|
||||||
+ &is_master);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
if (is_master) {
|
|
||||||
/* Well known RID of domain controllers group */
|
|
||||||
if (info3->base.rid == 0) {
|
|
||||||
|
|
@ -0,0 +1,175 @@
|
|||||||
|
From 5afda72afc6fd626359411b55f092989fdd7d82d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Jan 15 2024 13:39:21 +0000
|
||||||
|
Subject: ipatests: ignore nsslapd-accesslog-logbuffering WARN in healthcheck
|
||||||
|
|
||||||
|
|
||||||
|
Log buffering is disabled in the integration tests so we can have all
|
||||||
|
the logs at the end. This is causing a warning to show in the 389-ds
|
||||||
|
checks and causing tests to fail that expect all SUCCESS.
|
||||||
|
|
||||||
|
Add an exclude for this specific key so tests will pass again.
|
||||||
|
|
||||||
|
We may eventually want a more sophisiticated mechanism to handle
|
||||||
|
excludes, or updating the config in general, but this is fine for now.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9400
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
|
||||||
|
index 7fb8e40..14fba26 100644
|
||||||
|
--- a/ipatests/test_integration/test_ipahealthcheck.py
|
||||||
|
+++ b/ipatests/test_integration/test_ipahealthcheck.py
|
||||||
|
@@ -9,6 +9,7 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
|
from configparser import RawConfigParser, NoOptionError
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
+import io
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
@@ -208,6 +209,28 @@ def run_healthcheck(host, source=None, check=None, output_type="json",
|
||||||
|
return result.returncode, data
|
||||||
|
|
||||||
|
|
||||||
|
+def set_excludes(host, option, value,
|
||||||
|
+ config_file='/etc/ipahealthcheck/ipahealthcheck.conf'):
|
||||||
|
+ """Mark checks that should be excluded from the results
|
||||||
|
+
|
||||||
|
+ This will set in the [excludes] section on host:
|
||||||
|
+ option=value
|
||||||
|
+ """
|
||||||
|
+ EXCLUDES = "excludes"
|
||||||
|
+
|
||||||
|
+ conf = host.get_file_contents(config_file, encoding='utf-8')
|
||||||
|
+ cfg = RawConfigParser()
|
||||||
|
+ cfg.read_string(conf)
|
||||||
|
+ if not cfg.has_section(EXCLUDES):
|
||||||
|
+ cfg.add_section(EXCLUDES)
|
||||||
|
+ if not cfg.has_option(EXCLUDES, option):
|
||||||
|
+ cfg.set(EXCLUDES, option, value)
|
||||||
|
+ out = io.StringIO()
|
||||||
|
+ cfg.write(out)
|
||||||
|
+ out.seek(0)
|
||||||
|
+ host.put_file_contents(config_file, out.read())
|
||||||
|
+
|
||||||
|
+
|
||||||
|
@pytest.fixture
|
||||||
|
def restart_service():
|
||||||
|
"""Shut down and restart a service as a fixture"""
|
||||||
|
@@ -265,6 +288,7 @@ class TestIpaHealthCheck(IntegrationTest):
|
||||||
|
setup_dns=True,
|
||||||
|
extra_args=['--no-dnssec-validation']
|
||||||
|
)
|
||||||
|
+ set_excludes(cls.master, "key", "DSCLE0004")
|
||||||
|
|
||||||
|
def test_ipa_healthcheck_install_on_master(self):
|
||||||
|
"""
|
||||||
|
@@ -552,6 +576,7 @@ class TestIpaHealthCheck(IntegrationTest):
|
||||||
|
setup_dns=True,
|
||||||
|
extra_args=['--no-dnssec-validation']
|
||||||
|
)
|
||||||
|
+ set_excludes(self.replicas[0], "key", "DSCLE0004")
|
||||||
|
|
||||||
|
# Init a user on replica to assign a DNA range
|
||||||
|
tasks.kinit_admin(self.replicas[0])
|
||||||
|
@@ -692,6 +717,7 @@ class TestIpaHealthCheck(IntegrationTest):
|
||||||
|
'output_type=human'
|
||||||
|
])
|
||||||
|
)
|
||||||
|
+ set_excludes(self.master, "key", "DSCLE0004", config_file)
|
||||||
|
returncode, output = run_healthcheck(
|
||||||
|
self.master, failures_only=True, config=config_file
|
||||||
|
)
|
||||||
|
@@ -707,6 +733,7 @@ class TestIpaHealthCheck(IntegrationTest):
|
||||||
|
'output_file=%s' % HC_LOG,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
+ set_excludes(self.master, "key", "DSCLE0004")
|
||||||
|
returncode, _unused = run_healthcheck(
|
||||||
|
self.master, config=config_file
|
||||||
|
)
|
||||||
|
@@ -2396,6 +2423,7 @@ class TestIpaHealthCLI(IntegrationTest):
|
||||||
|
cls.master, setup_dns=True, extra_args=['--no-dnssec-validation']
|
||||||
|
)
|
||||||
|
tasks.install_packages(cls.master, HEALTHCHECK_PKG)
|
||||||
|
+ set_excludes(cls.master, "key", "DSCLE0004")
|
||||||
|
|
||||||
|
def test_indent(self):
|
||||||
|
"""
|
||||||
|
diff --git a/ipatests/test_integration/test_replica_promotion.py b/ipatests/test_integration/test_replica_promotion.py
|
||||||
|
index d477c3a..b71f2d5 100644
|
||||||
|
--- a/ipatests/test_integration/test_replica_promotion.py
|
||||||
|
+++ b/ipatests/test_integration/test_replica_promotion.py
|
||||||
|
@@ -13,7 +13,7 @@ import pytest
|
||||||
|
|
||||||
|
from ipatests.test_integration.base import IntegrationTest
|
||||||
|
from ipatests.test_integration.test_ipahealthcheck import (
|
||||||
|
- run_healthcheck, HEALTHCHECK_PKG
|
||||||
|
+ run_healthcheck, set_excludes, HEALTHCHECK_PKG
|
||||||
|
)
|
||||||
|
from ipatests.pytest_ipa.integration import tasks
|
||||||
|
from ipatests.pytest_ipa.integration.tasks import (
|
||||||
|
@@ -983,6 +983,9 @@ class TestHiddenReplicaPromotion(IntegrationTest):
|
||||||
|
# manually install KRA to verify that hidden state is synced
|
||||||
|
tasks.install_kra(cls.replicas[0])
|
||||||
|
|
||||||
|
+ set_excludes(cls.master, "key", "DSCLE0004")
|
||||||
|
+ set_excludes(cls.replicas[0], "key", "DSCLE0004")
|
||||||
|
+
|
||||||
|
def _check_dnsrecords(self, hosts_expected, hosts_unexpected=()):
|
||||||
|
domain = DNSName(self.master.domain.name).make_absolute()
|
||||||
|
rset = [
|
||||||
|
|
||||||
|
From f1cfe7d9ff2489dbb6cad70999b0e1bd433c0537 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Jan 15 2024 13:39:21 +0000
|
||||||
|
Subject: ipatests: fix expected output for ipahealthcheck.ipa.host
|
||||||
|
|
||||||
|
|
||||||
|
ipa-healthcheck commit e69589d5 changed the output when a service
|
||||||
|
keytab is missing to not report the GSSAPI error but to report
|
||||||
|
that the keytab doesn't exist at all. This distinguishes from real
|
||||||
|
Kerberos issues like kvno.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9482
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
|
||||||
|
index 14fba26..8aae9fa 100644
|
||||||
|
--- a/ipatests/test_integration/test_ipahealthcheck.py
|
||||||
|
+++ b/ipatests/test_integration/test_ipahealthcheck.py
|
||||||
|
@@ -629,9 +629,15 @@ class TestIpaHealthCheck(IntegrationTest):
|
||||||
|
ipahealthcheck.ipa.host when GSSAPI credentials cannot be obtained
|
||||||
|
from host's keytab.
|
||||||
|
"""
|
||||||
|
- msg = (
|
||||||
|
- "Minor (2529639107): No credentials cache found"
|
||||||
|
- )
|
||||||
|
+ version = tasks.get_healthcheck_version(self.master)
|
||||||
|
+ if parse_version(version) >= parse_version("0.15"):
|
||||||
|
+ msg = (
|
||||||
|
+ "Service {service} keytab {path} does not exist."
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ msg = (
|
||||||
|
+ "Minor (2529639107): No credentials cache found"
|
||||||
|
+ )
|
||||||
|
|
||||||
|
with tasks.FileBackup(self.master, paths.KRB5_KEYTAB):
|
||||||
|
self.master.run_command(["rm", "-f", paths.KRB5_KEYTAB])
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
From f68468718c1e01df4a9180e17d7e24d961850e19 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Mohammad Rizwan <myusuf@redhat.com>
|
|
||||||
Date: Wed, 14 Jun 2023 17:32:02 +0530
|
|
||||||
Subject: [PATCH] ipatests: enable firewall rule for http service on acme
|
|
||||||
client
|
|
||||||
|
|
||||||
when system hardning done i.e in case of STIG, sometimes http challanges
|
|
||||||
can't be validated by CA if port 80 is not open. This fix enable it to facilitate
|
|
||||||
the communication.
|
|
||||||
|
|
||||||
Signed-off-by: Mohammad Rizwan <myusuf@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
|
||||||
---
|
|
||||||
ipatests/test_integration/test_acme.py | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
|
|
||||||
index c69e810da70..414fae8d751 100644
|
|
||||||
--- a/ipatests/test_integration/test_acme.py
|
|
||||||
+++ b/ipatests/test_integration/test_acme.py
|
|
||||||
@@ -10,6 +10,7 @@
|
|
||||||
|
|
||||||
from ipalib.constants import IPA_CA_RECORD
|
|
||||||
from ipatests.test_integration.base import IntegrationTest
|
|
||||||
+from ipatests.pytest_ipa.integration.firewall import Firewall
|
|
||||||
from ipatests.pytest_ipa.integration import tasks
|
|
||||||
from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup
|
|
||||||
from ipaplatform.osinfo import osinfo
|
|
||||||
@@ -82,6 +83,9 @@ def prepare_acme_client(master, client):
|
|
||||||
acme_host = f'{IPA_CA_RECORD}.{master.domain.name}'
|
|
||||||
acme_server = f'https://{acme_host}/acme/directory'
|
|
||||||
|
|
||||||
+ # enable firewall rule on client
|
|
||||||
+ Firewall(client).enable_services(["http", "https"])
|
|
||||||
+
|
|
||||||
# install acme client packages
|
|
||||||
if not skip_certbot_tests:
|
|
||||||
tasks.install_packages(client, ['certbot'])
|
|
@ -1,193 +0,0 @@
|
|||||||
From 99aa03413421cf2839e89e10ca279ec19233dd01 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Jul 20 2023 08:23:36 +0000
|
|
||||||
Subject: User plugin: improve error related to non existing idp
|
|
||||||
|
|
||||||
|
|
||||||
The user and stageuser commands return the following error
|
|
||||||
when the user is created/updated with a non existing idp:
|
|
||||||
$ ipa user-add testuser --first test --last user --idp dummy
|
|
||||||
ipa: ERROR: no such entry
|
|
||||||
|
|
||||||
The error is not descriptive enough and has been modified to
|
|
||||||
display instead:
|
|
||||||
$ ipa user-add testuser --first test --last user --idp dummy
|
|
||||||
ipa: ERROR: External IdP configuration dummy not found
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9416
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py
|
|
||||||
index 73b76d3..ba5f9b7 100644
|
|
||||||
--- a/ipaserver/plugins/baseuser.py
|
|
||||||
+++ b/ipaserver/plugins/baseuser.py
|
|
||||||
@@ -708,7 +708,11 @@ class baseuser_mod(LDAPUpdate):
|
|
||||||
if 'ipaidpuser' not in obj_classes:
|
|
||||||
entry_attrs['objectclass'].append('ipaidpuser')
|
|
||||||
|
|
||||||
- answer = self.api.Object['idp'].get_dn_if_exists(cl)
|
|
||||||
+ try:
|
|
||||||
+ answer = self.api.Object['idp'].get_dn_if_exists(cl)
|
|
||||||
+ except errors.NotFound:
|
|
||||||
+ reason = "External IdP configuration {} not found"
|
|
||||||
+ raise errors.NotFound(reason=_(reason).format(cl))
|
|
||||||
entry_attrs['ipaidpconfiglink'] = answer
|
|
||||||
|
|
||||||
# Note: we could have used the method add_missing_object_class
|
|
||||||
diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py
|
|
||||||
index 51438a8..852e51b 100644
|
|
||||||
--- a/ipaserver/plugins/stageuser.py
|
|
||||||
+++ b/ipaserver/plugins/stageuser.py
|
|
||||||
@@ -404,7 +404,11 @@ class stageuser_add(baseuser_add):
|
|
||||||
if 'ipaidpuser' not in entry_attrs['objectclass']:
|
|
||||||
entry_attrs['objectclass'].append('ipaidpuser')
|
|
||||||
|
|
||||||
- answer = self.api.Object['idp'].get_dn_if_exists(cl)
|
|
||||||
+ try:
|
|
||||||
+ answer = self.api.Object['idp'].get_dn_if_exists(cl)
|
|
||||||
+ except errors.NotFound:
|
|
||||||
+ reason = "External IdP configuration {} not found"
|
|
||||||
+ raise errors.NotFound(reason=_(reason).format(cl))
|
|
||||||
entry_attrs['ipaidpconfiglink'] = answer
|
|
||||||
|
|
||||||
self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys,
|
|
||||||
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
|
|
||||||
index 643b44f..a337e1f 100644
|
|
||||||
--- a/ipaserver/plugins/user.py
|
|
||||||
+++ b/ipaserver/plugins/user.py
|
|
||||||
@@ -638,7 +638,11 @@ class user_add(baseuser_add):
|
|
||||||
if 'ipaidpuser' not in entry_attrs['objectclass']:
|
|
||||||
entry_attrs['objectclass'].append('ipaidpuser')
|
|
||||||
|
|
||||||
- answer = self.api.Object['idp'].get_dn_if_exists(rcl)
|
|
||||||
+ try:
|
|
||||||
+ answer = self.api.Object['idp'].get_dn_if_exists(rcl)
|
|
||||||
+ except errors.NotFound:
|
|
||||||
+ reason = "External IdP configuration {} not found"
|
|
||||||
+ raise errors.NotFound(reason=_(reason).format(rcl))
|
|
||||||
entry_attrs['ipaidpconfiglink'] = answer
|
|
||||||
|
|
||||||
self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys,
|
|
||||||
|
|
||||||
From dbcbe9a39c99008c6858bab53e2807b7bf01ba65 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Jul 20 2023 08:23:36 +0000
|
|
||||||
Subject: xmlrpc tests: add a test for user plugin with non-existing idp
|
|
||||||
|
|
||||||
|
|
||||||
Add new tests checking the error returned for
|
|
||||||
ipa user-add ... --idp nonexistingidp
|
|
||||||
ipa user-mod ... --idp nonexistingidp
|
|
||||||
ipa stageuser-add ... --idp nonexistingidp
|
|
||||||
ipa stageuser-mod ... --idp nonexistingidp
|
|
||||||
|
|
||||||
The expected error message is:
|
|
||||||
ipa: ERROR: External IdP configuration nonexistingidp not found
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/9416
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py
|
|
||||||
index 394015f..9ae5561 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py
|
|
||||||
@@ -39,6 +39,8 @@ gid = u'456'
|
|
||||||
invalidrealm1 = u'suser1@NOTFOUND.ORG'
|
|
||||||
invalidrealm2 = u'suser1@BAD@NOTFOUND.ORG'
|
|
||||||
|
|
||||||
+nonexistentidp = 'IdPDoesNotExist'
|
|
||||||
+
|
|
||||||
invaliduser1 = u'+tuser1'
|
|
||||||
invaliduser2 = u'tuser1234567890123456789012345678901234567890'
|
|
||||||
invaliduser3 = u'1234'
|
|
||||||
@@ -431,6 +433,15 @@ class TestCreateInvalidAttributes(XMLRPC_test):
|
|
||||||
invalidrealm2))):
|
|
||||||
command()
|
|
||||||
|
|
||||||
+ def test_create_invalid_idp(self, stageduser):
|
|
||||||
+ stageduser.ensure_missing()
|
|
||||||
+ command = stageduser.make_create_command(
|
|
||||||
+ options={u'ipaidpconfiglink': nonexistentidp})
|
|
||||||
+ with raises_exact(errors.NotFound(
|
|
||||||
+ reason="External IdP configuration {} not found".format(
|
|
||||||
+ nonexistentidp))):
|
|
||||||
+ command()
|
|
||||||
+
|
|
||||||
|
|
||||||
@pytest.mark.tier1
|
|
||||||
class TestUpdateInvalidAttributes(XMLRPC_test):
|
|
||||||
@@ -466,6 +477,15 @@ class TestUpdateInvalidAttributes(XMLRPC_test):
|
|
||||||
message=u'invalid \'gidnumber\': must be at least 1')):
|
|
||||||
command()
|
|
||||||
|
|
||||||
+ def test_update_invalididp(self, stageduser):
|
|
||||||
+ stageduser.ensure_exists()
|
|
||||||
+ command = stageduser.make_update_command(
|
|
||||||
+ updates={u'ipaidpconfiglink': nonexistentidp})
|
|
||||||
+ with raises_exact(errors.NotFound(
|
|
||||||
+ reason="External IdP configuration {} not found".format(
|
|
||||||
+ nonexistentidp))):
|
|
||||||
+ command()
|
|
||||||
+
|
|
||||||
|
|
||||||
@pytest.mark.tier1
|
|
||||||
class TestActive(XMLRPC_test):
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
index 8ac19a4..baa2867 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
@@ -86,6 +86,8 @@ expired_expiration_string = "1991-12-07T19:54:13Z"
|
|
||||||
# Date in ISO format (2013-12-10T12:00:00)
|
|
||||||
isodate_re = re.compile(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$')
|
|
||||||
|
|
||||||
+nonexistentidp = 'IdPDoesNotExist'
|
|
||||||
+
|
|
||||||
|
|
||||||
@pytest.fixture(scope='class')
|
|
||||||
def user_min(request, xmlrpc_setup):
|
|
||||||
@@ -542,6 +544,18 @@ class TestUpdate(XMLRPC_test):
|
|
||||||
command()
|
|
||||||
user.delete()
|
|
||||||
|
|
||||||
+ def test_update_invalid_idp(self, user):
|
|
||||||
+ """ Test user-mod --idp with a non-existent idp """
|
|
||||||
+ user.ensure_exists()
|
|
||||||
+ command = user.make_update_command(
|
|
||||||
+ updates=dict(ipaidpconfiglink=nonexistentidp)
|
|
||||||
+ )
|
|
||||||
+ with raises_exact(errors.NotFound(
|
|
||||||
+ reason="External IdP configuration {} not found".format(
|
|
||||||
+ nonexistentidp)
|
|
||||||
+ )):
|
|
||||||
+ command()
|
|
||||||
+
|
|
||||||
|
|
||||||
@pytest.mark.tier1
|
|
||||||
class TestCreate(XMLRPC_test):
|
|
||||||
@@ -770,6 +784,17 @@ class TestCreate(XMLRPC_test):
|
|
||||||
user_radius.check_create(result)
|
|
||||||
user_radius.delete()
|
|
||||||
|
|
||||||
+ def test_create_with_invalididp(self):
|
|
||||||
+ testuser = UserTracker(
|
|
||||||
+ name='idpuser', givenname='idp', sn='user',
|
|
||||||
+ ipaidpconfiglink=nonexistentidp
|
|
||||||
+ )
|
|
||||||
+ with raises_exact(errors.NotFound(
|
|
||||||
+ reason="External IdP configuration {} not found".format(
|
|
||||||
+ nonexistentidp)
|
|
||||||
+ )):
|
|
||||||
+ testuser.create()
|
|
||||||
+
|
|
||||||
|
|
||||||
@pytest.mark.tier1
|
|
||||||
class TestUserWithGroup(XMLRPC_test):
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
From dcb9d6edc7ae4278cd552e87f644705faa13d558 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Jan 31 2024 08:31:13 +0000
|
||||||
|
Subject: kdb: PAC generator: do not fail if canonical principal is missing
|
||||||
|
|
||||||
|
|
||||||
|
krbCanonicalName is mandatory for services but IPA services created
|
||||||
|
before commit e6ff83e (FreeIPA 4.4.0, ~2016) had no normalization done
|
||||||
|
to set krbCanonicalName; services created after that version were
|
||||||
|
upgraded to do have krbCanonicalName.
|
||||||
|
|
||||||
|
Accept krbPrincipalName alone since they have no alias either */
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9465
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index 9e1431c..8035036 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -496,8 +496,16 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
||||||
|
ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
"krbCanonicalName", &strres);
|
||||||
|
if (ret) {
|
||||||
|
- /* krbCanonicalName is mandatory for services */
|
||||||
|
- return ret;
|
||||||
|
+ /* krbCanonicalName is mandatory for services but IPA services
|
||||||
|
+ * created before commit e6ff83e (FreeIPA 4.4.0, ~2016) had no
|
||||||
|
+ * normalization to set krbCanonicalName; services created after
|
||||||
|
+ * that version were upgraded to do have krbCanonicalName.
|
||||||
|
+ *
|
||||||
|
+ * Accept krbPrincipalName alone since they have no alias either */
|
||||||
|
+ ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
+ "krbPrincipalName", &strres);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_parse_name(ipactx->kcontext, strres, &princ);
|
||||||
|
|
@ -1,169 +0,0 @@
|
|||||||
From f215d3f45396fa29bdd69f56096b50842df14908 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Date: Aug 01 2023 22:03:03 +0000
|
|
||||||
Subject: Prevent the admin user from being deleted
|
|
||||||
|
|
||||||
|
|
||||||
admin is required for trust operations
|
|
||||||
|
|
||||||
Note that testing for removing the last member is now
|
|
||||||
irrelevant because admin must always exist so the test
|
|
||||||
for it was removed, but the code check remains. It is done
|
|
||||||
after the protected member check.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/8878
|
|
||||||
|
|
||||||
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
|
|
||||||
index a337e1f..6f5e349 100644
|
|
||||||
--- a/ipaserver/plugins/user.py
|
|
||||||
+++ b/ipaserver/plugins/user.py
|
|
||||||
@@ -138,14 +138,23 @@ MEMBEROF_ADMINS = "(memberOf={})".format(
|
|
||||||
)
|
|
||||||
|
|
||||||
NOT_MEMBEROF_ADMINS = '(!{})'.format(MEMBEROF_ADMINS)
|
|
||||||
+PROTECTED_USERS = ('admin',)
|
|
||||||
|
|
||||||
|
|
||||||
def check_protected_member(user, protected_group_name=u'admins'):
|
|
||||||
'''
|
|
||||||
- Ensure the last enabled member of a protected group cannot be deleted or
|
|
||||||
- disabled by raising LastMemberError.
|
|
||||||
+ Ensure admin and the last enabled member of a protected group cannot
|
|
||||||
+ be deleted or disabled by raising ProtectedEntryError or
|
|
||||||
+ LastMemberError as appropriate.
|
|
||||||
'''
|
|
||||||
|
|
||||||
+ if user in PROTECTED_USERS:
|
|
||||||
+ raise errors.ProtectedEntryError(
|
|
||||||
+ label=_("user"),
|
|
||||||
+ key=user,
|
|
||||||
+ reason=_("privileged user"),
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
# Get all users in the protected group
|
|
||||||
result = api.Command.user_find(in_group=protected_group_name)
|
|
||||||
|
|
||||||
@@ -868,6 +877,12 @@ class user_mod(baseuser_mod):
|
|
||||||
|
|
||||||
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
|
|
||||||
dn, oc = self.obj.get_either_dn(*keys, **options)
|
|
||||||
+ if options.get('rename') and keys[-1] in PROTECTED_USERS:
|
|
||||||
+ raise errors.ProtectedEntryError(
|
|
||||||
+ label=_("user"),
|
|
||||||
+ key=keys[-1],
|
|
||||||
+ reason=_("privileged user"),
|
|
||||||
+ )
|
|
||||||
if 'objectclass' not in entry_attrs and 'rename' not in options:
|
|
||||||
entry_attrs.update({'objectclass': oc})
|
|
||||||
self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys,
|
|
||||||
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
index baa2867..df105a2 100644
|
|
||||||
--- a/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
|
|
||||||
@@ -978,22 +978,32 @@ class TestManagers(XMLRPC_test):
|
|
||||||
|
|
||||||
@pytest.mark.tier1
|
|
||||||
class TestAdmins(XMLRPC_test):
|
|
||||||
- def test_remove_original_admin(self):
|
|
||||||
- """ Try to remove the only admin """
|
|
||||||
+ def test_delete_admin(self):
|
|
||||||
+ """ Try to delete the protected admin user """
|
|
||||||
tracker = Tracker()
|
|
||||||
- command = tracker.make_command('user_del', [admin1])
|
|
||||||
+ command = tracker.make_command('user_del', admin1)
|
|
||||||
|
|
||||||
- with raises_exact(errors.LastMemberError(
|
|
||||||
- key=admin1, label=u'group', container=admin_group)):
|
|
||||||
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
|
|
||||||
+ key=admin1, reason='privileged user')):
|
|
||||||
+ command()
|
|
||||||
+
|
|
||||||
+ def test_rename_admin(self):
|
|
||||||
+ """ Try to rename the admin user """
|
|
||||||
+ tracker = Tracker()
|
|
||||||
+ command = tracker.make_command('user_mod', admin1,
|
|
||||||
+ **dict(rename=u'newadmin'))
|
|
||||||
+
|
|
||||||
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
|
|
||||||
+ key=admin1, reason='privileged user')):
|
|
||||||
command()
|
|
||||||
|
|
||||||
def test_disable_original_admin(self):
|
|
||||||
- """ Try to disable the only admin """
|
|
||||||
+ """ Try to disable the original admin """
|
|
||||||
tracker = Tracker()
|
|
||||||
command = tracker.make_command('user_disable', admin1)
|
|
||||||
|
|
||||||
- with raises_exact(errors.LastMemberError(
|
|
||||||
- key=admin1, label=u'group', container=admin_group)):
|
|
||||||
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
|
|
||||||
+ key=admin1, reason='privileged user')):
|
|
||||||
command()
|
|
||||||
|
|
||||||
def test_create_admin2(self, admin2):
|
|
||||||
@@ -1011,21 +1021,11 @@ class TestAdmins(XMLRPC_test):
|
|
||||||
admin2.disable()
|
|
||||||
tracker = Tracker()
|
|
||||||
|
|
||||||
- with raises_exact(errors.LastMemberError(
|
|
||||||
- key=admin1, label=u'group', container=admin_group)):
|
|
||||||
+ with raises_exact(errors.ProtectedEntryError(label=u'user',
|
|
||||||
+ key=admin1, reason='privileged user')):
|
|
||||||
tracker.run_command('user_disable', admin1)
|
|
||||||
- with raises_exact(errors.LastMemberError(
|
|
||||||
- key=admin1, label=u'group', container=admin_group)):
|
|
||||||
- tracker.run_command('user_del', admin1)
|
|
||||||
admin2.delete()
|
|
||||||
|
|
||||||
- with raises_exact(errors.LastMemberError(
|
|
||||||
- key=admin1, label=u'group', container=admin_group)):
|
|
||||||
- tracker.run_command('user_disable', admin1)
|
|
||||||
- with raises_exact(errors.LastMemberError(
|
|
||||||
- key=admin1, label=u'group', container=admin_group)):
|
|
||||||
- tracker.run_command('user_del', admin1)
|
|
||||||
-
|
|
||||||
|
|
||||||
@pytest.mark.tier1
|
|
||||||
class TestPreferredLanguages(XMLRPC_test):
|
|
||||||
|
|
||||||
From 7d62d84bdd3c2acd2f4bf70bb5fabf14c72e8ee7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Aug 08 2023 14:50:32 +0000
|
|
||||||
Subject: ipatests: update expected webui msg for admin deletion
|
|
||||||
|
|
||||||
|
|
||||||
The deletion of the admin is now forbidden (even if it is
|
|
||||||
not the last member of the admins group) and the error
|
|
||||||
message has changed from "admin cannot be deleted or
|
|
||||||
disabled because it is the last member of group admins"
|
|
||||||
to " user admin cannot be deleted/modified: privileged user".
|
|
||||||
|
|
||||||
Update the expected message in the webui test.
|
|
||||||
|
|
||||||
Related: https://pagure.io/freeipa/issue/8878
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_webui/test_user.py b/ipatests/test_webui/test_user.py
|
|
||||||
index 8d44fbd..a8a92d0 100644
|
|
||||||
--- a/ipatests/test_webui/test_user.py
|
|
||||||
+++ b/ipatests/test_webui/test_user.py
|
|
||||||
@@ -50,8 +50,7 @@ INV_FIRSTNAME = ("invalid 'first': Leading and trailing spaces are "
|
|
||||||
FIELD_REQ = 'Required field'
|
|
||||||
ERR_INCLUDE = 'may only include letters, numbers, _, -, . and $'
|
|
||||||
ERR_MISMATCH = 'Passwords must match'
|
|
||||||
-ERR_ADMIN_DEL = ('admin cannot be deleted or disabled because it is the last '
|
|
||||||
- 'member of group admins')
|
|
||||||
+ERR_ADMIN_DEL = ('user admin cannot be deleted/modified: privileged user')
|
|
||||||
USR_EXIST = 'user with name "{}" already exists'
|
|
||||||
ENTRY_EXIST = 'This entry already exists'
|
|
||||||
ACTIVE_ERR = 'active user with name "{}" already exists'
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
|||||||
|
From bac601b7f35827236a106f7137f378e4888260da Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Jan 30 2024 15:17:44 +0000
|
||||||
|
Subject: ipa-kdb: Fix memory leak during PAC verification
|
||||||
|
|
||||||
|
|
||||||
|
Commit 0022bd70d93708d325855d5271516d6cd894d6e8 introduced a memory leak
|
||||||
|
during the copy of some PAC buffers, because of an unfreed memory
|
||||||
|
allocation context.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9520
|
||||||
|
|
||||||
|
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index a18beff..9e1431c 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -2316,6 +2316,7 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||||
|
size_t i;
|
||||||
|
struct dom_sid *requester_sid = NULL;
|
||||||
|
struct dom_sid req_sid;
|
||||||
|
+ TALLOC_CTX *tmpctx = NULL;
|
||||||
|
|
||||||
|
if (signing_krbtgt != NULL &&
|
||||||
|
ipadb_is_cross_realm_krbtgt(signing_krbtgt->princ)) {
|
||||||
|
@@ -2371,6 +2372,12 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ tmpctx = talloc_new(NULL);
|
||||||
|
+ if (tmpctx == NULL) {
|
||||||
|
+ kerr = ENOMEM;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
for (i = 0; i < num_buffers; i++) {
|
||||||
|
if (types[i] == KRB5_PAC_SERVER_CHECKSUM ||
|
||||||
|
types[i] == KRB5_PAC_PRIVSVR_CHECKSUM ||
|
||||||
|
@@ -2395,32 +2402,21 @@ krb5_error_code ipadb_common_verify_pac(krb5_context context,
|
||||||
|
DATA_BLOB pac_attrs_data;
|
||||||
|
krb5_boolean pac_requested;
|
||||||
|
|
||||||
|
- TALLOC_CTX *tmpctx = talloc_new(NULL);
|
||||||
|
- if (tmpctx == NULL) {
|
||||||
|
- kerr = ENOMEM;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
kerr = ipadb_client_requested_pac(context, old_pac, tmpctx, &pac_requested);
|
||||||
|
- if (kerr != 0) {
|
||||||
|
- talloc_free(tmpctx);
|
||||||
|
+ if (kerr)
|
||||||
|
goto done;
|
||||||
|
- }
|
||||||
|
|
||||||
|
kerr = ipadb_get_pac_attrs_blob(tmpctx, &pac_requested, &pac_attrs_data);
|
||||||
|
- if (kerr) {
|
||||||
|
- talloc_free(tmpctx);
|
||||||
|
+ if (kerr)
|
||||||
|
goto done;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
data.magic = KV5M_DATA;
|
||||||
|
data.data = (char *)pac_attrs_data.data;
|
||||||
|
data.length = pac_attrs_data.length;
|
||||||
|
|
||||||
|
kerr = krb5_pac_add_buffer(context, new_pac, PAC_TYPE_ATTRIBUTES_INFO, &data);
|
||||||
|
- if (kerr) {
|
||||||
|
- talloc_free(tmpctx);
|
||||||
|
+ if (kerr)
|
||||||
|
goto done;
|
||||||
|
- }
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
@@ -2467,6 +2463,8 @@ done:
|
||||||
|
if (kerr != 0 && (new_pac != *pac)) {
|
||||||
|
krb5_pac_free(context, new_pac);
|
||||||
|
}
|
||||||
|
+ if (tmpctx)
|
||||||
|
+ talloc_free(tmpctx);
|
||||||
|
krb5_free_data_contents(context, &pac_blob);
|
||||||
|
free(types);
|
||||||
|
return kerr;
|
||||||
|
|
@ -1,114 +0,0 @@
|
|||||||
From 9438ce9207445e4ad4a9c7bdf0c9e569cabac571 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Date: Aug 01 2023 06:07:06 +0000
|
|
||||||
Subject: Fix memory leak in the OTP last token plugin
|
|
||||||
|
|
||||||
|
|
||||||
Three memory leaks are addressed:
|
|
||||||
|
|
||||||
1. String values retrieved from the pblock need to be manually
|
|
||||||
freed.
|
|
||||||
|
|
||||||
2. The list of objectclasses retreived from the pblock need to be
|
|
||||||
freed.
|
|
||||||
|
|
||||||
3. Internal search results need to be freed.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9403
|
|
||||||
|
|
||||||
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
|
||||||
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
|
|
||||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
|
|
||||||
index b7a2ba7..11106b2 100644
|
|
||||||
--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
|
|
||||||
+++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c
|
|
||||||
@@ -54,7 +54,7 @@ void *ipa_otp_lasttoken_plugin_id;
|
|
||||||
|
|
||||||
static bool entry_is_token(Slapi_Entry *entry)
|
|
||||||
{
|
|
||||||
- char **ocls;
|
|
||||||
+ char **ocls = NULL;
|
|
||||||
|
|
||||||
ocls = slapi_entry_attr_get_charray(entry, SLAPI_ATTR_OBJECTCLASS);
|
|
||||||
for (size_t i = 0; ocls != NULL && ocls[i] != NULL; i++) {
|
|
||||||
@@ -64,6 +64,7 @@ static bool entry_is_token(Slapi_Entry *entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ slapi_ch_array_free(ocls);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -138,7 +139,8 @@ static bool is_pwd_enabled(const char *user_dn)
|
|
||||||
static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
|
|
||||||
{
|
|
||||||
Slapi_DN *target_sdn = NULL;
|
|
||||||
- const char *bind_dn;
|
|
||||||
+ char *bind_dn;
|
|
||||||
+ bool rv = false;
|
|
||||||
|
|
||||||
/* Ignore internal operations. */
|
|
||||||
if (slapi_op_internal(pb))
|
|
||||||
@@ -147,23 +149,35 @@ static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry)
|
|
||||||
/* Load parameters. */
|
|
||||||
(void) slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
|
|
||||||
(void) slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
|
|
||||||
- if (target_sdn == NULL || bind_dn == NULL) {
|
|
||||||
- LOG_FATAL("Missing parameters!\n");
|
|
||||||
- return false;
|
|
||||||
+ if (bind_dn == NULL) {
|
|
||||||
+ LOG_FATAL("bind_dn parameter missing!\n");
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ if (target_sdn == NULL) {
|
|
||||||
+ LOG_FATAL("target_sdn parameter missing!\n");
|
|
||||||
+ goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry != NULL
|
|
||||||
? !entry_is_token(entry)
|
|
||||||
- : !sdn_in_otp_container(target_sdn))
|
|
||||||
- return true;
|
|
||||||
+ : !sdn_in_otp_container(target_sdn)) {
|
|
||||||
+ rv = true;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (!sdn_is_only_enabled_token(target_sdn, bind_dn))
|
|
||||||
- return true;
|
|
||||||
+ if (!sdn_is_only_enabled_token(target_sdn, bind_dn)) {
|
|
||||||
+ rv = true;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (is_pwd_enabled(bind_dn))
|
|
||||||
- return true;
|
|
||||||
+ if (is_pwd_enabled(bind_dn)) {
|
|
||||||
+ rv = true;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- return false;
|
|
||||||
+done:
|
|
||||||
+ slapi_ch_free_string(&bind_dn);
|
|
||||||
+ return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int send_error(Slapi_PBlock *pb, int rc, const char *errstr)
|
|
||||||
diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.c b/daemons/ipa-slapi-plugins/libotp/otp_token.c
|
|
||||||
index a3cbfb0..4be4ede 100644
|
|
||||||
--- a/daemons/ipa-slapi-plugins/libotp/otp_token.c
|
|
||||||
+++ b/daemons/ipa-slapi-plugins/libotp/otp_token.c
|
|
||||||
@@ -398,6 +398,7 @@ static struct otp_token **find(const struct otp_config *cfg, const char *user_dn
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
+ slapi_free_search_results_internal(pb);
|
|
||||||
slapi_pblock_destroy(pb);
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
238
SOURCES/0011-Fix-session-cookie-access_rhel#23622.patch
Normal file
238
SOURCES/0011-Fix-session-cookie-access_rhel#23622.patch
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
From 381af470779ea87335f57038dcbe72cd042ae6bb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stanislav Levin <slev@altlinux.org>
|
||||||
|
Date: Jan 30 2024 15:11:05 +0000
|
||||||
|
Subject: ipapython: Clean up krb5_error
|
||||||
|
|
||||||
|
|
||||||
|
`krb5_error` has different definition in MIT krb.
|
||||||
|
https://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/types/krb5_error.html
|
||||||
|
|
||||||
|
> Error message structure.
|
||||||
|
>
|
||||||
|
> Declaration:
|
||||||
|
> typedef struct _krb5_error krb5_error
|
||||||
|
|
||||||
|
While `krb5_error_code`
|
||||||
|
https://web.mit.edu/kerberos/www/krb5-latest/doc/appdev/refs/types/krb5_error_code.html#c.krb5_error_code
|
||||||
|
|
||||||
|
> krb5_error_code
|
||||||
|
> Used to convey an operation status.
|
||||||
|
>
|
||||||
|
> The value 0 indicates success; any other values are com_err codes. Use krb5_get_error_message() to obtain a string describing the error.
|
||||||
|
>
|
||||||
|
> Declaration
|
||||||
|
> typedef krb5_int32 krb5_error_code
|
||||||
|
|
||||||
|
And this is what was actually used.
|
||||||
|
|
||||||
|
To prevent confusion of types `krb5_error` was replaced with
|
||||||
|
`krb5_error_code`.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9519
|
||||||
|
Signed-off-by: Stanislav Levin <slev@altlinux.org>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
|
||||||
|
index c43ef7d..371cf15 100644
|
||||||
|
--- a/ipapython/session_storage.py
|
||||||
|
+++ b/ipapython/session_storage.py
|
||||||
|
@@ -111,7 +111,7 @@ class KRB5Error(Exception):
|
||||||
|
|
||||||
|
|
||||||
|
def krb5_errcheck(result, func, arguments):
|
||||||
|
- """Error checker for krb5_error return value"""
|
||||||
|
+ """Error checker for krb5_error_code return value"""
|
||||||
|
if result != 0:
|
||||||
|
raise KRB5Error(result, func.__name__, arguments)
|
||||||
|
|
||||||
|
@@ -119,14 +119,13 @@ def krb5_errcheck(result, func, arguments):
|
||||||
|
krb5_context = ctypes.POINTER(_krb5_context)
|
||||||
|
krb5_ccache = ctypes.POINTER(_krb5_ccache)
|
||||||
|
krb5_data_p = ctypes.POINTER(_krb5_data)
|
||||||
|
-krb5_error = ctypes.c_int32
|
||||||
|
krb5_creds = _krb5_creds
|
||||||
|
krb5_pointer = ctypes.c_void_p
|
||||||
|
krb5_cc_cursor = krb5_pointer
|
||||||
|
|
||||||
|
krb5_init_context = LIBKRB5.krb5_init_context
|
||||||
|
krb5_init_context.argtypes = (ctypes.POINTER(krb5_context), )
|
||||||
|
-krb5_init_context.restype = krb5_error
|
||||||
|
+krb5_init_context.restype = krb5_error_code
|
||||||
|
krb5_init_context.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_free_context = LIBKRB5.krb5_free_context
|
||||||
|
@@ -143,30 +142,30 @@ krb5_free_data_contents.restype = None
|
||||||
|
|
||||||
|
krb5_cc_default = LIBKRB5.krb5_cc_default
|
||||||
|
krb5_cc_default.argtypes = (krb5_context, ctypes.POINTER(krb5_ccache), )
|
||||||
|
-krb5_cc_default.restype = krb5_error
|
||||||
|
+krb5_cc_default.restype = krb5_error_code
|
||||||
|
krb5_cc_default.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_cc_close = LIBKRB5.krb5_cc_close
|
||||||
|
krb5_cc_close.argtypes = (krb5_context, krb5_ccache, )
|
||||||
|
-krb5_cc_close.restype = krb5_error
|
||||||
|
+krb5_cc_close.restype = krb5_error_code
|
||||||
|
krb5_cc_close.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_parse_name = LIBKRB5.krb5_parse_name
|
||||||
|
krb5_parse_name.argtypes = (krb5_context, ctypes.c_char_p,
|
||||||
|
ctypes.POINTER(krb5_principal), )
|
||||||
|
-krb5_parse_name.restype = krb5_error
|
||||||
|
+krb5_parse_name.restype = krb5_error_code
|
||||||
|
krb5_parse_name.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_cc_set_config = LIBKRB5.krb5_cc_set_config
|
||||||
|
krb5_cc_set_config.argtypes = (krb5_context, krb5_ccache, krb5_principal,
|
||||||
|
ctypes.c_char_p, krb5_data_p, )
|
||||||
|
-krb5_cc_set_config.restype = krb5_error
|
||||||
|
+krb5_cc_set_config.restype = krb5_error_code
|
||||||
|
krb5_cc_set_config.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_cc_get_principal = LIBKRB5.krb5_cc_get_principal
|
||||||
|
krb5_cc_get_principal.argtypes = (krb5_context, krb5_ccache,
|
||||||
|
ctypes.POINTER(krb5_principal), )
|
||||||
|
-krb5_cc_get_principal.restype = krb5_error
|
||||||
|
+krb5_cc_get_principal.restype = krb5_error_code
|
||||||
|
krb5_cc_get_principal.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
# krb5_build_principal is a variadic function but that can't be expressed
|
||||||
|
@@ -177,26 +176,26 @@ krb5_build_principal.argtypes = (krb5_context, ctypes.POINTER(krb5_principal),
|
||||||
|
ctypes.c_uint, ctypes.c_char_p,
|
||||||
|
ctypes.c_char_p, ctypes.c_char_p,
|
||||||
|
ctypes.c_char_p, ctypes.c_char_p, )
|
||||||
|
-krb5_build_principal.restype = krb5_error
|
||||||
|
+krb5_build_principal.restype = krb5_error_code
|
||||||
|
krb5_build_principal.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_cc_start_seq_get = LIBKRB5.krb5_cc_start_seq_get
|
||||||
|
krb5_cc_start_seq_get.argtypes = (krb5_context, krb5_ccache,
|
||||||
|
ctypes.POINTER(krb5_cc_cursor), )
|
||||||
|
-krb5_cc_start_seq_get.restype = krb5_error
|
||||||
|
+krb5_cc_start_seq_get.restype = krb5_error_code
|
||||||
|
krb5_cc_start_seq_get.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_cc_next_cred = LIBKRB5.krb5_cc_next_cred
|
||||||
|
krb5_cc_next_cred.argtypes = (krb5_context, krb5_ccache,
|
||||||
|
ctypes.POINTER(krb5_cc_cursor),
|
||||||
|
ctypes.POINTER(krb5_creds), )
|
||||||
|
-krb5_cc_next_cred.restype = krb5_error
|
||||||
|
+krb5_cc_next_cred.restype = krb5_error_code
|
||||||
|
krb5_cc_next_cred.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_cc_end_seq_get = LIBKRB5.krb5_cc_end_seq_get
|
||||||
|
krb5_cc_end_seq_get.argtypes = (krb5_context, krb5_ccache,
|
||||||
|
ctypes.POINTER(krb5_cc_cursor), )
|
||||||
|
-krb5_cc_end_seq_get.restype = krb5_error
|
||||||
|
+krb5_cc_end_seq_get.restype = krb5_error_code
|
||||||
|
krb5_cc_end_seq_get.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_free_cred_contents = LIBKRB5.krb5_free_cred_contents
|
||||||
|
@@ -212,7 +211,7 @@ krb5_principal_compare.restype = krb5_boolean
|
||||||
|
krb5_unparse_name = LIBKRB5.krb5_unparse_name
|
||||||
|
krb5_unparse_name.argtypes = (krb5_context, krb5_principal,
|
||||||
|
ctypes.POINTER(ctypes.c_char_p), )
|
||||||
|
-krb5_unparse_name.restype = krb5_error
|
||||||
|
+krb5_unparse_name.restype = krb5_error_code
|
||||||
|
krb5_unparse_name.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_free_unparsed_name = LIBKRB5.krb5_free_unparsed_name
|
||||||
|
|
||||||
|
From 2a4bad8bb3295c5c0f5a760ecd41871c4c5a0c56 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stanislav Levin <slev@altlinux.org>
|
||||||
|
Date: Jan 30 2024 15:11:05 +0000
|
||||||
|
Subject: ipapython: Correct return type of krb5_free_cred_contents
|
||||||
|
|
||||||
|
|
||||||
|
According to https://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/api/krb5_free_cred_contents.html
|
||||||
|
|
||||||
|
> krb5_free_cred_contents - Free the contents of a krb5_creds structure.
|
||||||
|
>
|
||||||
|
> void krb5_free_cred_contents(krb5_context context, krb5_creds * val)
|
||||||
|
> param:
|
||||||
|
> [in] context - Library context
|
||||||
|
>
|
||||||
|
> [in] val - Credential structure to free contents of
|
||||||
|
>
|
||||||
|
> This function frees the contents of val , but not the structure itself.
|
||||||
|
|
||||||
|
https://github.com/krb5/krb5/blob/5b00197227231943bd2305328c8260dd0b0dbcf0/src/lib/krb5/krb/kfree.c#L166
|
||||||
|
|
||||||
|
This leads to undefined behavior and `krb5_free_cred_contents` can
|
||||||
|
raise KRB5Error (because of garbage data) while actually its foreign
|
||||||
|
function doesn't.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9519
|
||||||
|
Signed-off-by: Stanislav Levin <slev@altlinux.org>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
|
||||||
|
index 371cf15..dc36f54 100644
|
||||||
|
--- a/ipapython/session_storage.py
|
||||||
|
+++ b/ipapython/session_storage.py
|
||||||
|
@@ -200,8 +200,7 @@ krb5_cc_end_seq_get.errcheck = krb5_errcheck
|
||||||
|
|
||||||
|
krb5_free_cred_contents = LIBKRB5.krb5_free_cred_contents
|
||||||
|
krb5_free_cred_contents.argtypes = (krb5_context, ctypes.POINTER(krb5_creds))
|
||||||
|
-krb5_free_cred_contents.restype = krb5_error
|
||||||
|
-krb5_free_cred_contents.errcheck = krb5_errcheck
|
||||||
|
+krb5_free_cred_contents.restype = None
|
||||||
|
|
||||||
|
krb5_principal_compare = LIBKRB5.krb5_principal_compare
|
||||||
|
krb5_principal_compare.argtypes = (krb5_context, krb5_principal,
|
||||||
|
|
||||||
|
From beb402afdbf32c01eed860e9416356f7b492ad74 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stanislav Levin <slev@altlinux.org>
|
||||||
|
Date: Jan 30 2024 15:11:05 +0000
|
||||||
|
Subject: ipapython: Propagate KRB5Error exceptions on iterating ccache
|
||||||
|
|
||||||
|
|
||||||
|
`ipapython.session_storage.get_data` iterates over
|
||||||
|
credentials in a credential cache till `krb5_cc_next_cred` returns
|
||||||
|
an error. This function doesn't expect any error on calling
|
||||||
|
other kerberos foreign functions during iteration. But that can
|
||||||
|
actually happen and KRB5Error exceptions stop an iteration while
|
||||||
|
they should be propagated.
|
||||||
|
|
||||||
|
With this change iteration will exactly stop on `krb5_cc_next_cred`
|
||||||
|
error as it was supposed to be.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9519
|
||||||
|
Signed-off-by: Stanislav Levin <slev@altlinux.org>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
|
||||||
|
index dc36f54..e890dc9 100644
|
||||||
|
--- a/ipapython/session_storage.py
|
||||||
|
+++ b/ipapython/session_storage.py
|
||||||
|
@@ -312,8 +312,12 @@ def get_data(princ_name, key):
|
||||||
|
checkcreds = krb5_creds()
|
||||||
|
# the next function will throw an error and break out of the
|
||||||
|
# while loop when we try to access past the last cred
|
||||||
|
- krb5_cc_next_cred(context, ccache, ctypes.byref(cursor),
|
||||||
|
- ctypes.byref(checkcreds))
|
||||||
|
+ try:
|
||||||
|
+ krb5_cc_next_cred(context, ccache, ctypes.byref(cursor),
|
||||||
|
+ ctypes.byref(checkcreds))
|
||||||
|
+ except KRB5Error:
|
||||||
|
+ break
|
||||||
|
+
|
||||||
|
if (krb5_principal_compare(context, principal,
|
||||||
|
checkcreds.client) == 1 and
|
||||||
|
krb5_principal_compare(context, srv_princ,
|
||||||
|
@@ -328,8 +332,6 @@ def get_data(princ_name, key):
|
||||||
|
else:
|
||||||
|
krb5_free_cred_contents(context,
|
||||||
|
ctypes.byref(checkcreds))
|
||||||
|
- except KRB5Error:
|
||||||
|
- pass
|
||||||
|
finally:
|
||||||
|
krb5_cc_end_seq_get(context, ccache, ctypes.byref(cursor))
|
||||||
|
|
||||||
|
|
@ -0,0 +1,109 @@
|
|||||||
|
From b56a80581ef388e19d5761020454e51463036cd6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Tue, 23 Jan 2024 14:47:50 +0200
|
||||||
|
Subject: [PATCH] sidgen: ignore staged users when generating SIDs
|
||||||
|
|
||||||
|
Staged users have
|
||||||
|
|
||||||
|
uidNumber: -1
|
||||||
|
gidNumber: -1
|
||||||
|
ipaUniqueID: autogenerate
|
||||||
|
|
||||||
|
We cannot generate ipaSecurityIdentifier based on those UID/GID numbers.
|
||||||
|
However, '-1' value will trigger an error
|
||||||
|
|
||||||
|
find_sid_for_ldap_entry - [file ipa_sidgen_common.c, line 483]: ID value too large.
|
||||||
|
|
||||||
|
And that, in turn, will cause stopping SID generation for all users.
|
||||||
|
|
||||||
|
Detect 'ipaUniqueID: autogenerate' situation and ignore these entries.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9517
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h | 2 ++
|
||||||
|
.../ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c | 12 ++++++++++++
|
||||||
|
2 files changed, 14 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h
|
||||||
|
index 0feff7eec..bd46982d0 100644
|
||||||
|
--- a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h
|
||||||
|
+++ b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h
|
||||||
|
@@ -45,6 +45,8 @@
|
||||||
|
#define UID_NUMBER "uidnumber"
|
||||||
|
#define GID_NUMBER "gidnumber"
|
||||||
|
#define IPA_SID "ipantsecurityidentifier"
|
||||||
|
+#define IPA_UNIQUEID "ipauniqueid"
|
||||||
|
+#define IPA_UNIQUEID_AUTOGENERATE "autogenerate"
|
||||||
|
#define DOM_ATTRS_FILTER OBJECTCLASS"=ipantdomainattrs"
|
||||||
|
#define DOMAIN_ID_RANGE_FILTER OBJECTCLASS"=ipadomainidrange"
|
||||||
|
#define POSIX_ACCOUNT "posixaccount"
|
||||||
|
diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c
|
||||||
|
index 6f784804c..cb763ebf8 100644
|
||||||
|
--- a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c
|
||||||
|
+++ b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen_common.c
|
||||||
|
@@ -454,6 +454,7 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
|
||||||
|
uint32_t id;
|
||||||
|
char *sid = NULL;
|
||||||
|
char **objectclasses = NULL;
|
||||||
|
+ char *uniqueid = NULL;
|
||||||
|
Slapi_PBlock *mod_pb = NULL;
|
||||||
|
Slapi_Mods *smods = NULL;
|
||||||
|
int result;
|
||||||
|
@@ -479,6 +480,16 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ uniqueid = slapi_entry_attr_get_charptr(entry, IPA_UNIQUEID);
|
||||||
|
+ if (uniqueid != NULL &&
|
||||||
|
+ strncmp(IPA_UNIQUEID_AUTOGENERATE, uniqueid,
|
||||||
|
+ sizeof(IPA_UNIQUEID_AUTOGENERATE)) == 0) {
|
||||||
|
+ LOG("Staged entry [%s] does not have Posix IDs, nothing to do.\n",
|
||||||
|
+ dn_str);
|
||||||
|
+ ret = 0;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (uid_number >= UINT32_MAX || gid_number >= UINT32_MAX) {
|
||||||
|
LOG_FATAL("ID value too large.\n");
|
||||||
|
ret = LDAP_CONSTRAINT_VIOLATION;
|
||||||
|
@@ -554,6 +565,7 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
+ slapi_ch_free_string(&uniqueid);
|
||||||
|
slapi_ch_free_string(&sid);
|
||||||
|
slapi_pblock_destroy(mod_pb);
|
||||||
|
slapi_mods_free(&smods);
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
From 07150b71537744f491d022c737ef04775c72a10a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Tue, 23 Jan 2024 14:53:39 +0200
|
||||||
|
Subject: [PATCH] sidgen: fix missing prototypes
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h
|
||||||
|
index bd46982d0..aec862796 100644
|
||||||
|
--- a/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h
|
||||||
|
+++ b/daemons/ipa-slapi-plugins/ipa-sidgen/ipa_sidgen.h
|
||||||
|
@@ -106,3 +106,6 @@ int find_sid_for_ldap_entry(struct slapi_entry *entry,
|
||||||
|
const char *base_dn,
|
||||||
|
const char *dom_sid,
|
||||||
|
struct range_info **ranges);
|
||||||
|
+
|
||||||
|
+int sidgen_task_init(Slapi_PBlock *pb);
|
||||||
|
+int ipa_sidgen_init(Slapi_PBlock *pb);
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -1,58 +0,0 @@
|
|||||||
From fdaad3a45f5674876fd3f6cc7ad1e916ebfc7080 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Aug 14 2023 13:02:20 +0000
|
|
||||||
Subject: ipatests: fix test_topology
|
|
||||||
|
|
||||||
|
|
||||||
The test TestTopologyOptions::test_add_remove_segment is
|
|
||||||
randomly failing downstream. Test scenario:
|
|
||||||
- create a line topology master <-> repl1 <-> repl2
|
|
||||||
- create user on master
|
|
||||||
- wait for repl success on master
|
|
||||||
- check that the user is seen on repl2
|
|
||||||
|
|
||||||
The test waits for replication to complete on the master but
|
|
||||||
it should also wait for the replication to complete on repl1
|
|
||||||
before checking the user presence on repl2.
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Anuja More <amore@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipatests/test_integration/test_topology.py b/ipatests/test_integration/test_topology.py
|
|
||||||
index 8a240fa..618c9d5 100644
|
|
||||||
--- a/ipatests/test_integration/test_topology.py
|
|
||||||
+++ b/ipatests/test_integration/test_topology.py
|
|
||||||
@@ -124,6 +124,9 @@ class TestTopologyOptions(IntegrationTest):
|
|
||||||
self.replicas[0],
|
|
||||||
self.replicas[1])
|
|
||||||
assert err == "", err
|
|
||||||
+ # At this point we have replicas[1] <-> master <-> replicas[0]
|
|
||||||
+ # ^--------------------------^
|
|
||||||
+
|
|
||||||
# Make sure the new segment is shown by `ipa topologysegment-find`
|
|
||||||
result1 = self.master.run_command(['ipa', 'topologysegment-find',
|
|
||||||
DOMAIN_SUFFIX_NAME]).stdout_text
|
|
||||||
@@ -137,9 +140,12 @@ class TestTopologyOptions(IntegrationTest):
|
|
||||||
deleteme = find_segment(self.master, self.replicas[1])
|
|
||||||
returncode, error = tasks.destroy_segment(self.master, deleteme)
|
|
||||||
assert returncode == 0, error
|
|
||||||
+ # At this point we have master <-> replicas[0] <-> replicas[1]
|
|
||||||
+
|
|
||||||
# Wait till replication ends and make sure replica1 does not have
|
|
||||||
# segment that was deleted on master
|
|
||||||
master_ldap = self.master.ldap_connect()
|
|
||||||
+ repl_ldap = self.replicas[0].ldap_connect()
|
|
||||||
tasks.wait_for_replication(master_ldap)
|
|
||||||
result3 = self.replicas[0].run_command(['ipa', 'topologysegment-find',
|
|
||||||
DOMAIN_SUFFIX_NAME]).stdout_text
|
|
||||||
@@ -150,6 +156,7 @@ class TestTopologyOptions(IntegrationTest):
|
|
||||||
'--first', 'test',
|
|
||||||
'--last', 'user'])
|
|
||||||
tasks.wait_for_replication(master_ldap)
|
|
||||||
+ tasks.wait_for_replication(repl_ldap)
|
|
||||||
result4 = self.replicas[1].run_command(['ipa', 'user-find'])
|
|
||||||
assert('someuser' in result4.stdout_text), 'User not found: someuser'
|
|
||||||
# We end up having a line topology: master <-> replica1 <-> replica2
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
From f38eefd9f7e54470de7c707782114b17aac8762a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Date: Aug 16 2023 15:25:34 +0000
|
|
||||||
Subject: Installer: activate nss and pam services in sssd.conf
|
|
||||||
|
|
||||||
|
|
||||||
If there is already a sssd.conf file before the installer is
|
|
||||||
executed, the nss and pam services may not be enabled by the
|
|
||||||
installer. This happens for instance if the machine is hardened
|
|
||||||
for STIG and sssd.conf does not define services=... in the
|
|
||||||
[sssd] section.
|
|
||||||
|
|
||||||
The consequence is that trust cannot be established with an AD
|
|
||||||
domain.
|
|
||||||
|
|
||||||
The installer must enable nss and pam services even if there is
|
|
||||||
a pre-existing sssd.conf file.
|
|
||||||
|
|
||||||
Fixes: https://pagure.io/freeipa/issue/9427
|
|
||||||
|
|
||||||
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
|
||||||
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
|
|
||||||
index ef29a2c..07d62a7 100644
|
|
||||||
--- a/ipaclient/install/client.py
|
|
||||||
+++ b/ipaclient/install/client.py
|
|
||||||
@@ -969,6 +969,9 @@ def configure_sssd_conf(
|
|
||||||
nss_service.set_option('memcache_timeout', 600)
|
|
||||||
sssdconfig.save_service(nss_service)
|
|
||||||
|
|
||||||
+ sssd_enable_service(sssdconfig, 'nss')
|
|
||||||
+ sssd_enable_service(sssdconfig, 'pam')
|
|
||||||
+
|
|
||||||
domain.set_option('ipa_domain', cli_domain)
|
|
||||||
domain.set_option('ipa_hostname', client_hostname)
|
|
||||||
if cli_domain.lower() != cli_realm.lower():
|
|
||||||
|
|
@ -0,0 +1,310 @@
|
|||||||
|
From 67ca47ba4092811029eec02f8af9c34ba7662924 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Mon, 9 Oct 2023 15:47:03 +0200
|
||||||
|
Subject: [PATCH] ipa-kdb: Ensure Bronze-Bit check can be enabled
|
||||||
|
|
||||||
|
MIT krb5 1.19 and older do not implement support for PAC ticket
|
||||||
|
signature to protect the encrypted part of tickets. This is the cause of
|
||||||
|
the Bronze-Bit vulnerability (CVE-2020-17043). The Bronze-Bit attack
|
||||||
|
detection mechanism introduced in a847e248 relies on the content of the
|
||||||
|
PAC.
|
||||||
|
|
||||||
|
However, since CVE-2022-37967, the content of the PAC can no longer be
|
||||||
|
trusted if the KDC does not support PAC extended KDC signature (aka.
|
||||||
|
PAC full checksum). This signature is supported in MIT krb5 since
|
||||||
|
version 1.21.
|
||||||
|
|
||||||
|
Support for the PAC extended KDC signature was backported downstream to
|
||||||
|
krb5 1.18.2 for CentOS 8 Stream (dist-git commit 7d215a54). This makes
|
||||||
|
the content of the PAC still trustworthy there.
|
||||||
|
|
||||||
|
This commit disables the Bronze-Bit attack detection mechanism at build
|
||||||
|
time in case krb5 does not provide the krb5_pac_full_sign_compat()
|
||||||
|
function.
|
||||||
|
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb.h | 4 ++++
|
||||||
|
daemons/ipa-kdb/ipa_kdb_kdcpolicy.c | 7 +++++++
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac.c | 4 ++++
|
||||||
|
3 files changed, 15 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
index 02b2cb631..c6926f7d5 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
@@ -367,6 +367,8 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
const char *test_realm, size_t size,
|
||||||
|
char **trusted_realm);
|
||||||
|
|
||||||
|
+#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
|
||||||
|
+# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
/* Try to detect a Bronze-Bit attack based on the content of the request and
|
||||||
|
* data from the KDB.
|
||||||
|
*
|
||||||
|
@@ -379,6 +381,8 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
krb5_error_code
|
||||||
|
ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
bool *detected, const char **status);
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* DELEGATION CHECKS */
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
index 1032dff0b..ee0546c01 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
@@ -185,11 +185,18 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||||
|
const char **status, krb5_deltat *lifetime_out,
|
||||||
|
krb5_deltat *renew_lifetime_out)
|
||||||
|
{
|
||||||
|
+#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
|
||||||
|
+# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
krb5_error_code kerr;
|
||||||
|
|
||||||
|
kerr = ipadb_check_for_bronze_bit_attack(context, request, NULL, status);
|
||||||
|
if (kerr)
|
||||||
|
return KRB5KDC_ERR_POLICY;
|
||||||
|
+# else
|
||||||
|
+# warning Support for Kerberos PAC extended KDC signature is missing.\
|
||||||
|
+ This makes FreeIPA vulnerable to the Bronze-Bit exploit (CVE-2020-17049).
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
*status = NULL;
|
||||||
|
*lifetime_out = 0;
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index b4e22d431..05d5b407d 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -3299,6 +3299,8 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
return KRB5_KDB_NOENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
|
||||||
|
+# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
krb5_error_code
|
||||||
|
ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
bool *detected, const char **status)
|
||||||
|
@@ -3471,3 +3473,5 @@ end:
|
||||||
|
ipadb_free_principal(context, proxy_entry);
|
||||||
|
return kerr;
|
||||||
|
}
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
From 27b96c17dd51d076e04d97662b7c788658a5094a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Jan 26 2024 09:35:57 +0000
|
||||||
|
Subject: ipa-kdb: Disable Bronze-Bit check if PAC not available
|
||||||
|
|
||||||
|
|
||||||
|
The Bronze-Bit check introduced in commit
|
||||||
|
a847e2483b4c4832ee5129901da169f4eb0d1392 requires the MS-PAC to be
|
||||||
|
present in the evidence ticket in order for S4U2Proxy requests to be
|
||||||
|
accepted. This actually requires SIDs to be set.
|
||||||
|
|
||||||
|
However, domains that were initialized before commit
|
||||||
|
e527857d000e558b3288a7a210400abaf2171237 may still not have SIDs
|
||||||
|
configured. This would results in all S4U2Proxy requests to fail
|
||||||
|
(including all the HTTP API requests).
|
||||||
|
|
||||||
|
This present commit disables the check for the Bronze-Bit exploit
|
||||||
|
(CVE-2020-17049) in case the domain is not able to generate PACs.
|
||||||
|
Instead, it prints a warning message in the KDC logs each time a
|
||||||
|
S4U2Proxy request is processed.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9521
|
||||||
|
|
||||||
|
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
index c6926f7..621c235 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
@@ -370,17 +370,21 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
|
||||||
|
# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
/* Try to detect a Bronze-Bit attack based on the content of the request and
|
||||||
|
- * data from the KDB.
|
||||||
|
+ * data from the KDB. This check will work only if the domain supports MS-PAC.
|
||||||
|
*
|
||||||
|
* context krb5 context
|
||||||
|
* request KDB request
|
||||||
|
- * detected Set to "true" if a bronze bit attack is detected and the
|
||||||
|
- * pointer is not NULL. Remains unset otherwise.
|
||||||
|
+ * supported If not NULL, set to "false" in case the Bronze-Bit exploit
|
||||||
|
+ * detection process silently failed to complete because the
|
||||||
|
+ * domain does not meet requirements. Set to "true" otherwise.
|
||||||
|
+ * detected If not NULL, set to "true" if a Bronze-Bit attack is detected.
|
||||||
|
+ * Set to "false" otherwise.
|
||||||
|
* status If the call fails and the pointer is not NULL, set it with a
|
||||||
|
* message describing the cause of the failure. */
|
||||||
|
krb5_error_code
|
||||||
|
ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
- bool *detected, const char **status);
|
||||||
|
+ bool *supported, bool *detected,
|
||||||
|
+ const char **status);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
index ee0546c..713e9a0 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
@@ -188,10 +188,18 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||||
|
#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
|
||||||
|
# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
krb5_error_code kerr;
|
||||||
|
+ bool supported;
|
||||||
|
|
||||||
|
- kerr = ipadb_check_for_bronze_bit_attack(context, request, NULL, status);
|
||||||
|
+ kerr = ipadb_check_for_bronze_bit_attack(context, request, supported, NULL,
|
||||||
|
+ status);
|
||||||
|
if (kerr)
|
||||||
|
return KRB5KDC_ERR_POLICY;
|
||||||
|
+
|
||||||
|
+ if (!supported)
|
||||||
|
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC not available. This makes "
|
||||||
|
+ "FreeIPA vulnerable to the Bronze-Bit exploit "
|
||||||
|
+ "(CVE-2020-17049). Please generate SIDs to enable "
|
||||||
|
+ "PAC support.");
|
||||||
|
# else
|
||||||
|
# warning Support for Kerberos PAC extended KDC signature is missing.\
|
||||||
|
This makes FreeIPA vulnerable to the Bronze-Bit exploit (CVE-2020-17049).
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index 05d5b40..a18beff 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -3303,11 +3303,14 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
krb5_error_code
|
||||||
|
ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
- bool *detected, const char **status)
|
||||||
|
+ bool *supported, bool *detected,
|
||||||
|
+ const char **status)
|
||||||
|
{
|
||||||
|
krb5_error_code kerr;
|
||||||
|
const char *st = NULL;
|
||||||
|
size_t i, j;
|
||||||
|
+ bool in_supported = true, in_detected = false;
|
||||||
|
+ struct ipadb_context *ipactx;
|
||||||
|
krb5_ticket *evidence_tkt;
|
||||||
|
krb5_authdata **authdata, **ifrel = NULL;
|
||||||
|
krb5_pac pac = NULL;
|
||||||
|
@@ -3327,6 +3330,21 @@ ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ipactx = ipadb_get_context(context);
|
||||||
|
+ if (!ipactx) {
|
||||||
|
+ kerr = KRB5_KDB_DBNOTINITED;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Handle the case where the domain is not able to generate PACs (probably
|
||||||
|
+ * because SIDs are not set). In this case, we just skip the Bronze-Bit
|
||||||
|
+ * check. */
|
||||||
|
+ if (!ipactx->mspac) {
|
||||||
|
+ in_supported = false;
|
||||||
|
+ kerr = 0;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
evidence_tkt = request->second_ticket[0];
|
||||||
|
|
||||||
|
/* No need to check the Forwardable flag. If it was not set, this request
|
||||||
|
@@ -3451,8 +3469,7 @@ ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
/* This evidence ticket cannot be forwardable given the privileges
|
||||||
|
* of the proxy principal.
|
||||||
|
* This is a Bronze Bit attack. */
|
||||||
|
- if (detected)
|
||||||
|
- *detected = true;
|
||||||
|
+ in_detected = true;
|
||||||
|
st = "S4U2PROXY_BRONZE_BIT_ATTACK_DETECTED";
|
||||||
|
kerr = EBADE;
|
||||||
|
goto end;
|
||||||
|
@@ -3464,6 +3481,10 @@ ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
end:
|
||||||
|
if (st && status)
|
||||||
|
*status = st;
|
||||||
|
+ if (supported)
|
||||||
|
+ *supported = in_supported;
|
||||||
|
+ if (detected)
|
||||||
|
+ *detected = in_detected;
|
||||||
|
|
||||||
|
krb5_free_authdata(context, ifrel);
|
||||||
|
krb5_pac_free(context, pac);
|
||||||
|
|
||||||
|
From 81aa6ef695838a4b2fb5a53e773ea379a492913d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Fri, 9 Feb 2024 16:36:03 +0100
|
||||||
|
Subject: [PATCH] ipd-kdb: Fix some mistakes in
|
||||||
|
ipadb_check_for_bronze_bit_attack()
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9521
|
||||||
|
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abbra@users.noreply.github.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb.h | 3 ++-
|
||||||
|
daemons/ipa-kdb/ipa_kdb_kdcpolicy.c | 2 +-
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac.c | 5 +++--
|
||||||
|
3 files changed, 6 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
index 621c23591..5de5ea7a5 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
@@ -382,7 +382,8 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
* status If the call fails and the pointer is not NULL, set it with a
|
||||||
|
* message describing the cause of the failure. */
|
||||||
|
krb5_error_code
|
||||||
|
-ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
+ipadb_check_for_bronze_bit_attack(krb5_context context,
|
||||||
|
+ const krb5_kdc_req *request,
|
||||||
|
bool *supported, bool *detected,
|
||||||
|
const char **status);
|
||||||
|
# endif
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
index 713e9a0c8..44959f3de 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
@@ -190,7 +190,7 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||||
|
krb5_error_code kerr;
|
||||||
|
bool supported;
|
||||||
|
|
||||||
|
- kerr = ipadb_check_for_bronze_bit_attack(context, request, supported, NULL,
|
||||||
|
+ kerr = ipadb_check_for_bronze_bit_attack(context, request, &supported, NULL,
|
||||||
|
status);
|
||||||
|
if (kerr)
|
||||||
|
return KRB5KDC_ERR_POLICY;
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index 80350364a..886ed7785 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -3308,13 +3308,14 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
|
||||||
|
# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
|
||||||
|
krb5_error_code
|
||||||
|
-ipadb_check_for_bronze_bit_attack(krb5_context context, krb5_kdc_req *request,
|
||||||
|
+ipadb_check_for_bronze_bit_attack(krb5_context context,
|
||||||
|
+ const krb5_kdc_req *request,
|
||||||
|
bool *supported, bool *detected,
|
||||||
|
const char **status)
|
||||||
|
{
|
||||||
|
krb5_error_code kerr;
|
||||||
|
const char *st = NULL;
|
||||||
|
- size_t i, j;
|
||||||
|
+ size_t i, j = 0;
|
||||||
|
bool in_supported = true, in_detected = false;
|
||||||
|
struct ipadb_context *ipactx;
|
||||||
|
krb5_ticket *evidence_tkt;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,272 @@
|
|||||||
|
From 00f8ddbfd2795228b343e1c39c1944b44d482c18 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Fri, 24 Nov 2023 11:46:19 +0200
|
||||||
|
Subject: [PATCH 1/4] ipa-kdb: add better detection of allowed user auth type
|
||||||
|
|
||||||
|
If default user authentication type is set to a list that does not
|
||||||
|
include a password or a hardened credential, the resulting configuration
|
||||||
|
might be incorrect for special service principals, including a krbtgt/..
|
||||||
|
one.
|
||||||
|
|
||||||
|
Add detection of special principals to avoid these situations and always
|
||||||
|
allow password or hardened for services.
|
||||||
|
|
||||||
|
Special handling is needed for the following principals:
|
||||||
|
|
||||||
|
- krbtgt/.. -- TGT service principals
|
||||||
|
- K/M -- master key principal
|
||||||
|
- kadmin/changepw -- service for changing passwords
|
||||||
|
- kadmin/kadmin -- kadmin service principal
|
||||||
|
- kadmin/history -- key used to encrypt history
|
||||||
|
|
||||||
|
Additionally, implicitly allow password or hardened credential use for
|
||||||
|
IPA services and IPA hosts since applications typically use keytabs for
|
||||||
|
that purpose.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9485
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb.c | 62 ++++++++++++++++++++++++++++++++++-----
|
||||||
|
1 file changed, 54 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
index 06d511c76..dbb98dba6 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#include "ipa_kdb.h"
|
||||||
|
#include "ipa_krb5.h"
|
||||||
|
#include "ipa_hostname.h"
|
||||||
|
+#include <kadm5/admin.h>
|
||||||
|
|
||||||
|
#define IPADB_GLOBAL_CONFIG_CACHE_TIME 60
|
||||||
|
|
||||||
|
@@ -207,6 +208,19 @@ static const struct {
|
||||||
|
{ "idp", IPADB_USER_AUTH_IDP },
|
||||||
|
{ "passkey", IPADB_USER_AUTH_PASSKEY },
|
||||||
|
{ }
|
||||||
|
+},
|
||||||
|
+ objclass_table[] = {
|
||||||
|
+ { "ipaservice", IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { "ipahost", IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { }
|
||||||
|
+},
|
||||||
|
+ princname_table[] = {
|
||||||
|
+ { KRB5_TGS_NAME, IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { KRB5_KDB_M_NAME, IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { KADM5_ADMIN_SERVICE, IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { KADM5_CHANGEPW_SERVICE, IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { KADM5_HIST_PRINCIPAL, IPADB_USER_AUTH_PASSWORD },
|
||||||
|
+ { }
|
||||||
|
};
|
||||||
|
|
||||||
|
void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
|
||||||
|
@@ -217,17 +231,49 @@ void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
|
||||||
|
|
||||||
|
*userauth = IPADB_USER_AUTH_NONE;
|
||||||
|
vals = ldap_get_values_len(lcontext, le, IPA_USER_AUTH_TYPE);
|
||||||
|
- if (!vals)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- for (i = 0; vals[i]; i++) {
|
||||||
|
- for (j = 0; userauth_table[j].name; j++) {
|
||||||
|
- if (strcasecmp(vals[i]->bv_val, userauth_table[j].name) == 0) {
|
||||||
|
- *userauth |= userauth_table[j].flag;
|
||||||
|
- break;
|
||||||
|
+ if (!vals) {
|
||||||
|
+ /* if there is no explicit ipaUserAuthType set, use objectclass */
|
||||||
|
+ vals = ldap_get_values_len(lcontext, le, "objectclass");
|
||||||
|
+ if (!vals)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ for (i = 0; vals[i]; i++) {
|
||||||
|
+ for (j = 0; objclass_table[j].name; j++) {
|
||||||
|
+ if (strcasecmp(vals[i]->bv_val, objclass_table[j].name) == 0) {
|
||||||
|
+ *userauth |= objclass_table[j].flag;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ for (i = 0; vals[i]; i++) {
|
||||||
|
+ for (j = 0; userauth_table[j].name; j++) {
|
||||||
|
+ if (strcasecmp(vals[i]->bv_val, userauth_table[j].name) == 0) {
|
||||||
|
+ *userauth |= userauth_table[j].flag;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* If neither ipaUserAuthType nor objectClass were definitive,
|
||||||
|
+ * check the krbPrincipalName to see if it is krbtgt/ or K/M one */
|
||||||
|
+ if (*userauth == IPADB_USER_AUTH_NONE) {
|
||||||
|
+ ldap_value_free_len(vals);
|
||||||
|
+ vals = ldap_get_values_len(lcontext, le, "krbprincipalname");
|
||||||
|
+ if (!vals)
|
||||||
|
+ return;
|
||||||
|
+ for (i = 0; vals[i]; i++) {
|
||||||
|
+ for (j = 0; princname_table[j].name; j++) {
|
||||||
|
+ if (strncmp(vals[i]->bv_val, princname_table[j].name,
|
||||||
|
+ strlen(princname_table[j].name)) == 0) {
|
||||||
|
+ *userauth |= princname_table[j].flag;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
/* If password auth is enabled, enable hardened policy too. */
|
||||||
|
if (*userauth & IPADB_USER_AUTH_PASSWORD) {
|
||||||
|
*userauth |= IPADB_USER_AUTH_HARDENED;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
|
||||||
|
From 69ae9febfb4462766b3bfe3e07e76550ece97b42 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Fri, 24 Nov 2023 11:54:04 +0200
|
||||||
|
Subject: [PATCH 2/4] ipa-kdb: when applying ticket policy, do not deny PKINIT
|
||||||
|
|
||||||
|
PKINIT differs from other pre-authentication methods by the fact that it
|
||||||
|
can be matched indepedently of the user authentication types via certmap
|
||||||
|
plugin in KDC.
|
||||||
|
|
||||||
|
Since PKINIT is a strong authentication method, allow its authentication
|
||||||
|
indicator and only apply the ticket policy.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9485
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb_kdcpolicy.c | 7 ++-----
|
||||||
|
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
index 436ee0e62..2802221c7 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
|
||||||
|
@@ -119,11 +119,8 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||||
|
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_RADIUS]);
|
||||||
|
} else if (strcmp(auth_indicator, "pkinit") == 0) {
|
||||||
|
valid_auth_indicators++;
|
||||||
|
- if (!(ua & IPADB_USER_AUTH_PKINIT)) {
|
||||||
|
- *status = "PKINIT pre-authentication not allowed for this user.";
|
||||||
|
- kerr = KRB5KDC_ERR_POLICY;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
+ /* allow PKINIT unconditionally -- it has passed already at this
|
||||||
|
+ * point so some certificate was useful, only apply the limits */
|
||||||
|
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_PKINIT]);
|
||||||
|
} else if (strcmp(auth_indicator, "hardened") == 0) {
|
||||||
|
valid_auth_indicators++;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
|
||||||
|
From 62c44c9e69aa2721990ca3628434713e1af6f59b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Fri, 24 Nov 2023 12:20:55 +0200
|
||||||
|
Subject: [PATCH 3/4] ipa-kdb: clarify user auth table mapping use of
|
||||||
|
_AUTH_PASSWORD
|
||||||
|
|
||||||
|
Related: https://pagure.io/freeipa/issue/9485
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
index dbb98dba6..4e6cacf24 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
@@ -195,6 +195,9 @@ done:
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* In this table all _AUTH_PASSWORD entries will be
|
||||||
|
+ * expanded to include _AUTH_HARDENED in ipadb_parse_user_auth()
|
||||||
|
+ * which means there is no need to explicitly add it here */
|
||||||
|
static const struct {
|
||||||
|
const char *name;
|
||||||
|
enum ipadb_user_auth flag;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
|
||||||
|
From c3bc938650b19a51706d8ccd98cdf8deaa26dc28 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Fri, 24 Nov 2023 13:00:48 +0200
|
||||||
|
Subject: [PATCH 4/4] ipatests: make sure PKINIT enrollment works with a strict
|
||||||
|
policy
|
||||||
|
|
||||||
|
Previously, for a global policy which does not include
|
||||||
|
'password', krb5kdc restart was failing. Now it should succeed.
|
||||||
|
|
||||||
|
We set admin user authentication type to PASSWORD to simplify
|
||||||
|
configuration in the test.
|
||||||
|
|
||||||
|
What matters here is that global policy does not include PKINIT and that
|
||||||
|
means a code in the ticket policy check will allow PKINIT implicitly
|
||||||
|
rather than explicitly.
|
||||||
|
|
||||||
|
Related: https://pagure.io/freeipa/issue/9485
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
---
|
||||||
|
.../test_integration/test_pkinit_install.py | 26 +++++++++++++++++++
|
||||||
|
1 file changed, 26 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_integration/test_pkinit_install.py b/ipatests/test_integration/test_pkinit_install.py
|
||||||
|
index caa0e6a34..5c2e7af02 100644
|
||||||
|
--- a/ipatests/test_integration/test_pkinit_install.py
|
||||||
|
+++ b/ipatests/test_integration/test_pkinit_install.py
|
||||||
|
@@ -23,6 +23,24 @@ class TestPkinitClientInstall(IntegrationTest):
|
||||||
|
def install(cls, mh):
|
||||||
|
tasks.install_master(cls.master)
|
||||||
|
|
||||||
|
+ def enforce_password_and_otp(self):
|
||||||
|
+ """enforce otp by default and password for admin """
|
||||||
|
+ self.master.run_command(
|
||||||
|
+ [
|
||||||
|
+ "ipa",
|
||||||
|
+ "config-mod",
|
||||||
|
+ "--user-auth-type=otp",
|
||||||
|
+ ]
|
||||||
|
+ )
|
||||||
|
+ self.master.run_command(
|
||||||
|
+ [
|
||||||
|
+ "ipa",
|
||||||
|
+ "user-mod",
|
||||||
|
+ "admin",
|
||||||
|
+ "--user-auth-type=password",
|
||||||
|
+ ]
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
def add_certmaperule(self):
|
||||||
|
"""add certmap rule to map SAN dNSName to host entry"""
|
||||||
|
self.master.run_command(
|
||||||
|
@@ -86,6 +104,14 @@ class TestPkinitClientInstall(IntegrationTest):
|
||||||
|
cabundle = self.master.get_file_contents(paths.KDC_CA_BUNDLE_PEM)
|
||||||
|
client.put_file_contents(self.tmpbundle, cabundle)
|
||||||
|
|
||||||
|
+ def test_restart_krb5kdc(self):
|
||||||
|
+ tasks.kinit_admin(self.master)
|
||||||
|
+ self.enforce_password_and_otp()
|
||||||
|
+ self.master.run_command(['systemctl', 'stop', 'krb5kdc.service'])
|
||||||
|
+ self.master.run_command(['systemctl', 'start', 'krb5kdc.service'])
|
||||||
|
+ self.master.run_command(['systemctl', 'stop', 'kadmin.service'])
|
||||||
|
+ self.master.run_command(['systemctl', 'start', 'kadmin.service'])
|
||||||
|
+
|
||||||
|
def test_client_install_pkinit(self):
|
||||||
|
tasks.kinit_admin(self.master)
|
||||||
|
self.add_certmaperule()
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,139 @@
|
|||||||
|
From 48846e98e5e988d600ddf81c937f353fcecdea1a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Mon, 27 Nov 2023 16:11:08 -0500
|
||||||
|
Subject: [PATCH 1/2] hbactest was not collecting or returning messages
|
||||||
|
|
||||||
|
hbactest does a number of internal searches, one of which
|
||||||
|
can exceed the configured sizelimit: hbacrule-find
|
||||||
|
|
||||||
|
Collect any messages returned from thsi call and display them
|
||||||
|
to the user on the cli.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9486
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
---
|
||||||
|
ipaclient/plugins/hbactest.py | 2 ++
|
||||||
|
ipaserver/plugins/hbactest.py | 14 +++++++++++---
|
||||||
|
2 files changed, 13 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ipaclient/plugins/hbactest.py b/ipaclient/plugins/hbactest.py
|
||||||
|
index 1b54530b2..e0f93b9c2 100644
|
||||||
|
--- a/ipaclient/plugins/hbactest.py
|
||||||
|
+++ b/ipaclient/plugins/hbactest.py
|
||||||
|
@@ -38,6 +38,8 @@ class hbactest(CommandOverride):
|
||||||
|
# Note that we don't actually use --detail below to see if details need
|
||||||
|
# to be printed as our execute() method will return None for corresponding
|
||||||
|
# entries and None entries will be skipped.
|
||||||
|
+ self.log_messages(output)
|
||||||
|
+
|
||||||
|
for o in self.output:
|
||||||
|
if o == 'value':
|
||||||
|
continue
|
||||||
|
diff --git a/ipaserver/plugins/hbactest.py b/ipaserver/plugins/hbactest.py
|
||||||
|
index 887a35b7e..568c13174 100644
|
||||||
|
--- a/ipaserver/plugins/hbactest.py
|
||||||
|
+++ b/ipaserver/plugins/hbactest.py
|
||||||
|
@@ -24,6 +24,8 @@ from ipalib import Command, Str, Flag, Int
|
||||||
|
from ipalib import _
|
||||||
|
from ipapython.dn import DN
|
||||||
|
from ipalib.plugable import Registry
|
||||||
|
+from ipalib.messages import VersionMissing
|
||||||
|
+
|
||||||
|
if api.env.in_server:
|
||||||
|
try:
|
||||||
|
import ipaserver.dcerpc
|
||||||
|
@@ -323,6 +325,9 @@ class hbactest(Command):
|
||||||
|
# 2. Required options are (user, target host, service)
|
||||||
|
# 3. Options: rules to test (--rules, --enabled, --disabled), request for detail output
|
||||||
|
rules = []
|
||||||
|
+ result = {
|
||||||
|
+ 'warning':None, 'matched':None, 'notmatched':None, 'error':None
|
||||||
|
+ }
|
||||||
|
|
||||||
|
# Use all enabled IPA rules by default
|
||||||
|
all_enabled = True
|
||||||
|
@@ -351,8 +356,12 @@ class hbactest(Command):
|
||||||
|
|
||||||
|
hbacset = []
|
||||||
|
if len(testrules) == 0:
|
||||||
|
- hbacset = self.api.Command.hbacrule_find(
|
||||||
|
- sizelimit=sizelimit, no_members=False)['result']
|
||||||
|
+ hbacrules = self.api.Command.hbacrule_find(
|
||||||
|
+ sizelimit=sizelimit, no_members=False)
|
||||||
|
+ hbacset = hbacrules['result']
|
||||||
|
+ for message in hbacrules['messages']:
|
||||||
|
+ if message['code'] != VersionMissing.errno:
|
||||||
|
+ result.setdefault('messages', []).append(message)
|
||||||
|
else:
|
||||||
|
for rule in testrules:
|
||||||
|
try:
|
||||||
|
@@ -469,7 +478,6 @@ class hbactest(Command):
|
||||||
|
error_rules = []
|
||||||
|
warning_rules = []
|
||||||
|
|
||||||
|
- result = {'warning':None, 'matched':None, 'notmatched':None, 'error':None}
|
||||||
|
if not options['nodetail']:
|
||||||
|
# Validate runs rules one-by-one and reports failed ones
|
||||||
|
for ipa_rule in rules:
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
|
||||||
|
From d1e09c68af8ac77f656dd639af5d9a7f07c41f9d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Tue, 28 Nov 2023 13:35:13 -0500
|
||||||
|
Subject: [PATCH 2/2] ipatests: Verify that hbactest will return messages
|
||||||
|
|
||||||
|
Limit the sizelimit of the hbactest request to confirm that
|
||||||
|
the output includes a SearchResultTruncated message.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9486
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
---
|
||||||
|
ipatests/test_xmlrpc/test_hbactest_plugin.py | 19 ++++++++++++++++++-
|
||||||
|
1 file changed, 18 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_xmlrpc/test_hbactest_plugin.py b/ipatests/test_xmlrpc/test_hbactest_plugin.py
|
||||||
|
index 73c4ce232..e2e66c759 100644
|
||||||
|
--- a/ipatests/test_xmlrpc/test_hbactest_plugin.py
|
||||||
|
+++ b/ipatests/test_xmlrpc/test_hbactest_plugin.py
|
||||||
|
@@ -134,6 +134,7 @@ class test_hbactest(XMLRPC_test):
|
||||||
|
assert ret['value']
|
||||||
|
assert ret['error'] is None
|
||||||
|
assert ret['matched'] is None
|
||||||
|
+ assert 'messages' not in ret
|
||||||
|
assert ret['notmatched'] is None
|
||||||
|
|
||||||
|
def test_c_hbactest_check_rules_enabled_detail(self):
|
||||||
|
@@ -200,7 +201,23 @@ class test_hbactest(XMLRPC_test):
|
||||||
|
nodetail=True
|
||||||
|
)
|
||||||
|
|
||||||
|
- def test_g_hbactest_clear_testing_data(self):
|
||||||
|
+ def test_g_hbactest_searchlimit_message(self):
|
||||||
|
+ """
|
||||||
|
+ Test running 'ipa hbactest' with limited --sizelimit
|
||||||
|
+
|
||||||
|
+ We know there are at least 6 rules, 4 created here + 2 default.
|
||||||
|
+ """
|
||||||
|
+ ret = api.Command['hbactest'](
|
||||||
|
+ user=self.test_user,
|
||||||
|
+ targethost=self.test_host,
|
||||||
|
+ service=self.test_service,
|
||||||
|
+ nodetail=True,
|
||||||
|
+ sizelimit=2,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ assert ret['messages'] is not None
|
||||||
|
+
|
||||||
|
+ def test_h_hbactest_clear_testing_data(self):
|
||||||
|
"""
|
||||||
|
Clear data for HBAC test plugin testing.
|
||||||
|
"""
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
From 16a739e0260f97705827f972d53c828809dbfdb2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Masahiro Matsuya <mmatsuya@redhat.com>
|
||||||
|
Date: Tue, 9 Jan 2024 23:12:11 +0900
|
||||||
|
Subject: [PATCH] ipatests: wait for replica update in test_dns_locations
|
||||||
|
|
||||||
|
test_ipa_ca_records and test_adtrust_system_records can fail with
|
||||||
|
NXDOMAIN, because it doesn't wait enough for the update on replica.
|
||||||
|
It can be resolved by waiting for the update with wait_for_replication.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9504
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
(cherry picked from commit 905a55a4ef926068630ebd2ab375f58c24dedcd1)
|
||||||
|
---
|
||||||
|
ipatests/test_integration/test_dns_locations.py | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/ipatests/test_integration/test_dns_locations.py b/ipatests/test_integration/test_dns_locations.py
|
||||||
|
index 44900af80..89a310892 100644
|
||||||
|
--- a/ipatests/test_integration/test_dns_locations.py
|
||||||
|
+++ b/ipatests/test_integration/test_dns_locations.py
|
||||||
|
@@ -534,6 +534,9 @@ class TestDNSLocations(IntegrationTest):
|
||||||
|
|
||||||
|
expected_servers = (self.master.ip, self.replicas[1].ip)
|
||||||
|
|
||||||
|
+ ldap = self.master.ldap_connect()
|
||||||
|
+ tasks.wait_for_replication(ldap)
|
||||||
|
+
|
||||||
|
for ip in (self.master.ip, self.replicas[0].ip, self.replicas[1].ip):
|
||||||
|
self._test_A_rec_against_server(ip, self.domain, expected_servers)
|
||||||
|
|
||||||
|
@@ -557,6 +560,9 @@ class TestDNSLocations(IntegrationTest):
|
||||||
|
(self.PRIO_HIGH, self.WEIGHT, DNSName(self.master.hostname)),
|
||||||
|
)
|
||||||
|
|
||||||
|
+ ldap = self.master.ldap_connect()
|
||||||
|
+ tasks.wait_for_replication(ldap)
|
||||||
|
+
|
||||||
|
for ip in (self.master.ip, self.replicas[0].ip, self.replicas[1].ip):
|
||||||
|
self._test_SRV_rec_against_server(
|
||||||
|
ip, self.domain, expected_servers,
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
707
SOURCES/0017-ipa-kdb-Rework-ipadb_reinit_mspac.patch
Normal file
707
SOURCES/0017-ipa-kdb-Rework-ipadb_reinit_mspac.patch
Normal file
@ -0,0 +1,707 @@
|
|||||||
|
From c3ac69e9cf8dfcc31ed11fc988c37bd99d3ec3cf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Wed, 14 Feb 2024 17:47:00 +0100
|
||||||
|
Subject: [PATCH] ipa-kdb: Rework ipadb_reinit_mspac()
|
||||||
|
|
||||||
|
Modify ipadb_reinit_mspac() to allocate and initialize ipactx->mspac
|
||||||
|
only if all its attributes can be set. If not, ipactx->mspac is set to
|
||||||
|
NULL. This makes easier to determine if the KDC is able to generate PACs
|
||||||
|
or not.
|
||||||
|
|
||||||
|
Also ipadb_reinit_mspac() is now able to return a status message
|
||||||
|
explaining why initialization of the PAC generator failed. This message
|
||||||
|
is printed in KDC logs.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9535
|
||||||
|
|
||||||
|
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||||
|
Reviewed-By: Alexander Bokovoy <abbra@users.noreply.github.com>
|
||||||
|
(cherry picked from commit 7f072e348d318e928f6270a182ca04dee8716677)
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb.c | 14 +-
|
||||||
|
daemons/ipa-kdb/ipa_kdb.h | 4 +-
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac.c | 340 +++++++++++++-----------
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac_private.h | 2 +-
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac_v6.c | 5 +-
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac_v9.c | 16 +-
|
||||||
|
daemons/ipa-kdb/ipa_kdb_principals.c | 6 +-
|
||||||
|
7 files changed, 218 insertions(+), 169 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
index 0c6325df9..fcadb8ee7 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.c
|
||||||
|
@@ -443,6 +443,7 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
|
||||||
|
struct timeval tv = { 5, 0 };
|
||||||
|
LDAPMessage *res = NULL;
|
||||||
|
LDAPMessage *first;
|
||||||
|
+ const char *stmsg;
|
||||||
|
int ret;
|
||||||
|
int v3;
|
||||||
|
|
||||||
|
@@ -522,16 +523,9 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get adtrust options using default refresh interval */
|
||||||
|
- ret = ipadb_reinit_mspac(ipactx, false);
|
||||||
|
- if (ret && ret != ENOENT) {
|
||||||
|
- /* TODO: log that there is an issue with adtrust settings */
|
||||||
|
- if (ipactx->lcontext == NULL) {
|
||||||
|
- /* for some reason ldap connection was reset in ipadb_reinit_mspac
|
||||||
|
- * and is no longer established => failure of ipadb_get_connection
|
||||||
|
- */
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ ret = ipadb_reinit_mspac(ipactx, false, &stmsg);
|
||||||
|
+ if (ret && stmsg)
|
||||||
|
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
index 5de5ea7a5..7baf4697f 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb.h
|
||||||
|
@@ -352,7 +352,9 @@ krb5_error_code ipadb_v9_issue_pac(krb5_context context, unsigned int flags,
|
||||||
|
krb5_data ***auth_indicators);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit);
|
||||||
|
+krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx,
|
||||||
|
+ bool force_reinit,
|
||||||
|
+ const char **stmsg);
|
||||||
|
|
||||||
|
void ipadb_mspac_struct_free(struct ipadb_mspac **mspac);
|
||||||
|
krb5_error_code ipadb_check_transited_realms(krb5_context kcontext,
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index 886ed7785..deed513b9 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -793,16 +793,16 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (!ipactx->mspac) {
|
||||||
|
+ /* can't give a PAC without server NetBIOS name or primary group RID */
|
||||||
|
+ return ENOENT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (info3->base.primary_gid == 0) {
|
||||||
|
if (is_host || is_service) {
|
||||||
|
info3->base.primary_gid = 515; /* Well known RID for domain computers group */
|
||||||
|
} else {
|
||||||
|
- if (ipactx->mspac->fallback_rid) {
|
||||||
|
- info3->base.primary_gid = ipactx->mspac->fallback_rid;
|
||||||
|
- } else {
|
||||||
|
- /* can't give a pack without a primary group rid */
|
||||||
|
- return ENOENT;
|
||||||
|
- }
|
||||||
|
+ info3->base.primary_gid = ipactx->mspac->fallback_rid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -812,26 +812,16 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx,
|
||||||
|
/* always zero out, not used for Krb, only NTLM */
|
||||||
|
memset(&info3->base.key, '\0', sizeof(info3->base.key));
|
||||||
|
|
||||||
|
- if (ipactx->mspac->flat_server_name) {
|
||||||
|
- info3->base.logon_server.string =
|
||||||
|
- talloc_strdup(memctx, ipactx->mspac->flat_server_name);
|
||||||
|
- if (!info3->base.logon_server.string) {
|
||||||
|
- return ENOMEM;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- /* can't give a pack without Server NetBIOS Name :-| */
|
||||||
|
- return ENOENT;
|
||||||
|
+ info3->base.logon_server.string =
|
||||||
|
+ talloc_strdup(memctx, ipactx->mspac->flat_server_name);
|
||||||
|
+ if (!info3->base.logon_server.string) {
|
||||||
|
+ return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (ipactx->mspac->flat_domain_name) {
|
||||||
|
- info3->base.logon_domain.string =
|
||||||
|
- talloc_strdup(memctx, ipactx->mspac->flat_domain_name);
|
||||||
|
- if (!info3->base.logon_domain.string) {
|
||||||
|
- return ENOMEM;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- /* can't give a pack without Domain NetBIOS Name :-| */
|
||||||
|
- return ENOENT;
|
||||||
|
+ info3->base.logon_domain.string =
|
||||||
|
+ talloc_strdup(memctx, ipactx->mspac->flat_domain_name);
|
||||||
|
+ if (!info3->base.logon_domain.string) {
|
||||||
|
+ return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_host || is_service) {
|
||||||
|
@@ -1044,6 +1034,11 @@ krb5_error_code ipadb_get_pac(krb5_context kcontext,
|
||||||
|
return KRB5_KDB_DBNOTINITED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Check if PAC generator is initialized */
|
||||||
|
+ if (!ipactx->mspac) {
|
||||||
|
+ return ENOENT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ied = (struct ipadb_e_data *)client->e_data;
|
||||||
|
if (ied->magic != IPA_E_DATA_MAGIC) {
|
||||||
|
return EINVAL;
|
||||||
|
@@ -1626,14 +1621,14 @@ static struct ipadb_adtrusts *get_domain_from_realm(krb5_context context,
|
||||||
|
{
|
||||||
|
struct ipadb_context *ipactx;
|
||||||
|
struct ipadb_adtrusts *domain;
|
||||||
|
- int i;
|
||||||
|
+ size_t i;
|
||||||
|
|
||||||
|
ipactx = ipadb_get_context(context);
|
||||||
|
if (!ipactx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (ipactx->mspac == NULL) {
|
||||||
|
+ if (!ipactx->mspac) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1655,6 +1650,7 @@ static struct ipadb_adtrusts *get_domain_from_realm_update(krb5_context context,
|
||||||
|
{
|
||||||
|
struct ipadb_context *ipactx;
|
||||||
|
struct ipadb_adtrusts *domain;
|
||||||
|
+ const char *stmsg = NULL;
|
||||||
|
krb5_error_code kerr;
|
||||||
|
|
||||||
|
ipactx = ipadb_get_context(context);
|
||||||
|
@@ -1663,8 +1659,10 @@ static struct ipadb_adtrusts *get_domain_from_realm_update(krb5_context context,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* re-init MS-PAC info using default update interval */
|
||||||
|
- kerr = ipadb_reinit_mspac(ipactx, false);
|
||||||
|
+ kerr = ipadb_reinit_mspac(ipactx, false, &stmsg);
|
||||||
|
if (kerr != 0) {
|
||||||
|
+ if (stmsg)
|
||||||
|
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
domain = get_domain_from_realm(context, realm);
|
||||||
|
@@ -1717,6 +1715,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||||
|
struct ipadb_e_data *ied = NULL;
|
||||||
|
int flags = 0;
|
||||||
|
struct dom_sid client_sid;
|
||||||
|
+ const char *stmsg = NULL;
|
||||||
|
#ifdef KRB5_KDB_FLAG_ALIAS_OK
|
||||||
|
flags = KRB5_KDB_FLAG_ALIAS_OK;
|
||||||
|
#endif
|
||||||
|
@@ -1730,10 +1729,14 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||||
|
* check that our own view on the PAC details is up to date */
|
||||||
|
if (ipactx->mspac->domsid.num_auths == 0) {
|
||||||
|
/* Force re-init of KDB's view on our domain */
|
||||||
|
- kerr = ipadb_reinit_mspac(ipactx, true);
|
||||||
|
+ kerr = ipadb_reinit_mspac(ipactx, true, &stmsg);
|
||||||
|
if (kerr != 0) {
|
||||||
|
- krb5_klog_syslog(LOG_ERR,
|
||||||
|
- "PAC issue: unable to update realm's view on PAC info");
|
||||||
|
+ if (stmsg) {
|
||||||
|
+ krb5_klog_syslog(LOG_ERR, "MS-PAC generator: %s", stmsg);
|
||||||
|
+ } else {
|
||||||
|
+ krb5_klog_syslog(LOG_ERR, "PAC issue: unable to update " \
|
||||||
|
+ "realm's view on PAC info");
|
||||||
|
+ }
|
||||||
|
return KRB5KDC_ERR_POLICY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1746,7 +1749,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context,
|
||||||
|
if (is_s4u && (ipactx->mspac->trusts != NULL)) {
|
||||||
|
/* Iterate through list of trusts and check if this SID belongs to
|
||||||
|
* one of the domains we trust */
|
||||||
|
- for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) {
|
||||||
|
+ for(size_t i = 0 ; i < ipactx->mspac->num_trusts ; i++) {
|
||||||
|
result = dom_sid_check(&ipactx->mspac->trusts[i].domsid,
|
||||||
|
info->info->info3.base.domain_sid, true);
|
||||||
|
if (result) {
|
||||||
|
@@ -1858,11 +1861,11 @@ krb5_error_code filter_logon_info(krb5_context context,
|
||||||
|
struct ipadb_mspac *mspac_ctx = ipactx->mspac;
|
||||||
|
result = FALSE;
|
||||||
|
/* Didn't match but perhaps the original PAC was issued by a child domain's DC? */
|
||||||
|
- for (k = 0; k < mspac_ctx->num_trusts; k++) {
|
||||||
|
- result = dom_sid_check(&mspac_ctx->trusts[k].domsid,
|
||||||
|
+ for (size_t m = 0; m < mspac_ctx->num_trusts; m++) {
|
||||||
|
+ result = dom_sid_check(&mspac_ctx->trusts[m].domsid,
|
||||||
|
info->info->info3.base.domain_sid, true);
|
||||||
|
if (result) {
|
||||||
|
- domain = &mspac_ctx->trusts[k];
|
||||||
|
+ domain = &mspac_ctx->trusts[m];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2091,10 +2094,10 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context,
|
||||||
|
return KRB5_KDB_DBNOTINITED;
|
||||||
|
}
|
||||||
|
/* In S4U case we might be dealing with the PAC issued by the trusted domain */
|
||||||
|
- if ((ipactx->mspac->trusts != NULL)) {
|
||||||
|
+ if (ipactx->mspac->trusts) {
|
||||||
|
/* Iterate through list of trusts and check if this SID belongs to
|
||||||
|
* one of the domains we trust */
|
||||||
|
- for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) {
|
||||||
|
+ for(size_t i = 0 ; i < ipactx->mspac->num_trusts ; i++) {
|
||||||
|
result = dom_sid_check(&ipactx->mspac->trusts[i].domsid,
|
||||||
|
&client_sid, false);
|
||||||
|
if (result) {
|
||||||
|
@@ -2631,7 +2634,7 @@ static char *get_server_netbios_name(struct ipadb_context *ipactx)
|
||||||
|
|
||||||
|
void ipadb_mspac_struct_free(struct ipadb_mspac **mspac)
|
||||||
|
{
|
||||||
|
- int i, j;
|
||||||
|
+ size_t i, j;
|
||||||
|
|
||||||
|
if (!*mspac) return;
|
||||||
|
|
||||||
|
@@ -2786,7 +2789,8 @@ ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx)
|
||||||
|
LDAPDN dn = NULL;
|
||||||
|
char **sid_blocklist_incoming = NULL;
|
||||||
|
char **sid_blocklist_outgoing = NULL;
|
||||||
|
- int ret, n, i;
|
||||||
|
+ size_t i, n;
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
ret = asprintf(&base, "cn=ad,cn=trusts,%s", ipactx->base);
|
||||||
|
if (ret == -1) {
|
||||||
|
@@ -2871,7 +2875,7 @@ ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx)
|
||||||
|
|
||||||
|
t[n].upn_suffixes_len = NULL;
|
||||||
|
if (t[n].upn_suffixes != NULL) {
|
||||||
|
- int len = 0;
|
||||||
|
+ size_t len = 0;
|
||||||
|
|
||||||
|
for (; t[n].upn_suffixes[len] != NULL; len++);
|
||||||
|
|
||||||
|
@@ -2986,108 +2990,114 @@ done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
-krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit)
|
||||||
|
+krb5_error_code
|
||||||
|
+ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit,
|
||||||
|
+ const char **stmsg)
|
||||||
|
{
|
||||||
|
char *dom_attrs[] = { "ipaNTFlatName",
|
||||||
|
"ipaNTFallbackPrimaryGroup",
|
||||||
|
"ipaNTSecurityIdentifier",
|
||||||
|
NULL };
|
||||||
|
char *grp_attrs[] = { "ipaNTSecurityIdentifier", NULL };
|
||||||
|
- krb5_error_code kerr;
|
||||||
|
LDAPMessage *result = NULL;
|
||||||
|
LDAPMessage *lentry;
|
||||||
|
- struct dom_sid gsid;
|
||||||
|
- char *resstr;
|
||||||
|
- int ret;
|
||||||
|
+ struct dom_sid gsid, domsid;
|
||||||
|
+ char *resstr = NULL;
|
||||||
|
+ char *flat_domain_name = NULL;
|
||||||
|
+ char *flat_server_name = NULL;
|
||||||
|
+ char *fallback_group = NULL;
|
||||||
|
+ uint32_t fallback_rid;
|
||||||
|
time_t now;
|
||||||
|
+ const char *in_stmsg = NULL;
|
||||||
|
+ int err;
|
||||||
|
+ krb5_error_code trust_kerr = 0;
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Do not update the mspac struct more than once a minute. This would
|
||||||
|
* avoid heavy load on the directory server if there are lots of requests
|
||||||
|
* from domains which we do not trust. */
|
||||||
|
now = time(NULL);
|
||||||
|
|
||||||
|
- if (ipactx->mspac != NULL &&
|
||||||
|
- (force_reinit == false) &&
|
||||||
|
- (now > ipactx->mspac->last_update) &&
|
||||||
|
- (now - ipactx->mspac->last_update) < 60) {
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ipactx->mspac && ipactx->mspac->num_trusts == 0) {
|
||||||
|
- /* Check if there is any trust configured. If not, just return
|
||||||
|
- * and do not re-initialize the MS-PAC structure. */
|
||||||
|
- kerr = ipadb_mspac_check_trusted_domains(ipactx);
|
||||||
|
- if (kerr == KRB5_KDB_NOENTRY) {
|
||||||
|
- kerr = 0;
|
||||||
|
- goto done;
|
||||||
|
- } else if (kerr != 0) {
|
||||||
|
- goto done;
|
||||||
|
+ if (ipactx->mspac) {
|
||||||
|
+ if (!force_reinit &&
|
||||||
|
+ (now > ipactx->mspac->last_update) &&
|
||||||
|
+ (now - ipactx->mspac->last_update) < 60) {
|
||||||
|
+ /* SKIP */
|
||||||
|
+ err = 0;
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* clean up in case we had old values around */
|
||||||
|
- ipadb_mspac_struct_free(&ipactx->mspac);
|
||||||
|
|
||||||
|
- ipactx->mspac = calloc(1, sizeof(struct ipadb_mspac));
|
||||||
|
- if (!ipactx->mspac) {
|
||||||
|
- kerr = ENOMEM;
|
||||||
|
- goto done;
|
||||||
|
+ if (ipactx->mspac->num_trusts == 0) {
|
||||||
|
+ /* Check if there is any trust configured. If not, just return
|
||||||
|
+ * and do not re-initialize the MS-PAC structure. */
|
||||||
|
+ err = ipadb_mspac_check_trusted_domains(ipactx);
|
||||||
|
+ if (err) {
|
||||||
|
+ if (err == KRB5_KDB_NOENTRY) {
|
||||||
|
+ /* SKIP */
|
||||||
|
+ err = 0;
|
||||||
|
+ } else {
|
||||||
|
+ in_stmsg = "Failed to fetch trusted domains information";
|
||||||
|
+ }
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- ipactx->mspac->last_update = now;
|
||||||
|
-
|
||||||
|
- kerr = ipadb_simple_search(ipactx, ipactx->base, LDAP_SCOPE_SUBTREE,
|
||||||
|
- "(objectclass=ipaNTDomainAttrs)", dom_attrs,
|
||||||
|
- &result);
|
||||||
|
- if (kerr == KRB5_KDB_NOENTRY) {
|
||||||
|
- return ENOENT;
|
||||||
|
- } else if (kerr != 0) {
|
||||||
|
- return EIO;
|
||||||
|
+ err = ipadb_simple_search(ipactx, ipactx->base, LDAP_SCOPE_SUBTREE,
|
||||||
|
+ "(objectclass=ipaNTDomainAttrs)", dom_attrs,
|
||||||
|
+ &result);
|
||||||
|
+ if (err == KRB5_KDB_NOENTRY) {
|
||||||
|
+ err = ENOENT;
|
||||||
|
+ in_stmsg = "Local domain NT attributes not configured";
|
||||||
|
+ goto end;
|
||||||
|
+ } else if (err) {
|
||||||
|
+ err = EIO;
|
||||||
|
+ in_stmsg = "Failed to fetch local domain NT attributes";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
lentry = ldap_first_entry(ipactx->lcontext, result);
|
||||||
|
if (!lentry) {
|
||||||
|
- kerr = ENOENT;
|
||||||
|
- goto done;
|
||||||
|
+ err = ENOENT;
|
||||||
|
+ in_stmsg = "Local domain NT attributes not configured";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
- "ipaNTFlatName",
|
||||||
|
- &ipactx->mspac->flat_domain_name);
|
||||||
|
- if (ret) {
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
+ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, "ipaNTFlatName",
|
||||||
|
+ &flat_domain_name);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = "Local domain NT flat name not configured";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
- "ipaNTSecurityIdentifier",
|
||||||
|
- &resstr);
|
||||||
|
- if (ret) {
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
+ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
+ "ipaNTSecurityIdentifier", &resstr);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = "Local domain SID not configured";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = ipadb_string_to_sid(resstr, &ipactx->mspac->domsid);
|
||||||
|
- if (ret) {
|
||||||
|
- kerr = ret;
|
||||||
|
- free(resstr);
|
||||||
|
- goto done;
|
||||||
|
+ err = ipadb_string_to_sid(resstr, &domsid);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = "Malformed local domain SID";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
free(resstr);
|
||||||
|
|
||||||
|
- free(ipactx->mspac->flat_server_name);
|
||||||
|
- ipactx->mspac->flat_server_name = get_server_netbios_name(ipactx);
|
||||||
|
- if (!ipactx->mspac->flat_server_name) {
|
||||||
|
- kerr = ENOMEM;
|
||||||
|
- goto done;
|
||||||
|
+ flat_server_name = get_server_netbios_name(ipactx);
|
||||||
|
+ if (!flat_server_name) {
|
||||||
|
+ err = ENOMEM;
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
- "ipaNTFallbackPrimaryGroup",
|
||||||
|
- &ipactx->mspac->fallback_group);
|
||||||
|
- if (ret && ret != ENOENT) {
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
+ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
+ "ipaNTFallbackPrimaryGroup", &fallback_group);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = (err == ENOENT)
|
||||||
|
+ ? "Local fallback primary group not configured"
|
||||||
|
+ : "Failed to fetch local fallback primary group";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* result and lentry not valid any more from here on */
|
||||||
|
@@ -3095,53 +3105,81 @@ krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_rein
|
||||||
|
result = NULL;
|
||||||
|
lentry = NULL;
|
||||||
|
|
||||||
|
- if (ret != ENOENT) {
|
||||||
|
- kerr = ipadb_simple_search(ipactx, ipactx->mspac->fallback_group,
|
||||||
|
- LDAP_SCOPE_BASE,
|
||||||
|
- "(objectclass=posixGroup)",
|
||||||
|
- grp_attrs, &result);
|
||||||
|
- if (kerr && kerr != KRB5_KDB_NOENTRY) {
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
+ err = ipadb_simple_search(ipactx, fallback_group, LDAP_SCOPE_BASE,
|
||||||
|
+ "(objectclass=posixGroup)", grp_attrs, &result);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = (err == KRB5_KDB_NOENTRY)
|
||||||
|
+ ? "Local fallback primary group has no POSIX definition"
|
||||||
|
+ : "Failed to fetch SID of POSIX group mapped as local fallback " \
|
||||||
|
+ "primary group";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- lentry = ldap_first_entry(ipactx->lcontext, result);
|
||||||
|
- if (!lentry) {
|
||||||
|
- kerr = ENOENT;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
+ lentry = ldap_first_entry(ipactx->lcontext, result);
|
||||||
|
+ if (!lentry) {
|
||||||
|
+ err = ENOENT;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (kerr == 0) {
|
||||||
|
- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
- "ipaNTSecurityIdentifier",
|
||||||
|
- &resstr);
|
||||||
|
- if (ret && ret != ENOENT) {
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
- if (ret == 0) {
|
||||||
|
- ret = ipadb_string_to_sid(resstr, &gsid);
|
||||||
|
- if (ret) {
|
||||||
|
- free(resstr);
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
- ret = sid_split_rid(&gsid, &ipactx->mspac->fallback_rid);
|
||||||
|
- if (ret) {
|
||||||
|
- free(resstr);
|
||||||
|
- kerr = ret;
|
||||||
|
- goto done;
|
||||||
|
- }
|
||||||
|
- free(resstr);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ err = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry,
|
||||||
|
+ "ipaNTSecurityIdentifier", &resstr);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = (err == ENOENT)
|
||||||
|
+ ? "The POSIX group set as fallback primary group has no SID " \
|
||||||
|
+ "configured"
|
||||||
|
+ : "Failed to fetch SID of POSIX group set as local fallback " \
|
||||||
|
+ "primary group";
|
||||||
|
+ goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
- kerr = ipadb_mspac_get_trusted_domains(ipactx);
|
||||||
|
+ err = ipadb_string_to_sid(resstr, &gsid);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = "Malformed SID of POSIX group set as local fallback " \
|
||||||
|
+ "primary group";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
-done:
|
||||||
|
+ err = sid_split_rid(&gsid, &fallback_rid);
|
||||||
|
+ if (err) {
|
||||||
|
+ in_stmsg = "Malformed SID of POSIX group mapped as local fallback " \
|
||||||
|
+ "primary group";
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* clean up in case we had old values around */
|
||||||
|
+ ipadb_mspac_struct_free(&ipactx->mspac);
|
||||||
|
+
|
||||||
|
+ ipactx->mspac = calloc(1, sizeof(struct ipadb_mspac));
|
||||||
|
+ if (!ipactx->mspac) {
|
||||||
|
+ err = ENOMEM;
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ipactx->mspac->last_update = now;
|
||||||
|
+ ipactx->mspac->flat_domain_name = flat_domain_name;
|
||||||
|
+ ipactx->mspac->flat_server_name = flat_server_name;
|
||||||
|
+ ipactx->mspac->domsid = domsid;
|
||||||
|
+ ipactx->mspac->fallback_group = fallback_group;
|
||||||
|
+ ipactx->mspac->fallback_rid = fallback_rid;
|
||||||
|
+
|
||||||
|
+ trust_kerr = ipadb_mspac_get_trusted_domains(ipactx);
|
||||||
|
+ if (trust_kerr)
|
||||||
|
+ in_stmsg = "Failed to assemble trusted domains information";
|
||||||
|
+
|
||||||
|
+end:
|
||||||
|
+ if (stmsg)
|
||||||
|
+ *stmsg = in_stmsg;
|
||||||
|
+
|
||||||
|
+ if (resstr) free(resstr);
|
||||||
|
ldap_msgfree(result);
|
||||||
|
- return kerr;
|
||||||
|
+
|
||||||
|
+ if (err) {
|
||||||
|
+ if (flat_domain_name) free(flat_domain_name);
|
||||||
|
+ if (flat_server_name) free(flat_server_name);
|
||||||
|
+ if (fallback_group) free(fallback_group);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return err ? (krb5_error_code)err : trust_kerr;
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_error_code ipadb_check_transited_realms(krb5_context kcontext,
|
||||||
|
@@ -3151,11 +3189,11 @@ krb5_error_code ipadb_check_transited_realms(krb5_context kcontext,
|
||||||
|
{
|
||||||
|
struct ipadb_context *ipactx;
|
||||||
|
bool has_transited_contents, has_client_realm, has_server_realm;
|
||||||
|
- int i;
|
||||||
|
+ size_t i;
|
||||||
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
ipactx = ipadb_get_context(kcontext);
|
||||||
|
- if (!ipactx || !ipactx->mspac) {
|
||||||
|
+ if (!ipactx) {
|
||||||
|
return KRB5_KDB_DBNOTINITED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3217,7 +3255,7 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||||
|
char **trusted_realm)
|
||||||
|
{
|
||||||
|
struct ipadb_context *ipactx;
|
||||||
|
- int i, j, length;
|
||||||
|
+ size_t i, j, length;
|
||||||
|
const char *name;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_private.h b/daemons/ipa-kdb/ipa_kdb_mspac_private.h
|
||||||
|
index 7f0ca7a79..e650cfa73 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac_private.h
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac_private.h
|
||||||
|
@@ -31,7 +31,7 @@ struct ipadb_mspac {
|
||||||
|
char *fallback_group;
|
||||||
|
uint32_t fallback_rid;
|
||||||
|
|
||||||
|
- int num_trusts;
|
||||||
|
+ size_t num_trusts;
|
||||||
|
struct ipadb_adtrusts *trusts;
|
||||||
|
time_t last_update;
|
||||||
|
};
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_v6.c b/daemons/ipa-kdb/ipa_kdb_mspac_v6.c
|
||||||
|
index faf47ad1b..96cd50e4c 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac_v6.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac_v6.c
|
||||||
|
@@ -233,6 +233,7 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
|
||||||
|
krb5_db_entry *client_entry = NULL;
|
||||||
|
krb5_boolean is_equal;
|
||||||
|
bool force_reinit_mspac = false;
|
||||||
|
+ const char *stmsg = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
|
||||||
|
@@ -309,7 +310,9 @@ krb5_error_code ipadb_sign_authdata(krb5_context context,
|
||||||
|
force_reinit_mspac = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)ipadb_reinit_mspac(ipactx, force_reinit_mspac);
|
||||||
|
+ kerr = ipadb_reinit_mspac(ipactx, force_reinit_mspac, &stmsg);
|
||||||
|
+ if (kerr && stmsg)
|
||||||
|
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
|
||||||
|
|
||||||
|
kerr = ipadb_get_pac(context, flags, client, server, NULL, authtime, &pac);
|
||||||
|
if (kerr != 0 && kerr != ENOENT) {
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_v9.c b/daemons/ipa-kdb/ipa_kdb_mspac_v9.c
|
||||||
|
index 3badd5b08..60db048e1 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac_v9.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac_v9.c
|
||||||
|
@@ -46,6 +46,7 @@ ipadb_v9_issue_pac(krb5_context context, unsigned int flags,
|
||||||
|
bool with_pad;
|
||||||
|
krb5_error_code kerr = 0;
|
||||||
|
bool is_as_req = flags & CLIENT_REFERRALS_FLAGS;
|
||||||
|
+ const char *stmsg = NULL;
|
||||||
|
|
||||||
|
if (is_as_req) {
|
||||||
|
get_authz_data_types(context, client, &with_pac, &with_pad);
|
||||||
|
@@ -110,12 +111,19 @@ ipadb_v9_issue_pac(krb5_context context, unsigned int flags,
|
||||||
|
force_reinit_mspac = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void)ipadb_reinit_mspac(ipactx, force_reinit_mspac);
|
||||||
|
|
||||||
|
- /* MS-PAC needs proper configuration and if it is missing, we simply skip issuing one */
|
||||||
|
- if (ipactx->mspac->flat_server_name == NULL) {
|
||||||
|
+ /* MS-PAC generator has to be initalized */
|
||||||
|
+ kerr = ipadb_reinit_mspac(ipactx, force_reinit_mspac, &stmsg);
|
||||||
|
+ if (kerr && stmsg)
|
||||||
|
+ krb5_klog_syslog(LOG_ERR, "MS-PAC generator: %s", stmsg);
|
||||||
|
+
|
||||||
|
+ /* Continue even if initilization of PAC generator failed.
|
||||||
|
+ * It may caused by the trust objects part only. */
|
||||||
|
+
|
||||||
|
+ /* At least the core part of the PAC generator is required. */
|
||||||
|
+ if (!ipactx->mspac)
|
||||||
|
return KRB5_PLUGIN_OP_NOTSUPP;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
kerr = ipadb_get_pac(context, flags,
|
||||||
|
client, server, replaced_reply_key,
|
||||||
|
authtime, &new_pac);
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
|
||||||
|
index fadb132ed..07cc87746 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
|
||||||
|
@@ -1495,6 +1495,7 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||||
|
krb5_db_entry *kentry = NULL;
|
||||||
|
krb5_data *realm;
|
||||||
|
krb5_boolean check = FALSE;
|
||||||
|
+ const char *stmsg = NULL;
|
||||||
|
|
||||||
|
/* TODO: also support hostbased aliases */
|
||||||
|
|
||||||
|
@@ -1562,8 +1563,11 @@ static krb5_error_code dbget_alias(krb5_context kcontext,
|
||||||
|
if (kerr == KRB5_KDB_NOENTRY) {
|
||||||
|
/* If no trusted realm found, refresh trusted domain data and try again
|
||||||
|
* because it might be a freshly added trust to AD */
|
||||||
|
- kerr = ipadb_reinit_mspac(ipactx, false);
|
||||||
|
+ kerr = ipadb_reinit_mspac(ipactx, false, &stmsg);
|
||||||
|
if (kerr != 0) {
|
||||||
|
+ if (stmsg)
|
||||||
|
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s",
|
||||||
|
+ stmsg);
|
||||||
|
kerr = KRB5_KDB_NOENTRY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
From 44a762413c83f9637399afeb61b1e4b1ac111260 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Date: Feb 14 2024 12:24:48 +0000
|
||||||
|
Subject: ipatests: fix tasks.wait_for_replication method
|
||||||
|
|
||||||
|
|
||||||
|
With the fix for https://pagure.io/freeipa/issue/9171, the
|
||||||
|
method entry.single_value['nsds5replicaupdateinprogress'] now
|
||||||
|
returns a Boolean instead of a string "TRUE"/"FALSE".
|
||||||
|
|
||||||
|
The method tasks.wait_for_replication needs to be fixed so that
|
||||||
|
it properly detects when replication is not done.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9530
|
||||||
|
|
||||||
|
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py
|
||||||
|
index 9068ba6..952c9e6 100755
|
||||||
|
--- a/ipatests/pytest_ipa/integration/tasks.py
|
||||||
|
+++ b/ipatests/pytest_ipa/integration/tasks.py
|
||||||
|
@@ -1510,7 +1510,7 @@ def wait_for_replication(ldap, timeout=30,
|
||||||
|
statuses = [entry.single_value[status_attr] for entry in entries]
|
||||||
|
wrong_statuses = [s for s in statuses
|
||||||
|
if not re.match(target_status_re, s)]
|
||||||
|
- if any(e.single_value[progress_attr] == 'TRUE' for e in entries):
|
||||||
|
+ if any(e.single_value[progress_attr] for e in entries):
|
||||||
|
msg = 'Replication not finished'
|
||||||
|
logger.debug(msg)
|
||||||
|
elif wrong_statuses:
|
||||||
|
|
127
SOURCES/0019-Vault-add-support-for-RSA-OAEP-wrapping-algo.patch
Normal file
127
SOURCES/0019-Vault-add-support-for-RSA-OAEP-wrapping-algo.patch
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
From 163f06cab678d517ab30ab6da59ae339f39ee7cf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
Date: Fri, 27 May 2022 17:31:40 +0200
|
||||||
|
Subject: [PATCH] Vault: add support for RSA-OAEP wrapping algo
|
||||||
|
|
||||||
|
None of the FIPS certified modules in RHEL support PKCS#1 v1.5 as FIPS
|
||||||
|
approved mechanism. This commit adds support for RSA-OAEP padding as a
|
||||||
|
fallback.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9191
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
(cherry picked from commit b1fb31fd20c900c9ff1d5d28dfe136439f6bf605)
|
||||||
|
---
|
||||||
|
ipaclient/plugins/vault.py | 57 ++++++++++++++++++++++++++++++--------
|
||||||
|
1 file changed, 45 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py
|
||||||
|
index d4c84eb6b..ed16c73ae 100644
|
||||||
|
--- a/ipaclient/plugins/vault.py
|
||||||
|
+++ b/ipaclient/plugins/vault.py
|
||||||
|
@@ -119,8 +119,8 @@ def encrypt(data, symmetric_key=None, public_key=None):
|
||||||
|
return public_key_obj.encrypt(
|
||||||
|
data,
|
||||||
|
padding.OAEP(
|
||||||
|
- mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
||||||
|
- algorithm=hashes.SHA1(),
|
||||||
|
+ mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||||
|
+ algorithm=hashes.SHA256(),
|
||||||
|
label=None
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@@ -154,8 +154,8 @@ def decrypt(data, symmetric_key=None, private_key=None):
|
||||||
|
return private_key_obj.decrypt(
|
||||||
|
data,
|
||||||
|
padding.OAEP(
|
||||||
|
- mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
||||||
|
- algorithm=hashes.SHA1(),
|
||||||
|
+ mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||||
|
+ algorithm=hashes.SHA256(),
|
||||||
|
label=None
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@@ -705,14 +705,39 @@ class ModVaultData(Local):
|
||||||
|
return transport_cert, wrapping_algo
|
||||||
|
|
||||||
|
def _do_internal(self, algo, transport_cert, raise_unexpected,
|
||||||
|
- *args, **options):
|
||||||
|
+ use_oaep=False, *args, **options):
|
||||||
|
public_key = transport_cert.public_key()
|
||||||
|
|
||||||
|
# wrap session key with transport certificate
|
||||||
|
- wrapped_session_key = public_key.encrypt(
|
||||||
|
- algo.key,
|
||||||
|
- padding.PKCS1v15()
|
||||||
|
- )
|
||||||
|
+ # KRA may be configured using either the default PKCS1v15 or RSA-OAEP.
|
||||||
|
+ # there is no way to query this info using the REST interface.
|
||||||
|
+ if not use_oaep:
|
||||||
|
+ # PKCS1v15() causes an OpenSSL exception when FIPS is enabled
|
||||||
|
+ # if so, we fallback to RSA-OAEP
|
||||||
|
+ try:
|
||||||
|
+ wrapped_session_key = public_key.encrypt(
|
||||||
|
+ algo.key,
|
||||||
|
+ padding.PKCS1v15()
|
||||||
|
+ )
|
||||||
|
+ except ValueError:
|
||||||
|
+ wrapped_session_key = public_key.encrypt(
|
||||||
|
+ algo.key,
|
||||||
|
+ padding.OAEP(
|
||||||
|
+ mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||||
|
+ algorithm=hashes.SHA256(),
|
||||||
|
+ label=None
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ wrapped_session_key = public_key.encrypt(
|
||||||
|
+ algo.key,
|
||||||
|
+ padding.OAEP(
|
||||||
|
+ mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||||
|
+ algorithm=hashes.SHA256(),
|
||||||
|
+ label=None
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
options['session_key'] = wrapped_session_key
|
||||||
|
|
||||||
|
name = self.name + '_internal'
|
||||||
|
@@ -723,7 +748,7 @@ class ModVaultData(Local):
|
||||||
|
errors.ExecutionError,
|
||||||
|
errors.GenericError):
|
||||||
|
_kra_config_cache.remove(self.api.env.domain)
|
||||||
|
- if raise_unexpected:
|
||||||
|
+ if raise_unexpected and use_oaep:
|
||||||
|
raise
|
||||||
|
return None
|
||||||
|
|
||||||
|
@@ -733,15 +758,23 @@ class ModVaultData(Local):
|
||||||
|
"""
|
||||||
|
# try call with cached transport certificate
|
||||||
|
result = self._do_internal(algo, transport_cert, False,
|
||||||
|
- *args, **options)
|
||||||
|
+ False, *args, **options)
|
||||||
|
if result is not None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# retrieve transport certificate (cached by vaultconfig_show)
|
||||||
|
transport_cert = self._get_vaultconfig(force_refresh=True)[0]
|
||||||
|
+
|
||||||
|
# call with the retrieved transport certificate
|
||||||
|
+ result = self._do_internal(algo, transport_cert, True,
|
||||||
|
+ False, *args, **options)
|
||||||
|
+
|
||||||
|
+ if result is not None:
|
||||||
|
+ return result
|
||||||
|
+
|
||||||
|
+ # call and use_oaep this time, last attempt
|
||||||
|
return self._do_internal(algo, transport_cert, True,
|
||||||
|
- *args, **options)
|
||||||
|
+ True, *args, **options)
|
||||||
|
|
||||||
|
|
||||||
|
@register(no_fail=True)
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,88 @@
|
|||||||
|
From 84798137fabf75fe79aebbd97e4b8418de8ab0f2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
Date: Fri, 19 Jan 2024 18:15:28 +0100
|
||||||
|
Subject: [PATCH] Vault: improve vault server archival/retrieval calls
|
||||||
|
error handling
|
||||||
|
|
||||||
|
If a vault operation fails, the error message just says "InternalError". This commit
|
||||||
|
improves error handling of key archival and retrieval calls by catching the PKIException
|
||||||
|
error and raising it as an IPA error.
|
||||||
|
|
||||||
|
Related: https://pagure.io/freeipa/issue/9191
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
(cherry picked from commit dc1ab53f0aa0398d493f7440b5ec4d70d9c7d663)
|
||||||
|
---
|
||||||
|
ipaserver/plugins/vault.py | 40 +++++++++++++++++++++++++-------------
|
||||||
|
1 file changed, 26 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ipaserver/plugins/vault.py b/ipaserver/plugins/vault.py
|
||||||
|
index 574c83a9a..13c4fac9a 100644
|
||||||
|
--- a/ipaserver/plugins/vault.py
|
||||||
|
+++ b/ipaserver/plugins/vault.py
|
||||||
|
@@ -45,6 +45,7 @@ if api.env.in_server:
|
||||||
|
import pki.key
|
||||||
|
from pki.crypto import DES_EDE3_CBC_OID
|
||||||
|
from pki.crypto import AES_128_CBC_OID
|
||||||
|
+ from pki import PKIException
|
||||||
|
|
||||||
|
if six.PY3:
|
||||||
|
unicode = str
|
||||||
|
@@ -1094,16 +1095,21 @@ class vault_archive_internal(PKQuery):
|
||||||
|
pki.key.KeyClient.KEY_STATUS_INACTIVE)
|
||||||
|
|
||||||
|
# forward wrapped data to KRA
|
||||||
|
- kra_client.keys.archive_encrypted_data(
|
||||||
|
- client_key_id,
|
||||||
|
- pki.key.KeyClient.PASS_PHRASE_TYPE,
|
||||||
|
- wrapped_vault_data,
|
||||||
|
- wrapped_session_key,
|
||||||
|
- algorithm_oid=algorithm_oid,
|
||||||
|
- nonce_iv=nonce,
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
- kra_account.logout()
|
||||||
|
+ try:
|
||||||
|
+ kra_client.keys.archive_encrypted_data(
|
||||||
|
+ client_key_id,
|
||||||
|
+ pki.key.KeyClient.PASS_PHRASE_TYPE,
|
||||||
|
+ wrapped_vault_data,
|
||||||
|
+ wrapped_session_key,
|
||||||
|
+ algorithm_oid=algorithm_oid,
|
||||||
|
+ nonce_iv=nonce,
|
||||||
|
+ )
|
||||||
|
+ except PKIException as e:
|
||||||
|
+ kra_account.logout()
|
||||||
|
+ raise errors.EncodingError(
|
||||||
|
+ message=_("Unable to archive key: %s") % e)
|
||||||
|
+ finally:
|
||||||
|
+ kra_account.logout()
|
||||||
|
|
||||||
|
response = {
|
||||||
|
'value': args[-1],
|
||||||
|
@@ -1174,11 +1180,17 @@ class vault_retrieve_internal(PKQuery):
|
||||||
|
kra_client.keys.encrypt_alg_oid = algorithm_oid
|
||||||
|
|
||||||
|
# retrieve encrypted data from KRA
|
||||||
|
- key = kra_client.keys.retrieve_key(
|
||||||
|
- key_info.get_key_id(),
|
||||||
|
- wrapped_session_key)
|
||||||
|
+ try:
|
||||||
|
|
||||||
|
- kra_account.logout()
|
||||||
|
+ key = kra_client.keys.retrieve_key(
|
||||||
|
+ key_info.get_key_id(),
|
||||||
|
+ wrapped_session_key)
|
||||||
|
+ except PKIException as e:
|
||||||
|
+ kra_account.logout()
|
||||||
|
+ raise errors.EncodingError(
|
||||||
|
+ message=_("Unable to retrieve key: %s") % e)
|
||||||
|
+ finally:
|
||||||
|
+ kra_account.logout()
|
||||||
|
|
||||||
|
response = {
|
||||||
|
'value': args[-1],
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From a406fd9aec7d053c044e73f16b05489bebd84bc8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
Date: Fri, 19 Jan 2024 17:12:07 +0100
|
||||||
|
Subject: [PATCH] kra: set RSA-OAEP as default wrapping algo when FIPS is
|
||||||
|
enabled
|
||||||
|
|
||||||
|
Vault uses PKCS1v15 as default padding wrapping algo, which is not an approved
|
||||||
|
FIPS algorithm. This commit ensures that KRA is installed with RSA-OAEP if FIPS
|
||||||
|
is enabled. It also handles upgrade path.
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9191
|
||||||
|
|
||||||
|
Signed-off-by: Francisco Trivino <ftrivino@redhat.com>
|
||||||
|
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
(cherry picked from commit f2eec9eb208e62f923375b9eaf34fcc491046a0d)
|
||||||
|
---
|
||||||
|
install/share/ipaca_default.ini | 3 +++
|
||||||
|
ipaserver/install/dogtaginstance.py | 4 +++-
|
||||||
|
ipaserver/install/krainstance.py | 12 ++++++++++++
|
||||||
|
ipaserver/install/server/upgrade.py | 12 ++++++++++++
|
||||||
|
4 files changed, 30 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/install/share/ipaca_default.ini b/install/share/ipaca_default.ini
|
||||||
|
index 082f507b2..691f1e1b7 100644
|
||||||
|
--- a/install/share/ipaca_default.ini
|
||||||
|
+++ b/install/share/ipaca_default.ini
|
||||||
|
@@ -166,3 +166,6 @@ pki_audit_signing_subject_dn=cn=KRA Audit,%(ipa_subject_base)s
|
||||||
|
# We will use the dbuser created for the CA.
|
||||||
|
pki_share_db=True
|
||||||
|
pki_share_dbuser_dn=uid=pkidbuser,ou=people,o=ipaca
|
||||||
|
+
|
||||||
|
+# KRA padding, set RSA-OAEP in FIPS mode
|
||||||
|
+pki_use_oaep_rsa_keywrap=%(fips_use_oaep_rsa_keywrap)s
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
|
||||||
|
index c2c6b3f49..c3c726f68 100644
|
||||||
|
--- a/ipaserver/install/dogtaginstance.py
|
||||||
|
+++ b/ipaserver/install/dogtaginstance.py
|
||||||
|
@@ -1020,7 +1020,9 @@ class PKIIniLoader:
|
||||||
|
# for softhsm2 testing
|
||||||
|
softhsm2_so=paths.LIBSOFTHSM2_SO,
|
||||||
|
# Configure a more secure AJP password by default
|
||||||
|
- ipa_ajp_secret=ipautil.ipa_generate_password(special=None)
|
||||||
|
+ ipa_ajp_secret=ipautil.ipa_generate_password(special=None),
|
||||||
|
+ # in FIPS mode use RSA-OAEP wrapping padding algo as default
|
||||||
|
+ fips_use_oaep_rsa_keywrap=tasks.is_fips_enabled()
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
|
||||||
|
index 13cb2dcaa..0e04840a1 100644
|
||||||
|
--- a/ipaserver/install/krainstance.py
|
||||||
|
+++ b/ipaserver/install/krainstance.py
|
||||||
|
@@ -277,6 +277,18 @@ class KRAInstance(DogtagInstance):
|
||||||
|
|
||||||
|
# A restart is required
|
||||||
|
|
||||||
|
+ def enable_oaep_wrap_algo(self):
|
||||||
|
+ """
|
||||||
|
+ Enable KRA OAEP key wrap algorithm
|
||||||
|
+ """
|
||||||
|
+ with installutils.stopped_service('pki-tomcatd', 'pki-tomcat'):
|
||||||
|
+ directivesetter.set_directive(
|
||||||
|
+ self.config,
|
||||||
|
+ 'keyWrap.useOAEP',
|
||||||
|
+ 'true', quotes=False, separator='=')
|
||||||
|
+
|
||||||
|
+ # A restart is required
|
||||||
|
+
|
||||||
|
def update_cert_config(self, nickname, cert):
|
||||||
|
"""
|
||||||
|
When renewing a KRA subsystem certificate the configuration file
|
||||||
|
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
|
||||||
|
index e4dc7ae73..c84516b56 100644
|
||||||
|
--- a/ipaserver/install/server/upgrade.py
|
||||||
|
+++ b/ipaserver/install/server/upgrade.py
|
||||||
|
@@ -1780,6 +1780,18 @@ def upgrade_configuration():
|
||||||
|
else:
|
||||||
|
logger.info('ephemeralRequest is already enabled')
|
||||||
|
|
||||||
|
+ if tasks.is_fips_enabled():
|
||||||
|
+ logger.info('[Ensuring KRA OAEP wrap algo is enabled in FIPS]')
|
||||||
|
+ value = directivesetter.get_directive(
|
||||||
|
+ paths.KRA_CS_CFG_PATH,
|
||||||
|
+ 'keyWrap.useOAEP',
|
||||||
|
+ separator='=')
|
||||||
|
+ if value is None or value.lower() != 'true':
|
||||||
|
+ logger.info('Use the OAEP key wrap algo')
|
||||||
|
+ kra.enable_oaep_wrap_algo()
|
||||||
|
+ else:
|
||||||
|
+ logger.info('OAEP key wrap algo is already enabled')
|
||||||
|
+
|
||||||
|
# several upgrade steps require running CA. If CA is configured,
|
||||||
|
# always run ca.start() because we need to wait until CA is really ready
|
||||||
|
# by checking status using http
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From a8e433f7c8d844d9f337a34db09b0197f2dbc5af Mon Sep 17 00:00:00 2001
|
||||||
|
From: Julien Rische <jrische@redhat.com>
|
||||||
|
Date: Tue, 20 Feb 2024 15:14:24 +0100
|
||||||
|
Subject: [PATCH] ipa-kdb: Fix double free in ipadb_reinit_mspac()
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9535
|
||||||
|
|
||||||
|
Signed-off-by: Julien Rische <jrische@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
||||||
|
(cherry picked from commit dd27d225524aa81c038a970961a4f878cf742e2a)
|
||||||
|
---
|
||||||
|
daemons/ipa-kdb/ipa_kdb_mspac.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
index deed513b9..0964d112a 100644
|
||||||
|
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
|
||||||
|
@@ -3084,6 +3084,7 @@ ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_reinit,
|
||||||
|
}
|
||||||
|
|
||||||
|
free(resstr);
|
||||||
|
+ resstr = NULL;
|
||||||
|
|
||||||
|
flat_server_name = get_server_netbios_name(ipactx);
|
||||||
|
if (!flat_server_name) {
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,392 @@
|
|||||||
|
From b039f3087a13de3f34b230dbe29a7cfb1965700d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Date: Feb 23 2024 09:49:27 +0000
|
||||||
|
Subject: rpcserver: validate Kerberos principal name before running kinit
|
||||||
|
|
||||||
|
|
||||||
|
Do minimal validation of the Kerberos principal name when passing it to
|
||||||
|
kinit command line tool. Also pass it as the final argument to prevent
|
||||||
|
option injection.
|
||||||
|
|
||||||
|
Accepted Kerberos principals are:
|
||||||
|
- user names, using the following regexp
|
||||||
|
(username with optional @realm, no spaces or slashes in the name):
|
||||||
|
"(?!^[0-9]+$)^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?@?[a-zA-Z0-9.-]*$"
|
||||||
|
|
||||||
|
- service names (with slash in the name but no spaces). Validation of
|
||||||
|
the hostname is done. There is no validation of the service name.
|
||||||
|
|
||||||
|
The regular expression above also covers cases where a principal name
|
||||||
|
starts with '-'. This prevents option injection as well.
|
||||||
|
|
||||||
|
This fixes CVE-2024-1481
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9541
|
||||||
|
|
||||||
|
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipalib/install/kinit.py b/ipalib/install/kinit.py
|
||||||
|
index cc839ec..4ad4eaa 100644
|
||||||
|
--- a/ipalib/install/kinit.py
|
||||||
|
+++ b/ipalib/install/kinit.py
|
||||||
|
@@ -6,12 +6,16 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
+import re
|
||||||
|
import time
|
||||||
|
|
||||||
|
import gssapi
|
||||||
|
|
||||||
|
from ipaplatform.paths import paths
|
||||||
|
from ipapython.ipautil import run
|
||||||
|
+from ipalib.constants import PATTERN_GROUPUSER_NAME
|
||||||
|
+from ipalib.util import validate_hostname
|
||||||
|
+from ipalib import api
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@@ -21,6 +25,40 @@ KRB5_KDC_UNREACH = 2529639068
|
||||||
|
# A service is not available that s required to process the request
|
||||||
|
KRB5KDC_ERR_SVC_UNAVAILABLE = 2529638941
|
||||||
|
|
||||||
|
+PATTERN_REALM = '@?([a-zA-Z0-9.-]*)$'
|
||||||
|
+PATTERN_PRINCIPAL = '(' + PATTERN_GROUPUSER_NAME[:-1] + ')' + PATTERN_REALM
|
||||||
|
+PATTERN_SERVICE = '([a-zA-Z0-9.-]+)/([a-zA-Z0-9.-]+)' + PATTERN_REALM
|
||||||
|
+
|
||||||
|
+user_pattern = re.compile(PATTERN_PRINCIPAL)
|
||||||
|
+service_pattern = re.compile(PATTERN_SERVICE)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def validate_principal(principal):
|
||||||
|
+ if not isinstance(principal, str):
|
||||||
|
+ raise RuntimeError('Invalid principal: not a string')
|
||||||
|
+ if ('/' in principal) and (' ' in principal):
|
||||||
|
+ raise RuntimeError('Invalid principal: bad spacing')
|
||||||
|
+ else:
|
||||||
|
+ realm = None
|
||||||
|
+ match = user_pattern.match(principal)
|
||||||
|
+ if match is None:
|
||||||
|
+ match = service_pattern.match(principal)
|
||||||
|
+ if match is None:
|
||||||
|
+ raise RuntimeError('Invalid principal: cannot parse')
|
||||||
|
+ else:
|
||||||
|
+ # service = match[1]
|
||||||
|
+ hostname = match[2]
|
||||||
|
+ realm = match[3]
|
||||||
|
+ try:
|
||||||
|
+ validate_hostname(hostname)
|
||||||
|
+ except ValueError as e:
|
||||||
|
+ raise RuntimeError(str(e))
|
||||||
|
+ else: # user match, validate realm
|
||||||
|
+ # username = match[1]
|
||||||
|
+ realm = match[2]
|
||||||
|
+ if realm and 'realm' in api.env and realm != api.env.realm:
|
||||||
|
+ raise RuntimeError('Invalid principal: realm mismatch')
|
||||||
|
+
|
||||||
|
|
||||||
|
def kinit_keytab(principal, keytab, ccache_name, config=None, attempts=1):
|
||||||
|
"""
|
||||||
|
@@ -29,6 +67,7 @@ def kinit_keytab(principal, keytab, ccache_name, config=None, attempts=1):
|
||||||
|
The optional parameter 'attempts' specifies how many times the credential
|
||||||
|
initialization should be attempted in case of non-responsive KDC.
|
||||||
|
"""
|
||||||
|
+ validate_principal(principal)
|
||||||
|
errors_to_retry = {KRB5KDC_ERR_SVC_UNAVAILABLE,
|
||||||
|
KRB5_KDC_UNREACH}
|
||||||
|
logger.debug("Initializing principal %s using keytab %s",
|
||||||
|
@@ -65,6 +104,7 @@ def kinit_keytab(principal, keytab, ccache_name, config=None, attempts=1):
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
+
|
||||||
|
def kinit_password(principal, password, ccache_name, config=None,
|
||||||
|
armor_ccache_name=None, canonicalize=False,
|
||||||
|
enterprise=False, lifetime=None):
|
||||||
|
@@ -73,8 +113,9 @@ def kinit_password(principal, password, ccache_name, config=None,
|
||||||
|
web-based authentication, use armor_ccache_path to specify http service
|
||||||
|
ccache.
|
||||||
|
"""
|
||||||
|
+ validate_principal(principal)
|
||||||
|
logger.debug("Initializing principal %s using password", principal)
|
||||||
|
- args = [paths.KINIT, principal, '-c', ccache_name]
|
||||||
|
+ args = [paths.KINIT, '-c', ccache_name]
|
||||||
|
if armor_ccache_name is not None:
|
||||||
|
logger.debug("Using armor ccache %s for FAST webauth",
|
||||||
|
armor_ccache_name)
|
||||||
|
@@ -91,6 +132,7 @@ def kinit_password(principal, password, ccache_name, config=None,
|
||||||
|
logger.debug("Using enterprise principal")
|
||||||
|
args.append('-E')
|
||||||
|
|
||||||
|
+ args.extend(['--', principal])
|
||||||
|
env = {'LC_ALL': 'C'}
|
||||||
|
if config is not None:
|
||||||
|
env['KRB5_CONFIG'] = config
|
||||||
|
@@ -154,6 +196,7 @@ def kinit_pkinit(
|
||||||
|
|
||||||
|
:raises: CalledProcessError if PKINIT fails
|
||||||
|
"""
|
||||||
|
+ validate_principal(principal)
|
||||||
|
logger.debug(
|
||||||
|
"Initializing principal %s using PKINIT %s", principal, user_identity
|
||||||
|
)
|
||||||
|
@@ -168,7 +211,7 @@ def kinit_pkinit(
|
||||||
|
assert pkinit_anchor.startswith(("FILE:", "DIR:", "ENV:"))
|
||||||
|
args.extend(["-X", f"X509_anchors={pkinit_anchor}"])
|
||||||
|
args.extend(["-X", f"X509_user_identity={user_identity}"])
|
||||||
|
- args.append(principal)
|
||||||
|
+ args.extend(['--', principal])
|
||||||
|
|
||||||
|
# this workaround enables us to capture stderr and put it
|
||||||
|
# into the raised exception in case of unsuccessful authentication
|
||||||
|
diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
|
||||||
|
index 3555014..60bfa61 100644
|
||||||
|
--- a/ipaserver/rpcserver.py
|
||||||
|
+++ b/ipaserver/rpcserver.py
|
||||||
|
@@ -1134,10 +1134,6 @@ class login_password(Backend, KerberosSession):
|
||||||
|
canonicalize=True,
|
||||||
|
lifetime=self.api.env.kinit_lifetime)
|
||||||
|
|
||||||
|
- if armor_path:
|
||||||
|
- logger.debug('Cleanup the armor ccache')
|
||||||
|
- ipautil.run([paths.KDESTROY, '-A', '-c', armor_path],
|
||||||
|
- env={'KRB5CCNAME': armor_path}, raiseonerr=False)
|
||||||
|
except RuntimeError as e:
|
||||||
|
if ('kinit: Cannot read password while '
|
||||||
|
'getting initial credentials') in str(e):
|
||||||
|
@@ -1155,6 +1151,11 @@ class login_password(Backend, KerberosSession):
|
||||||
|
raise KrbPrincipalWrongFAST(principal=principal)
|
||||||
|
raise InvalidSessionPassword(principal=principal,
|
||||||
|
message=unicode(e))
|
||||||
|
+ finally:
|
||||||
|
+ if armor_path:
|
||||||
|
+ logger.debug('Cleanup the armor ccache')
|
||||||
|
+ ipautil.run([paths.KDESTROY, '-A', '-c', armor_path],
|
||||||
|
+ env={'KRB5CCNAME': armor_path}, raiseonerr=False)
|
||||||
|
|
||||||
|
|
||||||
|
class change_password(Backend, HTTP_Status):
|
||||||
|
diff --git a/ipatests/prci_definitions/gating.yaml b/ipatests/prci_definitions/gating.yaml
|
||||||
|
index 91be057..400a248 100644
|
||||||
|
--- a/ipatests/prci_definitions/gating.yaml
|
||||||
|
+++ b/ipatests/prci_definitions/gating.yaml
|
||||||
|
@@ -310,3 +310,15 @@ jobs:
|
||||||
|
template: *ci-ipa-4-9-latest
|
||||||
|
timeout: 3600
|
||||||
|
topology: *master_1repl_1client
|
||||||
|
+
|
||||||
|
+ fedora-latest-ipa-4-9/test_ipalib_install:
|
||||||
|
+ requires: [fedora-latest-ipa-4-9/build]
|
||||||
|
+ priority: 100
|
||||||
|
+ job:
|
||||||
|
+ class: RunPytest
|
||||||
|
+ args:
|
||||||
|
+ build_url: '{fedora-latest-ipa-4-9/build_url}'
|
||||||
|
+ test_suite: test_ipalib_install/test_kinit.py
|
||||||
|
+ template: *ci-ipa-4-9-latest
|
||||||
|
+ timeout: 600
|
||||||
|
+ topology: *master_1repl
|
||||||
|
diff --git a/ipatests/prci_definitions/nightly_ipa-4-9_latest.yaml b/ipatests/prci_definitions/nightly_ipa-4-9_latest.yaml
|
||||||
|
index b2ab765..7c03a48 100644
|
||||||
|
--- a/ipatests/prci_definitions/nightly_ipa-4-9_latest.yaml
|
||||||
|
+++ b/ipatests/prci_definitions/nightly_ipa-4-9_latest.yaml
|
||||||
|
@@ -1801,3 +1801,15 @@ jobs:
|
||||||
|
template: *ci-ipa-4-9-latest
|
||||||
|
timeout: 5000
|
||||||
|
topology: *master_2repl_1client
|
||||||
|
+
|
||||||
|
+ fedora-latest-ipa-4-9/test_ipalib_install:
|
||||||
|
+ requires: [fedora-latest-ipa-4-9/build]
|
||||||
|
+ priority: 50
|
||||||
|
+ job:
|
||||||
|
+ class: RunPytest
|
||||||
|
+ args:
|
||||||
|
+ build_url: '{fedora-latest-ipa-4-9/build_url}'
|
||||||
|
+ test_suite: test_ipalib_install/test_kinit.py
|
||||||
|
+ template: *ci-ipa-4-9-latest
|
||||||
|
+ timeout: 600
|
||||||
|
+ topology: *master_1repl
|
||||||
|
diff --git a/ipatests/prci_definitions/nightly_ipa-4-9_latest_selinux.yaml b/ipatests/prci_definitions/nightly_ipa-4-9_latest_selinux.yaml
|
||||||
|
index b7b3d3b..802bd2a 100644
|
||||||
|
--- a/ipatests/prci_definitions/nightly_ipa-4-9_latest_selinux.yaml
|
||||||
|
+++ b/ipatests/prci_definitions/nightly_ipa-4-9_latest_selinux.yaml
|
||||||
|
@@ -1944,3 +1944,16 @@ jobs:
|
||||||
|
template: *ci-ipa-4-9-latest
|
||||||
|
timeout: 5000
|
||||||
|
topology: *master_2repl_1client
|
||||||
|
+
|
||||||
|
+ fedora-latest-ipa-4-9/test_ipalib_install:
|
||||||
|
+ requires: [fedora-latest-ipa-4-9/build]
|
||||||
|
+ priority: 50
|
||||||
|
+ job:
|
||||||
|
+ class: RunPytest
|
||||||
|
+ args:
|
||||||
|
+ build_url: '{fedora-latest-ipa-4-9/build_url}'
|
||||||
|
+ selinux_enforcing: True
|
||||||
|
+ test_suite: test_ipalib_install/test_kinit.py
|
||||||
|
+ template: *ci-ipa-4-9-latest
|
||||||
|
+ timeout: 600
|
||||||
|
+ topology: *master_1repl
|
||||||
|
diff --git a/ipatests/prci_definitions/nightly_ipa-4-9_previous.yaml b/ipatests/prci_definitions/nightly_ipa-4-9_previous.yaml
|
||||||
|
index eb3849e..1e1adb8 100644
|
||||||
|
--- a/ipatests/prci_definitions/nightly_ipa-4-9_previous.yaml
|
||||||
|
+++ b/ipatests/prci_definitions/nightly_ipa-4-9_previous.yaml
|
||||||
|
@@ -1801,3 +1801,15 @@ jobs:
|
||||||
|
template: *ci-ipa-4-9-previous
|
||||||
|
timeout: 5000
|
||||||
|
topology: *master_2repl_1client
|
||||||
|
+
|
||||||
|
+ fedora-previous-ipa-4-9/test_ipalib_install:
|
||||||
|
+ requires: [fedora-previous-ipa-4-9/build]
|
||||||
|
+ priority: 50
|
||||||
|
+ job:
|
||||||
|
+ class: RunPytest
|
||||||
|
+ args:
|
||||||
|
+ build_url: '{fedora-previous-ipa-4-9/build_url}'
|
||||||
|
+ test_suite: test_ipalib_install/test_kinit.py
|
||||||
|
+ template: *ci-ipa-4-9-previous
|
||||||
|
+ timeout: 600
|
||||||
|
+ topology: *master_1repl
|
||||||
|
diff --git a/ipatests/setup.py b/ipatests/setup.py
|
||||||
|
index 6217a1b..0aec4a7 100644
|
||||||
|
--- a/ipatests/setup.py
|
||||||
|
+++ b/ipatests/setup.py
|
||||||
|
@@ -41,6 +41,7 @@ if __name__ == '__main__':
|
||||||
|
"ipatests.test_integration",
|
||||||
|
"ipatests.test_ipaclient",
|
||||||
|
"ipatests.test_ipalib",
|
||||||
|
+ "ipatests.test_ipalib_install",
|
||||||
|
"ipatests.test_ipaplatform",
|
||||||
|
"ipatests.test_ipapython",
|
||||||
|
"ipatests.test_ipaserver",
|
||||||
|
diff --git a/ipatests/test_ipalib_install/__init__.py b/ipatests/test_ipalib_install/__init__.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e69de29
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/ipatests/test_ipalib_install/__init__.py
|
||||||
|
diff --git a/ipatests/test_ipalib_install/test_kinit.py b/ipatests/test_ipalib_install/test_kinit.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..f89ea17
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/ipatests/test_ipalib_install/test_kinit.py
|
||||||
|
@@ -0,0 +1,29 @@
|
||||||
|
+#
|
||||||
|
+# Copyright (C) 2024 FreeIPA Contributors see COPYING for license
|
||||||
|
+#
|
||||||
|
+"""Tests for ipalib.install.kinit module
|
||||||
|
+"""
|
||||||
|
+
|
||||||
|
+import pytest
|
||||||
|
+
|
||||||
|
+from ipalib.install.kinit import validate_principal
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# None means no exception is expected
|
||||||
|
+@pytest.mark.parametrize('principal, exception', [
|
||||||
|
+ ('testuser', None),
|
||||||
|
+ ('testuser@EXAMPLE.TEST', None),
|
||||||
|
+ ('test/ipa.example.test', None),
|
||||||
|
+ ('test/ipa.example.test@EXAMPLE.TEST', None),
|
||||||
|
+ ('test/ipa@EXAMPLE.TEST', RuntimeError),
|
||||||
|
+ ('test/-ipa.example.test@EXAMPLE.TEST', RuntimeError),
|
||||||
|
+ ('test/ipa.1example.test@EXAMPLE.TEST', RuntimeError),
|
||||||
|
+ ('test /ipa.example,test', RuntimeError),
|
||||||
|
+ ('testuser@OTHER.TEST', RuntimeError),
|
||||||
|
+ ('test/ipa.example.test@OTHER.TEST', RuntimeError),
|
||||||
|
+])
|
||||||
|
+def test_validate_principal(principal, exception):
|
||||||
|
+ try:
|
||||||
|
+ validate_principal(principal)
|
||||||
|
+ except Exception as e:
|
||||||
|
+ assert e.__class__ == exception
|
||||||
|
|
||||||
|
From 96a478bbedd49c31e0f078f00f2d1cb55bb952fd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Feb 23 2024 09:49:27 +0000
|
||||||
|
Subject: validate_principal: Don't try to verify that the realm is known
|
||||||
|
|
||||||
|
|
||||||
|
The actual value is less important than whether it matches the
|
||||||
|
regular expression. A number of legal but difficult to know in
|
||||||
|
context realms could be passed in here (trust for example).
|
||||||
|
|
||||||
|
This fixes CVE-2024-1481
|
||||||
|
|
||||||
|
Fixes: https://pagure.io/freeipa/issue/9541
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipalib/install/kinit.py b/ipalib/install/kinit.py
|
||||||
|
index 4ad4eaa..d5fb56b 100644
|
||||||
|
--- a/ipalib/install/kinit.py
|
||||||
|
+++ b/ipalib/install/kinit.py
|
||||||
|
@@ -15,7 +15,6 @@ from ipaplatform.paths import paths
|
||||||
|
from ipapython.ipautil import run
|
||||||
|
from ipalib.constants import PATTERN_GROUPUSER_NAME
|
||||||
|
from ipalib.util import validate_hostname
|
||||||
|
-from ipalib import api
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@@ -39,7 +38,9 @@ def validate_principal(principal):
|
||||||
|
if ('/' in principal) and (' ' in principal):
|
||||||
|
raise RuntimeError('Invalid principal: bad spacing')
|
||||||
|
else:
|
||||||
|
- realm = None
|
||||||
|
+ # For a user match in the regex
|
||||||
|
+ # username = match[1]
|
||||||
|
+ # realm = match[2]
|
||||||
|
match = user_pattern.match(principal)
|
||||||
|
if match is None:
|
||||||
|
match = service_pattern.match(principal)
|
||||||
|
@@ -48,16 +49,11 @@ def validate_principal(principal):
|
||||||
|
else:
|
||||||
|
# service = match[1]
|
||||||
|
hostname = match[2]
|
||||||
|
- realm = match[3]
|
||||||
|
+ # realm = match[3]
|
||||||
|
try:
|
||||||
|
validate_hostname(hostname)
|
||||||
|
except ValueError as e:
|
||||||
|
raise RuntimeError(str(e))
|
||||||
|
- else: # user match, validate realm
|
||||||
|
- # username = match[1]
|
||||||
|
- realm = match[2]
|
||||||
|
- if realm and 'realm' in api.env and realm != api.env.realm:
|
||||||
|
- raise RuntimeError('Invalid principal: realm mismatch')
|
||||||
|
|
||||||
|
|
||||||
|
def kinit_keytab(principal, keytab, ccache_name, config=None, attempts=1):
|
||||||
|
diff --git a/ipatests/test_ipalib_install/test_kinit.py b/ipatests/test_ipalib_install/test_kinit.py
|
||||||
|
index f89ea17..8289c4b 100644
|
||||||
|
--- a/ipatests/test_ipalib_install/test_kinit.py
|
||||||
|
+++ b/ipatests/test_ipalib_install/test_kinit.py
|
||||||
|
@@ -17,13 +17,16 @@ from ipalib.install.kinit import validate_principal
|
||||||
|
('test/ipa.example.test@EXAMPLE.TEST', None),
|
||||||
|
('test/ipa@EXAMPLE.TEST', RuntimeError),
|
||||||
|
('test/-ipa.example.test@EXAMPLE.TEST', RuntimeError),
|
||||||
|
- ('test/ipa.1example.test@EXAMPLE.TEST', RuntimeError),
|
||||||
|
+ ('test/ipa.1example.test@EXAMPLE.TEST', None),
|
||||||
|
('test /ipa.example,test', RuntimeError),
|
||||||
|
- ('testuser@OTHER.TEST', RuntimeError),
|
||||||
|
- ('test/ipa.example.test@OTHER.TEST', RuntimeError),
|
||||||
|
+ ('testuser@OTHER.TEST', None),
|
||||||
|
+ ('test/ipa.example.test@OTHER.TEST', None)
|
||||||
|
])
|
||||||
|
def test_validate_principal(principal, exception):
|
||||||
|
try:
|
||||||
|
validate_principal(principal)
|
||||||
|
except Exception as e:
|
||||||
|
assert e.__class__ == exception
|
||||||
|
+ else:
|
||||||
|
+ if exception is not None:
|
||||||
|
+ raise RuntimeError('Test should have failed')
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
From d7c1ba0672fc8964f7674a526f3019429a551372 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Date: Mar 06 2024 08:34:57 +0000
|
||||||
|
Subject: Vault: add additional fallback to RSA-OAEP wrapping algo
|
||||||
|
|
||||||
|
|
||||||
|
There is a fallback when creating the wrapping key but one was missing
|
||||||
|
when trying to use the cached transport_cert.
|
||||||
|
|
||||||
|
This allows, along with forcing keyWrap.useOAEP=true, vault creation
|
||||||
|
on an nCipher HSM.
|
||||||
|
|
||||||
|
This can be seen in HSMs where the device doesn't support the
|
||||||
|
PKCS#1 v1.5 mechanism. It will error out with either "invalid
|
||||||
|
algorithm" or CKR_FUNCTION_FAILED.
|
||||||
|
|
||||||
|
Related: https://pagure.io/freeipa/issue/9191
|
||||||
|
|
||||||
|
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py
|
||||||
|
index ed16c73..1523187 100644
|
||||||
|
--- a/ipaclient/plugins/vault.py
|
||||||
|
+++ b/ipaclient/plugins/vault.py
|
||||||
|
@@ -757,8 +757,12 @@ class ModVaultData(Local):
|
||||||
|
Calls the internal counterpart of the command.
|
||||||
|
"""
|
||||||
|
# try call with cached transport certificate
|
||||||
|
- result = self._do_internal(algo, transport_cert, False,
|
||||||
|
- False, *args, **options)
|
||||||
|
+ try:
|
||||||
|
+ result = self._do_internal(algo, transport_cert, False,
|
||||||
|
+ False, *args, **options)
|
||||||
|
+ except errors.EncodingError:
|
||||||
|
+ result = self._do_internal(algo, transport_cert, False,
|
||||||
|
+ True, *args, **options)
|
||||||
|
if result is not None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmRnL+gACgkQaYdvcqbi
|
|
||||||
00/1Gg/8CFABojXZyUkQnWeaHdrFeHeE+DW2qTs9Wr/TQwF67fYkh7lj3p+WqMlD
|
|
||||||
kMMNAfLn4wUnJNDMv64QlE6RAz71KetQlQt+mZQVT9M0nDepLhBw86qmNbJj611J
|
|
||||||
+2B79hzNLT8tmOf9NyLRJbFp3QebSPELX9hycPj1Ovd1tr/61tcwcNzE6ZLrX5vb
|
|
||||||
IPkCT2bo+6MceIsR50tTRxxK6J9jFYX73PjHJ5Ix7ssDf4vg2OBRTwUdLeZAkWlA
|
|
||||||
q+0bPPp+F3PWLhnSs+vIs5plHUI/hcGCt9pTvw/d6jUUxuwZadGGbRZSyDN7aj2Q
|
|
||||||
zEXeZsCtOSk5cx65lWHl+7TTyVvCoemeZPZ92EiCtVJfiuK3/6a/WFWanBZoO0E3
|
|
||||||
N0p6HUcvIRPrEj0nQwH2vr0zkfSPA4g30k+Q9qeP3ArN+i+5OFfuiwiqk1AIJ2rv
|
|
||||||
ERhBRryOaNeiVpYghMQdtacWP/qQunfH6VdhA61Q089/lhomGeSytQI+fV4TXOhV
|
|
||||||
ldV7dftaWpQT3QYWSsKzoiHpyjIwOA8dBvQF2YDX7LNmeO/hj4ToFp00CVCWdb0j
|
|
||||||
MHs2X9p42kkhw2oZOf3GNyNvpybxUv59ER4YDEHbj8+iZyVjiqfcp71373DqpieW
|
|
||||||
iGjB3Wc0gO3cdYk3Mdl0SgkD7k0U9iwwh7qJeqqUYT3gKf9mqbY=
|
|
||||||
=dT0o
|
|
||||||
-----END PGP SIGNATURE-----
|
|
16
SOURCES/freeipa-4.9.13.tar.gz.asc
Normal file
16
SOURCES/freeipa-4.9.13.tar.gz.asc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmVbZU0ACgkQaYdvcqbi
|
||||||
|
009Fgw/+PzHGNOJPs67TtoYITV/3ZCzMyrYTcazVACjD61Zw7JBgbZzZpQXxBSbj
|
||||||
|
7QWpNJa3P2JFtv2qOUXJto40mOGpMynyYpuYs4CtyJ86eHTUJyYTFppBmCzzozhT
|
||||||
|
2C2BeKKjzV8OOWQ7yO/2BTEZ7KtOcIr4ZI7iZCnLJF9Yt8x7TURjGRqxsHwT62Ip
|
||||||
|
vcrtm0LkkYv/fQ6pFZZfinKU1OBrZphwHMCU4Mlv411iQg4+NOxLSsVU/kegeKIO
|
||||||
|
adp4Y9g5dfAfdXEXb2Zt7gkmLaWMgf+XNSFDL/wkzRYt74HKwvbIPJQlTZ6pqLxQ
|
||||||
|
yTtiHGuMb7xNDWolpoueo1/lbxaHRRGJaSPs7zUht3IBxb7hiF65Gm3UaJhoeAXc
|
||||||
|
gVleZf/+0titOdkRfTD2N0P0hli7gaiRrbpw8K4joxMFpYrQGUxD8SI376gkOj6o
|
||||||
|
5RWSioPoG9txNM7Co+lVpci7WHhL+Tmhf1SlHyVJGKoNe/z4VHnjHeYlFWRVdDEI
|
||||||
|
OOupZzJQoLnso3lTwR5VEN8xGURnhbGV4MdUfD/6FhwmyHiPlYkytdZIsGsNDOab
|
||||||
|
978PPaKcIpbsZ4gUhshcbn7qaY809lNSpMtg8saYOP4J/5Nu+i9X5bJqOmoX0rKa
|
||||||
|
gAJDY5har+lExRnTEdYEGVB8qen5lqi8r1oYjnDpkSpq6BRoAHA=
|
||||||
|
=uQom
|
||||||
|
-----END PGP SIGNATURE-----
|
110
SPECS/ipa.spec
110
SPECS/ipa.spec
@ -64,7 +64,7 @@
|
|||||||
%if 0%{?rhel}
|
%if 0%{?rhel}
|
||||||
%global package_name ipa
|
%global package_name ipa
|
||||||
%global alt_name freeipa
|
%global alt_name freeipa
|
||||||
%global krb5_version 1.18.2-25
|
%global krb5_version 1.18.2-26
|
||||||
%global krb5_kdb_version 8.0
|
%global krb5_kdb_version 8.0
|
||||||
# 0.7.16: https://github.com/drkjam/netaddr/issues/71
|
# 0.7.16: https://github.com/drkjam/netaddr/issues/71
|
||||||
%global python_netaddr_version 0.7.19
|
%global python_netaddr_version 0.7.19
|
||||||
@ -176,7 +176,7 @@
|
|||||||
|
|
||||||
# Work-around fact that RPM SPEC parser does not accept
|
# Work-around fact that RPM SPEC parser does not accept
|
||||||
# "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement
|
# "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement
|
||||||
%define IPA_VERSION 4.9.12
|
%define IPA_VERSION 4.9.13
|
||||||
# Release candidate version -- uncomment with one percent for RC versions
|
# Release candidate version -- uncomment with one percent for RC versions
|
||||||
#%%global rc_version %%nil
|
#%%global rc_version %%nil
|
||||||
%define AT_SIGN @
|
%define AT_SIGN @
|
||||||
@ -208,20 +208,31 @@ Source1: https://releases.pagure.org/freeipa/freeipa-%{version}%{?rc_vers
|
|||||||
|
|
||||||
# RHEL spec file only: START
|
# RHEL spec file only: START
|
||||||
%if %{NON_DEVELOPER_BUILD}
|
%if %{NON_DEVELOPER_BUILD}
|
||||||
|
Patch0001: 0001-Handle-samba-exception-type-change_rhel#17623.patch
|
||||||
|
Patch0002: 0002-Check-the-HTTP-Referer-header-on-all-requests.patch
|
||||||
|
Patch0003: 0003-Integration-tests-for-verifying-Referer-header-in-th.patch
|
||||||
|
Patch0004: 0004-ipa-kdb-Detect-and-block-Bronze-Bit-attacks.patch
|
||||||
|
Patch0005: 0005-Improve-server-affinity-for-ca-less-deployments_rhel#22283.patch
|
||||||
|
Patch0006: 0006-host-update-System-Manage-Host-Keytab-permission_rhel#22286.patch
|
||||||
|
Patch0007: 0007-adtrustinstance-make-sure-NetBIOS-name-defaults-are-set-properly_rhel#21938.patch
|
||||||
|
Patch0008: 0008-ipatests-Fix-healthcheck-report-when-nsslapd-accesslog-logbuffering-is-set-to-off_rhel#19672.patch
|
||||||
|
Patch0009: 0009-kdb-PAC-generator-do-not-fail-if-canonical-principal-is-missing_rhel#23630.patch
|
||||||
|
Patch0010: 0010-ipa-kdb-Fix-memory-leak-during-PAC-verification_rhel#22644.patch
|
||||||
|
Patch0011: 0011-Fix-session-cookie-access_rhel#23622.patch
|
||||||
|
Patch0012: 0012-Do-not-ignore-staged-users-in-sidgen-plugin_rhel#23626.patch
|
||||||
|
Patch0013: 0013-ipa-kdb-Disable-Bronze-Bit-check-if-PAC-not-available_rhel#22313.patch
|
||||||
|
Patch0014: 0014-krb5kdc-Fix-start-when-pkinit-and-otp-auth-type-are-enabled_rhel#4874.patch
|
||||||
|
Patch0015: 0015-hbactest-was-not-collecting-or-returning-messages_rhel#12780.patch
|
||||||
|
Patch0016: 0016-ipatests-wait-for-replica-update-in-test_dns_locatio.patch
|
||||||
|
Patch0017: 0017-ipa-kdb-Rework-ipadb_reinit_mspac.patch
|
||||||
|
Patch0018: 0018-ipatests-fix-tasks-wait_for_replication-method_rhel#25708.patch
|
||||||
|
Patch0019: 0019-Vault-add-support-for-RSA-OAEP-wrapping-algo.patch
|
||||||
|
Patch0020: 0020-Vault-improve-vault-server-archival-retrieval-calls-.patch
|
||||||
|
Patch0021: 0021-kra-set-RSA-OAEP-as-default-wrapping-algo-when-FIPS-.patch
|
||||||
|
Patch0022: 0022-ipa-kdb-Fix-double-free-in-ipadb_reinit_mspac.patch
|
||||||
|
Patch0023: 0023-rpcserver-validate-Kerberos-principal-name-before-running-kinit_rhel#26153.patch
|
||||||
|
Patch0024: 0024-Vault-add-additional-fallback-to-RSA-OAEP-wrapping-algo_rhel#28259.patch
|
||||||
%if 0%{?rhel} >= 8
|
%if 0%{?rhel} >= 8
|
||||||
Patch0001: 0001-user-or-group-name-explain-the-supported-format_rhbz#2150217.patch
|
|
||||||
Patch0002: 0002-Use-the-python-cryptography-parser-directly-in-cert-find_rhbz#2164349.patch
|
|
||||||
Patch0003: 0003-Upgrade-add-PKI-drop-in-file-if-missing_rhbz#2215336.patch
|
|
||||||
Patch0004: 0004-Upgrade-fix-replica-agreement_rhbz#2216551.patch
|
|
||||||
Patch0005: 0005-OTP-fix-data-type-to-avoid-endianness-issue_rhbz#2218293.patch
|
|
||||||
Patch0006: 0006-Backport-test-updates-8-9-release_rhbz#2218847.patch
|
|
||||||
Patch0007: 0007-ipa-kdb-fix-error-handling-of-is_master_host_rhbz#2214638.patch
|
|
||||||
Patch0008: 0008-ipatests-enable-firewall-rule-for-http-service-on-acme-client_rhbz#2230256.patch
|
|
||||||
Patch0009: 0009-User-plugin-improve-error-related-to-non-existing-idp_rhbz#2224572.patch
|
|
||||||
Patch0010: 0010-Prevent-admin-user-from-being-deleted_rhbz#1921181.patch
|
|
||||||
Patch0011: 0011-Fix-memory-leak-in-the-OTP-last-token-plugin_rhbz#2227783.patch
|
|
||||||
Patch0012: 0012-ipatests-fix-test_topology_rhbz#2232351.patch
|
|
||||||
Patch0013: 0013-Installer-activate-nss-and-pam-services-in-sssd.conf_rhbz#2216532.patch
|
|
||||||
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
|
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
|
||||||
Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
|
Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
|
||||||
Patch1003: 1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch
|
Patch1003: 1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch
|
||||||
@ -1736,6 +1747,75 @@ fi
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 07 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-8
|
||||||
|
- rpcserver: validate Kerberos principal name before running kinit
|
||||||
|
Resolves: RHEL-26153
|
||||||
|
- Vault: add additional fallback to RSA-OAEP wrapping algo
|
||||||
|
Resolves: RHEL-28259
|
||||||
|
|
||||||
|
* Tue Feb 20 2024 Julien Rische <jrische@redhat.com> - 4.9.13-7
|
||||||
|
- ipa-kdb: Fix double free in ipadb_reinit_mspac()
|
||||||
|
Resolves: RHEL-25742
|
||||||
|
- kra: set RSA-OAEP as default wrapping algo when FIPS is enabled
|
||||||
|
Resolves: RHEL-12153
|
||||||
|
- Vault: improve vault server archival/retrieval calls error handling
|
||||||
|
Resolves: RHEL-12153
|
||||||
|
- Vault: add support for RSA-OAEP wrapping algo
|
||||||
|
Resolves: RHEL-12153
|
||||||
|
|
||||||
|
* Fri Feb 16 2024 Julien Rische <jrische@redhat.com> - 4.9.13-6
|
||||||
|
- ipa-kdb: Rework ipadb_reinit_mspac()
|
||||||
|
Resolves: RHEL-25742
|
||||||
|
- ipatests: wait for replica update in test_dns_locations
|
||||||
|
Resolves: RHEL-22373
|
||||||
|
- ipatests: fix tasks.wait_for_replication() method
|
||||||
|
Resolves: RHEL-25708
|
||||||
|
|
||||||
|
* Tue Feb 13 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-5
|
||||||
|
- kdb: PAC generator: do not fail if canonical principal is missing
|
||||||
|
Resolves: RHEL-23630
|
||||||
|
- ipa-kdb: Fix memory leak during PAC verification
|
||||||
|
Resolves: RHEL-22644
|
||||||
|
- Fix session cookie access
|
||||||
|
Resolves: RHEL-23622
|
||||||
|
- Do not ignore staged users in sidgen plugin
|
||||||
|
Resovlves: RHEL-23626
|
||||||
|
- ipa-kdb: Disable Bronze-Bit check if PAC not available
|
||||||
|
Resolves: RHEL-22313
|
||||||
|
- krb5kdc: Fix start when pkinit and otp auth type are enabled
|
||||||
|
Resolves: RHEL-4874
|
||||||
|
- hbactest was not collecting or returning messages
|
||||||
|
Resolves: RHEL-12780
|
||||||
|
|
||||||
|
|
||||||
|
* Tue Jan 23 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-4
|
||||||
|
- Improve server affinity for CA-less deployments
|
||||||
|
Resolves: RHEL-22283
|
||||||
|
- host: update system: Manage Host Keytab permission
|
||||||
|
Resolves: RHEL-22286
|
||||||
|
- adtrustinstance: make sure NetBIOS name defaults are set properly
|
||||||
|
Resolves: RHEL-21938
|
||||||
|
- ipatests: Fix healthcheck report when nsslapd accesslog logbuffering is set to off
|
||||||
|
Resolves: RHEL-19672
|
||||||
|
|
||||||
|
* Wed Jan 10 2024 Julien Rische <jrische@redhat.com> - 4.9.13-3
|
||||||
|
- ipa-kdb: Detect and block Bronze-Bit attacks
|
||||||
|
Resolves: RHEL-9984
|
||||||
|
- Fix for CVE-2023-5455
|
||||||
|
Resolves: RHEL-12578
|
||||||
|
|
||||||
|
* Thu Nov 30 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-2
|
||||||
|
- Handle new samba exception types.
|
||||||
|
Resolves: RHEL-17623
|
||||||
|
|
||||||
|
* Tue Nov 21 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-1
|
||||||
|
- Rebase ipa to 4.9.13
|
||||||
|
Resolves: RHEL-16936
|
||||||
|
|
||||||
|
* Wed Oct 04 2023 Julien Rische <jrische@redhat.com> - 4.9.12-9
|
||||||
|
- ipa-kdb: Make AD-SIGNEDPATH optional with krb5 DAL 8 and older
|
||||||
|
Resolves: RHEL-12198
|
||||||
|
|
||||||
* Thu Aug 31 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-8
|
* Thu Aug 31 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-8
|
||||||
- Require krb5 release 1.18.2-25 or later
|
- Require krb5 release 1.18.2-25 or later
|
||||||
Resolves: RHBZ#2234711
|
Resolves: RHBZ#2234711
|
||||||
|
Loading…
Reference in New Issue
Block a user