Require idstart to be larger than UID_MAX

ipa-server-install fails if idstart is set to 0. There might be
additional issues when idstart overlaps with local users. Ensure that
idstart is larger than UID_MAX or GID_MAX from /etc/login.defs.

Fixes: https://pagure.io/freeipa/issue/8137
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Christian Heimes 2019-12-10 09:11:23 +01:00
parent 650db3b80d
commit 44b3791bc3
2 changed files with 31 additions and 6 deletions

View File

@ -5,10 +5,6 @@
""" """
Server installer module Server installer module
""" """
from __future__ import print_function
import collections
import os.path import os.path
import random import random
@ -19,16 +15,15 @@ from ipalib.install.service import (enroll_only,
installs_master, installs_master,
installs_replica, installs_replica,
master_install_only, master_install_only,
prepares,
prepare_only, prepare_only,
replica_install_only) replica_install_only)
from ipapython import ipautil
from ipapython.dnsutil import check_zone_overlap from ipapython.dnsutil import check_zone_overlap
from ipapython.install import typing from ipapython.install import typing
from ipapython.install.core import group, knob, extend_knob from ipapython.install.core import group, knob, extend_knob
from ipapython.install.common import step from ipapython.install.common import step
from .install import validate_admin_password, validate_dm_password from .install import validate_admin_password, validate_dm_password
from .install import get_min_idstart
from .install import init as master_init from .install import init as master_init
from .install import install as master_install from .install import install as master_install
from .install import install_check as master_install_check from .install import install_check as master_install_check
@ -479,6 +474,15 @@ class ServerInstallInterface(ServerCertificateInstallInterface,
"'--ignore-topology-disconnect/--ignore-last-of-role' " "'--ignore-topology-disconnect/--ignore-last-of-role' "
"options can be used only during uninstallation") "options can be used only during uninstallation")
min_idstart = get_min_idstart()
if self.idstart < min_idstart:
raise RuntimeError(
"idstart (%i) must be larger than UID_MAX/GID_MAX (%i) "
"setting in /etc/login.defs." % (
self.idstart, min_idstart
)
)
if self.idmax < self.idstart: if self.idmax < self.idstart:
raise RuntimeError( raise RuntimeError(
"idmax (%s) cannot be smaller than idstart (%s)" % "idmax (%s) cannot be smaller than idstart (%s)" %

View File

@ -8,6 +8,7 @@ import errno
import logging import logging
import os import os
import pickle import pickle
import re
import shutil import shutil
import sys import sys
import time import time
@ -101,6 +102,26 @@ def validate_admin_password(password):
', '.join('"%s"' % c for c in bad_characters)) ', '.join('"%s"' % c for c in bad_characters))
def get_min_idstart(default_idstart=60000):
"""Get mininum idstart value from /etc/login.defs
"""
config = {}
# match decimal numbers
decimal_re = re.compile(r"^([A-Z][A-Z_]+)\s*([1-9]\d*)")
try:
with open('/etc/login.defs', 'r') as f:
for line in f:
mo = decimal_re.match(line)
if mo is not None:
config[mo.group(1)] = int(mo.group(2))
except OSError:
return default_idstart
idstart = max(config.get("UID_MAX", 0), config.get("GID_MAX", 0))
if idstart == 0:
idstart = default_idstart
return idstart
def read_cache(dm_password): def read_cache(dm_password):
""" """
Returns a dict of cached answers or empty dict if no cache file exists. Returns a dict of cached answers or empty dict if no cache file exists.