//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000. // // File: cadssec.cxx // // Contents: This file contains the support ADsSecurityUtility class // implementation and the support routines it requires. The // default interface for the ADsSecurityClassUtility class // is IADsSecurityUtility. // // History: 10-11-00 AjayR Created. // //---------------------------------------------------------------------------- #include "oleds.hxx" // // Helper functions. // //+--------------------------------------------------------------------------- // Function: GetServerAndResource - Helper routine. // // Synopsis: Splits the string into a serverName piece and rest piece. // This is used for fileshare paths like \\Computer\share to return // \\computer and share. In the case of registry a string like // \\Computer\HKLM\Microsoft will be split into \\Computer and // HKLM\Microsoft. if there is no computer name specified, then // the serverName will be NULL. // // Arguments: pszName - Name to be split. // ppszServer - Return value for server name. // ppszResource - Return value for rest of string. // // Returns: S_OK or any appropriate error code. // // Modifies: ppSD and pdwLength on success. // //---------------------------------------------------------------------------- HRESULT GetServerAndResource( LPWSTR pszName, LPWSTR *ppszServer, LPWSTR *ppszResource ) { HRESULT hr = S_OK; DWORD dwLength = wcslen(pszName); LPWSTR pszTemp = pszName; LPWSTR pszServer = NULL; LPWSTR pszResource = NULL; DWORD dwLen = 0; BOOL fNoServer = FALSE; *ppszServer = NULL; *ppszResource = NULL; // // If we have just 1 \ or no \'s there is no server name. // if ((dwLength < 2) || (pszName[0] != L'\\') || (pszName[1] != L'\\') ) { fNoServer = TRUE; } if (fNoServer) { // // Name is the entire string passed in. // pszResource = AllocADsStr(pszName); if (!pszResource) { BAIL_ON_FAILURE(hr = E_FAIL); } *ppszResource = pszResource; RRETURN(hr); } // // Make sure that the first 2 chars are \\ // if (pszTemp[0] != L'\\' || pszTemp[1] != L'\\' ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } pszTemp += 2; while (pszTemp && *pszTemp != L'\\') { dwLen++; pszTemp++; } if (!pszTemp || !*pszTemp || !dwLen ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } dwLen += 2; // the 2 \\ in the serverName // // Advance past the \ in \\testShare\FileShare. // pszTemp++; if (!pszTemp || !*pszTemp) { BAIL_ON_FAILURE(hr = E_INVALIDARG) } // // If we get here we have valid server and share names. // pszServer = (LPWSTR) AllocADsMem((dwLen+1) * sizeof(WCHAR)); if (!pszServer) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } wcsncpy(pszServer, pszName, dwLen); pszResource = AllocADsStr(pszTemp); if (!pszResource) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } *ppszServer = pszServer; *ppszResource = pszResource; error: if (FAILED(hr)) { if (pszResource) { FreeADsMem(pszResource); } if (pszServer) { FreeADsMem(pszServer); } } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: GetKeyRootAndSubKey - Helper routine. // // Synopsis: Gets the root (such as HKLM) from the registry key path. This // is needed when we open a handle to the key. The rest of the path // constitutes the SubKey name. // // Arguments: pszKeyName - Name of the key we need to open. // ppszSubKey - Return value for the subKey // phKey - Return value for key root to open. // // Returns: S_OK or any appropriate error code. // // Modifies: phKey, NULL on failure and one of // HKEY_USERS, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, // HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT // or HKEY_PERFORMANCE_DATA on success. // //---------------------------------------------------------------------------- HRESULT GetKeyRootAndSubKey( LPWSTR pszKeyName, LPWSTR * ppszSubKey, HKEY * phKey ) { HRESULT hr = S_OK; HKEY hKey = NULL; LPWSTR pszRoot = NULL; LPWSTR pszTemp = pszKeyName; LPWSTR pszSubKey = NULL; DWORD dwLen = 0; *phKey = NULL; *ppszSubKey = NULL; while (pszTemp && *pszTemp && *pszTemp != L'\\') { dwLen++; pszTemp++; } // // If the length is less than 3 something is wrong. // if ((dwLen < 3) || !pszTemp || !*pszTemp ) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); } // // To get the subkey, we need to move past the \. // pszTemp++; if (pszTemp && *pszTemp) { pszSubKey = AllocADsStr(pszTemp); if (!pszSubKey) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } } pszRoot = (LPWSTR) AllocADsMem((dwLen+1) * sizeof(WCHAR)); if (!pszRoot) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } // // Copy over the root so we can use it in the subsequent comparisions. // wcsncpy(pszRoot, pszKeyName, dwLen); if (_wcsicmp( pszRoot, L"HKEY_CLASSES_ROOT") == 0 || _wcsicmp( pszRoot, L"HKCR") == 0 ) { hKey = HKEY_CLASSES_ROOT; } else if (_wcsicmp( pszRoot, L"HKEY_LOCAL_MACHINE") == 0 || _wcsicmp( pszRoot, L"HKLM") == 0 ) { hKey = HKEY_LOCAL_MACHINE; } else if (_wcsicmp(pszRoot, L"HKEY_CURRENT_CONFIG") == 0 || _wcsicmp(pszRoot, L"HKCC") == 0 ) { hKey = HKEY_CURRENT_CONFIG; } else if (_wcsicmp(pszRoot, L"HKEY_CURRENT_USER" ) == 0 || _wcsicmp( pszRoot, L"HKCU") == 0 ) { hKey = HKEY_CURRENT_USER; } else if (_wcsicmp(pszRoot, L"HKEY_USERS") == 0 || _wcsicmp(pszRoot, L"HKU") == 0 ) { hKey = HKEY_USERS; } else if ( _wcsicmp(pszRoot, L"HKEY_PERFORMANCE_DATA") == 0) { hKey = HKEY_PERFORMANCE_DATA; } else { // // Has to be one of the above. // BAIL_ON_FAILURE(hr = E_FAIL); } *phKey = hKey; *ppszSubKey = pszSubKey; error: if (pszRoot) { FreeADsStr(pszRoot); } if (FAILED(hr) && pszSubKey) { FreeADsStr(pszSubKey); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: ConvertRawSDToBinary - Helper routine. // // Synopsis: Converts the binary SD to a VT_UI1 | VT_ARRAY. // // Arguments: pSecurityDescriptor - Binary sd to convert. // dwLength - Length of SD. // pVariant - Return value. // // Returns: S_OK or any appropriate error code. // // Modifies: pVariant to point to IID_IADsSecurityDescriptor on success. // //---------------------------------------------------------------------------- HRESULT ConvertRawSDToBinary( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwLength, VARIANT *pVariant ) { HRESULT hr = S_OK; SAFEARRAY * aList = NULL; SAFEARRAYBOUND aBound; CHAR HUGEP *pArray = NULL; aBound.lLbound = 0; aBound.cElements = dwLength; aList = SafeArrayCreate( VT_UI1, 1, &aBound ); if (!aList) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray ); BAIL_ON_FAILURE(hr); memcpy( pArray, pSecurityDescriptor, aBound.cElements ); SafeArrayUnaccessData( aList ); V_VT(pVariant) = VT_ARRAY | VT_UI1; V_ARRAY(pVariant) = aList; RRETURN(hr); error: if ( aList ) { SafeArrayDestroy( aList ); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: ConvertRawSDToHexString - Helper routine. // // Synopsis: Converts the binary SD to a VT_BSTR in hex string format. // // Arguments: pSecurityDescriptor - Binary sd to convert. // dwLength - Length of SD. // pVariant - Return value for VT_BSTR. // // Returns: S_OK or any appropriate error code. // // Modifies: pVariant to point to IID_IADsSecurityDescriptor on success. // //---------------------------------------------------------------------------- HRESULT ConvertRawSDToHexString( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwLength, VARIANT *pVariant ) { HRESULT hr = S_OK; LPWSTR pszHexStr = NULL; BSTR bstrHexSD = NULL; WCHAR szSmallStr[10]; pszHexStr = (LPWSTR) AllocADsMem((dwLength+1) * 2 * sizeof(WCHAR)); if (!pszHexStr) { BAIL_ON_FAILURE(hr); } for (DWORD dwCtr = 0; dwCtr < dwLength; dwCtr++) { wsprintf( szSmallStr, L"%02x", ((BYTE*)pSecurityDescriptor)[dwCtr] ); wcscat(pszHexStr, szSmallStr); } hr = ADsAllocString(pszHexStr, &bstrHexSD); if (SUCCEEDED(hr)) { pVariant->vt = VT_BSTR; pVariant->bstrVal = bstrHexSD; } error: if (pszHexStr) { FreeADsMem(pszHexStr); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: ConvertHexSDToRawSD - Helper routine. // // Synopsis: Converts the hex string SD to a binary SD. // // Arguments: pVarHexSD - Variant with hex string. // ppSecurityDescriptor - Return value for binary SD // pdwLength - Return value for length of SD. // // Returns: S_OK or any appropriate error code. // // Modifies: ppSecurityDescriptor and pdwLength updated accordingly. // //---------------------------------------------------------------------------- HRESULT ConvertHexSDToRawSD( PVARIANT pVarHexSD, PSECURITY_DESCRIPTOR *ppSecurityDescriptor, DWORD *pdwLength ) { HRESULT hr = S_OK; LPWSTR pszHexSD = V_BSTR(pVarHexSD); DWORD dwLen; LPBYTE lpByte = NULL; *ppSecurityDescriptor = NULL; *pdwLength = 0; if (!pszHexSD || ((dwLen = wcslen(pszHexSD)) == 0) ) { // // NULL SD. // RRETURN(S_OK); } dwLen = wcslen(pszHexSD); // // Length has to be even. // if (((dwLen/2) * 2) != dwLen) { BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE); } dwLen /= 2; if (dwLen) { lpByte = (LPBYTE) AllocADsMem(dwLen); if (!lpByte) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } // // Go through and read one 2 hex chars at a time. // for ( DWORD dwCtr = 0; (dwCtr < dwLen) && (pszHexSD && *pszHexSD); dwCtr++ ) { DWORD dwCount, dwHexVal; dwCount = swscanf(pszHexSD, L"%02x", &dwHexVal); // // The read has to be successful and the data valid. // if (dwCount != 1) { BAIL_ON_FAILURE(hr = E_FAIL); } // // Make sure that the value is in the correct range. // if (dwHexVal & (0xFFFFFF00)) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } lpByte[dwCtr] = (BYTE) dwHexVal; pszHexSD++; if (!pszHexSD) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } pszHexSD++; } // for loop // // The sd translation was succesful. // *ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)(LPVOID) lpByte; *pdwLength = dwLen; } // if the string had any data in it. error: if (FAILED(hr) && lpByte) { FreeADsMem(lpByte); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: ConvertBinarySDToRawSD - Helper routine. // // Synopsis: Converts a VT_UI1 | VT_ARRAY to a binary SD. // // Arguments: pvVarBinSD - The input variant array to convert. // ppSecurityDescriptor - Return value for binary sd. // pdwLength - Return value for length of binary sd. // // Returns: S_OK or any appropriate error code. // // Modifies: ppSecurityDescriptor and pdwLength modified appropriately. // //---------------------------------------------------------------------------- HRESULT ConvertBinarySDToRawSD( PVARIANT pvVarBinSD, PSECURITY_DESCRIPTOR *ppSecurityDescriptor, DWORD *pdwLength ) { HRESULT hr = S_OK; LPVOID lpMem = NULL; long lBoundLower = -1; long lBoundUpper = -1; CHAR HUGEP *pArray = NULL; *ppSecurityDescriptor = NULL; *pdwLength = 0; // // Make sure we have an array and then get length. // if( pvVarBinSD->vt != (VT_ARRAY | VT_UI1)) { RRETURN(hr = E_ADS_CANT_CONVERT_DATATYPE); } hr = SafeArrayGetLBound( V_ARRAY(pvVarBinSD), 1, &lBoundLower ); BAIL_ON_FAILURE(hr); hr = SafeArrayGetUBound( V_ARRAY(pvVarBinSD), 1, &lBoundUpper ); BAIL_ON_FAILURE(hr); if ((lBoundUpper == -1) && (lBoundLower == -1) ) { // // Nothing further to do in this case. // ; } else { long lLength; lLength = (lBoundUpper - lBoundLower) + 1; lpMem = AllocADsMem(lLength); if (!lpMem) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } hr = SafeArrayAccessData( V_ARRAY(pvVarBinSD), (void HUGEP * FAR *) &pArray ); BAIL_ON_FAILURE(hr); memcpy(lpMem, pArray, lLength); SafeArrayUnaccessData(V_ARRAY(pvVarBinSD)); *ppSecurityDescriptor = (PSECURITY_DESCRIPTOR) lpMem; *pdwLength = (DWORD) lLength; } error: if (FAILED(hr) && lpMem) { FreeADsMem(lpMem); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: GetRawSDFromFile - Helper routine. // // Synopsis: Gets the security descriptor from the file in binary format. // // Arguments: pszFileName - Name of file to get sd from. // secInfo - Security mask to use for the operation. // ppSD - Return value for the SD. // pdwLength - Return value for the lenght of the SD. // // Returns: S_OK or any appropriate error code. // // Modifies: ppSD and pdwLength on success. // //---------------------------------------------------------------------------- HRESULT GetRawSDFromFile( LPWSTR pszFileName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR *ppSD, PDWORD pdwLength ) { HRESULT hr = S_OK; DWORD dwLength = 0; PSECURITY_DESCRIPTOR pSD = NULL; *ppSD = NULL; *pdwLength = 0; // // Get the length of the SD. // if (!GetFileSecurity( pszFileName, secInfo, NULL, 0, &dwLength ) && (dwLength == 0) ) { // // There was an error. // BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } if (dwLength == 0) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength); if (!pSD) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } if (!GetFileSecurity( pszFileName, secInfo, pSD, dwLength, &dwLength ) ) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } *pdwLength = dwLength; *ppSD = pSD; error: if (FAILED(hr) && pSD) { FreeADsMem(pSD); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: SetRawSDToFile - Helper routine. // // Synopsis: Sets the binary security descriptor on the file. // // Arguments: pszFileName - Name of file to set sd on. // secInfo - Security mask to use for the operation. // pSD - Value of SD to set. // dwLength - Length of the sd. // // Returns: S_OK or any appropriate error code. // // Modifies: N/A. // //---------------------------------------------------------------------------- HRESULT SetRawSDToFile( LPWSTR pszFileName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR pSD ) { HRESULT hr = S_OK; if (!SetFileSecurity( pszFileName, secInfo, pSD ) ) { RRETURN(HRESULT_FROM_WIN32(GetLastError())); } else { RRETURN(S_OK); } } //+--------------------------------------------------------------------------- // Function: GetRawSDFromFileShare - Helper routine. // // Synopsis: Gets the security descriptor from the fileshare in bin format. // // Arguments: pszFileShareName - Name of fileshare to get sd from. // ppSD - Return value for the SD. // pdwLength - Return value for the lenght of the SD. // // Returns: S_OK or any appropriate error code. // // Modifies: ppSD and pdwLength on success. // //---------------------------------------------------------------------------- HRESULT GetRawSDFromFileShare( LPWSTR pszFileShareName, PSECURITY_DESCRIPTOR *ppSD, PDWORD pdwLength ) { HRESULT hr = S_OK; LPWSTR pszServerName = NULL; LPWSTR pszShareName = NULL; DWORD dwLength = 0; PSECURITY_DESCRIPTOR pSD = NULL; SHARE_INFO_502 * pShareInfo502 = NULL; NET_API_STATUS nasStatus = NERR_Success; *ppSD = NULL; *pdwLength = 0; // // We need to split the name into serverName and shareName // hr = GetServerAndResource( pszFileShareName, &pszServerName, &pszShareName ); BAIL_ON_FAILURE(hr); // // Only 502 level call returns the SD Info. // nasStatus = NetShareGetInfo( pszServerName, pszShareName, 502, (LPBYTE *)&pShareInfo502 ); if (nasStatus != NERR_Success) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus)); } // // If the SD is non NULL process the SD. // if (pShareInfo502->shi502_security_descriptor) { // // Get the length of the SD, it should not be 0. // SetLastError(0); dwLength = GetSecurityDescriptorLength( pShareInfo502->shi502_security_descriptor ); // // The return length should not be zero. // if (dwLength == 0) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength); if (!pSD) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } memcpy(pSD, pShareInfo502->shi502_security_descriptor, dwLength); *ppSD = pSD; *pdwLength = dwLength; } else { // // The SD was NULL the ret values are set correctly // ; } error: if (pszServerName) { FreeADsStr(pszServerName); } if (pszShareName) { FreeADsStr(pszShareName); } if (pShareInfo502) { NetApiBufferFree(pShareInfo502); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: SetRawSDToFileShare - Helper routine. // // Synopsis: Sets the binary SD on the fileshare. // // Arguments: pszFileShare - Name of fileshare to set sd on. // pSD - The SD to set. // // Returns: S_OK or any appropriate error code. // // Modifies: N/A. // //---------------------------------------------------------------------------- HRESULT SetRawSDToFileShare( LPWSTR pszFileShare, PSECURITY_DESCRIPTOR pSD ) { HRESULT hr = S_OK; LPWSTR pszServerName = NULL; LPWSTR pszShareName = NULL; SHARE_INFO_502 * pShareInfo502 = NULL; NET_API_STATUS nasStatus = NERR_Success; PSECURITY_DESCRIPTOR pTempSD = NULL; // // We need to split the name into serverName and shareName // hr = GetServerAndResource( pszFileShare, &pszServerName, &pszShareName ); BAIL_ON_FAILURE(hr); // // Ideally we should use 1501 level but that is only on Win2k. So // we need to read the info, update SD and then set it. // nasStatus = NetShareGetInfo( pszServerName, pszShareName, 502, (LPBYTE *) &pShareInfo502 ); if (nasStatus != NERR_Success) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus)); } // // Store away the SD so we restore before free. // pTempSD = pShareInfo502->shi502_security_descriptor; pShareInfo502->shi502_security_descriptor = pSD; nasStatus = NetShareSetInfo( pszServerName, pszShareName, 502, (LPBYTE) pShareInfo502, NULL ); pShareInfo502->shi502_security_descriptor = pTempSD; if (nasStatus != NERR_Success) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus)); } error: if (pShareInfo502) { NetApiBufferFree(pShareInfo502); } if (pszServerName) { FreeADsStr(pszServerName); } if (pszShareName) { FreeADsStr(pszShareName); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: GetRawSDFromRegistry - Helper routine. // // Synopsis: Gets the security descriptor from the registry in bin format. // // Arguments: pszFileRegKeyName - Name of fileshare to get sd from. // secInfo - Security mask to use for the operation. // ppSD - Return value for the SD. // pdwLength - Return value for the lenght of the SD. // // Returns: S_OK or any appropriate error code. // // Modifies: ppSD and pdwLength on success. // //---------------------------------------------------------------------------- HRESULT GetRawSDFromRegistry( LPWSTR pszFileRegKeyName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR *ppSD, PDWORD pdwLength ) { HRESULT hr; LPWSTR pszServerName = NULL; LPWSTR pszKeyName = NULL; LPWSTR pszSubKey = NULL; DWORD dwLength = 0; DWORD dwErr; PSECURITY_DESCRIPTOR pSD = NULL; HKEY hKey = NULL; HKEY hKeyRoot = NULL; HKEY hKeyMachine = NULL; *ppSD = NULL; *pdwLength = 0; // // We need to split the name into serverName and shareName // hr = GetServerAndResource( pszFileRegKeyName, &pszServerName, &pszKeyName ); BAIL_ON_FAILURE(hr); // // pszKeyName has to have a valid string. We need to process it // to find out which key set we need to open (such as HKLM). // hr = GetKeyRootAndSubKey(pszKeyName, &pszSubKey, &hKeyRoot); BAIL_ON_FAILURE(hr); // // Need to open the hKeyRoot on the appropriate machine. // If the serverName is NULL it will be local machine. // dwErr = RegConnectRegistry( pszServerName, hKeyRoot, &hKeyMachine ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } // // Open the key and try and read the security descriptor // dwErr = RegOpenKeyEx( hKeyMachine, pszSubKey, 0, KEY_READ, &hKey ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } dwErr = RegGetKeySecurity( hKey, secInfo, pSD, &dwLength ); if (dwLength == 0) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength); if (!pSD) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } dwErr = RegGetKeySecurity( hKey, secInfo, pSD, &dwLength ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } *ppSD = pSD; *pdwLength = dwLength; error: if (pszServerName) { FreeADsStr(pszServerName); } if (pszKeyName) { FreeADsStr(pszKeyName); } if (pszSubKey) { FreeADsStr(pszSubKey); } if (hKey) { RegCloseKey(hKey); } if (hKeyMachine) { RegCloseKey(hKeyMachine); } if (FAILED(hr) && pSD) { FreeADsMem(pSD); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: SetRawSDToRegistry - Helper routine. // // Synopsis: Sets the security descriptor to the specified key. // // Arguments: pszFileRegKeyName - Name of fileshare to set sd on. // secInfo - Security mask to use for the operation. // pSD - SD to set on the reg key. // // Returns: S_OK or any appropriate error code. // // Modifies: N/A. // //---------------------------------------------------------------------------- HRESULT SetRawSDToRegistry( LPWSTR pszFileRegKeyName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR pSD ) { HRESULT hr; LPWSTR pszServerName = NULL; LPWSTR pszKeyName = NULL; LPWSTR pszSubKey = NULL; DWORD dwErr; HKEY hKey = NULL; HKEY hKeyRoot = NULL; HKEY hKeyMachine = NULL; // // We need to split the name into serverName and shareName // hr = GetServerAndResource( pszFileRegKeyName, &pszServerName, &pszKeyName ); BAIL_ON_FAILURE(hr); // // pszKeyName has to have a valid string. We need to process it // to find out which key set we need to open (such as HKLM). // hr = GetKeyRootAndSubKey(pszKeyName, &pszSubKey, &hKeyRoot); BAIL_ON_FAILURE(hr); // // Need to open the hKeyRoot on the appropriate machine. // If the serverName is NULL it will be local machine. // dwErr = RegConnectRegistry( pszServerName, hKeyRoot, &hKeyMachine ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } // // Open the key and try and read the security descriptor // dwErr = RegOpenKeyEx( hKeyMachine, pszSubKey, 0, KEY_WRITE, &hKey ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } dwErr = RegSetKeySecurity( hKey, secInfo, pSD ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } error: if (pszServerName) { FreeADsStr(pszServerName); } if (pszKeyName) { FreeADsStr(pszKeyName); } if (pszSubKey) { FreeADsStr(pszSubKey); } if (hKey) { RegCloseKey(hKey); } if (hKeyMachine) { RegCloseKey(hKeyMachine); } RRETURN(hr); } /****************************************************************************/ // // CADsSecurityUtility Class. // /****************************************************************************/ DEFINE_IDispatch_Implementation(CADsSecurityUtility) //+--------------------------------------------------------------------------- // Function: CSecurity::CSecurityDescriptor - Constructor. // // Synopsis: Standard constructor. // // Arguments: N/A. // // Returns: N/A. // // Modifies: N/A. // //---------------------------------------------------------------------------- CADsSecurityUtility::CADsSecurityUtility(): _secInfo( DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION ), _pDispMgr(NULL) { } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::~CADsSecurityUtility - Destructor. // // Synopsis: Standard destructor. // // Arguments: N/A. // // Returns: N/A. // // Modifies: N/A. // //---------------------------------------------------------------------------- CADsSecurityUtility::~CADsSecurityUtility() { // // Only the dispmgr needs to be cleaned up. // delete _pDispMgr; } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::AllocateADsSecurityUtilityObject - // Static helper method. // // Synopsis: Standard static allocation routine. // // Arguments: ppADsSecurityUtil - Return ptr. // // Returns: S_OK on success or appropriate error code on failure. // // Modifies: *ppADsSecurity. // //---------------------------------------------------------------------------- HRESULT CADsSecurityUtility::AllocateADsSecurityUtilityObject( CADsSecurityUtility **ppADsSecurityUtil ) { HRESULT hr = S_OK; CADsSecurityUtility FAR * pADsSecurityUtil = NULL; CDispatchMgr FAR * pDispMgr = NULL; pADsSecurityUtil = new CADsSecurityUtility(); if (!pADsSecurityUtil) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } pDispMgr = new CDispatchMgr; if (!pDispMgr) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } hr = LoadTypeInfoEntry( pDispMgr, LIBID_ADs, IID_IADsSecurityUtility, (IADsSecurityUtility *)pADsSecurityUtil, DISPID_REGULAR ); BAIL_ON_FAILURE(hr); pADsSecurityUtil->_pDispMgr = pDispMgr; *ppADsSecurityUtil = pADsSecurityUtil; RRETURN(hr); error: delete pADsSecurityUtil; delete pDispMgr; RRETURN_EXP_IF_ERR(hr); } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::CreateADsSecurityUtility - Static // helper method. // // Synopsis: Standard static class factor helper method. // // Arguments: riid - IID needed on returned object. // ppvObj - Return ptr. // // Returns: S_OK on success or appropriate error code on failure. // // Modifies: *ppvObj is suitably modified. // //---------------------------------------------------------------------------- HRESULT CADsSecurityUtility::CreateADsSecurityUtility( REFIID riid, void **ppvObj ) { CADsSecurityUtility FAR * pADsSecurityUtil = NULL; HRESULT hr = S_OK; hr = AllocateADsSecurityUtilityObject(&pADsSecurityUtil); BAIL_ON_FAILURE(hr); hr = pADsSecurityUtil->QueryInterface(riid, ppvObj); BAIL_ON_FAILURE(hr); pADsSecurityUtil->Release(); RRETURN(hr); error: delete pADsSecurityUtil; RRETURN_EXP_IF_ERR(hr); } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::QueryInterface --- IUnknown support. // // Synopsis: Standard query interface method. // // Arguments: iid - Interface requested. // ppInterface - Return pointer to interface requested. // // Returns: S_OK on success. Error code otherwise. // // Modifies: *ppInterface to return interface pointer. // //---------------------------------------------------------------------------- STDMETHODIMP CADsSecurityUtility::QueryInterface( REFIID iid, LPVOID *ppInterface ) { HRESULT hr = S_OK; if (!ppInterface) { RRETURN(E_INVALIDARG); } if (IsEqualIID(iid, IID_IUnknown)) { *ppInterface = (IADsSecurityUtility *) this; } else if (IsEqualIID(iid, IID_IDispatch)) { *ppInterface = (IADsSecurityUtility *) this; } else if (IsEqualIID(iid, IID_IADsSecurityUtility)) { *ppInterface = (IADsSecurityUtility *) this; } else if (IsEqualIID(iid, IID_ISupportErrorInfo)) { *ppInterface = (ISupportErrorInfo *) this; } else { RRETURN(E_NOINTERFACE); } AddRef(); RRETURN(S_OK); } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::InterfaceSupportserrorInfo // ISupportErrorInfo support. // // Synopsis: N/A. // // Arguments: riid - Interface being tested.. // // Returns: S_OK or S_FALSE on failure. // // Modifies: N/A. // //---------------------------------------------------------------------------- STDMETHODIMP CADsSecurityUtility::InterfaceSupportsErrorInfo(THIS_ REFIID riid) { if (IsEqualIID(riid, IID_IADsSecurityUtility)) { return S_OK; } else { return S_FALSE; } } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::GetSecurityDescriptor - // IADsSecurityUtility support. // // Synopsis: Gets the security descriptor from the named object. // // Arguments: varPath - Path of object to get SD from. // lPathFormat - Specifies type of object path. // Only ADS_PATH_FILE, ADS_PATH_FILESHARE // and ADS_PATH_REGISTRY are supported. // lOutFormat - Specifies output SD format. // pVariant - Return value for SD. // // Returns: S_OK or any appropriate error code. // // Modifies: pVariant is update appropriately. // //---------------------------------------------------------------------------- STDMETHODIMP CADsSecurityUtility::GetSecurityDescriptor( IN VARIANT varPath, IN long lPathFormat, IN OPTIONAL long lOutFormat, OUT VARIANT *pVariant ) { HRESULT hr = S_OK; PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; DWORD dwLength = 0; VARIANT *pvPath = NULL; // // Make sure the params are correct. // if (!pVariant) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } VariantInit(pVariant); if (lPathFormat < ADS_PATH_FILE || lPathFormat > ADS_PATH_REGISTRY ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } // // Make sure we handle byRef params correctly. // pvPath = &varPath; if (V_VT(pvPath) == (VT_BYREF|VT_VARIANT)) { pvPath = V_VARIANTREF(&varPath); } // // For the path to be valid for now, it has to be a string. // if (pvPath->vt != VT_BSTR) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } if (pvPath->bstrVal == NULL) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } if (lOutFormat < ADS_SD_FORMAT_IID || lOutFormat > ADS_SD_FORMAT_HEXSTRING ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } // // Time to get the raw sd from the source. // switch (lPathFormat) { case ADS_PATH_FILE: hr = GetRawSDFromFile( pvPath->bstrVal, _secInfo, &pSecurityDescriptor, &dwLength ); break; case ADS_PATH_FILESHARE: hr = GetRawSDFromFileShare( pvPath->bstrVal, &pSecurityDescriptor, &dwLength ); break; case ADS_PATH_REGISTRY: hr = GetRawSDFromRegistry( pvPath->bstrVal, _secInfo, &pSecurityDescriptor, &dwLength ); break; default: hr = E_INVALIDARG; break; } // end of case to read sd. BAIL_ON_FAILURE(hr); // // Now convert the sd to the required format. // switch (lOutFormat) { case ADS_SD_FORMAT_IID: hr = BinarySDToSecurityDescriptor( pSecurityDescriptor, pVariant, NULL, NULL, NULL, 0 ); break; case ADS_SD_FORMAT_RAW: hr = ConvertRawSDToBinary( pSecurityDescriptor, dwLength, pVariant ); break; case ADS_SD_FORMAT_HEXSTRING: hr = ConvertRawSDToHexString( pSecurityDescriptor, dwLength, pVariant ); break; default: hr = E_INVALIDARG; } // end of case for output format. error: if (pSecurityDescriptor) { FreeADsMem(pSecurityDescriptor); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::SetSecurityDescriptor - // IADsSecurityUtility support. // // Synopsis: Sets the security descriptor from the named object. // // Arguments: varPath - Path of object to set SD on. // lPathFormat - Format of path. // varData - Variant with SD to set. // lDataFormat - Format of the SD data. // // Returns: S_OK or any appropriate error code. // // Modifies: N/A. // //---------------------------------------------------------------------------- STDMETHODIMP CADsSecurityUtility::SetSecurityDescriptor( IN VARIANT varPath, IN long lPathFormat, IN VARIANT varData, IN long lDataFormat ) { HRESULT hr = E_INVALIDARG; VARIANT *pvPath = NULL; VARIANT *pvData = NULL; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLength = 0; if ((lPathFormat < ADS_PATH_FILE) || (lPathFormat > ADS_PATH_REGISTRY) || (lDataFormat < ADS_SD_FORMAT_IID) || (lDataFormat > ADS_SD_FORMAT_HEXSTRING) ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } // // Make sure we handle byRef params correctly. // pvPath = &varPath; if (V_VT(pvPath) == (VT_BYREF | VT_VARIANT)) { pvPath = V_VARIANTREF(&varPath); } pvData = &varData; if (V_VT(pvData) == (VT_BYREF | VT_VARIANT)) { pvData = V_VARIANTREF(&varData); } // // Find out what format the SD is in and convert to raw binary // format as that is what we need to set. // switch (lDataFormat) { case ADS_SD_FORMAT_IID: hr = SecurityDescriptorToBinarySD( *pvData, &pSD, &dwLength, NULL, NULL, NULL, 0 ); break; case ADS_SD_FORMAT_HEXSTRING: if (V_VT(pvData) == VT_BSTR) { hr = ConvertHexSDToRawSD( pvData, &pSD, &dwLength ); } break; case ADS_SD_FORMAT_RAW: if (V_VT(pvData) == (VT_UI1 | VT_ARRAY)) { hr = ConvertBinarySDToRawSD( pvData, &pSD, &dwLength ); } default: hr = E_INVALIDARG; break; } // end switch type of input data. // // This will catch conversion failures as well as bad params. // BAIL_ON_FAILURE(hr); // // For now the path has to be a string. // if (pvPath->vt != VT_BSTR) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } switch (lPathFormat) { case ADS_PATH_FILE: hr = SetRawSDToFile( pvPath->bstrVal, _secInfo, pSD ); break; case ADS_PATH_FILESHARE: hr = SetRawSDToFileShare( pvPath->bstrVal, pSD ); break; case ADS_PATH_REGISTRY: hr = SetRawSDToRegistry( pvPath->bstrVal, _secInfo, pSD ); break; default: hr = E_INVALIDARG; break; } BAIL_ON_FAILURE(hr); error: if (pSD) { FreeADsMem(pSD); } RRETURN(hr); } //+--------------------------------------------------------------------------- // Function: CADsSecurityUtility::ConvertSecurityDescriptor - // IADsSecurityUtility method. // // Synopsis: Converts the input SD to the appropriate format requested. // // Arguments: varData - Input SD to convert. // lDataFormat - Input SD format. // loutFormat - Format of output SD. // pvResult - Return value. // // Returns: S_OK or any appropriate error code. // // Modifies: pvResult with appropriate value. // //---------------------------------------------------------------------------- STDMETHODIMP CADsSecurityUtility::ConvertSecurityDescriptor( IN VARIANT varData, IN long lDataFormat, IN long lOutFormat, OUT VARIANT *pvResult ) { HRESULT hr; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLenSD; VARIANT *pVarData = &varData; if (!pvResult) { BAIL_ON_FAILURE(hr= E_INVALIDARG); } if (V_VT(pVarData) == (VT_BYREF | VT_VARIANT)) { pVarData = V_VARIANTREF(&varData); } // // We will convert to binary format and then to // the requested format. // switch (lDataFormat) { case ADS_SD_FORMAT_IID: hr = SecurityDescriptorToBinarySD( *pVarData, &pSD, &dwLenSD, NULL, NULL, NULL, 0 ); break; case ADS_SD_FORMAT_RAW : hr = ConvertBinarySDToRawSD( pVarData, &pSD, &dwLenSD ); break; case ADS_SD_FORMAT_HEXSTRING: hr = ConvertHexSDToRawSD( pVarData, &pSD, &dwLenSD ); break; default: hr = E_INVALIDARG; break; } BAIL_ON_FAILURE(hr); // // Convert to the requested format. // switch (lOutFormat) { case ADS_SD_FORMAT_IID: hr = BinarySDToSecurityDescriptor( pSD, pvResult, NULL, NULL, NULL, 0 ); break; case ADS_SD_FORMAT_RAW: hr = ConvertRawSDToBinary( pSD, dwLenSD, pvResult ); break; case ADS_SD_FORMAT_HEXSTRING: hr = ConvertRawSDToHexString( pSD, dwLenSD, pvResult ); break; default: hr = E_INVALIDARG; break; } error: if (pSD) { FreeADsMem(pSD); } RRETURN(hr); } STDMETHODIMP CADsSecurityUtility::put_SecurityMask( long lSecurityMask ) { _secInfo = (SECURITY_INFORMATION) lSecurityMask; RRETURN(S_OK); } STDMETHODIMP CADsSecurityUtility::get_SecurityMask( long *plSecurityMask ) { if (!plSecurityMask) { RRETURN(E_INVALIDARG); } *plSecurityMask = (long) _secInfo; RRETURN(S_OK); }