diff options
Diffstat (limited to 'ipa-server')
-rwxr-xr-x | ipa-server/ipa-install/ipa-replica-manage | 8 | ||||
-rw-r--r-- | ipa-server/ipaserver/replication.py | 38 |
2 files changed, 44 insertions, 2 deletions
diff --git a/ipa-server/ipa-install/ipa-replica-manage b/ipa-server/ipa-install/ipa-replica-manage index 9b46748e3..c0051c7fb 100755 --- a/ipa-server/ipa-install/ipa-replica-manage +++ b/ipa-server/ipa-install/ipa-replica-manage @@ -46,6 +46,8 @@ def parse_options(): help="Full path and filename of CA certificate to use with TLS/SSL to the remote server") parser.add_option("--win-subtree", dest="win_subtree", help="DN of Windows subtree containing the users you want to sync (default cn=Users,<domain suffix)") + parser.add_option("--passsync", dest="passsync", + help="Password for the Windows PassSync user") options, args = parser.parse_args() @@ -115,10 +117,12 @@ def add_master(replman, hostname, options): other_args['cacert'] = options.cacert if options.win_subtree: other_args['win_subtree'] = options.win_subtree + if options.passsync: + other_args['passsync'] = options.passsync if options.winsync: other_args['winsync'] = True - if not options.binddn or not options.bindpw or not options.cacert: - logging.error("The arguments --binddn, --bindpw, and --cacert are required to create a winsync agreement") + if not options.binddn or not options.bindpw or not options.cacert or not options.passsync: + logging.error("The arguments --binddn, --bindpw, --passsync and --cacert are required to create a winsync agreement") sys.exit(1) if options.cacert: # have to install the given CA cert before doing anything else diff --git a/ipa-server/ipaserver/replication.py b/ipa-server/ipaserver/replication.py index 86d1f5f92..0a8ef9f6b 100644 --- a/ipa-server/ipaserver/replication.py +++ b/ipa-server/ipaserver/replication.py @@ -246,6 +246,43 @@ class ReplicationManager: chainbe = self.setup_chaining_backend(other_conn) self.enable_chain_on_update(chainbe) + def add_passsync_user(self, conn, password): + pass_dn = "uid=passsync,cn=sysaccounts,cn=etc,%s" % self.suffix + print "The user for the Windows PassSync service is %s" % pass_dn + try: + conn.getEntry(pass_dn, ldap.SCOPE_BASE) + print "Windows PassSync entry exists, not resetting password" + return + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + pass + + # The user doesn't exist, add it + entry = ipaldap.Entry(pass_dn) + entry.setValues("objectclass", ["account", "simplesecurityobject"]) + entry.setValues("uid", "passsync") + entry.setValues("userPassword", password) + conn.add_s(entry) + + # Add it to the list of users allowed to bypass password policy + extop_dn = "cn=ipa_pwd_extop,cn=plugins,cn=config" + entry = conn.getEntry(extop_dn, ldap.SCOPE_BASE) + pass_mgrs = entry.getValues('passSyncManagersDNs') + if not pass_mgrs: + pass_mgrs = [] + if not isinstance(pass_mgrs, list): + pass_mgrs = [pass_mgrs] + pass_mgrs.append(pass_dn) + mod = [(ldap.MOD_REPLACE, 'passSyncManagersDNs', pass_mgrs)] + conn.modify_s(extop_dn, mod) + + # And finally grant it permission to write passwords + mod = [(ldap.MOD_ADD, 'aci', + ['(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Windows PassSync service can write passwords"; allow (write) userdn="ldap:///%s";)' % pass_dn])] + try: + conn.modify_s(self.suffix, mod) + except ldap.TYPE_OR_VALUE_EXISTS: + logging.debug("passsync aci already exists in suffix %s on %s" % (self.suffix, conn.host)) + def setup_winsync_agmt(self, entry, **kargs): entry.setValues("objectclass", "nsDSWindowsReplicationAgreement") entry.setValues("nsds7WindowsReplicaSubtree", @@ -407,6 +444,7 @@ class ReplicationManager: self.setup_agreement(self.conn, other_conn) return self.start_replication(other_conn) else: + self.add_passsync_user(self.conn, kargs.get("passsync")) self.setup_agreement(self.conn, other_conn, **kargs) return self.start_replication(self.conn, other_conn) |