Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Windows Server 2003 включает функцию восстановления удаленных объектов.
Чтобы включить восстановление удаленных объектов, необходимо запустить по крайней мере один контроллер домена в домене в Windows Server 2003 или более поздней версии Windows. По умолчанию только администраторы домена могут восстановить удаленные объекты, хотя это можно делегировать другим пользователям.
Следующие ограничения применяются к восстановлению удаленных объектов:
- Объект не может быть восстановлен, если срок существования томбстоуна для объекта истек, потому что тогда объект окончательно удаляется.
- Объекты, существующие в корне контекста именования, такие как домен или раздел приложения, не могут быть восстановлены.
- Объекты схемы не могут быть восстановлены. Объекты схемы никогда не следует удалять.
- Можно восстановить удаленные контейнеры, но восстановление удаленных объектов, которые находились в контейнере до удаления, сложно, так как структура дерева в контейнере должна быть восстановлена вручную.
Разрешения, необходимые для восстановления удаленного объекта
При удалении объекта дескриптор безопасности объекта сохраняется. Хотя владелец идентифицируется из дескриптора безопасности, только администраторы домена могут восстанавливать удаленные объекты. Администраторы домена могут предоставить разрешение на восстановление удалённых объектов для других пользователей и групп, предоставив пользователю или группе право доступа "Reanimate Tombstone". Права контроля доступа "Reanimate Tombstone" предоставляются в корне пространства имен. Только пользователи, имеющие разрешение на доступ на чтение объекта и его атрибуты, могут читать объект и доступные атрибуты после удаления объекта.
Заметка
Предоставление пользователю этого разрешения может быть угрозой безопасности, так как это может позволить пользователю восстановить объект учетной записи, имеющий доступ к ресурсам, к которым пользователь обычно не имеет доступа. При восстановлении учетной записи пользователь фактически получает контроль над этой учетной записью, так как пользователь должен задать исходный пароль учетной записи при восстановлении учетной записи.
Чтобы полностью восстановить удаленный объект, пользователь должен:
Иметь или быть членом группы, которая имеет право на управление доступом "Reanimate Tombstone".
Убедитесь, что у вас есть доступ на запись для каждого обязательного атрибута, требующего обновления.
Иметь доступ на запись к относительно различаемого имени (RDN).
Иметь доступ на запись к каждому необязательному атрибуту, который необходимо обновить.
Имеют права на создание дочерних объектов в целевом контейнере для класса объектов восстановленного объекта.
Заметка
Атрибут isDeleted не проверяется во время операции восстановления. Разрешение "удаление потомков" в контейнере "Удаленные объекты" также не будет проверяться.
Восстановление удаленного объекта
Чтобы восстановить удаленный объект, объект должен сначала находиться в контейнере удаленных объектов. Дополнительную информацию о восстановлении удаленных объектов см. в разделе Восстановление удаленных объектов.
При обнаружении объекта в рамках одной операции LDAP необходимо выполнить следующие операции. Для этого требуется использование функции ldap_modify_ext_s с элементом управления LDAP_SERVER_SHOW_DELETED_OID.
- Удалите значение атрибута isDeleted. Значение атрибута isDeleted должно быть удалено, а не установлено в FALSE.
- Замените различающееся имя объекта таким образом, чтобы он перемещался в контейнер, отличный от контейнера удаленных объектов. Это может быть любой контейнер, который обычно может содержать объект. Различающееся имя предыдущего контейнера объекта можно найти в атрибуте lastKnownParent удаленного объекта. Атрибут lastKnownParent устанавливается только в том случае, если объект был удален на контроллере домена Windows Server 2003. Таким образом, возможно, содержимое атрибута lastKnownParent является неточным.
- Восстановите обязательные атрибуты для объекта, который был очищен во время удаления.
Заметка
Атрибут objectCategory также можно задать при восстановлении объекта, но не требуется. Если значение объекта не указано, используется по умолчанию для objectCategory объекта objectClass.
После восстановления объекта к нему можно получить доступ так же, как и до его удаления. На этом этапе необходимо восстановить все необязательные атрибуты, которые важны. Все ссылки на объект из других объектов в каталоге также должны быть восстановлены.
В качестве меры безопасности объекты пользователей отключаются при восстановлении. Пользовательские объекты должны быть включены после восстановления необязательных атрибутов, чтобы разрешить использовать объект пользователя.
Дополнительные сведения и пример кода, демонстрирующий восстановление удаленного объекта, см. в функции RestoreDeletedObject ниже.
ВосстановитьУдалённыйОбъект
В следующем примере кода C++ показано, как восстановить удаленный объект.
//***************************************************************************
//
// RestoreDeletedObject()
//
// Restores a deleted object.
//
// pwszDeletedDN - Contains the fully qualified distinguished name of the
// deleted object.
//
// pwszDestContainerDN - Contains the fully qualified distinguished name of
// the folder that the deleted object should be moved to.
//
// Returns S_OK if successful or an HRESULT or LDAP error code otherwise.
//
//***************************************************************************
HRESULT RestoreDeletedObject(LPCWSTR pwszDeletedDN, LPCWSTR pwszDestContainerDN)
{
if((NULL == pwszDeletedDN) || (NULL == pwszDestContainerDN))
{
return E_POINTER;
}
HRESULT hr = E_FAIL;
// Build the new distinguished name.
LPWSTR pwszNewDN = new WCHAR[lstrlenW(pwszDeletedDN) + lstrlenW(pwszDestContainerDN) + 1];
if(pwszNewDN)
{
wcscpy_s(pwszNewDN, pwszDeletedDN);
// Search for the first 0x0A character. This is the delimiter in the deleted object name.
LPWSTR pwszChar;
for(pwszChar = pwszNewDN; *pwszChar; pwszChar = CharNextW(pwszChar))
{
if(('\\' == *pwszChar) && ('0' == *(pwszChar + 1)) && ('A' == *(pwszChar + 2)))
{
break;
}
}
if(0 != *pwszChar)
{
// Truncate the name string at the delimiter.
*pwszChar = 0;
// Add the last known parent DN to complete the DN.
wcscat_s(pwszNewDN, L",");
wcscat_s(pwszNewDN, pwszDestContainerDN);
PLDAP ld;
// Initialize LDAP.
ld = ldap_init(NULL, LDAP_PORT);
if(NULL != ld)
{
ULONG ulRC;
ULONG version = LDAP_VERSION3;
// Set the LDAP version.
ulRC = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, (void*)&version);
if(LDAP_SUCCESS == ulRC)
{
// Establish a connection with the server.
ulRC = ldap_connect(ld, NULL);
if(LDAP_SUCCESS == ulRC)
{
// Bind to the LDAP server.
ulRC = ldap_bind_s(ld, NULL, NULL, LDAP_AUTH_NEGOTIATE);
if(LDAP_SUCCESS == ulRC)
{
// Setup the new values.
LPWSTR rgNewVals[] = {pwszNewDN, NULL};
/*
Remove the isDeleted attribute. This cannot be set
to FALSE or the restore operation will not work.
*/
LDAPModW modIsDeleted = { LDAP_MOD_DELETE, L"isDeleted", NULL };
/*
Set the new DN, in effect, moving the deleted
object to where it resided before the deletion.
*/
LDAPModW modDN = { LDAP_MOD_REPLACE, L"distinguishedName", rgNewVals };
// Initialize the LDAPMod structure.
PLDAPModW ldapMods[] =
{
&modIsDeleted,
&modDN,
NULL
};
/*
Use the LDAP_SERVER_SHOW_DELETED_OID control to
modify deleted objects.
*/
LDAPControlW showDeletedControl;
showDeletedControl.ldctl_oid = LDAP_SERVER_SHOW_DELETED_OID_W;
showDeletedControl.ldctl_value.bv_len = 0;
showDeletedControl.ldctl_value.bv_val = NULL;
showDeletedControl.ldctl_iscritical = TRUE;
// Initialzie the LDAPControl structure
PLDAPControlW ldapControls[] = { &showDeletedControl, NULL };
/*
Modify the specified attributes. This must performed
in one step, which is why the LDAP APIs must be used
to restore a deleted object.
*/
ulRC = ldap_modify_ext_sW(ld, (PWCHAR)pwszDeletedDN, ldapMods, ldapControls, NULL);
if(LDAP_SUCCESS == ulRC)
{
hr = S_OK;
}
else if(LDAP_ALREADY_EXISTS == ulRC)
{
/*
An object already exists with the specified name
in the specified target container. At this point,
a new name must be selected.
*/
}
}
}
}
if(LDAP_SUCCESS != ulRC)
{
hr = ulRC;
OutputDebugString(ldap_err2string(ulRC));
}
// Release the LDAP session.
ldap_unbind(ld);
}
}
else
{
/*
If the end of the string is reached before the delimiter is found, just
end and fail.
*/
hr = E_INVALIDARG;
}
delete pwszNewDN;
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}