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.

1082 lines
36 KiB

  1. //**********************************************************************************
  2. // Copyright (c) Microsoft Corporation
  3. //
  4. // Module Name:
  5. // CONNECTWMI.cpp
  6. //
  7. // Abstract:
  8. // Contains functions to connect to wmi.
  9. //
  10. // Author:
  11. // J.S.Vasu
  12. //
  13. // Revision History:
  14. // J.S.Vasu 26-sep-2k : Created It.
  15. // *********************************************************************************
  16. // Include files
  17. #include "pch.h"
  18. #include "resource.h"
  19. #include "driverquery.h"
  20. // error constants
  21. #define E_SERVER_NOTFOUND 0x800706ba
  22. // function prototypes
  23. BOOL IsValidServerEx( LPCWSTR pwszServer,
  24. BOOL &bLocalSystem );
  25. HRESULT GetSecurityArguments( IUnknown *pInterface,
  26. DWORD& dwAuthorization,
  27. DWORD& dwAuthentication );
  28. HRESULT SetInterfaceSecurity( IUnknown *pInterface,
  29. LPCWSTR pwszServer,
  30. LPCWSTR pwszUser,
  31. LPCWSTR pwszPassword,
  32. COAUTHIDENTITY **ppAuthIdentity );
  33. HRESULT WINAPI SetProxyBlanket( IUnknown *pInterface,
  34. DWORD dwAuthnSvc,
  35. DWORD dwAuthzSvc,
  36. LPWSTR pwszPrincipal,
  37. DWORD dwAuthLevel,
  38. DWORD dwImpLevel,
  39. RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
  40. DWORD dwCapabilities );
  41. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser,
  42. LPCWSTR pwszPassword,
  43. LPCWSTR pwszDomain,
  44. COAUTHIDENTITY **ppAuthIdent );
  45. BOOL ConnectWmi( IWbemLocator *pLocator,
  46. IWbemServices ** ppServices,
  47. LPCWSTR pwszServer,
  48. LPCWSTR pwszUser,
  49. LPCWSTR pwszPassword,
  50. COAUTHIDENTITY **ppAuthIdentity,
  51. BOOL bCheckWithNullPwd = FALSE,
  52. LPCWSTR pwszNamespace = CIMV2_NAME_SPACE,
  53. HRESULT *phr = NULL,
  54. BOOL *pbLocalSystem = NULL );
  55. VOID WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY **ppAuthIdentity );
  56. // ***************************************************************************
  57. // Routine Description:
  58. // Checks whether the server name is a valid server name or not.
  59. //
  60. // Arguments:
  61. // pwszServer [in] - Server name to be validated.
  62. // bLocalSystem [in/out] - Set to TRUE if server specified is local system.
  63. //
  64. // Return Value:
  65. // TRUE if server is valid else FALSE.
  66. //
  67. // ***************************************************************************
  68. BOOL IsValidServerEx( LPCWSTR pwszServer, BOOL &bLocalSystem )
  69. {
  70. // local variables
  71. CHString strTemp;
  72. if( pwszServer == NULL )
  73. {
  74. return FALSE;
  75. }
  76. bLocalSystem = FALSE;
  77. // get a local copy
  78. strTemp = pwszServer;
  79. // remove the forward slashes (UNC) if exist in the begining of the server name
  80. if ( IsUNCFormat( strTemp ) == TRUE )
  81. {
  82. strTemp = strTemp.Mid( 2 );
  83. if ( strTemp.GetLength() == 0 )
  84. return FALSE;
  85. }
  86. // now check if any '\' character appears in the server name. If so error
  87. if ( strTemp.Find( L'\\' ) != -1 )
  88. return FALSE;
  89. // now check if server name is '.' only which represent local system in WMI
  90. // else determine whether this is a local system or not
  91. bLocalSystem = TRUE;
  92. if ( strTemp.CompareNoCase( L"." ) != 0 )
  93. {
  94. // validate the server
  95. if ( IsValidServer( strTemp ) == FALSE )
  96. return FALSE;
  97. // check whether this is a local system or not
  98. bLocalSystem = IsLocalSystem( strTemp );
  99. }
  100. // valid server name
  101. return TRUE;
  102. }
  103. // ***************************************************************************
  104. // Routine Description:
  105. // Connects to wmi.
  106. //
  107. // Arguments:
  108. // pLocator [in] - Pointer to the IWbemLocator object.
  109. // ppServices [out] - Pointer to IWbemServices object.
  110. // pwszServer [in] - Holds the server name to connect to.
  111. // pwszUser [in/out] - Holds the user name.
  112. // pwszPassword [in/out] - Holds the password.
  113. // ppAuthIdentity [in/out] - Pointer to authentication structure.
  114. // bCheckWithNullPwd [in] - Specifies whether to connect through null password.
  115. // pwszNamespace [in] - Specifies the namespace to connect to.
  116. // phRes [in/out] - Holds the error value.
  117. // pbLocalSystem [in/out] - Holds the boolean value to represent whether the server
  118. // name is local or not.
  119. // Return Value:
  120. // TRUE if successfully connected, FALSE if not.
  121. // ***************************************************************************
  122. BOOL ConnectWmi( IWbemLocator *pLocator, IWbemServices **ppServices,
  123. LPCWSTR pwszServer, LPCWSTR pwszUser, LPCWSTR pwszPassword,
  124. COAUTHIDENTITY **ppAuthIdentity,
  125. BOOL bCheckWithNullPwd, LPCWSTR pwszNamespace, HRESULT *phRes,
  126. BOOL *pbLocalSystem )
  127. {
  128. // local variables
  129. HRESULT hRes = 0;
  130. BOOL bResult = FALSE;
  131. BOOL bLocalSystem = FALSE;
  132. _bstr_t bstrServer;
  133. _bstr_t bstrNamespace;
  134. _bstr_t bstrUser;
  135. _bstr_t bstrPassword;
  136. if ( pbLocalSystem != NULL )
  137. {
  138. *pbLocalSystem = FALSE;
  139. }
  140. if ( phRes != NULL )
  141. {
  142. *phRes = NO_ERROR;
  143. }
  144. try
  145. {
  146. // clear the error
  147. SetLastError( WBEM_S_NO_ERROR );
  148. // assume that connection to WMI namespace is failed
  149. bResult = FALSE;
  150. // check whether locator object exists or not if not return FALSE
  151. if ( pLocator == NULL )
  152. {
  153. if ( phRes != NULL )
  154. {
  155. *phRes = WBEM_E_INVALID_PARAMETER;
  156. }
  157. // return failure
  158. return FALSE;
  159. }
  160. // validate the server name
  161. // NOTE: The error being raised in custom define for '0x800706ba' value
  162. // The message that will be displayed in "The RPC server is unavailable."
  163. if ( IsValidServerEx( pwszServer, bLocalSystem ) == FALSE )
  164. {
  165. _com_issue_error( ERROR_BAD_NETPATH );
  166. }
  167. // validate the user name
  168. if ( IsValidUserEx( pwszUser ) == FALSE )
  169. {
  170. _com_issue_error( ERROR_NO_SUCH_USER );
  171. }
  172. // prepare namespace
  173. bstrNamespace = pwszNamespace; // name space
  174. if ( pwszServer != NULL && bLocalSystem == FALSE )
  175. {
  176. // get the server name
  177. bstrServer = pwszServer;
  178. // prepare the namespace
  179. // NOTE: check for the UNC naming format of the server and do
  180. if ( IsUNCFormat( pwszServer ) == TRUE )
  181. {
  182. bstrNamespace = bstrServer + L"\\" + pwszNamespace;
  183. }
  184. else
  185. {
  186. bstrNamespace = L"\\\\" + bstrServer + L"\\" + pwszNamespace;
  187. }
  188. // user credentials
  189. if ( pwszUser != NULL && StringLengthW( pwszUser, 0 ) != 0 )
  190. {
  191. // copy the user name
  192. bstrUser = pwszUser;
  193. // if password is empty string and if we need to check with
  194. // null password, then do not set the password and try
  195. bstrPassword = pwszPassword;
  196. if ( bCheckWithNullPwd == TRUE && bstrPassword.length() == 0 )
  197. {
  198. bstrPassword = (LPWSTR) NULL;
  199. }
  200. }
  201. }
  202. // release the existing services object ( to be in safer side )
  203. SAFE_RELEASE( *ppServices );
  204. // connect to the remote system's WMI
  205. // there is a twist here ...
  206. // do not trap the ConnectServer function failure into exception
  207. // instead handle that action manually
  208. // by default try the ConnectServer function as the information which we have
  209. // in our hands at this point. If the ConnectServer is failed,
  210. // check whether password variable has any contents are not ... if no contents
  211. // check with "" (empty) password ... this might pass in this situation ..
  212. // if this call is also failed ... nothing is there that we can do ... throw the exception
  213. hRes = pLocator->ConnectServer( bstrNamespace,
  214. bstrUser, bstrPassword, 0L, 0L, NULL, NULL, ppServices );
  215. if ( FAILED( hRes ) )
  216. {
  217. //
  218. // special case ...
  219. // check whether password exists or not
  220. // NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
  221. // this error code says that user with the current credentials is not
  222. // having access permisions to the 'namespace'
  223. if ( hRes == E_ACCESSDENIED )
  224. {
  225. // check if we tried to connect to the system using null password
  226. // if so, then try connecting to the remote system with empty string
  227. if ( bCheckWithNullPwd == TRUE &&
  228. bstrUser.length() != 0 && bstrPassword.length() == 0 )
  229. {
  230. // now invoke with ...
  231. hRes = pLocator->ConnectServer( bstrNamespace,
  232. bstrUser, _bstr_t( L"" ), 0L, 0L, NULL, NULL, ppServices );
  233. }
  234. }
  235. else if ( hRes == WBEM_E_LOCAL_CREDENTIALS )
  236. {
  237. // credentials were passed to the local system.
  238. // So ignore the credentials and try to reconnect
  239. bLocalSystem = TRUE;
  240. bstrUser = (LPWSTR) NULL;
  241. bstrPassword = (LPWSTR) NULL;
  242. bstrNamespace = pwszNamespace; // name space
  243. hRes = pLocator->ConnectServer( bstrNamespace,
  244. NULL, NULL, 0L, 0L, NULL, NULL, ppServices );
  245. // now check the result again .. if failed
  246. }
  247. // now check the result again .. if failed .. ummmm..
  248. if ( FAILED( hRes ) )
  249. {
  250. _com_issue_error( hRes );
  251. }
  252. else
  253. {
  254. bstrPassword = L"";
  255. }
  256. }
  257. // set the security at the interface level also
  258. SAFE_EXECUTE( SetInterfaceSecurity( *ppServices,
  259. pwszServer, bstrUser, bstrPassword, ppAuthIdentity ) );
  260. // connection to WMI is successful
  261. bResult = TRUE;
  262. // save the hr value if needed by the caller
  263. if ( phRes != NULL )
  264. {
  265. *phRes = WBEM_S_NO_ERROR;
  266. }
  267. }
  268. catch( _com_error& e )
  269. {
  270. // save the error
  271. WMISaveError( e );
  272. // save the hr value if needed by the caller
  273. if ( phRes != NULL )
  274. {
  275. *phRes = e.Error();
  276. }
  277. }
  278. if ( pbLocalSystem != NULL )
  279. {
  280. *pbLocalSystem = bLocalSystem;
  281. }
  282. // return the result
  283. return bResult;
  284. }
  285. // ***************************************************************************
  286. // Routine Description:
  287. // Connects to wmi.
  288. //
  289. // Arguments:
  290. // pLocator [in] - Pointer to the IWbemLocator object.
  291. // ppServices [out] - Pointer to IWbemServices object.
  292. // strServer [in] - Holds the server name to connect to.
  293. // strUserName [in/out] - Holds the user name.
  294. // strPassword [in/out] - Holds the password.
  295. // ppAuthIdentity [in/out] - Pointer to authentication structure.
  296. // bNeedPassword [in] - Specifies whether to prompt for password.
  297. // pwszNamespace [in] - Specifies the namespace to connect to.
  298. // pbLocalSystem [in/out] - Holds the boolean value to represent whether the server
  299. // name is local or not.
  300. // Return Value:
  301. // TRUE if successfully connected, FALSE if not.
  302. // ***************************************************************************
  303. BOOL ConnectWmiEx( IWbemLocator *pLocator,
  304. IWbemServices **ppServices,
  305. const CHString &strServer, CHString &strUserName, CHString &strPassword,
  306. COAUTHIDENTITY **ppAuthIdentity, BOOL bNeedPassword, LPCWSTR pwszNamespace,
  307. BOOL* pbLocalSystem )
  308. {
  309. // local variables
  310. HRESULT hRes = 0;
  311. DWORD dwSize = 0;
  312. BOOL bResult = FALSE;
  313. LPWSTR pwszPassword = NULL;
  314. CHString strBuffer = NULL_STRING;
  315. __MAX_SIZE_STRING szBuffer = NULL_STRING;
  316. // clear the error .. if any
  317. SetLastError( WBEM_S_NO_ERROR );
  318. // sometime users want the utility to prompt for the password
  319. // check what user wants the utility to do
  320. if ( bNeedPassword == TRUE && strPassword.Compare( L"*" ) == 0 )
  321. {
  322. // user wants the utility to prompt for the password
  323. // so skip this part and let the flow directly jump the password acceptance part
  324. }
  325. else
  326. {
  327. // try to establish connection to the remote system with the credentials supplied
  328. if ( strUserName.GetLength() == 0 )
  329. {
  330. // user name is empty
  331. // so, it is obvious that password will also be empty
  332. // even if password is specified, we have to ignore that
  333. bResult = ConnectWmi( pLocator, ppServices,
  334. (LPCWSTR)strServer, NULL, NULL, ppAuthIdentity, FALSE, pwszNamespace, &hRes, pbLocalSystem );
  335. }
  336. else
  337. {
  338. // credentials were supplied
  339. // but password might not be specified ... so check and act accordingly
  340. LPCWSTR pwszTemp = NULL;
  341. if ( bNeedPassword == FALSE )
  342. pwszTemp = strPassword;
  343. // ...
  344. bResult = ConnectWmi( pLocator, ppServices, (LPCWSTR)strServer,
  345. (LPCWSTR)strUserName, pwszTemp, ppAuthIdentity, FALSE, pwszNamespace, &hRes, pbLocalSystem );
  346. }
  347. // check the result ... if successful in establishing connection ... return
  348. if ( bResult == TRUE )
  349. return TRUE;
  350. // now check the kind of error occurred
  351. switch( hRes )
  352. {
  353. case 0x80040154:
  354. //the wmi is not registered on remote machine
  355. ShowMessage( stderr, ERROR_TAG );
  356. ShowMessage( stderr, GetResString(IDS_ERROR_REMOTE_INCOMPATIBLE));
  357. return FALSE;
  358. case E_ACCESSDENIED:
  359. break;
  360. case WBEM_E_LOCAL_CREDENTIALS:
  361. // needs to do special processing
  362. break;
  363. case WBEM_E_ACCESS_DENIED:
  364. default:
  365. GetWbemErrorText( hRes );
  366. ShowMessage( stderr, ERROR_TAG );
  367. ShowMessage( stderr, GetReason() );
  368. return( FALSE ); // no use of accepting the password .. return failure
  369. }
  370. // if failed in establishing connection to the remote terminal
  371. // even if the password is specifed, then there is nothing to do ... simply return failure
  372. if ( bNeedPassword == FALSE )
  373. {
  374. GetWbemErrorText( hRes );
  375. ShowMessage( stderr, ERROR_TAG );
  376. ShowMessage( stderr, GetReason() );
  377. return FALSE;
  378. }
  379. }
  380. // check whether user name is specified or not
  381. // if not, get the local system's current user name under whose credentials, the process
  382. // is running
  383. if ( strUserName.GetLength() == 0 )
  384. {
  385. // sub-local variables
  386. LPWSTR pwszUserName = NULL;
  387. try
  388. {
  389. // get the required buffer
  390. pwszUserName = strUserName.GetBufferSetLength( MAX_STRING_LENGTH );
  391. }
  392. catch( ... )
  393. {
  394. SetLastError( E_OUTOFMEMORY );
  395. SaveLastError();
  396. ShowMessage( stderr, ERROR_TAG );
  397. ShowLastError( stderr );
  398. return FALSE;
  399. }
  400. // get the user name
  401. _TCHAR szUserName[MAX_RES_STRING];
  402. ULONG ulLong = MAX_RES_STRING;
  403. if ( GetUserNameEx ( NameSamCompatible, szUserName , &ulLong)== FALSE )
  404. {
  405. // error occured while trying to get the current user info
  406. SaveLastError();
  407. ShowMessage( stderr, ERROR_TAG );
  408. ShowLastError( stderr );
  409. return FALSE;
  410. }
  411. StringCopy(pwszUserName,szUserName, MAX_STRING_LENGTH );
  412. // format the user name
  413. if ( _tcschr( pwszUserName, _T( '\\' ) ) == NULL )
  414. {
  415. // server not present in user name ... prepare ... this is only for display purpose
  416. StringCchPrintf( szBuffer, SIZE_OF_ARRAY(szBuffer), _T( "%s\\%s" ), (LPCWSTR)strServer, szUserName );
  417. StringCopy( pwszUserName, szBuffer, MAX_STRING_LENGTH );
  418. }
  419. // release the extra buffer allocated
  420. strUserName.ReleaseBuffer();
  421. }
  422. try
  423. {
  424. // get the required buffer
  425. pwszPassword = strPassword.GetBufferSetLength( MAX_STRING_LENGTH );
  426. }
  427. catch( ... )
  428. {
  429. SetLastError( E_OUTOFMEMORY );
  430. SaveLastError();
  431. ShowMessage( stderr, ERROR_TAG );
  432. ShowLastError( stderr );
  433. return FALSE;
  434. }
  435. // accept the password from the user
  436. strBuffer.Format( INPUT_PASSWORD, strUserName );
  437. WriteConsoleW( GetStdHandle( STD_ERROR_HANDLE ),
  438. strBuffer, strBuffer.GetLength(), &dwSize, NULL );
  439. GetPassword( pwszPassword, MAX_STRING_LENGTH );
  440. // release the buffer allocated for password
  441. strPassword.ReleaseBuffer();
  442. // now again try to establish the connection using the currently
  443. // supplied credentials
  444. bResult = ConnectWmi( pLocator, ppServices, (LPCWSTR)strServer,
  445. (LPCWSTR)strUserName, (LPCWSTR)strPassword, ppAuthIdentity, FALSE, pwszNamespace, &hRes, pbLocalSystem );
  446. if( bResult == FALSE )
  447. {
  448. if( 0x80040154 == hRes )
  449. {
  450. //the wmi is not registered on remote machine
  451. ShowMessage( stderr, ERROR_TAG );
  452. ShowMessage( stderr, GetResString(IDS_ERROR_REMOTE_INCOMPATIBLE));
  453. }
  454. else
  455. {
  456. GetWbemErrorText( hRes );
  457. ShowMessage( stderr, ERROR_TAG );
  458. ShowMessage( stderr, GetReason() );
  459. }
  460. return( FALSE ); // no use of accepting the password .. return failure
  461. }
  462. // return the success
  463. return bResult;
  464. }
  465. // ***************************************************************************
  466. // Routine Description:
  467. // Gets the security arguments for an interface.
  468. //
  469. // Arguments:
  470. // pInterface [in] - Pointer to interface stucture.
  471. // dwAuthorization [in/out] - Holds Authorization value.
  472. // dwAuthentication [in/out] - Holds the Authentication value.
  473. //
  474. // Return Value:
  475. // Returns HRESULT value.
  476. // ***************************************************************************
  477. HRESULT GetSecurityArguments( IUnknown *pInterface,
  478. DWORD& dwAuthorization, DWORD& dwAuthentication )
  479. {
  480. // local variables
  481. HRESULT hRes = 0;
  482. DWORD dwAuthnSvc = 0, dwAuthzSvc = 0;
  483. IClientSecurity *pClientSecurity = NULL;
  484. if(pInterface == NULL)
  485. {
  486. return WBEM_E_INVALID_PARAMETER; ;
  487. }
  488. // try to get the client security services values if possible
  489. hRes = pInterface->QueryInterface( IID_IClientSecurity, (void**) &pClientSecurity );
  490. if ( SUCCEEDED( hRes ) )
  491. {
  492. // got the client security interface
  493. // now try to get the security services values
  494. hRes = pClientSecurity->QueryBlanket( pInterface,
  495. &dwAuthnSvc, &dwAuthzSvc, NULL, NULL, NULL, NULL, NULL );
  496. if ( SUCCEEDED( hRes ) )
  497. {
  498. // we've got the values from the interface
  499. dwAuthentication = dwAuthnSvc;
  500. dwAuthorization = dwAuthzSvc;
  501. }
  502. // release the client security interface
  503. SAFEIRELEASE( pClientSecurity );
  504. }
  505. // return always success
  506. return S_OK;
  507. }
  508. // ***************************************************************************
  509. // Routine Description:
  510. // Sets the interface security for the interface.
  511. //
  512. // Arguments:
  513. // pInterface [in] - pointer to the interface.
  514. // pAuthIdentity [in] - pointer to authentication structure.
  515. //
  516. // Return Value:
  517. // returns HRESULT value.
  518. // ***************************************************************************
  519. HRESULT SetInterfaceSecurity( IUnknown *pInterface, COAUTHIDENTITY *pAuthIdentity )
  520. {
  521. // local variables
  522. HRESULT hRes;
  523. LPWSTR pwszDomain = NULL;
  524. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  525. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  526. // check the interface
  527. if ( pInterface == NULL )
  528. {
  529. return WBEM_E_INVALID_PARAMETER;
  530. }
  531. // get the current security argument value
  532. // GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  533. // set the security information to the interface
  534. hRes = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  535. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
  536. // return the result
  537. return hRes;
  538. }
  539. // ***************************************************************************
  540. // Routine Description:
  541. // Sets proxy blanket for the interface.
  542. //
  543. // Arguments:
  544. // pInterface [in] - pointer to the inteface.
  545. // dwAuthnsvc [in] - Authentication service to use.
  546. // dwAuthzSvc [in] - Authorization service to use.
  547. // pwszPricipal [in] - Server principal name to use with the authentication service.
  548. // dwAuthLevel [in] - Authentication level to use.
  549. // dwImpLevel [in] - Impersonation level to use.
  550. // pAuthInfo [in] - Identity of the client.
  551. // dwCapabilities [in] - Capability flags.
  552. //
  553. // Return Value:
  554. // Return HRESULT value.
  555. //
  556. // ***************************************************************************
  557. HRESULT WINAPI SetProxyBlanket( IUnknown *pInterface,
  558. DWORD dwAuthnSvc, DWORD dwAuthzSvc,
  559. LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
  560. RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities )
  561. {
  562. // local variables
  563. HRESULT hRes;
  564. IUnknown *pUnknown = NULL;
  565. IClientSecurity *pClientSecurity = NULL;
  566. if( pInterface == NULL )
  567. {
  568. return WBEM_E_INVALID_PARAMETER;
  569. }
  570. // get the IUnknown interface ... to check whether this is a valid interface or not
  571. hRes = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
  572. if ( hRes != S_OK )
  573. {
  574. return hRes;
  575. }
  576. // now get the client security interface
  577. hRes = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  578. if ( hRes != S_OK )
  579. {
  580. SAFEIRELEASE( pUnknown );
  581. return hRes;
  582. }
  583. //
  584. // Can't set pAuthInfo if cloaking requested, as cloaking implies
  585. // that the current proxy identity in the impersonated thread (rather
  586. // than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
  587. // is to be used.
  588. // See MSDN info on CoSetProxyBlanket for more details.
  589. //
  590. if ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) )
  591. pAuthInfo = NULL;
  592. // now set the security
  593. hRes = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  594. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  595. // release the security interface
  596. SAFEIRELEASE( pClientSecurity );
  597. // we should check the auth identity structure. if exists .. set for IUnknown also
  598. if ( pAuthInfo != NULL )
  599. {
  600. hRes = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  601. if ( hRes == S_OK )
  602. {
  603. // set security authentication
  604. hRes = pClientSecurity->SetBlanket(
  605. pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  606. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  607. // release
  608. SAFEIRELEASE( pClientSecurity );
  609. }
  610. else if ( hRes == E_NOINTERFACE )
  611. hRes = S_OK; // ignore no interface errors
  612. }
  613. // release the IUnknown
  614. SAFEIRELEASE( pUnknown );
  615. // return the result
  616. return hRes;
  617. }
  618. // ***************************************************************************
  619. // Routine Description:
  620. // Allocate memory for authentication variables.
  621. //
  622. // Arguments:
  623. // pwszUser [in/out] - User name.
  624. // pwszPassword [in/out] - Password.
  625. // pwszDomain [in/out] - Domain name.
  626. // ppAuthIdent [in/out] - Poointer to authentication structure.
  627. //
  628. // Return Value:
  629. // Returns HRESULT value.
  630. // ***************************************************************************
  631. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
  632. LPCWSTR pwszDomain, COAUTHIDENTITY **ppAuthIdent )
  633. {
  634. // local variables
  635. COAUTHIDENTITY* pAuthIdent = NULL;
  636. // validate the input parameter
  637. if ( ppAuthIdent == NULL )
  638. return WBEM_E_INVALID_PARAMETER;
  639. // allocation thru COM API
  640. pAuthIdent = ( COAUTHIDENTITY* ) CoTaskMemAlloc( sizeof( COAUTHIDENTITY ) );
  641. if ( NULL == pAuthIdent )
  642. return WBEM_E_OUT_OF_MEMORY;
  643. // init with 0's
  644. SecureZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
  645. //
  646. // Allocate needed memory and copy in data. Cleanup if anything goes wrong
  647. // user
  648. if ( pwszUser != NULL )
  649. {
  650. // allocate memory for user
  651. LONG lLength = StringLengthW( pwszUser, 0 );
  652. pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  653. if ( pAuthIdent->User == NULL )
  654. {
  655. WbemFreeAuthIdentity( &pAuthIdent );
  656. return WBEM_E_OUT_OF_MEMORY;
  657. }
  658. // set the length and do copy contents
  659. pAuthIdent->UserLength = lLength;
  660. StringCopy( pAuthIdent->User, pwszUser, lLength+1 );
  661. }
  662. // domain
  663. if ( pwszDomain != NULL )
  664. {
  665. // allocate memory for domain
  666. LONG lLength = StringLengthW( pwszDomain, 0 );
  667. pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  668. if ( pAuthIdent->Domain == NULL )
  669. {
  670. WbemFreeAuthIdentity( &pAuthIdent );
  671. return WBEM_E_OUT_OF_MEMORY;
  672. }
  673. // set the length and do copy contents
  674. pAuthIdent->DomainLength = lLength;
  675. StringCopy( pAuthIdent->Domain, pwszDomain, lLength+1 );
  676. }
  677. // passsord
  678. if ( pwszPassword != NULL )
  679. {
  680. // allocate memory for passsord
  681. LONG lLength = StringLengthW( pwszPassword, 0 );
  682. pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  683. if ( pAuthIdent->Password == NULL )
  684. {
  685. WbemFreeAuthIdentity( &pAuthIdent );
  686. return WBEM_E_OUT_OF_MEMORY;
  687. }
  688. // set the length and do copy contents
  689. pAuthIdent->PasswordLength = lLength;
  690. StringCopy( pAuthIdent->Password, pwszPassword, lLength+1 );
  691. }
  692. // type of the structure
  693. pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  694. // final set the address to out parameter
  695. *ppAuthIdent = pAuthIdent;
  696. // return result
  697. return S_OK;
  698. }
  699. // ***************************************************************************
  700. // Routine Description:
  701. // Frees the memory of authentication stucture variable.
  702. //
  703. // Arguments:
  704. // ppAuthIdentity [in] - Pointer to authentication structure.
  705. //
  706. // Return Value:
  707. // none.
  708. // ***************************************************************************
  709. VOID WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY** ppAuthIdentity )
  710. {
  711. // make sure we have a pointer, then walk the structure members and cleanup.
  712. if ( *ppAuthIdentity != NULL )
  713. {
  714. // free the memory allocated for user
  715. if ( (*ppAuthIdentity)->User != NULL )
  716. CoTaskMemFree( (*ppAuthIdentity)->User );
  717. // free the memory allocated for password
  718. if ( (*ppAuthIdentity)->Password != NULL )
  719. CoTaskMemFree( (*ppAuthIdentity)->Password );
  720. // free the memory allocated for domain
  721. if ( (*ppAuthIdentity)->Domain != NULL )
  722. CoTaskMemFree( (*ppAuthIdentity)->Domain );
  723. // final the structure
  724. CoTaskMemFree( *ppAuthIdentity );
  725. }
  726. // set to NULL
  727. *ppAuthIdentity = NULL;
  728. }
  729. // ***************************************************************************
  730. // Routine Description: checks if a user name is valid.
  731. //
  732. // Arguments: UserName
  733. //
  734. // Return Value: BOOL
  735. //
  736. // ***************************************************************************
  737. BOOL IsValidUserEx( LPCWSTR pwszUser )
  738. {
  739. // local variables
  740. CHString strUser;
  741. try
  742. {
  743. // get user into local memory
  744. strUser = pwszUser;
  745. // user name should not be just '\'
  746. if ( strUser.CompareNoCase( L"\\" ) == 0 )
  747. return FALSE;
  748. // user name should not contain invalid characters
  749. if ( strUser.FindOneOf( L"/[]:|<>+=;,?*" ) != -1 )
  750. return FALSE;
  751. }
  752. catch( ... )
  753. {
  754. SetLastError( E_OUTOFMEMORY );
  755. return FALSE;
  756. }
  757. // user name is valid
  758. return TRUE;
  759. }
  760. // ***************************************************************************
  761. // Routine Description:
  762. // Sets interface security.
  763. //
  764. // Arguments:
  765. // pInterface [in] - Pointer to the interface to which security has to be set.
  766. // pwszServer [in] - Holds the server name of the interface.
  767. // pwszUser [in] - Holds the user name of the server.
  768. // pwszPassword [in] - Hold the password of the user.
  769. // ppAuthIdentity [in/out] - Pointer to authentication structure.
  770. //
  771. // Return Value:
  772. // returns HRESULT value.
  773. // ***************************************************************************
  774. HRESULT SetInterfaceSecurity( IUnknown* pInterface,
  775. LPCWSTR pwszServer, LPCWSTR pwszUser,
  776. LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity )
  777. {
  778. // local variables
  779. HRESULT hr=0;
  780. CHString strUser;
  781. CHString strDomain;
  782. LPCWSTR pwszUserArg = NULL;
  783. LPCWSTR pwszDomainArg = NULL;
  784. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  785. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  786. // check the interface
  787. if ( pInterface == NULL )
  788. {
  789. return WBEM_E_INVALID_PARAMETER;
  790. }
  791. // check the authentity strcuture ... if authentity structure is already ready
  792. // simply invoke the 2nd version of SetInterfaceSecurity
  793. if ( *ppAuthIdentity != NULL )
  794. {
  795. return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
  796. }
  797. // get the current security argument value
  798. // GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  799. // If we are doing trivial case, just pass in a null authenication structure
  800. // for which the current logged in user's credentials will be considered
  801. if ( pwszUser == NULL && pwszPassword == NULL )
  802. {
  803. // set the security
  804. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
  805. NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  806. // return the result
  807. return hr;
  808. }
  809. // parse and find out if the user name contains the domain name
  810. // if contains, extract the domain value from it
  811. LONG lPos = -1;
  812. strDomain = L"";
  813. strUser = pwszUser;
  814. if ( ( lPos = strUser.Find( L'\\' ) ) != -1 )
  815. {
  816. // user name contains domain name ... domain\user format
  817. strDomain = strUser.Left( lPos );
  818. strUser = strUser.Mid( lPos + 1 );
  819. }
  820. // get the domain info if it exists only
  821. if ( strDomain.GetLength() != 0 )
  822. {
  823. pwszDomainArg = strDomain;
  824. }
  825. // get the user info if it exists only
  826. if ( strUser.GetLength() != 0 )
  827. {
  828. pwszUserArg = strUser;
  829. }
  830. // check if authentication info is available or not ...
  831. // initialize the security authenication information ... UNICODE VERSION STRUCTURE
  832. if ( ppAuthIdentity == NULL )
  833. {
  834. return WBEM_E_INVALID_PARAMETER;
  835. }
  836. else if ( *ppAuthIdentity == NULL )
  837. {
  838. hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
  839. if ( hr != S_OK )
  840. {
  841. return hr;
  842. }
  843. }
  844. // set the security information to the interface
  845. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  846. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
  847. // return the result
  848. return hr;
  849. }
  850. VOID
  851. WMISaveError(
  852. HRESULT hrError
  853. )
  854. /*++
  855. Routine Description:
  856. This function saves the description of the last error returned by WMI
  857. Arguments:
  858. HRESULT : The last return value from WMI
  859. Return Value:
  860. NONE
  861. --*/
  862. {
  863. // local variables
  864. HRESULT hr = S_OK;
  865. IWbemStatusCodeText* pWbemStatus = NULL;
  866. _bstr_t bstrErrorString;
  867. try
  868. {
  869. // Set error to different value.
  870. if ( E_ACCESSDENIED == hrError )
  871. {
  872. // change the error message to "Logon failure: unknown user name or bad password."
  873. hrError = ERROR_LOGON_FAILURE;
  874. }
  875. //Set the reason to incompatible os when no class is registered on remote mechine
  876. if( 0x80040154 == hrError )
  877. {
  878. bstrErrorString = _bstr_t( GetResString(IDS_ERROR_REMOTE_INCOMPATIBLE) );
  879. SetReason( bstrErrorString );
  880. return;
  881. }
  882. else
  883. { // Get error string.
  884. hr = CoCreateInstance( CLSID_WbemStatusCodeText,
  885. NULL, CLSCTX_INPROC_SERVER,
  886. IID_IWbemStatusCodeText,
  887. (LPVOID*) &pWbemStatus );
  888. if( SUCCEEDED( hr ) )
  889. {
  890. BSTR bstrString = NULL;
  891. // Get error string from error code.
  892. hr = pWbemStatus->GetErrorCodeText( hrError, 0, 0,
  893. &bstrString );
  894. if( NULL != bstrString )
  895. {
  896. bstrErrorString = _bstr_t( bstrString );
  897. SysFreeString( bstrString );
  898. }
  899. if( FAILED( hr ) )
  900. {
  901. _com_issue_error( hrError );
  902. }
  903. SAFE_RELEASE(pWbemStatus);
  904. }
  905. else
  906. {
  907. _com_issue_error( hrError );
  908. }
  909. }
  910. }
  911. catch( _com_error& e )
  912. { // We have got the error. Needs to handle carefully.
  913. LPWSTR lpwszGetString = NULL;
  914. SAFE_RELEASE(pWbemStatus);
  915. try
  916. { // ErrorMessage() can throw an exception.
  917. DWORD dwLength = StringLength( e.ErrorMessage(), 0 ) + 5 ;
  918. lpwszGetString = ( LPWSTR )AllocateMemory( dwLength * sizeof( WCHAR ) );
  919. if( NULL != lpwszGetString )
  920. {
  921. StringCopy( lpwszGetString, e.ErrorMessage(), dwLength );
  922. StringConcat( lpwszGetString, L"\n", dwLength );
  923. SetReason( ( LPCWSTR )lpwszGetString );
  924. FreeMemory( (LPVOID*) &lpwszGetString );
  925. }
  926. else
  927. { // Failed to know the exact error occured
  928. // due to insufficient memory.
  929. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  930. SaveLastError();
  931. }
  932. }
  933. catch( ... )
  934. {
  935. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  936. SaveLastError();
  937. }
  938. return;
  939. }
  940. SetReason( (LPCWSTR) bstrErrorString );
  941. return;
  942. }