From b00b8acca54267560c6d7ec614bc52cfe541200a Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Aug 19 2013 18:50:35 +0000 Subject: Ticket #48 - Active Directory has certain uids which are reserved and will cause a Directory Server replica initialization of an AD server to abort. Bug description: Some account names (e.g. "service") is reserved in Active Directory. If DS has an entry having such an NT user ID and the entry is synchronized to the AD, it fails with LDAP_ALREADY_ EXISTS, but the error is gracefully ignored. In the total update, updating Account Control bit follows the failed add, which fails since the AD entry WinSync expects does not exist and it aborts the total update. Fix description: If adding a DS entry to AD fails and the updating Account Control bit also fails, the following note is logged in the error log and the total update continues: windows_process_total_add: Creating AD entry "cn=service service, cn=Users,dc=EXAMPLE,dc=COM" from DS entry "uid=service,ou=People, dc=example,dc=com" failed. AD reserves the account name. Ignoring the error... In addition, in windows_parse_config_entry, f the attribute values in the agreement is retrieved before the agreement is started, the following error is logged, which is not necessary. This patch stops logging it if the agreement does not set "protocol" yet. Replication agreement for agmt="cn=WinSync" could not be updated. For replication to take place, please enable the suffix and restart the server. Reviewed by Rich (Thank you!!) https://fedorahosted.org/389/ticket/48 --- diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c index 7418768..e6bd062 100644 --- a/ldap/servers/plugins/replication/windows_connection.c +++ b/ldap/servers/plugins/replication/windows_connection.c @@ -425,7 +425,8 @@ windows_perform_operation(Repl_Connection *conn, int optype, const char *dn, } else if (err == LDAP_ALREADY_EXISTS && optype == CONN_ADD) { - conn->last_ldap_error = LDAP_SUCCESS; + /* Caller (windows_process_total_add) needs the ALREADY EXISTS info */ + conn->last_ldap_error = err; return_value = CONN_OPERATION_SUCCESS; } else if (err == LDAP_NO_SUCH_OBJECT && optype == CONN_DELETE) diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c index d108d1b..51e959a 100644 --- a/ldap/servers/plugins/replication/windows_private.c +++ b/ldap/servers/plugins/replication/windows_private.c @@ -183,7 +183,11 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e) windows_private_set_create_users(ra, PR_FALSE); } slapi_ch_free((void**)&tmpstr); - prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + /* If protocol is NULL; the agreement is not started yet. + * So, no need to notify. */ + if (agmt_get_protocol(ra)) { + prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + } retval = 1; } if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7CreateNewGroups)) @@ -198,7 +202,11 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e) windows_private_set_create_groups(ra, PR_FALSE); } slapi_ch_free((void**)&tmpstr); - prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + /* If protocol is NULL; the agreement is not started yet. + * So, no need to notify. */ + if (agmt_get_protocol(ra)) { + prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + } retval = 1; } if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsDomain)) @@ -218,7 +226,11 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e) if (NULL != tmpstr) { windows_private_set_sync_interval(ra,tmpstr); - prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + /* If protocol is NULL; the agreement is not started yet. + * So, no need to notify. */ + if (agmt_get_protocol(ra)) { + prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + } } slapi_ch_free_string(&tmpstr); retval = 1; @@ -245,7 +257,11 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e) windows_private_set_one_way(ra, ONE_WAY_SYNC_DISABLED); } slapi_ch_free((void**)&tmpstr); - prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + /* If protocol is NULL; the agreement is not started yet. + * So, no need to notify. */ + if (agmt_get_protocol(ra)) { + prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + } retval = 1; } if (type == NULL || slapi_attr_types_equivalent(type,type_winsyncMoveAction)) @@ -272,7 +288,11 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e) windows_private_set_move_action(ra, MOVE_DOES_NOTHING); } slapi_ch_free((void**)&tmpstr); - prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + /* If protocol is NULL; the agreement is not started yet. + * So, no need to notify. */ + if (agmt_get_protocol(ra)) { + prot_notify_agmt_changed(agmt_get_protocol(ra), (char *)agmt_get_long_name(ra)); + } retval = 1; } diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c index 8e92de2..02ac783 100644 --- a/ldap/servers/plugins/replication/windows_protocol_util.c +++ b/ldap/servers/plugins/replication/windows_protocol_util.c @@ -1220,6 +1220,10 @@ process_replay_add(Private_Repl_Protocol *prp, Slapi_Entry *add_entry, Slapi_Ent windows_log_add_entry_remote(local_dn, remote_dn); return_value = windows_conn_send_add(prp->conn, slapi_sdn_get_dn(remote_dn), entryattrs, NULL, NULL); + if (LDAP_ALREADY_EXISTS == ldap_result_code) { + /* Igoring ALREADY EXIST case. */ + ldap_result_code = LDAP_SUCCESS; + } windows_conn_get_error(prp->conn, &ldap_op, &ldap_result_code); if ((return_value != CONN_OPERATION_SUCCESS) && !ldap_result_code) { /* op failed but no ldap error code ??? */ @@ -5080,9 +5084,15 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r { int ldap_op = 0; int ldap_result_code = 0; + int alreadyexists = 0; windows_log_add_entry_remote(local_dn, remote_dn); retval = windows_conn_send_add(prp->conn, slapi_sdn_get_dn(remote_dn), entryattrs, NULL, NULL /* returned controls */); windows_conn_get_error(prp->conn, &ldap_op, &ldap_result_code); + /* special treatment for ALREADY EXISTS */ + if (LDAP_ALREADY_EXISTS == ldap_result_code) { + alreadyexists = 1; + ldap_result_code = LDAP_SUCCESS; + } if ((retval != CONN_OPERATION_SUCCESS) && !ldap_result_code) { /* op failed but no ldap error code ??? */ ldap_result_code = LDAP_OPERATIONS_ERROR; @@ -5111,6 +5121,15 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r if ((retval == 0) && is_user) { /* set the account control bits only for users */ retval = send_accountcontrol_modify(remote_dn, prp, missing_entry); + if (alreadyexists) { + slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, + "%s: windows_process_total_add: " + "Creating AD entry \"%s\" from DS entry \"%s\" failed. " + "AD reserves the account name. Ignoring the error...\n", + agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(remote_dn), + slapi_sdn_get_dn(local_dn)); + retval = 0; + } } } } else