diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py index 2402689cc..573e6040c 100644 --- a/ipapython/ipautil.py +++ b/ipapython/ipautil.py @@ -1330,6 +1330,29 @@ def restore_hostname(statestore): except CalledProcessError as e: print("Failed to set this machine hostname back to %s: %s" % (old_hostname, str(e)), file=sys.stderr) +def posixify(string): + """ + Convert a string to a more strict alpha-numeric representation. + + - Alpha-numeric, underscore, dot and dash characters are accepted + - Space is converted to underscore + - Other characters are omitted + - Leading dash is stripped + + Note: This mapping is not one-to-one and may map different input to the + same result. When using posixify, make sure the you do not map two different + entities to one unintentionally. + """ + + def valid_char(char): + return char.isalnum() or char in ('_', '.', '-') + + # First replace space characters + replaced = string.replace(' ','_') + omitted = ''.join(filter(valid_char, replaced)) + + # Leading dash is not allowed + return omitted.lstrip('-') @contextmanager def private_ccache(path=None): diff --git a/ipaserver/install/ipa_winsync_migrate.py b/ipaserver/install/ipa_winsync_migrate.py index cafec9d18..d0c6cc80c 100644 --- a/ipaserver/install/ipa_winsync_migrate.py +++ b/ipaserver/install/ipa_winsync_migrate.py @@ -26,7 +26,7 @@ from ipalib import api from ipalib import errors from ipapython import admintool from ipapython.dn import DN -from ipapython.ipautil import realm_to_suffix +from ipapython.ipautil import realm_to_suffix, posixify from ipapython.ipa_log_manager import log_mgr from ipaserver.plugins.ldap2 import ldap2 from ipaserver.install import replication @@ -219,12 +219,21 @@ class WinsyncMigrate(admintool.AdminTool): def winsync_group_name(object_entry): """ - Returns the generated name of group containing migrated external users + Returns the generated name of group containing migrated external + users. + + The group name is of the form: + "__winsync_external" + + Object name is converted to posix-friendly string by omitting + and/or replacing characters. This may lead to collisions, i.e. + if both 'trust_admins' and 'trust admin' groups have winsync + users being migrated. """ return u"{0}_{1}_winsync_external".format( winsync_group_prefix, - object_entry['cn'][0] + posixify(object_entry['cn'][0]) ) def create_winsync_group(object_entry):