Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

550 lines
15 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. bitssrvcfgimp.h
  5. Abstract:
  6. Implementation header to define server configuration information.
  7. --*/
  8. HRESULT PropertyIDManager::LoadPropertyInfo( const WCHAR * MachineName )
  9. {
  10. bool ComLoaded;
  11. HRESULT Hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  12. if ( RPC_E_CHANGED_MODE == Hr )
  13. ComLoaded = false;
  14. else if ( FAILED(Hr) )
  15. return Hr;
  16. else
  17. ComLoaded = true;
  18. BSTR MetaIDBSTR = NULL;
  19. BSTR UserTypeBSTR = NULL;
  20. WCHAR *PathBuffer = NULL;
  21. SIZE_T PathBufferSize = 0;
  22. MetaIDBSTR = SysAllocString( L"MetaId" );
  23. UserTypeBSTR = SysAllocString( L"UserType" );
  24. if ( !MetaIDBSTR || !UserTypeBSTR)
  25. {
  26. Hr = E_OUTOFMEMORY;
  27. goto exit;
  28. }
  29. PathBuffer = (WCHAR*)HeapAlloc( GetProcessHeap(), 0, 1024 );
  30. if ( !PathBuffer )
  31. {
  32. Hr = E_OUTOFMEMORY;
  33. goto exit;
  34. }
  35. PathBufferSize = 1024;
  36. for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
  37. {
  38. WCHAR SchemaPrefix[] = L"IIS://";
  39. WCHAR SchemaPath[] = L"/Schema/";
  40. SIZE_T SchemaPrefixSize = ( sizeof( SchemaPrefix ) / sizeof( WCHAR ) ) - 1;
  41. SIZE_T SchemaPathSize = ( sizeof( SchemaPath ) / sizeof( WCHAR ) ) - 1;
  42. SIZE_T MachineNameSize = wcslen( MachineName );
  43. SIZE_T PropertyNameSize = wcslen( g_Properties[i].PropertyName );
  44. SIZE_T PathSize = SchemaPrefixSize + SchemaPathSize +
  45. MachineNameSize + PropertyNameSize + 1;
  46. if ( PathBufferSize < ( PathSize * sizeof( WCHAR ) ) )
  47. {
  48. WCHAR *NewBuffer =
  49. (WCHAR*)HeapReAlloc(
  50. GetProcessHeap(),
  51. 0,
  52. PathBuffer,
  53. PathSize * sizeof( WCHAR ) );
  54. if ( !NewBuffer )
  55. {
  56. Hr = E_OUTOFMEMORY;
  57. goto exit;
  58. }
  59. PathBuffer = NewBuffer;
  60. PathBufferSize = PathSize * sizeof( WCHAR );
  61. }
  62. // build schema path
  63. WCHAR *ObjectPath = PathBuffer;
  64. {
  65. WCHAR *TempPointer = ObjectPath;
  66. memcpy( TempPointer, SchemaPrefix, SchemaPrefixSize * sizeof( WCHAR ) );
  67. TempPointer += SchemaPrefixSize;
  68. memcpy( TempPointer, MachineName, MachineNameSize * sizeof( WCHAR ) );
  69. TempPointer += MachineNameSize;
  70. memcpy( TempPointer, SchemaPath, SchemaPathSize * sizeof( WCHAR ) );
  71. TempPointer += SchemaPathSize;
  72. memcpy( TempPointer, g_Properties[i].PropertyName, ( PropertyNameSize + 1 ) * sizeof( WCHAR ) );
  73. }
  74. // Open the object
  75. IADs *MbObject = NULL;
  76. Hr = ADsGetObject(
  77. ObjectPath,
  78. __uuidof( *MbObject ),
  79. reinterpret_cast<void**>( &MbObject ) );
  80. if ( FAILED( Hr ) )
  81. {
  82. #if defined( ALLOW_OVERWRITES )
  83. // workaround for IIS issue. IIS isn't handling schema extension property. Dream up a ID.
  84. if ( E_ADS_UNKNOWN_OBJECT == Hr &&
  85. MD_BITS_ALLOW_OVERWRITES == i )
  86. {
  87. m_PropertyIDs[i] = m_PropertyIDs[ i - 1] + 1;
  88. m_PropertyUserTypes[i] = m_PropertyUserTypes[ i - 1 ];
  89. continue;
  90. }
  91. else
  92. #endif
  93. goto exit;
  94. }
  95. VARIANT var;
  96. VariantInit( &var );
  97. Hr = MbObject->Get( MetaIDBSTR, &var );
  98. if ( FAILED(Hr ) )
  99. {
  100. MbObject->Release();
  101. goto exit;
  102. }
  103. Hr = VariantChangeType( &var, &var, 0, VT_UI4 );
  104. if ( FAILED(Hr ) )
  105. {
  106. MbObject->Release();
  107. VariantClear( &var );
  108. goto exit;
  109. }
  110. m_PropertyIDs[i] = var.ulVal;
  111. VariantClear( &var );
  112. Hr = MbObject->Get( UserTypeBSTR, &var );
  113. if ( FAILED( Hr ) )
  114. {
  115. MbObject->Release();
  116. goto exit;
  117. }
  118. Hr = VariantChangeType( &var, &var, 0, VT_UI4 );
  119. if ( FAILED( Hr ) )
  120. {
  121. MbObject->Release();
  122. VariantClear( &var );
  123. goto exit;
  124. }
  125. m_PropertyUserTypes[i] = var.ulVal;
  126. VariantClear( &var );
  127. MbObject->Release();
  128. }
  129. Hr = S_OK;
  130. exit:
  131. SysFreeString( MetaIDBSTR );
  132. SysFreeString( UserTypeBSTR );
  133. if ( ComLoaded )
  134. CoUninitialize();
  135. if ( PathBuffer )
  136. {
  137. HeapFree( GetProcessHeap(), 0, PathBuffer );
  138. PathBuffer = 0;
  139. PathBufferSize = 0;
  140. }
  141. return Hr;
  142. }
  143. // ================================================================================================
  144. // Auxiliary functions that access the IIS Metabase
  145. // ================================================================================================
  146. LPWSTR
  147. CSimplePropertyReader::ConvertObjectPathToADSI(
  148. LPCWSTR szObjectPath )
  149. {
  150. WCHAR *szReturnPath = NULL;
  151. SIZE_T ReturnPathSize = 0;
  152. if ( _wcsnicmp( L"IIS://", szObjectPath, wcslen( L"IIS://") ) == 0 )
  153. {
  154. // already have an adsi path
  155. ReturnPathSize = wcslen( szObjectPath ) + 1;
  156. szReturnPath = new WCHAR[ ReturnPathSize ];
  157. THROW_OUTOFMEMORY_IFNULL( szReturnPath );
  158. memcpy( szReturnPath, szObjectPath, ReturnPathSize * sizeof( WCHAR ) );
  159. }
  160. else if ( _wcsnicmp( L"/LM/", szObjectPath, wcslen( L"/LM/" ) ) == 0 )
  161. {
  162. //metabase path to local machine
  163. ReturnPathSize = wcslen( szObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1;
  164. szReturnPath = new WCHAR[ ReturnPathSize ];
  165. THROW_OUTOFMEMORY_IFNULL( szReturnPath );
  166. StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS://LocalHost/" );
  167. StringCchCatW( szReturnPath, ReturnPathSize, szObjectPath + wcslen( L"/LM/" ) );
  168. }
  169. else if ( _wcsnicmp( L"LM/", szObjectPath, wcslen( L"LM/" ) ) == 0 )
  170. {
  171. //metabase path to local machine
  172. ReturnPathSize = wcslen( szObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1;
  173. szReturnPath = new WCHAR[ ReturnPathSize ];
  174. THROW_OUTOFMEMORY_IFNULL( szReturnPath );
  175. StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS://LocalHost/" );
  176. StringCchCatW( szReturnPath, ReturnPathSize, szObjectPath + wcslen( L"LM/" ) );
  177. }
  178. else
  179. {
  180. //metabase path to another server
  181. ReturnPathSize = wcslen( szObjectPath ) + wcslen( L"IIS://" ) + 1;
  182. szReturnPath = new WCHAR[ ReturnPathSize ];
  183. THROW_OUTOFMEMORY_IFNULL( szReturnPath );
  184. if ( '/' == szObjectPath[0] )
  185. StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS:/" );
  186. else
  187. StringCchCopyW( szReturnPath, ReturnPathSize, L"IIS://" );
  188. StringCchCatW( szReturnPath, ReturnPathSize, (WCHAR*)szObjectPath );
  189. }
  190. // check for a trailing \ character
  191. SIZE_T StringLength = wcslen( szReturnPath );
  192. if ( StringLength >= 1 )
  193. {
  194. if ( L'\\' == szReturnPath[ StringLength - 1 ] ||
  195. L'/' == szReturnPath[ StringLength - 1 ] )
  196. {
  197. szReturnPath[ StringLength - 1 ] = L'\0';
  198. }
  199. }
  200. return szReturnPath;
  201. }
  202. BSTR CSimplePropertyReader::GetADsStringProperty( IADs *MetaObj, BSTR bstrPropName)
  203. {
  204. BSTR bstrRetval;
  205. VARIANT vt;
  206. THROW_COMERROR( MetaObj->Get( bstrPropName, &vt ) );
  207. THROW_COMERROR( VariantChangeType( &vt, &vt, 0, VT_BSTR ) );
  208. bstrRetval = vt.bstrVal;
  209. vt.bstrVal = NULL;
  210. VariantClear( &vt );
  211. return bstrRetval;
  212. }
  213. LPWSTR CSimplePropertyReader::GetAdmObjStringProperty(
  214. SmartIMSAdminBasePointer IISAdminBase,
  215. METADATA_HANDLE MdVDirKey,
  216. DWORD dwMDIdentifier )
  217. {
  218. METADATA_RECORD MdRecord;
  219. DWORD dwBytesRequired = 0;
  220. WCHAR *szBuffer = NULL;
  221. try
  222. {
  223. memset( &MdRecord, 0, sizeof( MdRecord ) );
  224. MdRecord.dwMDIdentifier = dwMDIdentifier;
  225. MdRecord.dwMDAttributes = METADATA_INHERIT;
  226. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  227. MdRecord.dwMDDataType = STRING_METADATA;
  228. MdRecord.dwMDDataLen = 0;
  229. MdRecord.pbMDData = NULL;
  230. HRESULT hr =
  231. IISAdminBase->GetData(
  232. MdVDirKey,
  233. NULL,
  234. &MdRecord,
  235. &dwBytesRequired );
  236. if (hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
  237. throw ComError( hr );
  238. szBuffer = reinterpret_cast<WCHAR *>(new BYTE[ dwBytesRequired ]);
  239. THROW_OUTOFMEMORY_IFNULL(szBuffer);
  240. memset( szBuffer, 0, dwBytesRequired );
  241. MdRecord.dwMDDataLen = dwBytesRequired;
  242. MdRecord.pbMDData = (PBYTE)szBuffer;
  243. THROW_COMERROR(
  244. IISAdminBase->GetData(
  245. MdVDirKey,
  246. NULL,
  247. &MdRecord,
  248. &dwBytesRequired ) );
  249. }
  250. catch( ComError Error )
  251. {
  252. // just forward the error
  253. throw;
  254. }
  255. return szBuffer;
  256. }
  257. CAccessRemoteVDir::CAccessRemoteVDir() :
  258. m_MetaObj(NULL),
  259. m_fIsImpersonated(FALSE),
  260. m_hUserToken(INVALID_HANDLE_VALUE),
  261. m_szUNCPath(NULL),
  262. m_szUNCUsername(NULL),
  263. m_szUNCPassword(NULL)
  264. {
  265. }
  266. CAccessRemoteVDir::~CAccessRemoteVDir()
  267. {
  268. //
  269. // Free the user token obtained when/if LogonUser() was called
  270. //
  271. if (m_hUserToken != INVALID_HANDLE_VALUE)
  272. {
  273. CloseHandle( m_hUserToken );
  274. m_hUserToken = INVALID_HANDLE_VALUE;
  275. }
  276. //
  277. // If CAccessRemoteVDir::RevertFromUNCAccount() wasn't called before
  278. // the destructor was called, then make sure we revert the impersonation.
  279. // Is advised the the code that is using this class explicity call
  280. // RevertFromUNCAccount(), however. This test is a safe guard in case
  281. // the call is not made.
  282. //
  283. if (m_fIsImpersonated)
  284. {
  285. RevertToSelf();
  286. }
  287. //
  288. // Free variables used when using the IIS AdmObj to access the meta store.
  289. // All the m_szUNC* variables assume memory was allocated by calling
  290. // CSimplePropertyReader::GetAdmObjStringProperty(), which allocated a buffer
  291. // by calling "new BYTE[ ...]"
  292. //
  293. if (m_szUNCPath)
  294. {
  295. delete [] reinterpret_cast<BYTE*>(m_szUNCPath);
  296. m_szUNCPath = NULL;
  297. }
  298. if (m_szUNCUsername)
  299. {
  300. delete [] reinterpret_cast<BYTE*>(m_szUNCUsername);
  301. m_szUNCUsername = NULL;
  302. }
  303. if (m_szUNCPassword)
  304. {
  305. delete [] reinterpret_cast<BYTE*>(m_szUNCPassword);
  306. m_szUNCPassword = NULL;
  307. }
  308. }
  309. void
  310. CAccessRemoteVDir::RevertFromUNCAccount()
  311. {
  312. // revert to previous security setting
  313. if (m_fIsImpersonated)
  314. {
  315. if (!RevertToSelf())
  316. {
  317. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  318. }
  319. m_fIsImpersonated = FALSE;
  320. }
  321. if (m_hUserToken != INVALID_HANDLE_VALUE)
  322. {
  323. // revert to previous security setting
  324. CloseHandle( m_hUserToken );
  325. m_hUserToken = INVALID_HANDLE_VALUE;
  326. }
  327. }
  328. inline BOOL
  329. CAccessRemoteVDir::IsUNCPath(LPCWSTR szPath)
  330. {
  331. if ( szPath && szPath[0] == L'\\' && szPath[1] == L'\\' )
  332. {
  333. return TRUE;
  334. }
  335. return FALSE;
  336. }
  337. void
  338. CAccessRemoteVDir::LoginToUNC(
  339. SmartIMSAdminBasePointer IISAdminBase,
  340. METADATA_HANDLE MdVDirKey )
  341. {
  342. try
  343. {
  344. m_szUNCPath = CSimplePropertyReader::GetAdmObjStringProperty(IISAdminBase, MdVDirKey, MD_VR_PATH);
  345. //
  346. // Don't logon if the path isn't a UNC path
  347. //
  348. if (!IsUNCPath(m_szUNCPath))
  349. {
  350. // this class destructor will free m_szUNCPath;
  351. return;
  352. }
  353. m_szUNCUsername = CSimplePropertyReader::GetAdmObjStringProperty(IISAdminBase, MdVDirKey, MD_VR_USERNAME);
  354. m_szUNCPassword = CSimplePropertyReader::GetAdmObjStringProperty(IISAdminBase, MdVDirKey, MD_VR_PASSWORD);
  355. ImpersonateUNCUser(m_szUNCPath, m_szUNCUsername, m_szUNCPassword, &m_hUserToken);
  356. m_fIsImpersonated = TRUE;
  357. }
  358. catch( ComError Error )
  359. {
  360. // just forward the error
  361. throw;
  362. }
  363. }
  364. void
  365. CAccessRemoteVDir::ImpersonateUNCUser(IN LPCWSTR szUNCPath, IN LPCWSTR szUNCUsername, IN LPCWSTR szUNCPassword, OUT HANDLE *hUserToken)
  366. {
  367. *hUserToken = INVALID_HANDLE_VALUE;
  368. // make sure we are not getting unexpected data
  369. if (!szUNCUsername || !szUNCPassword || szUNCUsername[0] == L'\0')
  370. {
  371. throw ComError( HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) );
  372. }
  373. // crack the user name into a user and domain
  374. WCHAR *szUserName = (WCHAR*)szUNCUsername;
  375. WCHAR *szDomainName = NULL;
  376. WCHAR *p = szUserName;
  377. while(*p != L'\0')
  378. {
  379. if(*p == L'\\')
  380. {
  381. *p = L'\0';
  382. p++;
  383. //
  384. // first part is domain
  385. // second is user.
  386. //
  387. szDomainName = szUserName;
  388. szUserName = p;
  389. break;
  390. }
  391. p++;
  392. }
  393. if ( !LogonUserW(
  394. szUserName,
  395. szDomainName,
  396. (WCHAR*)szUNCPassword,
  397. LOGON32_LOGON_BATCH,
  398. LOGON32_PROVIDER_DEFAULT,
  399. hUserToken ) )
  400. {
  401. if ( GetLastError() == ERROR_LOGON_TYPE_NOT_GRANTED )
  402. {
  403. if ( !LogonUserW(
  404. szUserName,
  405. szDomainName,
  406. (WCHAR*)szUNCPassword,
  407. LOGON32_LOGON_INTERACTIVE,
  408. LOGON32_PROVIDER_DEFAULT,
  409. hUserToken ) )
  410. {
  411. // LogonUser() may touch the handle
  412. // make sure we don't think we have a valid handle
  413. *hUserToken = INVALID_HANDLE_VALUE;
  414. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  415. }
  416. }
  417. else
  418. {
  419. *hUserToken = INVALID_HANDLE_VALUE;
  420. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  421. }
  422. }
  423. if ( !ImpersonateLoggedOnUser( *hUserToken ) )
  424. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  425. }