ipa-4.12.0-1

- Resolves: RHEL-39144 Rebase ipa to the latest 4.12 version for RHEL 10
- Resolves: RHEL-30537 ipa: freeipa: argument injection into the username field of the /ipa/session/login_password requests
This commit is contained in:
Florence Blanc-Renaud 2024-06-04 19:55:30 +02:00
parent 123abb92ab
commit 90dae868c3
22 changed files with 380 additions and 2085 deletions

2
.gitignore vendored
View File

@ -132,3 +132,5 @@
/freeipa-4.11.0.tar.gz.asc
/freeipa-4.11.1.tar.gz
/freeipa-4.11.1.tar.gz.asc
/freeipa-4.12.0.tar.gz
/freeipa-4.12.0.tar.gz.asc

View File

@ -1,28 +0,0 @@
From 499f1e3e996aadbd4f26a90db81a0b1b68b61c57 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Tue, 12 Sep 2023 17:07:52 +0300
Subject: [PATCH] Restore selinux states if they exist at uninstall time
Related: https://pagure.io/freeipa/issue/9434
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
ipaclient/install/client.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index 1aaa4ed60..01a5f2339 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -3624,7 +3624,7 @@ def uninstall(options):
"Failed to disable automatic startup of the SSSD daemon: %s",
e)
- if was_sssd_installed and selinux_works:
+ if statestore.has_state('selinux'):
# Restore SELinux boolean states
boolean_states = {name: statestore.restore_state('selinux', name)
for name in constants.SELINUX_BOOLEAN_SSSD}
--
2.41.0

View File

@ -0,0 +1,238 @@
From dfeb01d5e4e8934bae8f495bbbd5b6570f3dc862 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 4 Jun 2024 13:56:56 +0200
Subject: [PATCH] Revert "Replace netifaces with ifaddr"
This reverts commit 6c6b9354b5f970983655ca5423c726763d9015fa.
---
doc/requirements.txt | 1 -
freeipa.spec.in | 4 +--
ipaclient/install/client.py | 43 ++++++++++++++-----------------
ipapython/ipautil.py | 51 ++++++++++++++++++++-----------------
ipapython/setup.py | 2 +-
ipasetup.py.in | 2 +-
pylintrc | 1 +
7 files changed, 52 insertions(+), 52 deletions(-)
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 8d91b893fbcb5de784f5abdf802b976c6b2ae277..cdaa42658c73e495379d87b7c50195fbd79533ee 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -11,7 +11,6 @@ m2r2
## ipa dependencies
dnspython
jwcrypto
-ifaddr
netaddr
qrcode
six
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 6803de752bc122bf6e1eafd610d399cde994cad5..a532fe85c34a523519187b6fd1297c198d9f4a4e 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -403,7 +403,7 @@ BuildRequires: python3-libipa_hbac
BuildRequires: python3-libsss_nss_idmap
BuildRequires: python3-lxml
BuildRequires: python3-netaddr >= %{python_netaddr_version}
-BuildRequires: python3-ifaddr
+BuildRequires: python3-netifaces
BuildRequires: python3-pki >= %{pki_version}
BuildRequires: python3-polib
BuildRequires: python3-pyasn1
@@ -885,7 +885,7 @@ Requires: python3-gssapi >= 1.2.0
Requires: python3-jwcrypto >= 0.4.2
Requires: python3-libipa_hbac
Requires: python3-netaddr >= %{python_netaddr_version}
-Requires: python3-ifaddr
+Requires: python3-netifaces >= 0.10.4
Requires: python3-pyasn1 >= 0.3.2-2
Requires: python3-pyasn1-modules >= 0.3.2-2
Requires: python3-pyusb
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index 29aff5f413e7f27136e236382031171f068284c5..263dc8e302cccd76412c294e0740af9744a2c62d 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -18,7 +18,7 @@ import logging
import dns
import getpass
import gssapi
-import ifaddr
+import netifaces
import os
import re
import SSSDConfig
@@ -1374,36 +1374,31 @@ def unconfigure_nisdomain(statestore):
def get_iface_from_ip(ip_addr):
- for adapter in ifaddr.get_adapters():
- for ips in adapter.ips:
- # IPv6 is reported as a tuple, IPv4 is reported as str
- if ip_addr in (ips.ip[0], ips.ip):
- return adapter.name
+ for interface in netifaces.interfaces():
+ if_addrs = netifaces.ifaddresses(interface)
+ for family in [netifaces.AF_INET, netifaces.AF_INET6]:
+ for ip in if_addrs.get(family, []):
+ if ip['addr'] == ip_addr:
+ return interface
raise RuntimeError("IP %s not assigned to any interface." % ip_addr)
-def __get_ifaddr_adapters(iface=None):
+def get_local_ipaddresses(iface=None):
if iface:
- interfaces = set(iface if isinstance(iface, (list, tuple)) else [iface])
+ interfaces = [iface]
else:
- interfaces = set(adapter.name for adapter in ifaddr.get_adapters())
- return [
- adapter
- for adapter in ifaddr.get_adapters()
- if adapter.name in interfaces or adapter.nice_name in interfaces
- ]
+ interfaces = netifaces.interfaces()
-
-def get_local_ipaddresses(iface=None):
ips = []
- for adapter in __get_ifaddr_adapters(iface):
- for ifip in adapter.ips:
- try:
- ip_addr = ifip.ip[0] if isinstance(ifip.ip, tuple) else ifip.ip
- ips.append(ipautil.CheckedIPAddress(ip_addr))
- logger.debug('IP check successful: %s', ip_addr)
- except ValueError as e:
- logger.debug('IP check failed: %s', e)
+ for interface in interfaces:
+ if_addrs = netifaces.ifaddresses(interface)
+ for family in [netifaces.AF_INET, netifaces.AF_INET6]:
+ for ip in if_addrs.get(family, []):
+ try:
+ ips.append(ipautil.CheckedIPAddress(ip['addr']))
+ logger.debug('IP check successful: %s', ip['addr'])
+ except ValueError as e:
+ logger.debug('IP check failed: %s', e)
return ips
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index b02d58839ed74215d7253fc23be94846d689f91e..6802dde574d179b2d4bf868a2c38546cc01fc46b 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -48,9 +48,9 @@ import six
from six.moves import input
try:
- import ifaddr
+ import netifaces
except ImportError:
- ifaddr = None
+ netifaces = None
from ipapython.dn import DN
from ipaplatform.paths import paths
@@ -203,37 +203,42 @@ class CheckedIPAddress(UnsafeIPAddress):
:return: InterfaceDetails named tuple or None if no interface has
this address
"""
- if ifaddr is None:
- raise ImportError("ifaddr")
+ if netifaces is None:
+ raise ImportError("netifaces")
logger.debug("Searching for an interface of IP address: %s", self)
-
if self.version == 4:
- family_ips = (
- (ip.ip, ip.network_prefix, ip.nice_name)
- for ips in [a.ips for a in ifaddr.get_adapters()]
- for ip in ips if not isinstance(ip.ip, tuple)
- )
+ family = netifaces.AF_INET
elif self.version == 6:
- family_ips = (
- (ip.ip[0], ip.network_prefix, ip.nice_name)
- for ips in [a.ips for a in ifaddr.get_adapters()]
- for ip in ips if isinstance(ip.ip, tuple)
- )
+ family = netifaces.AF_INET6
else:
raise ValueError(
"Unsupported address family ({})".format(self.version)
)
- for ip, prefix, ifname in family_ips:
- ifaddrmask = "{ip}/{prefix}".format(ip=ip, prefix=prefix)
- logger.debug(
- "Testing local IP address: %s (interface: %s)",
- ifaddrmask, ifname)
- ifnet = netaddr.IPNetwork(ifaddrmask)
+ for interface in netifaces.interfaces():
+ for ifdata in netifaces.ifaddresses(interface).get(family, []):
+
+ # link-local addresses contain '%suffix' that causes parse
+ # errors in IPNetwork
+ ifaddr = ifdata['addr'].split(u'%', 1)[0]
+
+ # newer versions of netifaces provide IPv6 netmask in format
+ # 'ffff:ffff:ffff:ffff::/64'. We have to split and use prefix
+ # or the netmask with older versions
+ ifmask = ifdata['netmask'].split(u'/')[-1]
+
+ ifaddrmask = '{addr}/{netmask}'.format(
+ addr=ifaddr,
+ netmask=ifmask
+ )
+ logger.debug(
+ "Testing local IP address: %s (interface: %s)",
+ ifaddrmask, interface)
- if ifnet.ip == self:
- return InterfaceDetails(ifname, ifnet)
+ ifnet = netaddr.IPNetwork(ifaddrmask)
+ if ifnet.ip == self:
+ return InterfaceDetails(interface, ifnet)
return None
def set_ip_net(self, ifnet):
diff --git a/ipapython/setup.py b/ipapython/setup.py
index b7b25c8b480f0dc80ae20c4027554b27fe6d87b3..ea55f5c729e8ba65a4436ebf3eb4898870558648 100644
--- a/ipapython/setup.py
+++ b/ipapython/setup.py
@@ -48,6 +48,6 @@ if __name__ == '__main__':
extras_require={
"ldap": ["python-ldap"], # ipapython.ipaldap
# CheckedIPAddress.get_matching_interface
- "ifaddr": ["ifaddr"],
+ "netifaces": ["netifaces"],
},
)
diff --git a/ipasetup.py.in b/ipasetup.py.in
index 56a1f3b066c70385949c86d0d35ce393331ad1c5..25eac3b214b4e6443fe29dd3d656c2fdbe84343a 100644
--- a/ipasetup.py.in
+++ b/ipasetup.py.in
@@ -75,7 +75,7 @@ PACKAGE_VERSION = {
'ipaserver': 'ipaserver == {}'.format(VERSION),
'jwcrypto': 'jwcrypto >= 0.4.2',
'kdcproxy': 'kdcproxy >= 0.3',
- 'ifaddr': 'ifaddr >= 0.1.7',
+ 'netifaces': 'netifaces >= 0.10.4',
'python-ldap': 'python-ldap >= 3.0.0',
'python-yubico': 'python-yubico >= 1.2.3',
'qrcode': 'qrcode >= 5.0',
diff --git a/pylintrc b/pylintrc
index 50278cc76031af68959a138f6ea185c4288c7155..22053a9b55e9dc8e71c1835a63c9393e8ad6803d 100644
--- a/pylintrc
+++ b/pylintrc
@@ -13,6 +13,7 @@ extension-pkg-allow-list=
_ldap,
cryptography,
gssapi,
+ netifaces,
lxml.etree,
pysss_murmur,
--
2.45.1

View File

@ -1,107 +0,0 @@
From a44fd5a7691d263d670312e0c8e02efd868618c1 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Tue, 6 Jun 2023 17:15:11 +0200
Subject: [PATCH] Revert "cert_find: fix call with --all"
This reverts commit 918b6e011795ba4854d178d18c86ad54f3cf75ab.
Revert "Use the OpenSSL certificate parser in cert-find"
This reverts commit 50dd79d1a35549034bc281fbdffea4399baed3c7.
---
freeipa.spec.in | 2 --
ipaserver/plugins/cert.py | 27 +++------------------------
2 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 3e23bbfe9d054a3a9febf468de0bcb4a6e81bb32..bec9780a82fe0d9bc5a50a93bdce8aa7e27a9f30 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -412,7 +412,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
@@ -884,7 +883,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 400b1b3cec0aba82e699a4a981516e121f3e0c77..36a0e8cb31b4dbdd9bff09165d1d8aa203936d37 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, SerialNumber
from ipalib import api
@@ -1618,19 +1617,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()
@@ -1750,11 +1737,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 = []
@@ -1813,21 +1795,18 @@ 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.
# 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))
--
2.40.1

View File

@ -1,82 +0,0 @@
From a96dae1a9918cfc1413e199336eece447920ef8e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Wed, 5 Jul 2023 08:52:59 +0200
Subject: [PATCH] Use ssl.match_hostname from urllib3 as it was removed from
Python 3.12
See https://pagure.io/freeipa/issue/9409
and https://github.com/python/cpython/pull/94224#issuecomment-1621097418
---
ipalib/x509.py | 5 +++--
ipaserver/install/cainstance.py | 4 +++-
ipaserver/install/server/upgrade.py | 4 +++-
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/ipalib/x509.py b/ipalib/x509.py
index 5adb511..faf62d4 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -385,6 +385,8 @@ class IPACertificate(crypto_x509.Certificate):
return result
def match_hostname(self, hostname):
+ from urllib3.util import ssl_match_hostname
+
match_cert = {}
match_cert['subject'] = match_subject = []
@@ -401,8 +403,7 @@ class IPACertificate(crypto_x509.Certificate):
for value in values:
match_san.append(('DNS', value))
- # deprecated in Python3.7 without replacement
- ssl.match_hostname( # pylint: disable=deprecated-method
+ ssl_match_hostname.match_hostname(
match_cert, DNSName(hostname).ToASCII()
)
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index fa8942d..e9f3ecb 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -2373,12 +2373,14 @@ def check_ipa_ca_san(cert):
On success returns None, on failure raises ValidationError
"""
+ from urllib3.util import ssl_match_hostname
+
expect = f'{ipalib.constants.IPA_CA_RECORD}.' \
f'{ipautil.format_netloc(api.env.domain)}'
try:
cert.match_hostname(expect)
- except ssl.CertificateError:
+ except ssl_match_hostname.CertificateError:
raise errors.ValidationError(
name='certificate',
error='Does not have a \'{}\' SAN'.format(expect)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index f8701c8..9e5f5aa 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -710,6 +710,8 @@ def http_certificate_ensure_ipa_ca_dnsname(http):
steps.
"""
+ from urllib3.util import ssl_match_hostname
+
logger.info('[Adding ipa-ca alias to HTTP certificate]')
expect = f'{IPA_CA_RECORD}.{ipautil.format_netloc(api.env.domain)}'
@@ -717,7 +719,7 @@ def http_certificate_ensure_ipa_ca_dnsname(http):
try:
cert.match_hostname(expect)
- except ssl.CertificateError:
+ except ssl_match_hostname.CertificateError:
if certs.is_ipa_issued_cert(api, cert):
request_id = certmonger.get_request_id(
{'cert-file': paths.HTTPD_CERT_FILE})
--
2.40.1

View File

@ -1,140 +0,0 @@
From d355761f23fae412bb01a1d737cee342c7bd04f9 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Tue, 29 Aug 2023 12:37:57 +0300
Subject: [PATCH] ipa-client-install: enable SELinux for SSSD
For passkeys (FIDO2) support, SSSD uses libfido2 library which needs
access to USB devices. Add SELinux booleans handling to ipa-client-install
so that correct SELinux booleans can be enabled and disabled during
install and uninstall. Ignore and record a warning when SELinux policy
does not support the boolean.
Fixes: https://pagure.io/freeipa/issue/9434
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipaclient/install/client.py | 35 ++++++++++++++++++++++++++++++++++-
ipaplatform/base/constants.py | 3 +++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index 07d62a748..1aaa4ed60 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -67,6 +67,7 @@ from ipapython.ipautil import (
)
from ipapython.ssh import SSHPublicKey
from ipapython import version
+from ipapython.errors import SetseboolError
from . import automount, timeconf, sssd
from ipaclient import discovery
@@ -98,6 +99,7 @@ cli_realm = None
cli_kdc = None
client_domain = None
cli_basedn = None
+selinux_works = None
# end of global variables
@@ -2153,6 +2155,7 @@ def install_check(options):
global cli_kdc
global client_domain
global cli_basedn
+ global selinux_works
print("This program will set up IPA client.")
print("Version {}".format(version.VERSION))
@@ -2166,7 +2169,7 @@ def install_check(options):
"You must be root to run ipa-client-install.",
rval=CLIENT_INSTALL_ERROR)
- tasks.check_selinux_status()
+ selinux_works = tasks.check_selinux_status()
if is_ipa_client_configured(on_master=options.on_master):
logger.error("IPA client is already configured on this system.")
@@ -2674,6 +2677,20 @@ def restore_time_sync(statestore, fstore):
logger.error('Failed to restore time synchronization service: %s', e)
+def configure_selinux_for_client(statestore):
+ def backup_state(key, value):
+ statestore.backup_state('selinux', key, value)
+
+ try:
+ tasks.set_selinux_booleans(constants.SELINUX_BOOLEAN_SSSD,
+ backup_state)
+ except SetseboolError as e:
+ for c in constants.SELINUX_BOOLEAN_SSSD:
+ if c in e.failed:
+ logger.warning(
+ "SELinux does not support SSSD boolean %s, ignoring", c)
+
+
def install(options):
try:
_install(options, dict())
@@ -3198,6 +3215,9 @@ def _install(options, tdict):
logger.info("%s enabled", "SSSD" if options.sssd else "LDAP")
if options.sssd:
+ if selinux_works:
+ configure_selinux_for_client(statestore)
+
sssd = services.service('sssd', api)
try:
sssd.restart()
@@ -3322,6 +3342,8 @@ def _install(options, tdict):
def uninstall_check(options):
+ global selinux_works
+
if not is_ipa_client_configured():
if options.on_master:
rval = SUCCESS
@@ -3337,6 +3359,8 @@ def uninstall_check(options):
logger.info("Refer to ipa-server-install for uninstallation.")
raise ScriptError(rval=CLIENT_NOT_CONFIGURED)
+ selinux_works = tasks.check_selinux_status()
+
def uninstall(options):
env = {'PATH': SECURE_PATH}
@@ -3600,6 +3624,15 @@ def uninstall(options):
"Failed to disable automatic startup of the SSSD daemon: %s",
e)
+ if was_sssd_installed and selinux_works:
+ # Restore SELinux boolean states
+ boolean_states = {name: statestore.restore_state('selinux', name)
+ for name in constants.SELINUX_BOOLEAN_SSSD}
+ try:
+ tasks.set_selinux_booleans(boolean_states)
+ except SetseboolError as e:
+ logger.warning("Unable to reset SELinux variable: %s", str(e))
+
tasks.restore_hostname(fstore, statestore)
if fstore.has_files():
diff --git a/ipaplatform/base/constants.py b/ipaplatform/base/constants.py
index 61b864376..1689efe52 100644
--- a/ipaplatform/base/constants.py
+++ b/ipaplatform/base/constants.py
@@ -151,6 +151,9 @@ class BaseConstantsNamespace:
'samba_share_nfs': 'on',
},
}
+ SELINUX_BOOLEAN_SSSD = {
+ 'sssd_use_usb': 'on',
+ }
SELINUX_MCS_MAX = 1023
SELINUX_MCS_REGEX = r"^c(\d+)([.,-]c(\d+))*$"
SELINUX_MLS_MAX = 15
--
2.41.0

View File

@ -1,33 +0,0 @@
From 5fe447532f573fc3f73511073070f5dfe6b6535a Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Fri, 15 Sep 2023 10:12:16 +0300
Subject: [PATCH] Allow ipa-otpd to access USB devices for passkeys
Main SELinux policy will allow transition of passkey_child (SSSD) to
ipa_otpd_t context to perform FIDO2 operations with USB devices.
This means ipa-otpd will need to be able to read data from sysfs and
connect to USB devices.
Add required permissions to IPA subpolicy as well. See rhbz#2238224 for
discussion.
Related: https://pagure.io/freeipa/issue/9434
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
selinux/ipa.te | 2 ++
1 file changed, 2 insertions(+)
diff --git a/selinux/ipa.te b/selinux/ipa.te
index 92e6b295b19..c8a44b64e82 100644
--- a/selinux/ipa.te
+++ b/selinux/ipa.te
@@ -106,6 +106,8 @@ corenet_tcp_connect_radius_port(ipa_otpd_t)
dev_read_urand(ipa_otpd_t)
dev_read_rand(ipa_otpd_t)
+dev_read_sysfs(ipa_otpd_t)
+dev_rw_generic_usb_dev(ipa_otpd_t)
sysnet_dns_name_resolve(ipa_otpd_t)

View File

@ -1,91 +0,0 @@
From 34b58d8ee93ab385c1f3ba1166377fc1008a9c17 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Wed, 24 Jan 2024 15:50:17 +0100
Subject: [PATCH] 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>
---
daemons/ipa-kdb/ipa_kdb_mspac.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index 1558e2bea..2866304e1 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 ||
@@ -2398,32 +2405,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;
}
@@ -2470,6 +2466,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;
--
2.43.0

View File

@ -1,247 +0,0 @@
From 33638de180a8157e369ad6c61f9e3406d9e85404 Mon Sep 17 00:00:00 2001
From: Stanislav Levin <slev@altlinux.org>
Date: Tue, 23 Jan 2024 19:12:53 +0300
Subject: [PATCH 1/3] 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>
---
ipapython/session_storage.py | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
index c43ef7d4e..371cf1524 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
--
2.43.0
From f8a616dc6196324145372713da772fe9b2352e53 Mon Sep 17 00:00:00 2001
From: Stanislav Levin <slev@altlinux.org>
Date: Tue, 23 Jan 2024 19:19:43 +0300
Subject: [PATCH 2/3] 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>
---
ipapython/session_storage.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
index 371cf1524..dc36f5493 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,
--
2.43.0
From 59b8a9fb7169561c7ba9168fe84f47ae94e5ce23 Mon Sep 17 00:00:00 2001
From: Stanislav Levin <slev@altlinux.org>
Date: Tue, 23 Jan 2024 19:52:34 +0300
Subject: [PATCH 3/3] 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>
---
ipapython/session_storage.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
index dc36f5493..e890dc9b1 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))
--
2.43.0

View File

@ -1,424 +0,0 @@
From fa46b41af42797dba8dcd04b8cacbc78d602ab80 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Wed, 24 Jan 2024 09:23:22 +0100
Subject: [PATCH 1/2] Compatibility fix for PyCA cryptography 42.0.0
Cryptography 42.0.0 introduced two new abstract properties
`not_valid_before_utc` and `not_valid_after_utc`, which are non-naive UTC
variants of the `not_valid_before` and `not_valid_after` properties.
The old properties are deprecated. The changeset also modifies code and
tests to use the new `_utc` variants.
Fixes: https://pagure.io/freeipa/issue/9518
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
ipaclient/install/client.py | 4 ++--
ipalib/x509.py | 22 +++++++++++++++++++
ipapython/certdb.py | 15 +++++++------
ipaserver/install/ipa_cacert_manage.py | 2 +-
ipaserver/install/ipa_cert_fix.py | 12 +++++-----
ipaserver/plugins/cert.py | 4 ++--
ipaserver/plugins/dogtag.py | 12 +++++-----
ipaserver/plugins/service.py | 5 +++--
ipatests/test_integration/test_acme.py | 4 ++--
.../test_integration/test_installation.py | 2 +-
.../test_integration/test_ipa_cert_fix.py | 2 +-
.../test_integration/test_ipahealthcheck.py | 2 +-
ipatests/test_ipalib/test_x509.py | 6 +++++
13 files changed, 61 insertions(+), 31 deletions(-)
diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py
index 976d3821d..5b97a37f2 100644
--- a/ipaclient/install/client.py
+++ b/ipaclient/install/client.py
@@ -1727,8 +1727,8 @@ def cert_summary(msg, certs, indent=' '):
for cert in certs:
s += '%sSubject: %s\n' % (indent, DN(cert.subject))
s += '%sIssuer: %s\n' % (indent, DN(cert.issuer))
- s += '%sValid From: %s\n' % (indent, cert.not_valid_before)
- s += '%sValid Until: %s\n' % (indent, cert.not_valid_after)
+ s += '%sValid From: %s\n' % (indent, cert.not_valid_before_utc)
+ s += '%sValid Until: %s\n' % (indent, cert.not_valid_after_utc)
s += '\n'
s = s[:-1]
diff --git a/ipalib/x509.py b/ipalib/x509.py
index 769d48007..daeea8195 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -272,6 +272,28 @@ class IPACertificate(crypto_x509.Certificate):
def not_valid_after(self):
return self._cert.not_valid_after.replace(tzinfo=datetime.timezone.utc)
+ if hasattr(crypto_x509.Certificate, "not_valid_before_utc"):
+ # added in python-cryptography 42.0.0
+ @property
+ def not_valid_before_utc(self):
+ return self._cert.not_valid_before_utc
+
+ @property
+ def not_valid_after_utc(self):
+ return self._cert.not_valid_after_utc
+ else:
+ @property
+ def not_valid_before_utc(self):
+ return self._cert.not_valid_before.replace(
+ tzinfo=datetime.timezone.utc
+ )
+
+ @property
+ def not_valid_after_utc(self):
+ return self._cert.not_valid_after.replace(
+ tzinfo=datetime.timezone.utc
+ )
+
@property
def tbs_certificate_bytes(self):
return self._cert.tbs_certificate_bytes
diff --git a/ipapython/certdb.py b/ipapython/certdb.py
index 21af42d23..e3a80bcec 100644
--- a/ipapython/certdb.py
+++ b/ipapython/certdb.py
@@ -944,19 +944,20 @@ class NSSDatabase:
"""Common checks for cert validity
"""
utcnow = datetime.datetime.now(tz=datetime.timezone.utc)
- if cert.not_valid_before > utcnow:
+ if cert.not_valid_before_utc > utcnow:
raise ValueError(
- f"not valid before {cert.not_valid_before} UTC is in the "
- "future."
+ f"not valid before {cert.not_valid_before_utc} UTC is in "
+ "the future."
)
- if cert.not_valid_after < utcnow:
+ if cert.not_valid_after_utc < utcnow:
raise ValueError(
- f"has expired {cert.not_valid_after} UTC"
+ f"has expired {cert.not_valid_after_utc} UTC"
)
# make sure the cert does not expire during installation
- if cert.not_valid_after + datetime.timedelta(hours=1) < utcnow:
+ if cert.not_valid_after_utc + datetime.timedelta(hours=1) < utcnow:
raise ValueError(
- f"expires in less than one hour ({cert.not_valid_after} UTC)"
+ f"expires in less than one hour ({cert.not_valid_after_utc} "
+ "UTC)"
)
def verify_server_cert_validity(self, nickname, hostname):
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index d371a854b..f6ab736fa 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -558,7 +558,7 @@ class CACertManage(admintool.AdminTool):
now = datetime.datetime.now(tz=datetime.timezone.utc)
for ca_cert, ca_nickname, _ca_trust_flags in ca_certs:
- if ca_cert.not_valid_after < now:
+ if ca_cert.not_valid_after_utc < now:
expired_certs.append(ca_nickname)
diff --git a/ipaserver/install/ipa_cert_fix.py b/ipaserver/install/ipa_cert_fix.py
index 834e9557d..8e02d1e75 100644
--- a/ipaserver/install/ipa_cert_fix.py
+++ b/ipaserver/install/ipa_cert_fix.py
@@ -208,7 +208,7 @@ def expired_dogtag_certs(now):
except RuntimeError:
pass # unfortunately certdb doesn't give us a better exception
else:
- if cert.not_valid_after <= now:
+ if cert.not_valid_after_utc <= now:
certs.append((certid, cert))
return certs
@@ -226,12 +226,12 @@ def expired_ipa_certs(now):
# IPA RA
cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM)
- if cert.not_valid_after <= now:
+ if cert.not_valid_after_utc <= now:
certs.append((IPACertType.IPARA, cert))
# Apache HTTPD
cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
- if cert.not_valid_after <= now:
+ if cert.not_valid_after_utc <= now:
if not is_ipa_issued_cert(api, cert):
non_renewed.append((IPACertType.HTTPS, cert))
else:
@@ -244,7 +244,7 @@ def expired_ipa_certs(now):
ds_nickname = ds.get_server_cert_nickname(serverid)
db = NSSDatabase(nssdir=ds_dbdir)
cert = db.get_cert(ds_nickname)
- if cert.not_valid_after <= now:
+ if cert.not_valid_after_utc <= now:
if not is_ipa_issued_cert(api, cert):
non_renewed.append((IPACertType.LDAPS, cert))
else:
@@ -252,7 +252,7 @@ def expired_ipa_certs(now):
# KDC
cert = x509.load_certificate_from_file(paths.KDC_CERT)
- if cert.not_valid_after <= now:
+ if cert.not_valid_after_utc <= now:
if not is_ipa_issued_cert(api, cert):
non_renewed.append((IPACertType.HTTPS, cert))
else:
@@ -286,7 +286,7 @@ def print_cert_info(context, desc, cert):
print("{} {} certificate:".format(context, desc))
print(" Subject: {}".format(DN(cert.subject)))
print(" Serial: {}".format(cert.serial_number))
- print(" Expires: {}".format(cert.not_valid_after))
+ print(" Expires: {}".format(cert.not_valid_after_utc))
print()
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index 4fb85069a..d52cdc1e2 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -486,9 +486,9 @@ class BaseCertObject(Object):
obj['serial_number'] = str(cert.serial_number)
obj['serial_number_hex'] = '0x%X' % cert.serial_number
obj['valid_not_before'] = x509.format_datetime(
- cert.not_valid_before)
+ cert.not_valid_before_utc)
obj['valid_not_after'] = x509.format_datetime(
- cert.not_valid_after)
+ cert.not_valid_after_utc)
if full:
obj['sha1_fingerprint'] = x509.to_hex_with_colons(
cert.fingerprint(hashes.SHA1()))
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index 7cd51ae58..23667c3dd 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -1475,14 +1475,14 @@ class ra(rabase.rabase, RestClient):
if issuer_dn:
response_request['issuer'] = issuer_dn
- not_valid_before = cert.get('NotValidBefore')
- if not_valid_before:
+ not_valid_before_utc = cert.get('NotValidBefore')
+ if not_valid_before_utc:
response_request['valid_not_before'] = (
- not_valid_before)
+ not_valid_before_utc)
- not_valid_after = cert.get('NotValidAfter')
- if not_valid_after:
- response_request['valid_not_after'] = (not_valid_after)
+ not_valid_after_utc = cert.get('NotValidAfter')
+ if not_valid_after_utc:
+ response_request['valid_not_after'] = (not_valid_after_utc)
status = cert.get('Status')
if status:
diff --git a/ipaserver/plugins/service.py b/ipaserver/plugins/service.py
index f4b107213..075a1be8a 100644
--- a/ipaserver/plugins/service.py
+++ b/ipaserver/plugins/service.py
@@ -303,8 +303,9 @@ def set_certificate_attrs(entry_attrs):
entry_attrs['serial_number_hex'] = u'0x%X' % cert.serial_number
entry_attrs['issuer'] = unicode(DN(cert.issuer))
entry_attrs['valid_not_before'] = x509.format_datetime(
- cert.not_valid_before)
- entry_attrs['valid_not_after'] = x509.format_datetime(cert.not_valid_after)
+ cert.not_valid_before_utc)
+ entry_attrs['valid_not_after'] = x509.format_datetime(
+ cert.not_valid_after_utc)
entry_attrs['sha1_fingerprint'] = x509.to_hex_with_colons(
cert.fingerprint(hashes.SHA1()))
entry_attrs['sha256_fingerprint'] = x509.to_hex_with_colons(
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index ee13eb4a0..8e6243d4c 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -670,7 +670,7 @@ class TestACMERenew(IntegrationTest):
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
)
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
- initial_expiry = cert.not_valid_after
+ initial_expiry = cert.not_valid_after_utc
self.clients[0].run_command(['certbot', 'renew'])
@@ -678,7 +678,7 @@ class TestACMERenew(IntegrationTest):
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
)
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
- renewed_expiry = cert.not_valid_after
+ renewed_expiry = cert.not_valid_after_utc
assert initial_expiry != renewed_expiry
diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
index 36142447f..217aae019 100644
--- a/ipatests/test_integration/test_installation.py
+++ b/ipatests/test_integration/test_installation.py
@@ -1565,7 +1565,7 @@ class TestKRAinstallAfterCertRenew(IntegrationTest):
certs = x509.load_certificate_list(cmd.stdout_text.encode('utf-8'))
# get expiry date of agent cert
- cert_expiry = certs[0].not_valid_after
+ cert_expiry = certs[0].not_valid_after_utc
# move date to grace period so that certs get renewed
self.master.run_command(['systemctl', 'stop', 'chronyd'])
diff --git a/ipatests/test_integration/test_ipa_cert_fix.py b/ipatests/test_integration/test_ipa_cert_fix.py
index ec9456e51..219e7d0e1 100644
--- a/ipatests/test_integration/test_ipa_cert_fix.py
+++ b/ipatests/test_integration/test_ipa_cert_fix.py
@@ -92,7 +92,7 @@ def get_cert_expiry(host, nssdb_path, cert_nick):
])
data = host.get_file_contents('/root/cert.pem')
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
- return cert.not_valid_after
+ return cert.not_valid_after_utc
@pytest.fixture
diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py
index 40c848988..28200e096 100644
--- a/ipatests/test_integration/test_ipahealthcheck.py
+++ b/ipatests/test_integration/test_ipahealthcheck.py
@@ -1595,7 +1595,7 @@ class TestIpaHealthCheck(IntegrationTest):
# Pick a cert to find the upcoming expiration
certfile = self.master.get_file_contents(paths.RA_AGENT_PEM)
cert = x509.load_certificate_list(certfile)
- cert_expiry = cert[0].not_valid_after
+ cert_expiry = cert[0].not_valid_after_utc
# Stop chronyd so it doesn't freak out with time so off
restart_service(self.master, 'chronyd')
diff --git a/ipatests/test_ipalib/test_x509.py b/ipatests/test_ipalib/test_x509.py
index 74287c84a..8ab2ea8c3 100644
--- a/ipatests/test_ipalib/test_x509.py
+++ b/ipatests/test_ipalib/test_x509.py
@@ -246,6 +246,8 @@ class test_x509:
assert cert.serial_number == 1093
assert cert.not_valid_before == not_before
assert cert.not_valid_after == not_after
+ assert cert.not_valid_before_utc == not_before
+ assert cert.not_valid_after_utc == not_after
assert cert.san_general_names == []
assert cert.san_a_label_dns_names == []
assert cert.extended_key_usage == {'1.3.6.1.5.5.7.3.1'}
@@ -277,6 +279,8 @@ class test_x509:
# ensure the timezone doesn't mess with not_before and not_after
assert cert.not_valid_before == not_before
assert cert.not_valid_after == not_after
+ assert cert.not_valid_before_utc == not_before
+ assert cert.not_valid_after_utc == not_after
def test_load_pkcs7_pem(self):
certlist = x509.pkcs7_to_certs(good_pkcs7, datatype=x509.PEM)
@@ -312,6 +316,8 @@ class test_x509:
datetime.timezone.utc)
assert cert.not_valid_before == not_before
assert cert.not_valid_after == not_after
+ assert cert.not_valid_before_utc == not_before
+ assert cert.not_valid_after_utc == not_after
assert cert.san_general_names == [DNSName('ipa.demo1.freeipa.org')]
assert cert.san_a_label_dns_names == ['ipa.demo1.freeipa.org']
assert cert.extended_key_usage == {
--
2.43.0
From 18244d7ec1103ec6fba0f94c385e62dba774ed3d Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Thu, 25 Jan 2024 08:56:11 +0100
Subject: [PATCH 2/2] test_acme: Use ipalib.x509
Use IPA's x509 module instead of `cryptography.x509`. This fixes a
regression which was introduced in commit a45a7a20.
Related: https://pagure.io/freeipa/issue/9518
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Mohammad Rizwan Yusuf <myusuf@redhat.com>
---
ipatests/test_integration/test_acme.py | 9 ++++-----
ipatests/test_integration/test_ipa_cert_fix.py | 5 ++---
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py
index 8e6243d4c..4032d266a 100644
--- a/ipatests/test_integration/test_acme.py
+++ b/ipatests/test_integration/test_acme.py
@@ -4,11 +4,10 @@
import time
-from cryptography.hazmat.backends import default_backend
-from cryptography import x509
import pytest
from ipalib.constants import IPA_CA_RECORD
+from ipalib import x509
from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration.firewall import Firewall
from ipatests.pytest_ipa.integration import tasks
@@ -278,7 +277,7 @@ class TestACME(CALessBase):
cert_path = \
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
data = self.clients[0].get_file_contents(cert_path)
- cert = x509.load_pem_x509_certificate(data, backend=default_backend())
+ cert = x509.load_pem_x509_certificate(data)
# revoke cert via ACME
self.clients[0].run_command(
@@ -669,7 +668,7 @@ class TestACMERenew(IntegrationTest):
data = self.clients[0].get_file_contents(
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
)
- cert = x509.load_pem_x509_certificate(data, backend=default_backend())
+ cert = x509.load_pem_x509_certificate(data)
initial_expiry = cert.not_valid_after_utc
self.clients[0].run_command(['certbot', 'renew'])
@@ -677,7 +676,7 @@ class TestACMERenew(IntegrationTest):
data = self.clients[0].get_file_contents(
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
)
- cert = x509.load_pem_x509_certificate(data, backend=default_backend())
+ cert = x509.load_pem_x509_certificate(data)
renewed_expiry = cert.not_valid_after_utc
assert initial_expiry != renewed_expiry
diff --git a/ipatests/test_integration/test_ipa_cert_fix.py b/ipatests/test_integration/test_ipa_cert_fix.py
index 219e7d0e1..e6ec30de1 100644
--- a/ipatests/test_integration/test_ipa_cert_fix.py
+++ b/ipatests/test_integration/test_ipa_cert_fix.py
@@ -5,13 +5,12 @@
"""
Module provides tests for ipa-cert-fix CLI.
"""
-from cryptography.hazmat.backends import default_backend
-from cryptography import x509
from datetime import datetime, date
import pytest
import time
import logging
+from ipalib import x509
from ipaplatform.paths import paths
from ipapython.ipaldap import realm_to_serverid
from ipatests.pytest_ipa.integration import tasks
@@ -91,7 +90,7 @@ def get_cert_expiry(host, nssdb_path, cert_nick):
'-o', '/root/cert.pem'
])
data = host.get_file_contents('/root/cert.pem')
- cert = x509.load_pem_x509_certificate(data, backend=default_backend())
+ cert = x509.load_pem_x509_certificate(data)
return cert.not_valid_after_utc
--
2.43.0

View File

@ -1,69 +0,0 @@
From 5dbb3101cee7a96ec8eef40be8e802d456c0d06c Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 22 Jan 2024 08:36:27 -0500
Subject: [PATCH] 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>
---
ipaserver/install/ca.py | 7 ++++---
ipaserver/install/server/replicainstall.py | 7 +++++--
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
index c93ae1fce..187f8032b 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 191913ddb..b3fd27e6a 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -1382,11 +1382,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
@@ -1398,7 +1400,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")
--
2.43.0

View File

@ -1,35 +0,0 @@
From eab52d3cda9bbec716008c040551bd11facd0e11 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Wed, 17 Jan 2024 12:27:26 +0200
Subject: [PATCH] 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>
---
ipaserver/install/adtrustinstance.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
index d55ba8491..2ff68dfb4 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" % \
--
2.43.0

View File

@ -1,101 +0,0 @@
From 3842116185de6ae8714f30b57bd75c7eddde53d8 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Thu, 21 Dec 2023 09:38:57 +0200
Subject: [PATCH] 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>
---
ACI.txt | 2 +-
ipaserver/plugins/host.py | 3 ++-
ipatests/test_integration/test_user_permissions.py | 7 +++++++
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/ACI.txt b/ACI.txt
index e6d6e3d15..236bb4367 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 3ef510edc..b02c8b55f 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 3333a4f6b..cd1096ff3 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
--
2.43.0

View File

@ -1,50 +0,0 @@
From f8b444c563094173c17c3327d72ce9b70da254af Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Tue, 30 Jan 2024 19:58:05 +0200
Subject: [PATCH] ipa-kdb: support Samba 4.20 private libraries
Samba 4.20 will change name extension of the private libraries from
'samba4' to 'private-samba'. Detect private extension through configure
step and make sure to use the right library name in Makefile.
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
daemons/ipa-kdb/Makefile.am | 2 +-
server.m4 | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am
index 777c6b4bd..ca1593bc8 100644
--- a/daemons/ipa-kdb/Makefile.am
+++ b/daemons/ipa-kdb/Makefile.am
@@ -116,7 +116,7 @@ ipa_kdb_tests_LDADD = \
$(top_builddir)/util/libutil.la \
-lkdb5 \
-lsss_idmap \
- -lsamba-security-samba4 \
+ -l$(SAMBA_SECURITY_LIBS)\
-lsamba-errors \
$(NULL)
diff --git a/server.m4 b/server.m4
index 2ee2cf519..f97ceddea 100644
--- a/server.m4
+++ b/server.m4
@@ -182,6 +182,14 @@ AC_CHECK_LIB([smbldap],[smbldap_set_bind_callback],
[AC_DEFINE([HAVE_SMBLDAP_SET_BIND_CALLBACK], [1], [struct smbldap_state is opaque])],
[AC_MSG_WARN([libsmbldap is not opaque, not using smbldap_set_bind_callback])],
[$SAMBA40EXTRA_LIBPATH])
+AC_CHECK_LIB([samba-security-private-samba],[dom_sid_string],
+ [SAMBA_SECURITY_LIBS=samba-security-private-samba],
+ [AC_CHECK_LIB([samba-security-samba4],[dom_sid_string],
+ [SAMBA_SECURITY_LIBS=samba-security-samba4],
+ [AC_MSG_ERROR([Cannot find private samba-security library])],
+ [$SAMBA40EXTRA_LIBPATH])],
+ [$SAMBA40EXTRA_LIBPATH])
+AC_SUBST(SAMBA_SECURITY_LIBS)
dnl ---------------------------------------------------------------------------
dnl Check for libunistring
--
2.43.0

View File

@ -1,153 +0,0 @@
From d4271391adc45c781092db0fb89b802743a9dda8 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 11 Sep 2023 21:37:05 +0000
Subject: [PATCH 1/2] The PKI JSON API the revocation reason key may be
case-sensitive
PKI 11.4.0 changed the reason keyword in the REST API from lower-case
to camel-case in https://github.com/dogtagpki/pki/commit/926eb221ce6
Use Reason instead of reason as the keyword for revocations
for PKI 11.4.0+
Related: https://pagure.io/freeipa/issue/9345
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Thomas Woerner <twoerner@redhat.com>
---
ipaserver/plugins/dogtag.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index 1c2c51824..0036803c8 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -274,6 +274,8 @@ if six.PY3:
logger = logging.getLogger(__name__)
+pki_version = pki.util.Version(pki.specification_version())
+
# These are general status return values used when
# CMSServlet.outputError() is invoked.
CMS_SUCCESS = 0
@@ -1130,7 +1132,11 @@ class ra(rabase.rabase, RestClient):
serial_number = int(serial_number, 0)
path = 'agent/certs/{}/revoke'.format(serial_number)
- data = '{{"reason":"{}"}}'.format(reasons[revocation_reason])
+ if pki_version < pki.util.Version("11.4.0"):
+ keyword = "reason"
+ else:
+ keyword = "Reason"
+ data = '{{"{}":"{}"}}'.format(keyword, reasons[revocation_reason])
http_status, _http_headers, http_body = self._ssldo(
'POST', path,
--
2.41.0
From 0539d97f3e9d2b7d80549ff08d78fe55afcc2dbb Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 26 Oct 2023 13:59:21 -0400
Subject: [PATCH 2/2] WIP: Get the PKI version from the remote to determine the
argument
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Thomas Woerner <twoerner@redhat.com>
---
ipaserver/plugins/dogtag.py | 55 ++++++++++++++++++++++++++++++++-----
1 file changed, 48 insertions(+), 7 deletions(-)
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index 0036803c8..7cd51ae58 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -274,8 +274,6 @@ if six.PY3:
logger = logging.getLogger(__name__)
-pki_version = pki.util.Version(pki.specification_version())
-
# These are general status return values used when
# CMSServlet.outputError() is invoked.
CMS_SUCCESS = 0
@@ -1059,6 +1057,39 @@ class ra(rabase.rabase, RestClient):
return cmd_result
+ def get_pki_version(self):
+ """
+ Retrieve the version of a remote PKI server.
+
+ The REST API request is a GET to the info URI:
+ GET /pki/rest/info HTTP/1.1
+
+ The response is: {"Version":"11.5.0","Attributes":{"Attribute":[]}}
+ """
+ path = "/pki/rest/info"
+ logger.debug('%s.get_pki_version()', type(self).__name__)
+ http_status, _http_headers, http_body = self._ssldo(
+ 'GET', path,
+ headers={
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ },
+ use_session=False,
+ )
+ if http_status != 200:
+ self.raise_certificate_operation_error('get_pki_version',
+ detail=http_status)
+
+ try:
+ response = json.loads(ipautil.decode_json(http_body))
+ except ValueError as e:
+ logger.debug("Response from CA was not valid JSON: %s", e)
+ raise errors.RemoteRetrieveError(
+ reason=_("Response from CA was not valid JSON")
+ )
+
+ return response.get('Version')
+
def revoke_certificate(self, serial_number, revocation_reason=0):
"""
@@ -1125,6 +1156,20 @@ class ra(rabase.rabase, RestClient):
detail='7 is not a valid revocation reason'
)
+ # dogtag changed the argument case for revocation from
+ # "reason" to "Reason" in PKI 11.4.0. Detect that change
+ # based on the remote version and pass the expected value
+ # in.
+ pki_version = pki.util.Version(self.get_pki_version())
+ if pki_version is None:
+ self.raise_certificate_operation_error('revoke_certificate',
+ detail="Remove version not "
+ "detected")
+ if pki_version < pki.util.Version("11.4.0"):
+ reason = "reason"
+ else:
+ reason = "Reason"
+
# Convert serial number to integral type from string to properly handle
# radix issues. Note: the int object constructor will properly handle
# large magnitude integral values by returning a Python long type
@@ -1132,11 +1177,7 @@ class ra(rabase.rabase, RestClient):
serial_number = int(serial_number, 0)
path = 'agent/certs/{}/revoke'.format(serial_number)
- if pki_version < pki.util.Version("11.4.0"):
- keyword = "reason"
- else:
- keyword = "Reason"
- data = '{{"{}":"{}"}}'.format(keyword, reasons[revocation_reason])
+ data = '{{"{}":"{}"}}'.format(reason, reasons[revocation_reason])
http_status, _http_headers, http_body = self._ssldo(
'POST', path,
--
2.41.0

View File

@ -1,135 +0,0 @@
From 9b0b723a0e62f18d41be53900ab8a3e710708563 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 18 May 2023 09:23:32 -0400
Subject: [PATCH] Allow password policy minlength to be removed like other
values
This is a side-effect of adding the libpwquality options. It
imposes its own hardcoded minimum password length so some care
was needed to ensure that it isn't set too low.
So if there are no libpwquality options used then it's fine to
have no minlength in the policy.
Fixes: https://pagure.io/freeipa/issue/9297
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
ipaserver/plugins/pwpolicy.py | 10 +++--
ipatests/test_integration/test_pwpolicy.py | 45 +++++++++++++++++++++-
2 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/ipaserver/plugins/pwpolicy.py b/ipaserver/plugins/pwpolicy.py
index 5ea3e6b78..15cfef45b 100644
--- a/ipaserver/plugins/pwpolicy.py
+++ b/ipaserver/plugins/pwpolicy.py
@@ -462,6 +462,7 @@ class pwpolicy(LDAPObject):
return False
has_pwquality_value = False
+ min_length = 0
if not add:
if len(keys) > 0:
existing_entry = self.api.Command.pwpolicy_show(
@@ -470,14 +471,15 @@ class pwpolicy(LDAPObject):
existing_entry = self.api.Command.pwpolicy_show(
all=True,)['result']
existing_entry.update(entry_attrs)
- min_length = int(get_val(existing_entry, 'krbpwdminlength'))
-
+ if existing_entry.get('krbpwdminlength'):
+ min_length = int(get_val(existing_entry, 'krbpwdminlength'))
has_pwquality_value = has_pwquality_set(existing_entry)
else:
- min_length = int(get_val(entry_attrs, 'krbpwdminlength'))
+ if entry_attrs.get('krbpwdminlength'):
+ min_length = int(get_val(entry_attrs, 'krbpwdminlength'))
has_pwquality_value = has_pwquality_set(entry_attrs)
- if min_length and min_length < 6 and has_pwquality_value:
+ if min_length < 6 and has_pwquality_value:
raise errors.ValidationError(
name='minlength',
error=_('Minimum length must be >= 6 if maxrepeat, '
diff --git a/ipatests/test_integration/test_pwpolicy.py b/ipatests/test_integration/test_pwpolicy.py
index 41d6e9070..652c95e47 100644
--- a/ipatests/test_integration/test_pwpolicy.py
+++ b/ipatests/test_integration/test_pwpolicy.py
@@ -36,7 +36,9 @@ class TestPWPolicy(IntegrationTest):
cls.master.run_command(['ipa', 'group-add-member', POLICY,
'--users', USER])
cls.master.run_command(['ipa', 'pwpolicy-add', POLICY,
- '--priority', '1', '--gracelimit', '-1'])
+ '--priority', '1',
+ '--gracelimit', '-1',
+ '--minlength', '6'])
cls.master.run_command(['ipa', 'passwd', USER],
stdin_text='{password}\n{password}\n'.format(
password=PASSWORD
@@ -92,6 +94,12 @@ class TestPWPolicy(IntegrationTest):
"--minlength", "0",
"--minclasses", "0",],
)
+ # minlength => 6 is required for any of the libpwquality settings
+ self.master.run_command(
+ ["ipa", "pwpolicy-mod", POLICY,
+ "--minlength", "6"],
+ raiseonerr=False,
+ )
@pytest.fixture
def reset_pwpolicy(self):
@@ -212,6 +220,7 @@ class TestPWPolicy(IntegrationTest):
assert 'Password is too simple' in \
result.stdout_text
+ self.reset_password(self.master)
# test with valid password
for valid in ('Passw0rd', 'password1!', 'Password!'):
self.kinit_as_user(self.master, PASSWORD, valid)
@@ -252,6 +261,40 @@ class TestPWPolicy(IntegrationTest):
assert result.returncode != 0
assert 'minlength' in result.stderr_text
+ def test_minlength_empty(self, reset_pwpolicy):
+ """Test that the pwpolicy minlength can be blank
+ """
+ # Ensure it is set to a non-zero value to avoid EmptyModlist
+ self.master.run_command(
+ ["ipa", "pwpolicy-mod", POLICY,
+ "--minlength", "10",]
+ )
+ # Enable one of the libpwquality options, removing minlength
+ # should fail.
+ self.master.run_command(
+ ["ipa", "pwpolicy-mod", POLICY,
+ "--maxrepeat", "4",]
+ )
+ result = self.master.run_command(
+ ["ipa", "pwpolicy-mod", POLICY,
+ "--minlength", "",], raiseonerr=False
+ )
+ assert result.returncode != 0
+
+ # Remove the blocking value
+ self.master.run_command(
+ ["ipa", "pwpolicy-mod", POLICY,
+ "--maxrepeat", "",]
+ )
+
+ # Now erase it
+ result = self.master.run_command(
+ ["ipa", "pwpolicy-mod", POLICY,
+ "--minlength", "",]
+ )
+ assert result.returncode == 0
+ assert 'minlength' not in result.stderr_text
+
def test_minlength_add(self):
"""Test that adding a new policy with minlength is caught.
"""
--
2.41.0

View File

@ -1,88 +0,0 @@
From d9ad56155e76f97ad9326d5c1bcc6e19eea3a0da Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mon, 9 Oct 2023 13:54:17 +0200
Subject: [PATCH] ipalib: fix the IPACertificate validity dates
The class IPACertificate builds objects from x509 Certificate
objects and creates the not_valid_before and not_valid_after values
by converting to a timestamp + applying timezone delta to UTC + reading
from the timestamp. This results in applying twice the delta.
Use a simpler method that replaces the timezone info with UTC in the
datetime object.
Fixes: https://pagure.io/freeipa/issue/9462
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
ipalib/x509.py | 6 ++----
ipatests/test_ipalib/test_x509.py | 25 +++++++++++++++++++++++++
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/ipalib/x509.py b/ipalib/x509.py
index 7396688ae..769d48007 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -266,13 +266,11 @@ class IPACertificate(crypto_x509.Certificate):
@property
def not_valid_before(self):
- return datetime.datetime.fromtimestamp(
- self._cert.not_valid_before.timestamp(), tz=datetime.timezone.utc)
+ return self._cert.not_valid_before.replace(tzinfo=datetime.timezone.utc)
@property
def not_valid_after(self):
- return datetime.datetime.fromtimestamp(
- self._cert.not_valid_after.timestamp(), tz=datetime.timezone.utc)
+ return self._cert.not_valid_after.replace(tzinfo=datetime.timezone.utc)
@property
def tbs_certificate_bytes(self):
diff --git a/ipatests/test_ipalib/test_x509.py b/ipatests/test_ipalib/test_x509.py
index c25e8a0b5..74287c84a 100644
--- a/ipatests/test_ipalib/test_x509.py
+++ b/ipatests/test_ipalib/test_x509.py
@@ -26,6 +26,7 @@ from binascii import hexlify
from configparser import RawConfigParser
import datetime
from io import StringIO
+import os
import pickle
import pytest
@@ -253,6 +254,30 @@ class test_x509:
b'+\x06\x01\x05\x05\x07\x03\x01'
)
+ def test_cert_with_timezone(self):
+ """
+ Test the not_before and not_after values in a diffent timezone
+
+ Test for https://pagure.io/freeipa/issue/9462
+ """
+ # Store initial timezone, then set to New York
+ tz = os.environ.get('TZ', None)
+ os.environ['TZ'] = 'America/New_York'
+ # Load the cert, extract not before and not after
+ cert = x509.load_pem_x509_certificate(goodcert_headers)
+ not_before = datetime.datetime(2010, 6, 25, 13, 0, 42, 0,
+ datetime.timezone.utc)
+ not_after = datetime.datetime(2015, 6, 25, 13, 0, 42, 0,
+ datetime.timezone.utc)
+ # Reset timezone to previous value
+ if tz:
+ os.environ['TZ'] = tz
+ else:
+ del os.environ['TZ']
+ # ensure the timezone doesn't mess with not_before and not_after
+ assert cert.not_valid_before == not_before
+ assert cert.not_valid_after == not_after
+
def test_load_pkcs7_pem(self):
certlist = x509.pkcs7_to_certs(good_pkcs7, datatype=x509.PEM)
assert len(certlist) == 1
--
2.41.0

View File

@ -1,80 +0,0 @@
From d50624dce932d02ea03a00d3ac2ec1be69e8d3b6 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 1/2] 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 741f0608f..7e585c876 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -303,7 +303,7 @@ class DomainValidator:
# 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'))
--
2.41.0
From ed6fa6029d863aed1522b449d3360e6c4028e066 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 2/2] 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 7e585c876..675572c03 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -97,7 +97,7 @@ logger = logging.getLogger(__name__)
def is_sid_valid(sid):
try:
security.dom_sid(sid)
- except TypeError:
+ except (TypeError, ValueError):
return False
else:
return True
@@ -457,7 +457,7 @@ class DomainValidator:
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 '
--
2.41.0

View File

@ -1,83 +0,0 @@
From 677d30806662856595289525ef529a77adbf2272 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Fri, 26 Jan 2024 13:26:48 +0100
Subject: [PATCH] ipa-backup: adapt for 389ds switch to LMDB
ipa-backup is relying on the presence of the directory
/var/lib/dirsrv/slapd-<INSTANCE>/db/ipaca/
to detect if the CA is installed on the server and backup
the ipaca backend.
With the switch to LMDB, this directory does not exist and the
backup is missing ipaca information.
Use lib389.cli_ctl.dblib.run_dbscan utility instead to
check if ipaca backend is present (this method has been
introduced in 389ds 2.1.0 and works with Berkeley DB and LMDB).
Fixes: https://pagure.io/freeipa/issue/9516
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
---
freeipa.spec.in | 7 ++++---
ipaserver/install/ipa_backup.py | 8 ++++++--
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/freeipa.spec.in b/freeipa.spec.in
index a091fee68..997a55d8d 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -78,8 +78,8 @@
%global ds_version 1.4.3.16-12
%global selinux_policy_version 3.14.3-107
%else
-# DNA interval enabled
-%global ds_version 2.0.5-1
+# version supporting LMDB and lib389.cli_ctl.dblib.run_dbscan utility
+%global ds_version 2.1.0
%global selinux_policy_version 38.1.1-1
%endif
@@ -124,10 +124,11 @@
# Make sure to use 389-ds-base versions that fix https://github.com/389ds/389-ds-base/issues/4700
# and has DNA interval enabled
+# version supporting LMDB and lib389.cli_ctl.dblib.run_dbscan utility
%if 0%{?fedora} < 34
%global ds_version 1.4.4.16-1
%else
-%global ds_version 2.0.7-1
+%global ds_version 2.1.0
%endif
# Fix for TLS 1.3 PHA, RHBZ#1775146
diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
index 2904c9e2e..f4fa73ff5 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -41,6 +41,7 @@ from ipaserver.install import installutils
from ipapython import ipaldap
from ipaplatform.constants import constants
from ipaplatform.tasks import tasks
+from lib389.cli_ctl.dblib import run_dbscan
# pylint: disable=import-error
if six.PY3:
@@ -337,8 +338,11 @@ class Backup(admintool.AdminTool):
instance = ipaldap.realm_to_serverid(api.env.realm)
if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE %
instance):
- if os.path.exists(paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
- (instance, 'ipaca')):
+ # Check existence of ipaca backend
+ dbpath = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
+ (instance, ""))
+ output = run_dbscan(['-L', dbpath])
+ if 'ipaca/' in output:
self.db2ldif(instance, 'ipaca', online=options.online)
self.db2ldif(instance, 'userRoot', online=options.online)
self.db2bak(instance, online=options.online)
--
2.43.0

View File

@ -1,106 +0,0 @@
From cb16071635e8c60faa5b6062ed1dd61c3f133fa3 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Wed, 7 Feb 2024 13:42:11 -0500
Subject: ipa-restore: adapt for 389-ds switch to LMDB
ipa-restore is relying on the presence of specific directories,
e.g. /var/lib/dirsrv/slapd-<INSTANCE>/db/ipaca, to detect
which backends are in use (userRoot or ipaca).
With the switch to LMDB, these directories do not exist and the
restore fails finding the ipaca backend.
Use lib389.cli_ctl.dblib.run_dbscan utility instead to
check which backends are present.
This method was been introduced in 389ds 2.1.0 and works with
Berkeley DB and LMDB.
Fixes: https://pagure.io/freeipa/issue/9526
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
ipaserver/install/ipa_restore.py | 45 +++++++++++++++++++++++++++-----
1 file changed, 38 insertions(+), 7 deletions(-)
diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
index 5b7ac61d08f..88b34477049 100644
--- a/ipaserver/install/ipa_restore.py
+++ b/ipaserver/install/ipa_restore.py
@@ -50,6 +50,8 @@
from ipaplatform import services
from ipaplatform.paths import paths
+from lib389.cli_ctl.dblib import run_dbscan
+
try:
from ipaserver.install import adtrustinstance
except ImportError:
@@ -65,6 +67,29 @@
logger = logging.getLogger(__name__)
+backends = [] # global to save running dbscan multiple times
+
+
+def get_backends(db_dir):
+ """Retrieve the set of backends directly from the current database"""
+ global backends
+
+ if backends:
+ return backends
+
+ output = run_dbscan(['-L', db_dir])
+ output = output.replace(db_dir + '/', '')
+ output = output.split('\n')
+ for line in output:
+ if '/' not in line:
+ continue
+ backends.append(line.split('/')[0].strip().lower())
+ backends = set(backends)
+ if 'changelog' in backends:
+ backends.remove('changelog')
+
+ return backends
+
def recursive_chown(path, uid, gid):
'''
@@ -295,8 +320,9 @@ def run(self):
if options.backend:
for instance in self.instances:
db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
- (instance, options.backend))
- if os.path.exists(db_dir):
+ (instance, ""))
+ backends = get_backends(db_dir)
+ if options.backend.lower() in backends:
break
else:
raise admintool.ScriptError(
@@ -304,15 +330,20 @@ def run(self):
self.backends = [options.backend]
+ missing_backends = []
for instance, backend in itertools.product(self.instances,
self.backends):
db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
- (instance, backend))
- if os.path.exists(db_dir):
- break
- else:
+ (instance, ""))
+ backends = get_backends(db_dir)
+ if backend.lower() not in backends:
+ missing_backends.append(backend)
+
+ if missing_backends:
raise admintool.ScriptError(
- "Cannot restore a data backup into an empty system")
+ "Cannot restore a data backup into an empty system. "
+ "Missing backend(s) %s" % ', '.join(missing_backends)
+ )
logger.info("Performing %s restore from %s backup",
restore_type, self.backup_type)

View File

@ -70,7 +70,7 @@
%global krb5_kdb_version 9.0
# 0.7.16: https://github.com/drkjam/netaddr/issues/71
%global python_netaddr_version 0.7.19
%global samba_version 4.17.4-101
%global samba_version 4.20.0
%global slapi_nis_version 0.56.4
%global python_ldap_version 3.1.0-1
%if 0%{?rhel} < 9
@ -111,9 +111,14 @@
# fix for segfault in python3-ldap, https://pagure.io/freeipa/issue/7324
%global python_ldap_version 3.1.0-1
# 389-ds-base version that fixes a number of crashes and performance issues
# https://bodhi.fedoraproject.org/updates/FEDORA-2023-9133b9b669
%global ds_version 2.4.3-1
# Make sure to use 389-ds-base versions that fix https://github.com/389ds/389-ds-base/issues/4700
# and has DNA interval enabled
# version supporting LMDB and lib389.cli_ctl.dblib.run_dbscan utility
%if 0%{?fedora} < 34
%global ds_version 1.4.4.16-1
%else
%global ds_version 2.1.0
%endif
# Fix for TLS 1.3 PHA, RHBZ#1775146
%global httpd_version 2.4.41-9
@ -150,7 +155,7 @@
%endif
# RHEL 8.3+, F32+ has 0.79.13
%global certmonger_version 0.79.7-3
%global certmonger_version 0.79.17-1
# RHEL 8.2+, F32+ has 3.58
%global nss_version 3.44.0-4
@ -187,7 +192,7 @@
# Work-around fact that RPM SPEC parser does not accept
# "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement
%define IPA_VERSION 4.11.1
%define IPA_VERSION 4.12.0
# Release candidate version -- uncomment with one percent for RC versions
#%%global rc_version
%define AT_SIGN @
@ -200,7 +205,7 @@
Name: %{package_name}
Version: %{IPA_VERSION}
Release: 4%{?rc_version:.%rc_version}%{?dist}
Release: 1%{?rc_version:.%rc_version}%{?dist}
Summary: The Identity, Policy and Audit system
License: GPL-3.0-or-later
@ -219,19 +224,6 @@ Source1: https://releases.pagure.org/freeipa/freeipa-%{version}%{?rc_vers
Source2: gpgkey-0E63D716D76AC080A4A33513F40800B6298EB963.asc
%endif
Patch0001: freeipa-4.11-samba-changes.patch
Patch0002: freeipa-4.11-pki-revocation-changes.patch
Patch0003: freeipa-4.11-py3.12-timezone-changes.patch
Patch0004: freeipa-4.11-pwpolicy-minlength.patch
Patch0005: 0009-host-keytab-permission.patch
Patch0006: 0008-netbios-defaults.patch
Patch0009: 0005-pyca-42.0.0-support.patch
Patch0010: 0004-ipa-cli-krb5-crash.patch
Patch0011: 0003-kdb-memory-leak.patch
Patch0012: 0010-support-samba-4.20.patch
Patch0013: freeipa-support-389-ds-with-lmdb-backup.patch
Patch0014: freeipa-support-389-ds-with-lmdb-restore.patch
# RHEL spec file only: START: Change branding to IPA and Identity Management
# Moved branding logos and background to redhat-logos-ipa-80.4:
# header-logo.png, login-screen-background.jpg, login-screen-logo.png,
@ -244,7 +236,8 @@ Patch0014: freeipa-support-389-ds-with-lmdb-restore.patch
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
%endif
%if 0%{?rhel} == 9
%if 0%{?rhel} >= 9
Patch0001: 0001-Revert-Replace-netifaces-with-ifaddr.patch
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
%endif
%endif
@ -279,6 +272,7 @@ BuildRequires: gettext
BuildRequires: gettext-devel
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-argcomplete
BuildRequires: systemd >= %{systemd_version}
# systemd-tmpfiles which is executed from make install requires apache user
BuildRequires: httpd
@ -555,12 +549,8 @@ Requires: python3-pyasn1 >= 0.3.2-2
Requires: python3-sssdconfig >= %{sssd_version}
Requires: python3-psutil
Requires: rpm-libs
%if 0%{?rhel}
Requires: python3-urllib3 >= 1.24.2-3
%else
# For urllib3.util.ssl_match_hostname
Requires: python3-urllib3 >= 1.25.8
%endif
%description -n python3-ipaserver
IPA is an integrated solution to provide centrally managed Identity (users,
@ -704,7 +694,7 @@ Requires: oddjob-mkhomedir
Requires: libsss_autofs
Requires: autofs
Requires: libnfsidmap
Requires: nfs-utils
Requires: (nfs-utils or nfsv4-client-utils)
Requires: sssd-tools >= %{sssd_version}
Requires(post): policycoreutils
@ -863,6 +853,7 @@ Requires: %{name}-common = %{version}-%{release}
Requires(pre): python3-ldap >= %{python_ldap_version}
Requires: gnupg2
Requires: keyutils
Requires: python3-argcomplete
Requires: python3-cffi
Requires: python3-cryptography >= 1.6
Requires: python3-dateutil
@ -886,12 +877,9 @@ Requires: platform-python-setuptools
%else
Requires: python3-setuptools
%endif
%if 0%{?rhel}
Requires: python3-urllib3 >= 1.24.2-3
%else
# For urllib3.util.ssl_match_hostname
Requires: python3-urllib3 >= 1.25.8
%endif
Requires: python3-systemd
%description -n python3-ipalib
IPA is an integrated solution to provide centrally managed Identity (users,
@ -983,6 +971,26 @@ Requires(post): selinux-policy-%{selinuxtype}
%description selinux
Custom SELinux policy module for FreeIPA
%package selinux-nfast
Summary: FreeIPA SELinux policy for nCipher nfast HSMs
BuildArch: noarch
Requires: selinux-policy-%{selinuxtype}
Requires(post): selinux-policy-%{selinuxtype}
%{?selinux_requires}
%description selinux-nfast
Custom SELinux policy module for nCipher nfast HSMs
%package selinux-luna
Summary: FreeIPA SELinux policy for Thales Luna HSMs
BuildArch: noarch
Requires: selinux-policy-%{selinuxtype}
Requires(post): selinux-policy-%{selinuxtype}
%{?selinux_requires}
%description selinux-luna
Custom SELinux policy module for Thales Luna HSMs
# with selinux
%endif
@ -1069,6 +1077,17 @@ rm -f %{buildroot}%{_usr}/share/ipa/ui/images/product-name.png
%endif
# RHEL spec file only: END
%if ! %{ONLY_CLIENT}
%if 0%{?fedora} >= 38
# Register CLI tools for bash completion (fedora only)
for clitool in ipa-migrate
do
register-python-argcomplete "${clitool}" > "${clitool}"
install -p -m 0644 -D -t '%{buildroot}%{bash_completions_dir}' "${clitool}"
done
%endif
%endif
%find_lang %{gettext_domain}
%if ! %{ONLY_CLIENT}
@ -1132,6 +1151,10 @@ fi
/bin/systemctl reload-or-try-restart oddjobd
%tmpfiles_create ipa.conf
%journal_catalog_update
%postun server
%journal_catalog_update
%posttrans server
# don't execute upgrade and restart of IPA when server is not installed
@ -1268,13 +1291,21 @@ if [ $1 -gt 1 ] ; then
cp /etc/ipa/ca.crt /var/lib/ipa-client/pki/kdc-ca-bundle.pem
cp /etc/ipa/ca.crt /var/lib/ipa-client/pki/ca-bundle.pem
fi
%{__python3} -c 'from ipaclient.install.client import configure_krb5_snippet; configure_krb5_snippet()' >>/var/log/ipaupgrade.log 2>&1
%{__python3} -c 'from ipaclient.install.client import update_ipa_nssdb; update_ipa_nssdb()' >>/var/log/ipaupgrade.log 2>&1
chmod 0600 /var/log/ipaupgrade.log
SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config"
if [ -f "$SSH_CLIENT_SYSTEM_CONF" ]; then
sed -E --in-place=.orig 's/^(HostKeyAlgorithms ssh-rsa,ssh-dss)$/# disabled by ipa-client update\n# \1/' "$SSH_CLIENT_SYSTEM_CONF"
# https://pagure.io/freeipa/issue/9536
# replace sss_ssh_knownhostsproxy with sss_ssh_knownhosts
if [ -f '/usr/bin/sss_ssh_knownhosts' ]; then
if grep -E -q 'Include' $SSH_CLIENT_SYSTEM_CONF 2>/dev/null ; then
SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config.d/04-ipa.conf"
fi
sed -E --in-place=.orig 's/^(GlobalKnownHostsFile \/var\/lib\/sss\/pubconf\/known_hosts)$/# disabled by ipa-client update\n# \1/' $SSH_CLIENT_SYSTEM_CONF
sed -E --in-place=.orig 's/(ProxyCommand \/usr\/bin\/sss_ssh_knownhostsproxy -p \%p \%h)/# replaced by ipa-client update\n KnownHostsCommand \/usr\/bin\/sss_ssh_knownhosts \%H/' $SSH_CLIENT_SYSTEM_CONF
fi
fi
fi
fi
@ -1290,17 +1321,75 @@ fi
semodule -d ipa_custodia &> /dev/null || true;
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2
%post selinux-nfast
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}-nfast.pp.bz2
%post selinux-luna
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}-luna.pp.bz2
%postun selinux
if [ $1 -eq 0 ]; then
%selinux_modules_uninstall -s %{selinuxtype} %{modulename}
semodule -e ipa_custodia &> /dev/null || true;
fi
%postun selinux-nfast
if [ $1 -eq 0 ]; then
%selinux_modules_uninstall -s %{selinuxtype} %{modulename}-nfast
fi
%postun selinux-luna
if [ $1 -eq 0 ]; then
%selinux_modules_uninstall -s %{selinuxtype} %{modulename}-luna
%posttrans selinux
%selinux_relabel_post -s %{selinuxtype}
# with_selinux
%endif
%triggerin client -- sssd-common < 2.10
# Has the client been configured?
restore=0
test -f '/var/lib/ipa-client/sysrestore/sysrestore.index' && restore=$(wc -l '/var/lib/ipa-client/sysrestore/sysrestore.index' | awk '{print $1}')
if [ -f '/etc/ssh/sshd_config' -a $restore -ge 2 ]; then
SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config"
if [ -f "$SSH_CLIENT_SYSTEM_CONF" ]; then
# https://pagure.io/freeipa/issue/9536
# downgrade sss_ssh_knownhosts with sss_ssh_knownhostsproxy
if [ -f '/usr/bin/sss_ssh_knownhosts' ]; then
if grep -E -q 'Include' $SSH_CLIENT_SYSTEM_CONF 2>/dev/null ; then
SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config.d/04-ipa.conf"
fi
GLOBALKNOWNHOSTFILE="GlobalKnownHostsFile /var/lib/sss/pubconf/known_hosts/"
grep -qF '$GLOBALKNOWNHOSTFILE' $SSH_CLIENT_SYSTEM_CONF
if [ $? -ne 0 ]; then
sed -E --in-place=.orig '/(# IPA-related configuration changes to ssh_config)/a # added by ipa-client update\n'"$GLOBALKNOWNHOSTFILE"'' $SSH_CLIENT_SYSTEM_CONF
fi
sed -E --in-place=.orig 's/(KnownHostsCommand \/usr\/bin\/sss_ssh_knownhosts \%H)/ProxyCommand \/usr\/bin\/sss_ssh_knownhostsproxy -p \%p \%h/' $SSH_CLIENT_SYSTEM_CONF
fi
fi
fi
%triggerin client -- sssd-common >= 2.10
# Has the client been configured?
restore=0
test -f '/var/lib/ipa-client/sysrestore/sysrestore.index' && restore=$(wc -l '/var/lib/ipa-client/sysrestore/sysrestore.index' | awk '{print $1}')
if [ -f '/etc/ssh/sshd_config' -a $restore -ge 2 ]; then
SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config"
if [ -f "$SSH_CLIENT_SYSTEM_CONF" ]; then
# https://pagure.io/freeipa/issue/9536
# upgrade sss_ssh_knownhostsproxy with sss_ssh_knownhosts
if [ -f '/usr/bin/sss_ssh_knownhosts' ]; then
if grep -E -q 'Include' $SSH_CLIENT_SYSTEM_CONF 2>/dev/null ; then
SSH_CLIENT_SYSTEM_CONF="/etc/ssh/ssh_config.d/04-ipa.conf"
fi
sed -E --in-place=.orig 's/^(GlobalKnownHostsFile \/var\/lib\/sss\/pubconf\/known_hosts)$/# disabled by ipa-client update\n# \1/' $SSH_CLIENT_SYSTEM_CONF
sed -E --in-place=.orig 's/(ProxyCommand \/usr\/bin\/sss_ssh_knownhostsproxy -p \%p \%h)/# replaced by ipa-client update\n KnownHostsCommand \/usr\/bin\/sss_ssh_knownhosts \%H/' $SSH_CLIENT_SYSTEM_CONF
fi
fi
fi
%triggerin client -- openssh-server < 8.2
# Has the client been configured?
@ -1399,6 +1488,10 @@ fi
%{_sbindir}/ipa-crlgen-manage
%{_sbindir}/ipa-cert-fix
%{_sbindir}/ipa-acme-manage
%{_sbindir}/ipa-migrate
%if 0%{?fedora} >= 38
%{bash_completions_dir}/ipa-migrate
%endif
%{_libexecdir}/certmonger/dogtag-ipa-ca-renew-agent-submit
%{_libexecdir}/certmonger/ipa-server-guard
%dir %{_libexecdir}/ipa
@ -1431,6 +1524,7 @@ fi
%attr(644,root,root) %{_unitdir}/ipa-otpd@.service
%attr(644,root,root) %{_unitdir}/ipa-ccache-sweep.service
%attr(644,root,root) %{_unitdir}/ipa-ccache-sweep.timer
%attr(644,root,root) %{_journalcatalogdir}/ipa.catalog
# END
%attr(755,root,root) %{plugin_dir}/libipa_pwd_extop.so
%attr(755,root,root) %{plugin_dir}/libipa_enrollment_extop.so
@ -1473,6 +1567,7 @@ fi
%{_mandir}/man1/ipa-crlgen-manage.1*
%{_mandir}/man1/ipa-cert-fix.1*
%{_mandir}/man1/ipa-acme-manage.1*
%{_mandir}/man1/ipa-migrate.1*
%files -n python3-ipaserver
@ -1747,10 +1842,22 @@ fi
%files selinux
%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.*
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
%files selinux-nfast
%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}-nfast.pp.*
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}-nfast
%files selinux-luna
%{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}-luna.pp.*
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}-luna
# with selinux
%endif
%changelog
* Tue Jun 04 2024 Florence Blanc-Renaud <flo@redhat.com> - 4.12.0-1
- Resolves: RHEL-39144 Rebase ipa to the latest 4.12 version for RHEL 10
- Resolves: RHEL-30537 ipa: freeipa: argument injection into the username field of the /ipa/session/login_password requests
* Thu Feb 22 2024 Troy Dawson <tdawson@redhat.com> - 4.11.1-4
- Bump release to rebuild on correct samba

View File

@ -1,2 +1,2 @@
SHA512 (freeipa-4.11.1.tar.gz) = 65c3ccc8a6da71b2bad3efdf9e798b0d65e6d1e2c3a6ed6617ab86d7e8a5fa01ba2787714a3004b01e35fe087f464e0ae22d0fe4b254956262e7d96d61b1e84d
SHA512 (freeipa-4.11.1.tar.gz.asc) = 31157e852653681d3914aebc4b98babf16c4131f647ed6b4c2b49d07f50ac393f54fb1a9d9fcbcf6772eccf5bae7331912ad3e3508bf8cac7d7e74c676bdbc60
SHA512 (freeipa-4.12.0.tar.gz) = 1e95250a6892e85b4782a1f2451a99d21c90ce82db2be369d9e0e1706575229d4539b20f8dd2b97da0d6f73f4fb59168ab6e05eb2fe185b4bb854f42c1e7fd29
SHA512 (freeipa-4.12.0.tar.gz.asc) = 896170fee005acc3cf46b22053d9f0f0e75f0af31af5c9fbd993674dc26549e479ea3468412ff35f947f7cf42bb7b9bf96f1ead21d754eec92a27b30d731dbe1