|
|
//#pragma title( "SDResolve.cpp - SDResolve: A Domain Migration Utility" )
/*
Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved. =============================================================================== Module - sdresolve.cpp System - SDResolve Author - Christy Boles Created - 97/07/11 Description - Routines to iterate through files, shares, and printers when processing security on a machine. Updates - =============================================================================== */
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#include <assert.h>
#include "Common.hpp"
#include "ErrDct.hpp"
#include "UString.hpp"
#include "sd.hpp"
#include "sidcache.hpp"
#include "enumvols.hpp"
#include "SecObj.hpp"
#include "ealen.hpp"
#include "BkupRstr.hpp"
#include "TxtSid.h"
#include "array.h"
// this makes sure the funciton name IteratePathUnderlying is not mangled by C++
extern "C" { #include "sdresolv_stkoflw.h"
}
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
bool enforce; extern TErrorDct err; extern bool silent; extern bool IsMachineName(const LPWSTR name); extern bool IsShareName(const LPWSTR name); extern bool ContainsWildcard( WCHAR const * name);
struct SSeException { SSeException(UINT uCode) : uCode(uCode) { }
UINT uCode; };
void SeTranslator(unsigned int u, EXCEPTION_POINTERS* pepExceptions) { throw SSeException(u); }
#define MAX_BUFFER_LENGTH 10000
#define PRINT_BUFFER_SIZE 2000
//******************************************************************************************************
// Main routine for SDResolve
// Iterates files and directories to be resolved
void IteratePath( WCHAR * path, // in -path to start iterating from
SecurityTranslatorArgs * args, // in -translation settings
TSDResolveStats * stats, // in -stats (to display pathnames & pass to ResolveSD)
TSecurableObject * LC, // in -last container
TSecurableObject * LL, // in -last file
bool haswc // in -indicates whether path contains a wc character
) { _se_translator_function pfnSeTranslatorOld = _set_se_translator((_se_translator_function)SeTranslator);
try { IteratePathUnderlying(path,(void*)args,(void*)stats,(void*)LC,(void*)LL,haswc ? TRUE : FALSE); } catch (SSeException sse) { _set_se_translator(pfnSeTranslatorOld); _com_issue_error(HRESULT_FROM_WIN32(sse.uCode)); } catch (...) { _set_se_translator(pfnSeTranslatorOld); throw; }
_set_se_translator(pfnSeTranslatorOld); }
#define safecopy_wc_array(trg,src) ((src) ? UStrCpy((WCHAR*)trg,src,trg.size()) : *((WCHAR*)trg) = 0)
void IteratePathUnderlying( WCHAR * path, // in -path to start iterating from
void * argsC, // in -translation settings
void * statsC, // in -stats (to display pathnames & pass to ResolveSD)
void * LCC, // in -last container
void * LLC, // in -last file
BOOL haswc // in -indicates whether path contains a wc character
) { SecurityTranslatorArgs *args = (SecurityTranslatorArgs *) argsC; TSDResolveStats *stats = (TSDResolveStats *) statsC; TSecurableObject *LC = (TSecurableObject*) LCC; TSecurableObject *LL = (TSecurableObject*) LLC; HANDLE hFind; WIN32_FIND_DATA findEntry; BOOL b; TFileSD * currSD; bool changeLastCont; bool changeLastLeaf; WCHAR * appendPath = NULL; c_array<WCHAR> safepath(LEN_Path + 10); TFileSD * LastContain = (TFileSD*) LC; TFileSD * LastLeaf = (TFileSD*) LL; c_array<WCHAR> localPath(LEN_Path); // this is the first (for this) dir
safecopy_wc_array(safepath,path); safecopy_wc_array(localPath,path); // Check to see if path is longer than MAX_PATH
// if so, add \\?\ to the beginning of it to
// turn off path parsing
if ( UStrLen(path) >= MAX_PATH && path[2] != L'?' ) { WCHAR temp[LEN_Path];
if ( (path[0] == L'\\') && (path[1] == L'\\') ) // UNC name
{ UStrCpy(temp,L"\\\\?\\UNC\\"); } else { UStrCpy(temp,L"\\\\?\\"); } UStrCpy(temp + UStrLen(temp),path); safecopy_wc_array(localPath,temp); } appendPath = (WCHAR*)localPath + UStrLen((WCHAR*)localPath);
if ( *(appendPath-1) == L'\\' ) // if there's already a backslash on the end of the path, don't add another one
appendPath--; if ( ! haswc ) UStrCpy(appendPath, "\\*.*"); if ( args->LogVerbose() ) err.DbgMsgWrite(0,L"Starting IteratePath: %ls",path); for ( b = ((hFind = FindFirstFile((WCHAR*)localPath, &findEntry)) != INVALID_HANDLE_VALUE) ; b ; b = FindNextFile(hFind, &findEntry) ) { if ( ! haswc) appendPath[1] = '\0'; // restore path -- remove \*.* append
if ( ! UStrCmp((LPWSTR)findEntry.cFileName,L".") || ! UStrCmp((LPWSTR)findEntry.cFileName,L"..") ) continue; // ignore names '.' and '..'
if ( ! haswc ) UStrCpy(appendPath+1, findEntry.cFileName); else { for ( WCHAR * ch = appendPath-1; ch >= path && *ch != L'\\' ; ch-- ) ; UStrCpy(ch+1,findEntry.cFileName); } if ( ((TAccountCache *)args->Cache())->IsCancelled() ) { break; } currSD = new TFileSD(localPath, (findEntry.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0); stats->DisplayPath(localPath); if ( !currSD || !currSD->HasSecurity() ) { //err.MsgWrite(0,"Error: Couldn't get the SD");
} else { if ( findEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) // if dir
{ // resolve this container & iterate next container
changeLastCont = currSD->ResolveSD(args,stats,directory,LastContain); if ( changeLastCont ) { if ( LastContain && LastContain != LC ) { delete LastContain; } LastContain = currSD; } else { delete currSD; } try { BOOL bLogError; UINT status = IteratePathUnderlyingNoObjUnwinding(localPath,(void*)args,(void*)stats,(void*)LastContain,(void*)LastLeaf,FALSE,&bLogError); if (bLogError) err.SysMsgWrite(ErrE, HRESULT_FROM_WIN32(STATUS_STACK_OVERFLOW), DCT_MSG_CANNOT_TRANSLATE_DIRECTORY_SD, (WCHAR*)localPath, HRESULT_FROM_WIN32(STATUS_STACK_OVERFLOW)); if (status != 0) _com_issue_error(HRESULT_FROM_WIN32(status)); } catch (SSeException sse) { err.SysMsgWrite(ErrE, HRESULT_FROM_WIN32(sse.uCode), DCT_MSG_CANNOT_TRANSLATE_DIRECTORY_SD, (WCHAR*)localPath, HRESULT_FROM_WIN32(sse.uCode)); _com_issue_error(HRESULT_FROM_WIN32(sse.uCode)); } } else { // iterate this file with last
changeLastLeaf = currSD->ResolveSD(args,stats,file,LastLeaf); if ( changeLastLeaf ) { if ( LastLeaf && LastLeaf != LL ) { delete LastLeaf; } LastLeaf = currSD; } else { delete currSD; } } } } if ( LastContain && LastContain != LC ) { delete LastContain; } if ( LastLeaf && LastLeaf != LL ) { delete LastLeaf; } appendPath[0] = '\0'; DWORD rc = GetLastError();
if ( args->LogVerbose() ) err.DbgMsgWrite(0,L"Closing IteratePath %S",(WCHAR*)safepath); FindClose(hFind); switch ( rc ) { case ERROR_NO_MORE_FILES: case 0: break; default: err.SysMsgWrite(ErrE, rc, DCT_MSG_FIND_FILE_FAILED_SD, path, rc); } }
DWORD ResolvePrinter( PRINTER_INFO_4 * pPrinter, // in - printer information
SecurityTranslatorArgs * args, // in - translation settings
TSDResolveStats * stats // in - stats
) { DWORD rc = 0; // DWORD needed = 0;
TPrintSD sd(pPrinter->pPrinterName);
if ( sd.GetSecurity() ) { sd.ResolveSD(args,stats,printer,NULL); }
return rc; }
int ServerResolvePrinters( WCHAR const * server, // in -translate the printers on this server
SecurityTranslatorArgs * args, // in -translation settings
TSDResolveStats * stats // in -stats
) { DWORD rc = 0; PRINTER_INFO_4 * pInfo = NULL; BYTE * buffer = new BYTE[PRINT_BUFFER_SIZE]; DWORD cbNeeded = PRINT_BUFFER_SIZE; DWORD nReturned = 0;
if (!buffer) { rc = ERROR_NOT_ENOUGH_MEMORY; }
if (!rc && !EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,buffer,PRINT_BUFFER_SIZE,&cbNeeded,&nReturned) ) { rc = GetLastError(); if ( rc == ERROR_INSUFFICIENT_BUFFER ) { // try again with a bigger buffer size
delete [] buffer; buffer = NULL;
buffer = new BYTE[cbNeeded]; if (!buffer) { rc = ERROR_NOT_ENOUGH_MEMORY; } else if (! EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,buffer,cbNeeded,&cbNeeded,&nReturned) ) { rc = GetLastError(); } else rc = ERROR_SUCCESS; } }
if ( ! rc ) { pInfo = (PRINTER_INFO_4 *)buffer; for ( DWORD i = 0 ; i < nReturned && !args->Cache()->IsCancelled(); i++ ) { ResolvePrinter(&(pInfo[i]),args,stats); } } else { err.SysMsgWrite(ErrE,rc,DCT_MSG_ERROR_ENUMERATING_LOCAL_PRINTERS_D,rc); }
if (args->Cache()->IsCancelled()) err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_PRINTERS);
delete [] buffer;
return rc; } int ServerResolveShares( WCHAR const * server, // in -enumerate and translate the shares on this server
SecurityTranslatorArgs * args, // in -translation settings
TSDResolveStats * stats // in -stats (to display pathnames & pass to ResolveSD)
) { DWORD rc = 0; DWORD numRead = 0; DWORD totalEntries = 0; DWORD resumeHandle = 0; SHARE_INFO_0 * bufPtr = NULL; WCHAR serverName[LEN_Computer]; WCHAR fullPath[LEN_Path]; WCHAR * pServerName = serverName; DWORD ttlRead = 0;
if (!args->Cache()->IsCancelled()) { if ( server ) { safecopy(serverName,server); } else { pServerName = NULL;
}
do { if (args->Cache()->IsCancelled()) break; rc = NetShareEnum(pServerName,0,(LPBYTE *)&bufPtr,MAX_BUFFER_LENGTH,&numRead,&totalEntries,&resumeHandle); if ( ! rc || rc == ERROR_MORE_DATA ) { for ( UINT i = 0 ; i < numRead ; i++ ) { // Process the SD
if ( pServerName ) { swprintf(fullPath,L"%s\\%s",pServerName,bufPtr[i].shi0_netname); } else { swprintf(fullPath,L"%s",bufPtr[i].shi0_netname); }
TShareSD tSD(fullPath);
if ( tSD.HasSecurity() ) { stats->DisplayPath(fullPath,TRUE); tSD.ResolveSD(args,stats,share,NULL); } } ttlRead += numRead; resumeHandle = ttlRead; NetApiBufferFree(bufPtr); } } while ( rc == ERROR_MORE_DATA && numRead < totalEntries);
if ( rc && rc != ERROR_MORE_DATA ) err.SysMsgWrite(ErrE,rc,DCT_MSG_SHARE_ENUM_FAILED_SD,server,rc); }
if (args->Cache()->IsCancelled()) err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_SHARES); return rc; }
void ResolveFilePath( SecurityTranslatorArgs * args, // in - translation options
TSDResolveStats * Stats, // in - class to display stats
WCHAR * path, // in - path name
bool validAlone, // in - whether this object exists (false for share names and volume roots)
bool containsWC, // in - true if path contains wildcard
bool iscontainer // in - whether the starting path is a container
) { TFileSD * pSD; if ( args->LogVerbose() ) err.MsgWrite(0,DCT_MSG_PROCESSING_S,path); Stats->DisplayPath(path); if ( validAlone && ! containsWC ) { pSD = new TFileSD(path); if (!pSD) return; if ( pSD->HasSecurity() ) pSD->ResolveSD(args, Stats, iscontainer?directory:file, NULL); delete pSD; } if ( iscontainer || containsWC ) { IteratePath(path, args, Stats, NULL, NULL, containsWC); }
if (args->Cache()->IsCancelled()) err.MsgWrite(0, DCT_MSG_OPERATION_ABORTED_FILES); }
void WriteOptions(SecurityTranslatorArgs * args) { //* WCHAR cmd[1000] = L"SecurityTranslation ";;
WCHAR cmd[1000]; WCHAR arg[300];
UStrCpy(cmd, GET_STRING(IDS_STOptions_Start)); if ( args->NoChange() ) { //* UStrCpy(cmd +UStrLen(cmd), L"WriteChanges:No ");
UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_WriteChng)); } if ( args->TranslateFiles() ) { //* UStrCpy(cmd +UStrLen(cmd), L"Files:Yes ");
UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_Files)); } if ( args->TranslateShares() ) { //* UStrCpy(cmd + UStrLen(cmd),L"Shares:Yes ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Shares)); } if ( args->TranslateLocalGroups() ) { //* UStrCpy(cmd + UStrLen(cmd),L"LGroups:Yes ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_LocalGroup)); } if ( args->TranslateUserRights() ) { // UStrCpy(cmd + UStrLen(cmd),L"UserRights:Yes ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_URights)); } if ( args->TranslatePrinters() ) { // UStrCpy(cmd + UStrLen(cmd),L"UserRights:Yes ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Printers)); } if ( args->TranslateUserProfiles() ) { //* UStrCpy(cmd + UStrLen(cmd),L"Profiles:Yes ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Profiles)); } if ( args->TranslateRecycler() ) { //* UStrCpy(cmd + UStrLen(cmd),L"RecycleBin:Yes ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_RBin)); } if ( *args->LogFile() ) { //* wsprintf(arg,L"LogFile:%S ",args->LogFile());
wsprintf(arg,GET_STRING(IDS_STOptions_LogName),args->LogFile()); UStrCpy(cmd +UStrLen(cmd), arg); } if ( args->TranslationMode() == ADD_SECURITY ) { //* UStrCpy(cmd +UStrLen(cmd), L"TranslationMode:Add ");
UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_AddMode)); } else if ( args->TranslationMode() == REMOVE_SECURITY ) { //* UStrCpy(cmd +UStrLen(cmd), L"TranslationMode:Remove ");
UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_RemoveMode)); } else { //* UStrCpy(cmd + UStrLen(cmd),L"TranslationMode:Replace ");
UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_ReplaceMode)); } wsprintf(arg,L"%s %s ",args->Source(), args->Target()); UStrCpy(cmd +UStrLen(cmd), arg);
err.MsgWrite(0,DCT_MSG_GENERIC_S,&*cmd); }
void TranslateRecycler( SecurityTranslatorArgs * args, // in - translation options
TSDResolveStats * Stats, // in - class to display stats
WCHAR * path // in - drive name
) { err.MsgWrite(0,DCT_MSG_PROCESSING_RECYCLER_S,path); WCHAR folder[LEN_Path]; WCHAR const * recycler = L"RECYCLER"; WCHAR strSid[200]; WCHAR srcPath[LEN_Path]; WCHAR tgtPath[LEN_Path]; DWORD lenStrSid = DIM(strSid); _wfinddata_t fData; // long hRecycler;
LONG_PTR hRecycler; PSID pSidSrc = NULL, pSidTgt = NULL; TRidNode * pNode; DWORD rc = 0; BOOL bUseMapFile = args->UsingMapFile();
swprintf(folder,L"%s\\%s\\*",path,recycler);
long mode = args->TranslationMode();
// Windows 2000 checks the SD for the recycle bin when the recycle bin is opened. If the SD does not match the
// default template (permissions for user, admin, and system), Windows displays a message that the recycle bin is corrupt.
// This change may also be in NT 4 SP 7. To avoid causing this corrupt recycle bin message, we will always translate the
// recycle bins in replace mode. We will not change if we are doing a remove.
if (args->TranslationMode() != REMOVE_SECURITY) args->SetTranslationMode(REPLACE_SECURITY); // use _wfind to look for hidden files in the folder
for ( hRecycler = _wfindfirst(folder,&fData) ; hRecycler != -1 && ( rc == 0 ); rc = (DWORD)_wfindnext(hRecycler,&fData) ) { pSidSrc = SidFromString(fData.name); if ( pSidSrc ) { err.MsgWrite(0,DCT_MSG_PROCESSING_RECYCLE_FOLDER_S,fData.name); if (!bUseMapFile) pNode = (TRidNode*)args->Cache()->Lookup(pSidSrc); else pNode = (TRidNode*)args->Cache()->LookupWODomain(pSidSrc); if ( pNode && pNode != (TRidNode*)-1 ) { if (!bUseMapFile) pSidTgt = args->Cache()->GetTgtSid(pNode); else pSidTgt = args->Cache()->GetTgtSidWODomain(pNode); // get the target directory name
GetTextualSid(pSidTgt,strSid,&lenStrSid); if ( args->LogVerbose() ) err.DbgMsgWrite(0,L"Target sid is: %ls",strSid); if ( ! args->NoChange() && args->TranslationMode() != REMOVE_SECURITY ) { // rename the directory
swprintf(srcPath,L"%s\\%s\\%s",path,recycler,fData.name); swprintf(tgtPath,L"%s\\%s\\%s",path,recycler,strSid); if ( ! MoveFile(srcPath,tgtPath) ) { rc = GetLastError(); if ( (rc == ERROR_ALREADY_EXISTS) && (args->TranslationMode() == REPLACE_SECURITY) ) { // the target recycle bin already exists
// attempt to rename it with a suffix, so we can rename the new bin to the SID
WCHAR tmpPath[LEN_Path]; long ndx = 0;
do { swprintf(tmpPath,L"%ls%ls%ld",tgtPath,GET_STRING(IDS_RenamedRecyclerSuffix),ndx); if (! MoveFile(tgtPath,tmpPath) ) { rc = GetLastError(); ndx++; } else { rc = 0; err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,tgtPath,tmpPath); } } while ( rc == ERROR_ALREADY_EXISTS ); if ( ! rc ) { // we have moved the pre-existing target recycler out of the way
// now retry the rename
if (! MoveFile(srcPath,tgtPath) ) { err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc); } else { err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,srcPath,tgtPath); // run security translation on the new folder
ResolveFilePath(args,Stats,tgtPath,TRUE,FALSE,TRUE); } } else { err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc); } } else { err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc); } } else { err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,srcPath,tgtPath); // run security translation on the new folder
ResolveFilePath(args,Stats,tgtPath,TRUE,FALSE,TRUE); }
} free(pSidTgt); } FreeSid(pSidSrc); } } // set the translation mode back to its original value
args->SetTranslationMode(mode); }
// if the specified node is a normal share, this attempts to convert it to a path
// using the administrative shares
void BuildAdminPathForShare( TPathNode * tnode, WCHAR * adminShare ) { // if all else fails, return the same name as specified in the node
UStrCpy(adminShare,tnode->GetPathName());
SHARE_INFO_502 * shInfo = NULL; DWORD rc = 0; WCHAR shareName[LEN_Path]; WCHAR * slash = NULL;
UStrCpy(shareName,tnode->GetPathName() + UStrLen(tnode->GetServerName()) +1); slash = wcschr(shareName,L'\\'); if ( slash ) *slash = 0;
rc = NetShareGetInfo(tnode->GetServerName(),shareName,502,(LPBYTE*)&shInfo); if ( ! rc ) { if ( *shInfo->shi502_path ) { // build the administrative path name for the share
UStrCpy(adminShare,tnode->GetServerName()); UStrCpy(adminShare + UStrLen(adminShare),L"\\"); UStrCpy(adminShare + UStrLen(adminShare),shInfo->shi502_path); WCHAR * colon = wcschr(adminShare,L':'); if ( colon ) { *colon = L'$'; UStrCpy(adminShare + UStrLen(adminShare),L"\\"); UStrCpy(adminShare + UStrLen(adminShare),slash+1);
} else { // something went wrong -- revert to the given path
UStrCpy(adminShare,tnode->GetPathName()); }
} NetApiBufferFree(shInfo); } }
// Main routine for resolving file and directory SD's.
int ResolveAll( SecurityTranslatorArgs * args, // in- translation settings
TSDResolveStats * Stats // in- counts of examined, changed objects, etc.
) { WCHAR * warg; WCHAR * machine; UINT errmode; int retcode = 0; TPathNode * tnode; errmode = SetErrorMode(SEM_FAILCRITICALERRORS); if ( ! retcode ) { WriteOptions(args); Stats->InitDisplay(args->NoChange());
err.MsgWrite(0,DCT_MSG_FST_STARTING); // Process Files and Directories
if (! args->IsLocalSystem() ) { TNodeListEnum tenum; for (tnode = (TPathNode *)tenum.OpenFirst((TNodeList *)args->PathList()) ; tnode && !args->Cache()->IsCancelled(); tnode = (TPathNode *)tenum.Next() ) { DWORD rc; BOOL needToGetBR = FALSE; // BOOL abort = FALSE;
// BOOL firstTime = TRUE;
warg = tnode->GetPathName(); machine = GetMachineName(warg); needToGetBR = ( args->TranslateFiles() );
if ( *tnode->GetServerName() && ! args->IsLocalSystem() ) { warg = tnode->GetPathName(); err.MsgWrite(0,DCT_MSG_PROCESSING_S,warg); if ( args->TranslateFiles() && !args->Cache()->IsCancelled()) { if ( needToGetBR ) { //get needed privileges and keep them until the agent removes itself
GetBkupRstrPriv(tnode->GetServerName()); } if ( IsMachineName(warg) ) { // need to process each drive on this machine
TVolumeEnum vEnum; rc = vEnum.Open(warg,VERIFY_PERSISTENT_ACLS,args->LogVerbose()); if ( rc ) { err.SysMsgWrite(ErrE,rc,DCT_MSG_ERROR_ACCESSING_DRIVES_SD,warg,rc); } else { while ( (warg = vEnum.Next()) && !args->Cache()->IsCancelled()) {
ResolveFilePath(args, Stats, warg, false, // not valid alone
false, // no wildcard
true ); // container
} warg = machine; } vEnum.Close(); } else { WCHAR adminShare[LEN_Path]; // Verify that the volume is NTFS
rc = tnode->VerifyPersistentAcls(); switch ( rc ) { case ERROR_SUCCESS: // Process the path
// if it's a share name, process the root of the share
if( IsShareName(tnode->GetPathName()) ) { WCHAR sharePath[LEN_Path]; swprintf(sharePath,L"%s\\.",tnode->GetPathName()); TFileSD sd(sharePath); if ( sd.HasSecurity() ) { sd.ResolveSD(args, Stats, directory, NULL); } } // if this is a normal share, convert it to an administrative share
// path, so that we can take advantage of backup/restore privileges
BuildAdminPathForShare(tnode,adminShare); ResolveFilePath(args, Stats, adminShare, !IsShareName(tnode->GetPathName()), ContainsWildcard(tnode->GetPathName()), tnode->IsContainer() || IsShareName(tnode->GetPathName())); break; case ERROR_NO_SECURITY_ON_OBJECT: err.MsgWrite(ErrW,DCT_MSG_SKIPPING_FAT_VOLUME_S,warg); break; default: err.SysMsgWrite(ErrE,rc,DCT_MSG_SKIPPING_PATH_SD,warg,rc ); break; } } } // Process the shares for this machine
if ( args->TranslateShares() && !args->Cache()->IsCancelled()) { if ( IsMachineName(warg) ) { err.MsgWrite(0,DCT_MSG_PROCESSING_SHARES_S,tnode->GetServerName()); ServerResolveShares(tnode->GetServerName(),args,Stats); } else if ( IsShareName(warg) ) { TShareSD sd(warg); if ( sd.HasSecurity() ) { if ( args->LogVerbose() ) { err.MsgWrite(0,DCT_MSG_PROCESSING_SHARE_S,warg); } sd.ResolveSD(args, Stats, share, NULL); } } } } else { // this is a local path
// Verify that the volume is NTFS
DWORD rc2; //get needed privileges and keep them until the agent removes itself
GetBkupRstrPriv((WCHAR*)NULL); rc2 = tnode->VerifyPersistentAcls(); switch ( rc2 ) { case ERROR_SUCCESS: // Process the path
if ( args->TranslateFiles() ) { ResolveFilePath(args, Stats, tnode->GetPathName(), true, // isValidAlone
ContainsWildcard(tnode->GetPathName()), tnode->IsContainer() ); } break; case ERROR_NO_SECURITY_ON_OBJECT: err.MsgWrite(ErrW,DCT_MSG_SKIPPING_FAT_VOLUME_S,warg); break; default: err.SysMsgWrite(ErrE,rc2,DCT_MSG_SKIPPING_PATH_SD,warg,rc2 ); break; } } if ( machine ) { delete machine; machine = NULL; } } tenum.Close(); } else { // Translate the entire machine
err.MsgWrite(0,DCT_MSG_LOCAL_TRANSLATION); if ((args->TranslateFiles() || args->TranslateRecycler()) && !args->Cache()->IsCancelled() ) { //get needed privileges and keep them until the agent removes itself
GetBkupRstrPriv((WCHAR const*)NULL); // need to process each drive on this machine
TVolumeEnum vEnum;
vEnum.SetLocalMode(TRUE);
DWORD rc2 = vEnum.Open(NULL,VERIFY_PERSISTENT_ACLS,args->LogVerbose()); if ( rc2 ) { err.SysMsgWrite(ErrE,rc2,DCT_MSG_ERROR_ACCESSING_LOCAL_DRIVES_D,rc2); } else { while ( (warg = vEnum.Next()) && !args->Cache()->IsCancelled()) { err.MsgWrite(0,DCT_MSG_PROCESSING_S,warg); if ( args->TranslateFiles() ) { ResolveFilePath(args, Stats, warg, false, // not valid alone
false, // no wildcard
true ); // container
} if ( args->TranslateRecycler() ) { TranslateRecycler(args,Stats,warg); } } warg = NULL; } vEnum.Close(); } if ( args->TranslateShares() && !args->Cache()->IsCancelled()) { err.MsgWrite(0,DCT_MSG_PROCESSING_LOCAL_SHARES,NULL); ServerResolveShares(NULL,args,Stats); } if ( args->TranslatePrinters() && !args->Cache()->IsCancelled()) { // for printer security translation, we also need to turn on the privilege
if (GetBkupRstrPriv(NULL, TRUE) == FALSE) err.MsgWrite(ErrE, DCT_MSG_UNABLE_TO_OBTAIN_BACKUP_RESTORE_PRIVILEGES, GetLastError()); err.MsgWrite(0,DCT_MSG_PROCESSING_LOCAL_PRINTERS,NULL); ServerResolvePrinters(NULL,args,Stats); // turn off the privilege
if (GetBkupRstrPriv(NULL, FALSE) == FALSE) err.MsgWrite(ErrW, DCT_MSG_UNABLE_TO_RELEASE_BACKUP_RESTORE_PRIVILEGES, GetLastError()); } } Stats->DisplayPath(L""); } // end if ( ! retcode)
SetErrorMode(errmode); return retcode; }
|