diff --git a/ipaserver/install/server/__init__.py b/ipaserver/install/server/__init__.py index 8c6a26b14..d9adf76f3 100644 --- a/ipaserver/install/server/__init__.py +++ b/ipaserver/install/server/__init__.py @@ -5,10 +5,6 @@ """ Server installer module """ - -from __future__ import print_function - -import collections import os.path import random @@ -19,16 +15,15 @@ from ipalib.install.service import (enroll_only, installs_master, installs_replica, master_install_only, - prepares, prepare_only, replica_install_only) -from ipapython import ipautil from ipapython.dnsutil import check_zone_overlap from ipapython.install import typing from ipapython.install.core import group, knob, extend_knob from ipapython.install.common import step 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 install as master_install from .install import install_check as master_install_check @@ -479,6 +474,15 @@ class ServerInstallInterface(ServerCertificateInstallInterface, "'--ignore-topology-disconnect/--ignore-last-of-role' " "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: raise RuntimeError( "idmax (%s) cannot be smaller than idstart (%s)" % diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index 7cdf2a510..6b08b702b 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -8,6 +8,7 @@ import errno import logging import os import pickle +import re import shutil import sys import time @@ -101,6 +102,26 @@ def validate_admin_password(password): ', '.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): """ Returns a dict of cached answers or empty dict if no cache file exists.