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.

790 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. application.cxx
  5. Abstract:
  6. Encapsulates the IAzApplication object. Does all the grunt work to
  7. get an AzContext, determine operations, and build up server variable
  8. table
  9. Author:
  10. Bilal Alam (balam) Nov 26, 2001
  11. --*/
  12. #include "precomp.hxx"
  13. BSTR AZ_APPLICATION::sm_bstrOperationName;
  14. DWORD AZ_APPLICATION::sm_cParameterCount;
  15. VARIANT AZ_APPLICATION::sm_vNameArray;
  16. CHAR * AZ_APPLICATION::sm_rgParameterNames[] = {
  17. "ALL_HTTP",
  18. "APPL_MD_PATH",
  19. "APPL_PHYSICAL_PATH",
  20. "AUTH_PASSWORD",
  21. "AUTH_TYPE",
  22. "AUTH_USER",
  23. "CERT_COOKIE",
  24. "CERT_FLAGS",
  25. "CERT_ISSUER",
  26. "CERT_KEYSIZE",
  27. "CERT_SECRETKEYSIZE",
  28. "CERT_SERIALNUMBER",
  29. "CERT_SERVER_ISSUER",
  30. "CERT_SERVER_SUBJECT",
  31. "CERT_SUBJECT",
  32. "CONTENT_LENGTH",
  33. "CONTENT_TYPE",
  34. "GATEWAY_INTERFACE",
  35. "LOGON_USER",
  36. "HTTPS",
  37. "HTTPS_KEYSIZE",
  38. "HTTPS_SECRETKEYSIZE",
  39. "HTTPS_SERVER_ISSUER",
  40. "HTTPS_SERVER_SUBJECT",
  41. "INSTANCE_ID",
  42. "INSTANCE_META_PATH",
  43. "PATH_INFO",
  44. "PATH_TRANSLATED",
  45. "QUERY_STRING",
  46. "REMOTE_ADDR",
  47. "REMOTE_HOST",
  48. "REMOTE_USER",
  49. "REQUEST_METHOD",
  50. "SERVER_NAME",
  51. "LOCAL_ADDR",
  52. "SERVER_PORT",
  53. "SERVER_PORT_SECURE",
  54. "SERVER_PROTOCOL",
  55. "SERVER_SOFTWARE",
  56. "UNMAPPED_REMOTE_USER",
  57. "URL",
  58. "HTTP_METHOD",
  59. "HTTP_VERSION",
  60. "APP_POOL_ID",
  61. "SCRIPT_TRANSLATED",
  62. "UNENCODED_URL",
  63. NULL
  64. };
  65. //static
  66. HRESULT
  67. AZ_APPLICATION::Initialize(
  68. VOID
  69. )
  70. /*++
  71. Routine Description:
  72. Global initialization of AZ_APPLICATION
  73. Arguments:
  74. None
  75. Return Value:
  76. HRESULT
  77. --*/
  78. {
  79. VARIANT vName;
  80. SAFEARRAY * psaNames = NULL;
  81. SAFEARRAYBOUND rgsaBound[ 1 ];
  82. LONG lArrayIndex[ 1 ];
  83. HRESULT hr = NO_ERROR;
  84. BSTR bstrName = NULL;
  85. STACK_STRU( strTemp, 512 );
  86. VariantInit( &sm_vNameArray );
  87. //
  88. // Allocate the single operation BSTR only once
  89. //
  90. sm_bstrOperationName = SysAllocString( URL_AUTH_OPERATION_NAME );
  91. if ( sm_bstrOperationName == NULL )
  92. {
  93. hr = HRESULT_FROM_WIN32( GetLastError() );
  94. goto Finished;
  95. }
  96. //
  97. // Allocate the parameter name array for use with AccessCheck() and
  98. // business logic
  99. //
  100. //
  101. // How many parameters in array?
  102. //
  103. DBG_ASSERT( sm_cParameterCount == 0 );
  104. while ( sm_rgParameterNames[ sm_cParameterCount ] != NULL )
  105. {
  106. sm_cParameterCount++;
  107. }
  108. DBG_ASSERT( sm_cParameterCount > 0 );
  109. //
  110. // Allocate the array
  111. //
  112. rgsaBound[ 0 ].lLbound = 0;
  113. rgsaBound[ 0 ].cElements = sm_cParameterCount;
  114. psaNames = SafeArrayCreate( VT_VARIANT, 1, rgsaBound );
  115. if ( psaNames == NULL )
  116. {
  117. hr = HRESULT_FROM_WIN32( GetLastError() );
  118. goto Finished;
  119. }
  120. //
  121. // Create a new BSTR for each parameter name and add to safe array
  122. //
  123. lArrayIndex[ 0 ] = 0;
  124. for ( DWORD j = 0; j < sm_cParameterCount; j++ )
  125. {
  126. DBG_ASSERT( sm_rgParameterNames[ j ] != NULL );
  127. hr = strTemp.CopyA( sm_rgParameterNames[ j ] );
  128. if ( FAILED( hr ) )
  129. {
  130. goto Finished;
  131. }
  132. bstrName = SysAllocString( strTemp.QueryStr() );
  133. if ( bstrName == NULL )
  134. {
  135. hr = HRESULT_FROM_WIN32( GetLastError() );
  136. goto Finished;
  137. }
  138. VariantInit( &vName );
  139. vName.vt = VT_BSTR;
  140. vName.bstrVal = bstrName;
  141. hr = SafeArrayPutElement( psaNames,
  142. lArrayIndex,
  143. &vName );
  144. if ( FAILED( hr ) )
  145. {
  146. goto Finished;
  147. }
  148. bstrName = NULL;
  149. (lArrayIndex[ 0 ])++;
  150. }
  151. //
  152. // Finally, setup the variant for the array
  153. //
  154. sm_vNameArray.vt = VT_ARRAY;
  155. sm_vNameArray.parray = psaNames;
  156. psaNames = NULL;
  157. Finished:
  158. if ( bstrName != NULL )
  159. {
  160. SysFreeString( bstrName );
  161. bstrName = NULL;
  162. }
  163. if ( psaNames != NULL )
  164. {
  165. SafeArrayDestroy( psaNames );
  166. psaNames = NULL;
  167. }
  168. return hr;
  169. }
  170. //static
  171. VOID
  172. AZ_APPLICATION::Terminate(
  173. VOID
  174. )
  175. /*++
  176. Routine Description:
  177. Cleanup globals for AZ_APPLICATION
  178. Arguments:
  179. None
  180. Return Value:
  181. None
  182. --*/
  183. {
  184. VariantClear( &sm_vNameArray );
  185. if ( sm_bstrOperationName != NULL )
  186. {
  187. SysFreeString( sm_bstrOperationName );
  188. sm_bstrOperationName = NULL;
  189. }
  190. }
  191. HRESULT
  192. AZ_APPLICATION::Create(
  193. VOID
  194. )
  195. /*++
  196. Routine Description:
  197. Initialize an AZ_APPLICATION object
  198. Arguments:
  199. None
  200. Return Value:
  201. HRESULT
  202. --*/
  203. {
  204. IAzOperation * pIOperation;
  205. HRESULT hr;
  206. VARIANT vNoParam;
  207. LONG operationId;
  208. SAFEARRAY * psaOperations = NULL;
  209. SAFEARRAYBOUND rgsaBound[ 1 ];
  210. LONG lArrayIndex[ 1 ];
  211. VARIANT vOperation;
  212. DBG_ASSERT( _pIApplication != NULL );
  213. //
  214. // We need to get the one operation we care about.
  215. //
  216. VariantInit( &vNoParam );
  217. vNoParam.vt = VT_ERROR;
  218. vNoParam.scode = DISP_E_PARAMNOTFOUND;
  219. hr = _pIApplication->OpenOperation( sm_bstrOperationName,
  220. vNoParam,
  221. &pIOperation );
  222. if ( FAILED( hr ) )
  223. {
  224. return hr;
  225. }
  226. DBG_ASSERT( pIOperation != NULL );
  227. //
  228. // Get the operation ID
  229. //
  230. hr = pIOperation->get_OperationID( &operationId );
  231. pIOperation->Release();
  232. //
  233. // Now do some grunt work and create a variant array for use in our call
  234. // to AccessCheck(). How do developers live with this crap?
  235. //
  236. rgsaBound[ 0 ].lLbound = 0;
  237. rgsaBound[ 0 ].cElements = 1;
  238. psaOperations = SafeArrayCreate( VT_VARIANT, 1, rgsaBound );
  239. if ( psaOperations == NULL )
  240. {
  241. return HRESULT_FROM_WIN32( GetLastError() );
  242. }
  243. lArrayIndex[ 0 ] = 0;
  244. VariantInit( &vOperation );
  245. vOperation.vt = VT_I4;
  246. vOperation.lVal = operationId;
  247. hr = SafeArrayPutElement( psaOperations,
  248. lArrayIndex,
  249. &vOperation );
  250. if ( FAILED( hr ) )
  251. {
  252. SafeArrayDestroy( psaOperations );
  253. return hr;
  254. }
  255. VariantInit( &_vOperations );
  256. _vOperations.vt = VT_ARRAY;
  257. _vOperations.parray = psaOperations;
  258. psaOperations = NULL;
  259. return NO_ERROR;
  260. }
  261. HRESULT
  262. AZ_APPLICATION::BuildValueArray(
  263. EXTENSION_CONTROL_BLOCK * pecb,
  264. VARIANT * pValueArray
  265. )
  266. /*++
  267. Routine Description:
  268. Build value array for the given ECB. This just means retrieving all the
  269. server variables and building up an array with these values
  270. Arguments:
  271. pecb - ECB from which operations and sever variable table are built
  272. pValueArray - Filled with a variant for the array of values :-(
  273. Return Value:
  274. HRESULT
  275. --*/
  276. {
  277. SAFEARRAY * psaValues = NULL;
  278. SAFEARRAYBOUND rgsaBound[ 1 ];
  279. LONG lArrayIndex[ 1 ];
  280. VARIANT vValue;
  281. HRESULT hr = NO_ERROR;
  282. STACK_BUFFER( buffVariable, 512 );
  283. STACK_STRU( strVariable, 512 );
  284. DWORD cbVariable;
  285. BSTR bstrValue = NULL;
  286. BOOL fRet;
  287. if ( pecb == NULL ||
  288. pValueArray == NULL )
  289. {
  290. DBG_ASSERT( FALSE );
  291. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  292. }
  293. //
  294. // First create a safe array of required size
  295. //
  296. rgsaBound[ 0 ].lLbound = 0;
  297. rgsaBound[ 0 ].cElements = sm_cParameterCount;
  298. psaValues = SafeArrayCreate( VT_VARIANT, 1, rgsaBound );
  299. if ( psaValues == NULL )
  300. {
  301. hr = HRESULT_FROM_WIN32( GetLastError() );
  302. goto Finished;
  303. }
  304. lArrayIndex[ 0 ] = 0;
  305. //
  306. // Now iterate thru variables, retrieve each one and add to array
  307. //
  308. for ( DWORD i = 0; i < sm_cParameterCount; i++ )
  309. {
  310. DBG_ASSERT( sm_rgParameterNames[ i ] != NULL );
  311. //
  312. // First get the variable
  313. //
  314. cbVariable = buffVariable.QuerySize();
  315. fRet = pecb->GetServerVariable( pecb->ConnID,
  316. sm_rgParameterNames[ i ],
  317. buffVariable.QueryPtr(),
  318. &cbVariable );
  319. if ( !fRet )
  320. {
  321. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  322. {
  323. hr = HRESULT_FROM_WIN32( GetLastError() );
  324. goto Finished;
  325. }
  326. DBG_ASSERT( cbVariable > buffVariable.QuerySize() );
  327. fRet = buffVariable.Resize( cbVariable );
  328. if ( !fRet )
  329. {
  330. hr = HRESULT_FROM_WIN32( GetLastError() );
  331. goto Finished;
  332. }
  333. cbVariable = buffVariable.QuerySize();
  334. fRet = pecb->GetServerVariable( pecb->ConnID,
  335. sm_rgParameterNames[ i ],
  336. buffVariable.QueryPtr(),
  337. &cbVariable );
  338. if ( !fRet )
  339. {
  340. hr = HRESULT_FROM_WIN32( GetLastError() );
  341. goto Finished;
  342. }
  343. }
  344. //
  345. // Convert to UNICODE
  346. //
  347. hr = strVariable.CopyA( (CHAR*) buffVariable.QueryPtr() );
  348. if ( FAILED( hr ) )
  349. {
  350. goto Finished;
  351. }
  352. //
  353. // Make a BSTR
  354. //
  355. bstrValue = SysAllocString( strVariable.QueryStr() );
  356. if ( bstrValue == NULL )
  357. {
  358. hr = HRESULT_FROM_WIN32( GetLastError() );
  359. goto Finished;
  360. }
  361. VariantInit( &vValue );
  362. vValue.vt = VT_BSTR;
  363. vValue.bstrVal = bstrValue;
  364. hr = SafeArrayPutElement( psaValues,
  365. lArrayIndex,
  366. &vValue );
  367. if ( FAILED( hr ) )
  368. {
  369. goto Finished;
  370. }
  371. bstrValue = NULL;
  372. (lArrayIndex[ 0 ])++;
  373. }
  374. //
  375. // Finally, setup the variant for the array
  376. //
  377. pValueArray->vt = VT_ARRAY;
  378. pValueArray->parray = psaValues;
  379. psaValues = NULL;
  380. Finished:
  381. if ( bstrValue != NULL )
  382. {
  383. SysFreeString( bstrValue );
  384. bstrValue = NULL;
  385. }
  386. if ( psaValues != NULL )
  387. {
  388. SafeArrayDestroy( psaValues );
  389. psaValues = NULL;
  390. }
  391. return hr;
  392. }
  393. HRESULT
  394. AZ_APPLICATION::DoAccessCheck(
  395. EXTENSION_CONTROL_BLOCK * pecb,
  396. WCHAR * pszScopeName,
  397. BOOL * pfAccessGranted
  398. )
  399. /*++
  400. Routine Description:
  401. Check access
  402. Arguments:
  403. pecb - ECB from which operations and sever variable table are built
  404. pszScopeName - Scope name
  405. pfAccessGranted - Set to TRUE if access is granted
  406. Return Value:
  407. HRESULT
  408. --*/
  409. {
  410. BOOL fRet;
  411. HANDLE hToken;
  412. HRESULT hr = NO_ERROR;
  413. VARIANT vNoParam;
  414. IAzClientContext * pIClientContext = NULL;
  415. SAFEARRAY * psaScopes = NULL;
  416. SAFEARRAYBOUND rgsaBound[ 1 ];
  417. LONG lArrayIndex[ 1 ];
  418. VARIANT vScope;
  419. VARIANT vScopes;
  420. BSTR bstrScope = NULL;
  421. BSTR bstrObjectName = NULL;
  422. STACK_BUFFER( buffUrl, 256 );
  423. DWORD cbBuffUrl;
  424. VARIANT vAccessCheckOutput;
  425. VARIANT * pResults = NULL;
  426. LONG lTokenHandle;
  427. VARIANT vValueArray;
  428. if ( pecb == NULL ||
  429. pfAccessGranted == NULL )
  430. {
  431. DBG_ASSERT( FALSE );
  432. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  433. }
  434. VariantInit( &vNoParam );
  435. VariantInit( &vScope );
  436. VariantInit( &vScopes );
  437. VariantInit( &vAccessCheckOutput );
  438. VariantInit( &vValueArray );
  439. *pfAccessGranted = FALSE;
  440. //
  441. // First, get the token for this request.
  442. //
  443. fRet = pecb->ServerSupportFunction( pecb->ConnID,
  444. HSE_REQ_GET_IMPERSONATION_TOKEN,
  445. (VOID*)&hToken,
  446. NULL,
  447. NULL );
  448. if ( !fRet )
  449. {
  450. hr = HRESULT_FROM_WIN32( GetLastError() );
  451. goto Finished;
  452. }
  453. //
  454. // Now, get the AzClientContext from the token
  455. //
  456. DBG_ASSERT( _pIApplication != NULL );
  457. vNoParam.vt = VT_ERROR;
  458. vNoParam.scode = DISP_E_PARAMNOTFOUND;
  459. //
  460. // BUGBUG: This AZRoles API needs to be Win64 friendly
  461. //
  462. #if defined( _WIN64 )
  463. LARGE_INTEGER liLarge;
  464. liLarge.QuadPart = (LONGLONG) hToken;
  465. lTokenHandle = liLarge.LowPart;
  466. #else
  467. lTokenHandle = (LONG) hToken;
  468. #endif
  469. hr = _pIApplication->InitializeClientContextFromToken( lTokenHandle,
  470. vNoParam,
  471. &pIClientContext );
  472. if ( FAILED( hr ) )
  473. {
  474. goto Finished;
  475. }
  476. DBG_ASSERT( pIClientContext != NULL );
  477. //
  478. // Determine the object name. We'll just use the URL (probably want to
  479. // expose a "FULL_URL" variable which is just the Unicode-untranslated
  480. // (i.e. pathinfo/URL not split) string.
  481. //
  482. cbBuffUrl = buffUrl.QuerySize();
  483. fRet = pecb->GetServerVariable( pecb->ConnID,
  484. "UNICODE_URL",
  485. (CHAR*) buffUrl.QueryPtr(),
  486. &cbBuffUrl );
  487. if ( !fRet )
  488. {
  489. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  490. {
  491. hr = HRESULT_FROM_WIN32( GetLastError() );
  492. goto Finished;
  493. }
  494. DBG_ASSERT( cbBuffUrl > buffUrl.QuerySize() );
  495. fRet = buffUrl.Resize( cbBuffUrl );
  496. if ( !fRet )
  497. {
  498. hr = HRESULT_FROM_WIN32( GetLastError() );
  499. goto Finished;
  500. }
  501. cbBuffUrl = buffUrl.QuerySize();
  502. fRet = pecb->GetServerVariable( pecb->ConnID,
  503. "UNICODE_URL",
  504. (CHAR*) buffUrl.QueryPtr(),
  505. &cbBuffUrl );
  506. if ( !fRet )
  507. {
  508. hr = HRESULT_FROM_WIN32( GetLastError() );
  509. goto Finished;
  510. }
  511. }
  512. //
  513. // How many more heap allocations can we do???
  514. //
  515. bstrObjectName = SysAllocString( (WCHAR*) buffUrl.QueryPtr() );
  516. if ( bstrObjectName == NULL )
  517. {
  518. hr = HRESULT_FROM_WIN32( GetLastError() );
  519. goto Finished;
  520. }
  521. //
  522. // Setup the scope variant array for this request. This is excruciating!
  523. //
  524. rgsaBound[ 0 ].lLbound = 0;
  525. rgsaBound[ 0 ].cElements = 1;
  526. psaScopes = SafeArrayCreate( VT_VARIANT, 1, rgsaBound );
  527. if ( psaScopes == NULL )
  528. {
  529. hr = HRESULT_FROM_WIN32( GetLastError() );
  530. goto Finished;
  531. }
  532. bstrScope = SysAllocString( pszScopeName ? pszScopeName : L"" );
  533. if ( bstrScope == NULL )
  534. {
  535. hr = HRESULT_FROM_WIN32( GetLastError() );
  536. goto Finished;
  537. }
  538. vScope.vt = VT_BSTR;
  539. vScope.bstrVal = bstrScope;
  540. lArrayIndex[ 0 ] = 0;
  541. hr = SafeArrayPutElement( psaScopes,
  542. lArrayIndex,
  543. &vScope );
  544. if ( FAILED( hr ) )
  545. {
  546. goto Finished;
  547. }
  548. bstrScope = NULL;
  549. vScopes.vt = VT_ARRAY;
  550. vScopes.parray = psaScopes;
  551. psaScopes = NULL;
  552. //
  553. // Build up the value array for use with business logic
  554. //
  555. hr = BuildValueArray( pecb,
  556. &vValueArray );
  557. //
  558. // After that ordeal, we're ready to call AccessCheck()!
  559. //
  560. hr = pIClientContext->AccessCheck( bstrObjectName,
  561. vScopes,
  562. _vOperations,
  563. sm_vNameArray,
  564. vValueArray,
  565. vNoParam,
  566. vNoParam,
  567. vNoParam,
  568. &vAccessCheckOutput );
  569. if ( FAILED( hr ) )
  570. {
  571. goto Finished;
  572. }
  573. //
  574. // Joy continues. Need to parse out what AccessCheck() returned
  575. //
  576. //
  577. // Return variant should be 1 dimension, 0 based array
  578. //
  579. DBG_ASSERT( vAccessCheckOutput.parray->rgsabound[ 0 ].lLbound == 0 );
  580. DBG_ASSERT( vAccessCheckOutput.parray->rgsabound[ 0 ].cElements == 1 );
  581. SafeArrayAccessData( vAccessCheckOutput.parray, (VOID**) &pResults );
  582. DBG_ASSERT( pResults[ 0 ].vt == VT_I4 );
  583. //
  584. // Finally, we can tell whether access was allowed or not
  585. //
  586. *pfAccessGranted = pResults[ 0 ].lVal == 0 ? TRUE : FALSE;
  587. SafeArrayUnaccessData( vAccessCheckOutput.parray );
  588. Finished:
  589. if ( pIClientContext != NULL )
  590. {
  591. pIClientContext->Release();
  592. pIClientContext = NULL;
  593. }
  594. if ( bstrScope != NULL )
  595. {
  596. SysFreeString( bstrScope );
  597. bstrScope = NULL;
  598. }
  599. if ( bstrObjectName != NULL )
  600. {
  601. SysFreeString( bstrObjectName );
  602. bstrObjectName = NULL;
  603. }
  604. if ( psaScopes != NULL )
  605. {
  606. SafeArrayDestroy( psaScopes );
  607. psaScopes = NULL;
  608. }
  609. VariantClear( &vScopes );
  610. VariantClear( &vAccessCheckOutput );
  611. VariantClear( &vValueArray );
  612. return hr;
  613. }