Source code of Windows XP (NT5)
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.

1079 lines
30 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 && lstrlen( pwszUser ) != 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. 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, strServer,
  345. 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 E_ACCESSDENIED:
  354. break;
  355. case WBEM_E_LOCAL_CREDENTIALS:
  356. // needs to do special processing
  357. break;
  358. case WBEM_E_ACCESS_DENIED:
  359. default:
  360. GetWbemErrorText( hRes );
  361. DISPLAY_MESSAGE( stderr, ERROR_TAG );
  362. DISPLAY_MESSAGE( stderr, GetReason() );
  363. return( FALSE ); // no use of accepting the password .. return failure
  364. }
  365. // if failed in establishing connection to the remote terminal
  366. // even if the password is specifed, then there is nothing to do ... simply return failure
  367. if ( bNeedPassword == FALSE )
  368. {
  369. GetWbemErrorText( hRes );
  370. DISPLAY_MESSAGE( stderr, ERROR_TAG );
  371. DISPLAY_MESSAGE( stderr, GetReason() );
  372. return FALSE;
  373. }
  374. }
  375. // check whether user name is specified or not
  376. // if not, get the local system's current user name under whose credentials, the process
  377. // is running
  378. if ( strUserName.GetLength() == 0 )
  379. {
  380. // sub-local variables
  381. LPWSTR pwszUserName = NULL;
  382. try
  383. {
  384. // get the required buffer
  385. pwszUserName = strUserName.GetBufferSetLength( MAX_STRING_LENGTH );
  386. }
  387. catch( ... )
  388. {
  389. SetLastError( E_OUTOFMEMORY );
  390. SaveLastError();
  391. DISPLAY_MESSAGE( stderr, ERROR_TAG );
  392. ShowLastError( stderr );
  393. return FALSE;
  394. }
  395. // get the user name
  396. _TCHAR szUserName[MAX_RES_STRING];
  397. ULONG ulLong = MAX_RES_STRING;
  398. if ( GetUserNameEx ( NameSamCompatible, szUserName , &ulLong)== FALSE )
  399. {
  400. // error occured while trying to get the current user info
  401. SaveLastError();
  402. DISPLAY_MESSAGE( stderr, ERROR_TAG );
  403. ShowLastError( stderr );
  404. return FALSE;
  405. }
  406. lstrcpy(pwszUserName,szUserName);
  407. // format the user name
  408. if ( _tcschr( pwszUserName, _T( '\\' ) ) == NULL )
  409. {
  410. // server not present in user name ... prepare ... this is only for display purpose
  411. FORMAT_STRING2( szBuffer, _T( "%s\\%s" ), strServer, szUserName );
  412. lstrcpy( pwszUserName, szBuffer );
  413. }
  414. // release the extra buffer allocated
  415. strUserName.ReleaseBuffer();
  416. }
  417. try
  418. {
  419. // get the required buffer
  420. pwszPassword = strPassword.GetBufferSetLength( MAX_STRING_LENGTH );
  421. }
  422. catch( ... )
  423. {
  424. SetLastError( E_OUTOFMEMORY );
  425. SaveLastError();
  426. DISPLAY_MESSAGE( stderr, ERROR_TAG );
  427. ShowLastError( stderr );
  428. return FALSE;
  429. }
  430. // accept the password from the user
  431. strBuffer.Format( INPUT_PASSWORD, strUserName );
  432. WriteConsoleW( GetStdHandle( STD_ERROR_HANDLE ),
  433. strBuffer, strBuffer.GetLength(), &dwSize, NULL );
  434. GetPassword( pwszPassword, MAX_PASSWORD_LENGTH );
  435. // release the buffer allocated for password
  436. strPassword.ReleaseBuffer();
  437. // now again try to establish the connection using the currently
  438. // supplied credentials
  439. bResult = ConnectWmi( pLocator, ppServices, strServer,
  440. strUserName, strPassword, ppAuthIdentity, FALSE, pwszNamespace, &hRes, pbLocalSystem );
  441. if( bResult == FALSE )
  442. {
  443. GetWbemErrorText( hRes );
  444. DISPLAY_MESSAGE( stderr, ERROR_TAG );
  445. DISPLAY_MESSAGE( stderr, GetReason() );
  446. return( FALSE ); // no use of accepting the password .. return failure
  447. }
  448. // return the success
  449. return bResult;
  450. }
  451. // ***************************************************************************
  452. // Routine Description:
  453. // Gets the security arguments for an interface.
  454. //
  455. // Arguments:
  456. // pInterface [in] - Pointer to interface stucture.
  457. // dwAuthorization [in/out] - Holds Authorization value.
  458. // dwAuthentication [in/out] - Holds the Authentication value.
  459. //
  460. // Return Value:
  461. // Returns HRESULT value.
  462. // ***************************************************************************
  463. HRESULT GetSecurityArguments( IUnknown *pInterface,
  464. DWORD& dwAuthorization, DWORD& dwAuthentication )
  465. {
  466. // local variables
  467. HRESULT hRes = 0;
  468. DWORD dwAuthnSvc = 0, dwAuthzSvc = 0;
  469. IClientSecurity *pClientSecurity = NULL;
  470. if(pInterface == NULL)
  471. {
  472. return WBEM_E_INVALID_PARAMETER; ;
  473. }
  474. // try to get the client security services values if possible
  475. hRes = pInterface->QueryInterface( IID_IClientSecurity, (void**) &pClientSecurity );
  476. if ( SUCCEEDED( hRes ) )
  477. {
  478. // got the client security interface
  479. // now try to get the security services values
  480. hRes = pClientSecurity->QueryBlanket( pInterface,
  481. &dwAuthnSvc, &dwAuthzSvc, NULL, NULL, NULL, NULL, NULL );
  482. if ( SUCCEEDED( hRes ) )
  483. {
  484. // we've got the values from the interface
  485. dwAuthentication = dwAuthnSvc;
  486. dwAuthorization = dwAuthzSvc;
  487. }
  488. // release the client security interface
  489. SAFEIRELEASE( pClientSecurity );
  490. }
  491. // return always success
  492. return S_OK;
  493. }
  494. // ***************************************************************************
  495. // Routine Description:
  496. // Sets the interface security for the interface.
  497. //
  498. // Arguments:
  499. // pInterface [in] - pointer to the interface.
  500. // pAuthIdentity [in] - pointer to authentication structure.
  501. //
  502. // Return Value:
  503. // returns HRESULT value.
  504. // ***************************************************************************
  505. HRESULT SetInterfaceSecurity( IUnknown *pInterface, COAUTHIDENTITY *pAuthIdentity )
  506. {
  507. // local variables
  508. HRESULT hRes;
  509. LPWSTR pwszDomain = NULL;
  510. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  511. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  512. // check the interface
  513. if ( pInterface == NULL )
  514. {
  515. return WBEM_E_INVALID_PARAMETER;
  516. }
  517. // get the current security argument value
  518. // GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  519. // set the security information to the interface
  520. hRes = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  521. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
  522. // return the result
  523. return hRes;
  524. }
  525. // ***************************************************************************
  526. // Routine Description:
  527. // Sets proxy blanket for the interface.
  528. //
  529. // Arguments:
  530. // pInterface [in] - pointer to the inteface.
  531. // dwAuthnsvc [in] - Authentication service to use.
  532. // dwAuthzSvc [in] - Authorization service to use.
  533. // pwszPricipal [in] - Server principal name to use with the authentication service.
  534. // dwAuthLevel [in] - Authentication level to use.
  535. // dwImpLevel [in] - Impersonation level to use.
  536. // pAuthInfo [in] - Identity of the client.
  537. // dwCapabilities [in] - Capability flags.
  538. //
  539. // Return Value:
  540. // Return HRESULT value.
  541. //
  542. // ***************************************************************************
  543. HRESULT WINAPI SetProxyBlanket( IUnknown *pInterface,
  544. DWORD dwAuthnSvc, DWORD dwAuthzSvc,
  545. LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
  546. RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities )
  547. {
  548. // local variables
  549. HRESULT hRes;
  550. IUnknown *pUnknown = NULL;
  551. IClientSecurity *pClientSecurity = NULL;
  552. if( pInterface == NULL )
  553. {
  554. return WBEM_E_INVALID_PARAMETER;
  555. }
  556. // get the IUnknown interface ... to check whether this is a valid interface or not
  557. hRes = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
  558. if ( hRes != S_OK )
  559. {
  560. return hRes;
  561. }
  562. // now get the client security interface
  563. hRes = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  564. if ( hRes != S_OK )
  565. {
  566. SAFEIRELEASE( pUnknown );
  567. return hRes;
  568. }
  569. //
  570. // Can't set pAuthInfo if cloaking requested, as cloaking implies
  571. // that the current proxy identity in the impersonated thread (rather
  572. // than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
  573. // is to be used.
  574. // See MSDN info on CoSetProxyBlanket for more details.
  575. //
  576. if ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) )
  577. pAuthInfo = NULL;
  578. // now set the security
  579. hRes = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  580. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  581. // release the security interface
  582. SAFEIRELEASE( pClientSecurity );
  583. // we should check the auth identity structure. if exists .. set for IUnknown also
  584. if ( pAuthInfo != NULL )
  585. {
  586. hRes = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  587. if ( hRes == S_OK )
  588. {
  589. // set security authentication
  590. hRes = pClientSecurity->SetBlanket(
  591. pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  592. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  593. // release
  594. SAFEIRELEASE( pClientSecurity );
  595. }
  596. else if ( hRes == E_NOINTERFACE )
  597. hRes = S_OK; // ignore no interface errors
  598. }
  599. // release the IUnknown
  600. SAFEIRELEASE( pUnknown );
  601. // return the result
  602. return hRes;
  603. }
  604. // ***************************************************************************
  605. // Routine Description:
  606. // Allocate memory for authentication variables.
  607. //
  608. // Arguments:
  609. // pwszUser [in/out] - User name.
  610. // pwszPassword [in/out] - Password.
  611. // pwszDomain [in/out] - Domain name.
  612. // ppAuthIdent [in/out] - Poointer to authentication structure.
  613. //
  614. // Return Value:
  615. // Returns HRESULT value.
  616. // ***************************************************************************
  617. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
  618. LPCWSTR pwszDomain, COAUTHIDENTITY **ppAuthIdent )
  619. {
  620. // local variables
  621. COAUTHIDENTITY* pAuthIdent = NULL;
  622. // validate the input parameter
  623. if ( ppAuthIdent == NULL )
  624. return WBEM_E_INVALID_PARAMETER;
  625. // allocation thru COM API
  626. pAuthIdent = ( COAUTHIDENTITY* ) CoTaskMemAlloc( sizeof( COAUTHIDENTITY ) );
  627. if ( NULL == pAuthIdent )
  628. return WBEM_E_OUT_OF_MEMORY;
  629. // init with 0's
  630. ZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
  631. //
  632. // Allocate needed memory and copy in data. Cleanup if anything goes wrong
  633. // user
  634. if ( pwszUser != NULL )
  635. {
  636. // allocate memory for user
  637. LONG lLength = wcslen( pwszUser );
  638. pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  639. if ( pAuthIdent->User == NULL )
  640. {
  641. WbemFreeAuthIdentity( &pAuthIdent );
  642. return WBEM_E_OUT_OF_MEMORY;
  643. }
  644. // set the length and do copy contents
  645. pAuthIdent->UserLength = lLength;
  646. wcscpy( pAuthIdent->User, pwszUser );
  647. }
  648. // domain
  649. if ( pwszDomain != NULL )
  650. {
  651. // allocate memory for domain
  652. LONG lLength = wcslen( pwszDomain );
  653. pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  654. if ( pAuthIdent->Domain == NULL )
  655. {
  656. WbemFreeAuthIdentity( &pAuthIdent );
  657. return WBEM_E_OUT_OF_MEMORY;
  658. }
  659. // set the length and do copy contents
  660. pAuthIdent->DomainLength = lLength;
  661. wcscpy( pAuthIdent->Domain, pwszDomain );
  662. }
  663. // passsord
  664. if ( pwszPassword != NULL )
  665. {
  666. // allocate memory for passsord
  667. LONG lLength = wcslen( pwszPassword );
  668. pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  669. if ( pAuthIdent->Password == NULL )
  670. {
  671. WbemFreeAuthIdentity( &pAuthIdent );
  672. return WBEM_E_OUT_OF_MEMORY;
  673. }
  674. // set the length and do copy contents
  675. pAuthIdent->PasswordLength = lLength;
  676. wcscpy( pAuthIdent->Password, pwszPassword );
  677. }
  678. // type of the structure
  679. pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  680. // final set the address to out parameter
  681. *ppAuthIdent = pAuthIdent;
  682. // return result
  683. return S_OK;
  684. }
  685. // ***************************************************************************
  686. // Routine Description:
  687. // Frees the memory of authentication stucture variable.
  688. //
  689. // Arguments:
  690. // ppAuthIdentity [in] - Pointer to authentication structure.
  691. //
  692. // Return Value:
  693. // none.
  694. // ***************************************************************************
  695. VOID WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY** ppAuthIdentity )
  696. {
  697. // make sure we have a pointer, then walk the structure members and cleanup.
  698. if ( *ppAuthIdentity != NULL )
  699. {
  700. // free the memory allocated for user
  701. if ( (*ppAuthIdentity)->User != NULL )
  702. CoTaskMemFree( (*ppAuthIdentity)->User );
  703. // free the memory allocated for password
  704. if ( (*ppAuthIdentity)->Password != NULL )
  705. CoTaskMemFree( (*ppAuthIdentity)->Password );
  706. // free the memory allocated for domain
  707. if ( (*ppAuthIdentity)->Domain != NULL )
  708. CoTaskMemFree( (*ppAuthIdentity)->Domain );
  709. // final the structure
  710. CoTaskMemFree( *ppAuthIdentity );
  711. }
  712. // set to NULL
  713. *ppAuthIdentity = NULL;
  714. }
  715. // ***************************************************************************
  716. // Routine Description: checks if a user name is valid.
  717. //
  718. // Arguments: UserName
  719. //
  720. // Return Value: BOOL
  721. //
  722. // ***************************************************************************
  723. BOOL IsValidUserEx( LPCWSTR pwszUser )
  724. {
  725. // local variables
  726. CHString strUser;
  727. try
  728. {
  729. // get user into local memory
  730. strUser = pwszUser;
  731. // user name should not be just '\'
  732. if ( strUser.CompareNoCase( L"\\" ) == 0 )
  733. return FALSE;
  734. // user name should not contain invalid characters
  735. if ( strUser.FindOneOf( L"/[]:|<>+=;,?*" ) != -1 )
  736. return FALSE;
  737. }
  738. catch( ... )
  739. {
  740. SetLastError( E_OUTOFMEMORY );
  741. return FALSE;
  742. }
  743. // user name is valid
  744. return TRUE;
  745. }
  746. // ***************************************************************************
  747. // Routine Description:
  748. // Sets interface security.
  749. //
  750. // Arguments:
  751. // pInterface [in] - Pointer to the interface to which security has to be set.
  752. // pwszServer [in] - Holds the server name of the interface.
  753. // pwszUser [in] - Holds the user name of the server.
  754. // pwszPassword [in] - Hold the password of the user.
  755. // ppAuthIdentity [in/out] - Pointer to authentication structure.
  756. //
  757. // Return Value:
  758. // returns HRESULT value.
  759. // ***************************************************************************
  760. HRESULT SetInterfaceSecurity( IUnknown* pInterface,
  761. LPCWSTR pwszServer, LPCWSTR pwszUser,
  762. LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity )
  763. {
  764. // local variables
  765. HRESULT hr=0;
  766. CHString strUser;
  767. CHString strDomain;
  768. LPCWSTR pwszUserArg = NULL;
  769. LPCWSTR pwszDomainArg = NULL;
  770. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  771. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  772. // check the interface
  773. if ( pInterface == NULL )
  774. {
  775. return WBEM_E_INVALID_PARAMETER;
  776. }
  777. // check the authentity strcuture ... if authentity structure is already ready
  778. // simply invoke the 2nd version of SetInterfaceSecurity
  779. if ( *ppAuthIdentity != NULL )
  780. {
  781. return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
  782. }
  783. // get the current security argument value
  784. // GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  785. // If we are doing trivial case, just pass in a null authenication structure
  786. // for which the current logged in user's credentials will be considered
  787. if ( pwszUser == NULL && pwszPassword == NULL )
  788. {
  789. // set the security
  790. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
  791. NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  792. // return the result
  793. return hr;
  794. }
  795. // parse and find out if the user name contains the domain name
  796. // if contains, extract the domain value from it
  797. LONG lPos = -1;
  798. strDomain = L"";
  799. strUser = pwszUser;
  800. if ( ( lPos = strUser.Find( L'\\' ) ) != -1 )
  801. {
  802. // user name contains domain name ... domain\user format
  803. strDomain = strUser.Left( lPos );
  804. strUser = strUser.Mid( lPos + 1 );
  805. }
  806. // get the domain info if it exists only
  807. if ( strDomain.GetLength() != 0 )
  808. {
  809. pwszDomainArg = strDomain;
  810. }
  811. // get the user info if it exists only
  812. if ( strUser.GetLength() != 0 )
  813. {
  814. pwszUserArg = strUser;
  815. }
  816. // check if authentication info is available or not ...
  817. // initialize the security authenication information ... UNICODE VERSION STRUCTURE
  818. if ( ppAuthIdentity == NULL )
  819. {
  820. return WBEM_E_INVALID_PARAMETER;
  821. }
  822. else if ( *ppAuthIdentity == NULL )
  823. {
  824. hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
  825. if ( hr != S_OK )
  826. {
  827. return hr;
  828. }
  829. }
  830. // set the security information to the interface
  831. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  832. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
  833. // return the result
  834. return hr;
  835. }
  836. // ***************************************************************************
  837. // Routine Description:
  838. // Gets WMI error description.
  839. //
  840. // Arguments:
  841. // hResError [in] - Contain error value.
  842. //
  843. // Return Value:
  844. // none.
  845. // ***************************************************************************
  846. VOID WMISaveError( HRESULT hResError )
  847. {
  848. // local variables
  849. HRESULT hRes;
  850. CHString strBuffer = NULL_STRING;
  851. IWbemStatusCodeText *pWbemStatus = NULL;
  852. // if the error is win32 based, choose FormatMessage to get the message
  853. switch( hResError )
  854. {
  855. case E_ACCESSDENIED: // Message: "Access Denied"
  856. case ERROR_NO_SUCH_USER: // Message: "The specified user does not exist."
  857. {
  858. // change the error message to "Logon failure: unknown user name or bad password."
  859. if ( hResError == E_ACCESSDENIED )
  860. {
  861. hResError = ERROR_LOGON_FAILURE;
  862. }
  863. // ...
  864. SetLastError( hResError );
  865. SaveLastError();
  866. return;
  867. }
  868. }
  869. try
  870. {
  871. // get the pointer to buffer
  872. LPWSTR pwszBuffer = NULL;
  873. pwszBuffer = strBuffer.GetBufferSetLength( MAX_STRING_LENGTH );
  874. // get the wbem specific status code text
  875. hRes = CoCreateInstance( CLSID_WbemStatusCodeText,
  876. NULL, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, ( LPVOID* ) &pWbemStatus );
  877. // check whether we got the interface or not
  878. if ( SUCCEEDED( hRes ) )
  879. {
  880. // get the error message
  881. BSTR bstr = NULL;
  882. hRes = pWbemStatus->GetErrorCodeText( hResError, 0, 0, &bstr );
  883. if ( SUCCEEDED( hRes ) )
  884. {
  885. // get the error message in proper format
  886. GetCompatibleStringFromUnicode( bstr, pwszBuffer, MAX_STRING_LENGTH );
  887. //
  888. // supress all the new-line characters and add '.' at the end ( if not exists )
  889. LPWSTR pwszTemp = NULL;
  890. pwszTemp = wcstok( pwszBuffer, L"\r\n" );
  891. if( pwszTemp == NULL )
  892. {
  893. _com_issue_error( WBEM_E_INVALID_PARAMETER );
  894. }
  895. if ( *( pwszTemp + lstrlenW( pwszTemp ) - 1 ) != L'.' )
  896. {
  897. lstrcatW( pwszTemp, L"." );
  898. }
  899. // free the BSTR
  900. SysFreeString( bstr );
  901. bstr = NULL;
  902. // now release status code interface
  903. SAFE_RELEASE( pWbemStatus );
  904. }
  905. else
  906. {
  907. // failed to get the error message ... get the com specific error message
  908. _com_issue_error( hResError );
  909. }
  910. }
  911. else
  912. {
  913. // failed to get the error message ... get the com specific error message
  914. _com_issue_error( hResError );
  915. }
  916. // release the buffer
  917. strBuffer.ReleaseBuffer();
  918. }
  919. catch( _com_error& e )
  920. {
  921. try
  922. {
  923. // get the error message
  924. strBuffer.ReleaseBuffer();
  925. if ( e.ErrorMessage() != NULL )
  926. strBuffer = e.ErrorMessage();
  927. }
  928. catch( ... )
  929. {
  930. SetLastError( E_OUTOFMEMORY );
  931. SaveLastError();
  932. }
  933. }
  934. catch( ... )
  935. {
  936. SetLastError( E_OUTOFMEMORY );
  937. SaveLastError();
  938. return;
  939. }
  940. // set the reason
  941. strBuffer += L"\n";
  942. SetReason( strBuffer );
  943. }