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.

1203 lines
38 KiB

  1. /*++
  2. Copyright Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. COMINIT.CPP
  5. Abstract:
  6. WMI COM Helper functions
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <wbemidl.h>
  11. #define _COMINIT_CPP_
  12. #include "cominit.h"
  13. #include "autobstr.h"
  14. BOOL WINAPI DoesContainCredentials( COAUTHIDENTITY* pAuthIdentity )
  15. {
  16. try
  17. {
  18. if ( NULL != pAuthIdentity && COLE_DEFAULT_AUTHINFO != pAuthIdentity)
  19. {
  20. return ( pAuthIdentity->UserLength != 0 || pAuthIdentity->PasswordLength != 0 );
  21. }
  22. return FALSE;
  23. }
  24. catch(...)
  25. {
  26. return FALSE;
  27. }
  28. }
  29. HRESULT WINAPI WbemSetProxyBlanket(
  30. IUnknown *pInterface,
  31. DWORD dwAuthnSvc,
  32. DWORD dwAuthzSvc,
  33. OLECHAR *pServerPrincName,
  34. DWORD dwAuthLevel,
  35. DWORD dwImpLevel,
  36. RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
  37. DWORD dwCapabilities,
  38. bool fIgnoreUnk )
  39. {
  40. IUnknown * pUnk = NULL;
  41. IClientSecurity * pCliSec = NULL;
  42. HRESULT sc = pInterface->QueryInterface(IID_IUnknown, (void **) &pUnk);
  43. if(sc != S_OK)
  44. return sc;
  45. sc = pInterface->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
  46. if(sc != S_OK)
  47. {
  48. pUnk->Release();
  49. return sc;
  50. }
  51. /*
  52. * Can't set pAuthInfo if cloaking requested, as cloaking implies
  53. * that the current proxy identity in the impersonated thread (rather
  54. * than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
  55. * is to be used.
  56. * See MSDN info on CoSetProxyBlanket for more details.
  57. */
  58. if (dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING))
  59. pAuthInfo = NULL;
  60. sc = pCliSec->SetBlanket(pInterface, dwAuthnSvc, dwAuthzSvc, pServerPrincName,
  61. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities);
  62. pCliSec->Release();
  63. pCliSec = NULL;
  64. // If we are not explicitly told to ignore the IUnknown, then we should
  65. // check the auth identity structure. This performs a heuristic which
  66. // assumes a COAUTHIDENTITY structure. If the structure is not one, we're
  67. // wrapped with a try/catch in case we AV (this should be benign since
  68. // we're not writing to memory).
  69. if ( !fIgnoreUnk && DoesContainCredentials( (COAUTHIDENTITY*) pAuthInfo ) )
  70. {
  71. sc = pUnk->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
  72. if(sc == S_OK)
  73. {
  74. sc = pCliSec->SetBlanket(pUnk, dwAuthnSvc, dwAuthzSvc, pServerPrincName,
  75. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities);
  76. pCliSec->Release();
  77. }
  78. else if (sc == 0x80004002)
  79. sc = S_OK;
  80. }
  81. pUnk->Release();
  82. return sc;
  83. }
  84. BOOL WINAPI IsDcomEnabled()
  85. {
  86. return TRUE;
  87. }
  88. HRESULT WINAPI InitializeCom()
  89. {
  90. return CoInitializeEx(0, COINIT_MULTITHREADED);
  91. }
  92. HRESULT WINAPI InitializeSecurity(
  93. PSECURITY_DESCRIPTOR pSecDesc,
  94. LONG cAuthSvc,
  95. SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
  96. void *pReserved1,
  97. DWORD dwAuthnLevel,
  98. DWORD dwImpLevel,
  99. void *pReserved2,
  100. DWORD dwCapabilities,
  101. void *pReserved3)
  102. {
  103. // Initialize security
  104. return CoInitializeSecurity(pSecDesc,
  105. cAuthSvc,
  106. asAuthSvc,
  107. pReserved1,
  108. dwAuthnLevel,
  109. dwImpLevel,
  110. pReserved2,
  111. dwCapabilities,
  112. pReserved3);
  113. }
  114. DWORD WINAPI WbemWaitForMultipleObjects(DWORD nCount, HANDLE* ahHandles, DWORD dwMilli)
  115. {
  116. MSG msg;
  117. DWORD dwRet;
  118. while(1)
  119. {
  120. dwRet = MsgWaitForMultipleObjects(nCount, ahHandles, FALSE, dwMilli,
  121. QS_SENDMESSAGE);
  122. if(dwRet == (WAIT_OBJECT_0 + nCount))
  123. {
  124. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  125. DispatchMessage(&msg);
  126. }
  127. continue;
  128. }
  129. else
  130. {
  131. break;
  132. }
  133. }
  134. return dwRet;
  135. }
  136. DWORD WINAPI WbemWaitForSingleObject(HANDLE hHandle, DWORD dwMilli)
  137. {
  138. return WbemWaitForMultipleObjects(1, &hHandle, dwMilli);
  139. }
  140. HRESULT WINAPI WbemCoCreateInstance(REFCLSID rclsid, IUnknown* pUnkOuter,
  141. DWORD dwClsContext, REFIID riid, void** ppv)
  142. {
  143. if(!IsDcomEnabled())
  144. {
  145. dwClsContext &= ~CLSCTX_REMOTE_SERVER;
  146. }
  147. return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
  148. }
  149. HRESULT WINAPI WbemCoGetClassObject(REFCLSID rclsid, DWORD dwClsContext,
  150. COSERVERINFO* pServerInfo, REFIID riid, void** ppv)
  151. {
  152. if(!IsDcomEnabled())
  153. {
  154. dwClsContext &= ~CLSCTX_REMOTE_SERVER;
  155. }
  156. return CoGetClassObject(rclsid, dwClsContext, pServerInfo, riid, ppv);
  157. }
  158. HRESULT WINAPI WbemCoGetCallContext(REFIID riid, void** ppv)
  159. {
  160. return CoGetCallContext(riid, ppv);
  161. }
  162. HRESULT WINAPI WbemCoSwitchCallContext( IUnknown *pNewObject, IUnknown **ppOldObject )
  163. {
  164. return CoSwitchCallContext(pNewObject, ppOldObject);
  165. }
  166. //***************************************************************************
  167. //
  168. // SCODE DetermineLoginType
  169. //
  170. // DESCRIPTION:
  171. //
  172. // Examines the Authority and User argument and determines the authentication
  173. // type and possibly extracts the domain name from the user arugment in the
  174. // NTLM case. For NTLM, the domain can be at the end of the authentication
  175. // string, or in the front of the user name, ex; "redmond\a-davj"
  176. //
  177. // PARAMETERS:
  178. //
  179. // AuthArg Output, contains the domain name
  180. // UserArg Output, user name
  181. // Authority Input
  182. // User Input
  183. //
  184. // RETURN VALUE:
  185. //
  186. // S_OK all is well
  187. // else error listed in WBEMSVC.H
  188. //
  189. //***************************************************************************
  190. SCODE WINAPI DetermineLoginType(BSTR & AuthArg_out, BSTR & UserArg_out,
  191. BSTR Authority,BSTR User)
  192. {
  193. // Determine the connection type by examining the Authority string
  194. auto_bstr AuthArg(NULL);
  195. auto_bstr UserArg(NULL);
  196. if(!(Authority == NULL || wcslen(Authority) == 0 || !wbem_wcsnicmp(Authority, L"NTLMDOMAIN:",11)))
  197. return WBEM_E_INVALID_PARAMETER;
  198. // The ntlm case is more complex. There are four cases
  199. // 1) Authority = NTLMDOMAIN:name" and User = "User"
  200. // 2) Authority = NULL and User = "User"
  201. // 3) Authority = "NTLMDOMAIN:" User = "domain\user"
  202. // 4) Authority = NULL and User = "domain\user"
  203. // first step is to determine if there is a backslash in the user name somewhere between the
  204. // second and second to last character
  205. WCHAR * pSlashInUser = NULL;
  206. if(User)
  207. {
  208. WCHAR * pEnd = User + wcslen(User) - 1;
  209. for(pSlashInUser = User; pSlashInUser <= pEnd; pSlashInUser++)
  210. if(*pSlashInUser == L'\\') // dont think forward slash is allowed!
  211. break;
  212. if(pSlashInUser > pEnd)
  213. pSlashInUser = NULL;
  214. }
  215. if(Authority && wcslen(Authority) > 11)
  216. {
  217. if(pSlashInUser)
  218. return WBEM_E_INVALID_PARAMETER;
  219. AuthArg = auto_bstr(SysAllocString(Authority + 11));
  220. if (NULL == AuthArg.get()) return WBEM_E_OUT_OF_MEMORY;
  221. if(User)
  222. {
  223. UserArg = auto_bstr(SysAllocString(User));
  224. if (NULL == UserArg.get()) return WBEM_E_OUT_OF_MEMORY;
  225. }
  226. }
  227. else if(pSlashInUser)
  228. {
  229. DWORD_PTR iDomLen = pSlashInUser-User;
  230. AuthArg = auto_bstr(SysAllocStringLen(User,iDomLen));
  231. if (NULL == AuthArg.get()) return WBEM_E_OUT_OF_MEMORY;
  232. if(wcslen(pSlashInUser+1))
  233. {
  234. UserArg = auto_bstr(SysAllocString(pSlashInUser+1));
  235. if (NULL == UserArg.get()) return WBEM_E_OUT_OF_MEMORY;
  236. }
  237. }
  238. else
  239. {
  240. if(User)
  241. {
  242. UserArg = auto_bstr(SysAllocString(User));
  243. if (NULL == UserArg.get()) return WBEM_E_OUT_OF_MEMORY;
  244. }
  245. }
  246. AuthArg_out = AuthArg.release();
  247. UserArg_out = UserArg.release();
  248. return S_OK;
  249. }
  250. //***************************************************************************
  251. //
  252. // SCODE DetermineLoginTypeEx
  253. //
  254. // DESCRIPTION:
  255. //
  256. // Extended version that supports Kerberos. To do so, the authority string
  257. // must start with Kerberos: and the other parts be compatible with the normal
  258. // login. Ie, user should be domain\user.
  259. //
  260. // PARAMETERS:
  261. //
  262. // AuthArg Output, contains the domain name
  263. // UserArg Output, user name
  264. // PrincipalArg Output, user name
  265. // Authority Input
  266. // User Input
  267. //
  268. // RETURN VALUE:
  269. //
  270. // S_OK all is well
  271. // else error listed in WBEMSVC.H
  272. //
  273. //***************************************************************************
  274. SCODE WINAPI DetermineLoginTypeEx(BSTR & AuthArg, BSTR & UserArg,BSTR & PrincipalArg_out,
  275. BSTR Authority,BSTR User)
  276. {
  277. // Normal case, just let existing code handle it
  278. PrincipalArg_out = NULL;
  279. if(Authority == NULL || wbem_wcsnicmp(Authority, L"KERBEROS:",9))
  280. return DetermineLoginType(AuthArg, UserArg, Authority, User);
  281. if(!IsKerberosAvailable())
  282. return WBEM_E_INVALID_PARAMETER;
  283. auto_bstr PrincipalArg( SysAllocString(&Authority[9]));
  284. if (NULL == PrincipalArg.get()) return WBEM_E_OUT_OF_MEMORY;
  285. SCODE sc = DetermineLoginType(AuthArg, UserArg, NULL, User);
  286. if (S_OK == sc)
  287. {
  288. PrincipalArg_out = PrincipalArg.release();
  289. }
  290. return sc;
  291. }
  292. //***************************************************************************
  293. //
  294. // bool bIsNT
  295. //
  296. // DESCRIPTION:
  297. //
  298. // Returns true if running windows NT.
  299. //
  300. // RETURN VALUE:
  301. //
  302. // see description.
  303. //
  304. //***************************************************************************
  305. bool WINAPI bIsNT(void)
  306. {
  307. OSVERSIONINFO os;
  308. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  309. if(!GetVersionEx(&os))
  310. return FALSE; // should never happen
  311. return os.dwPlatformId == VER_PLATFORM_WIN32_NT;
  312. }
  313. //***************************************************************************
  314. //
  315. // bool IsKeberosAvailable
  316. //
  317. // DESCRIPTION:
  318. //
  319. // Returns true if Kerberos is available.
  320. //
  321. // RETURN VALUE:
  322. //
  323. // see description.
  324. //
  325. //***************************************************************************
  326. BOOL WINAPI IsKerberosAvailable(void)
  327. {
  328. OSVERSIONINFO os;
  329. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  330. if(!GetVersionEx(&os))
  331. return FALSE; // should never happen
  332. // IMPORTANT!! This will need to be chanted if Kerberos is ever ported to 98
  333. return ( os.dwPlatformId == VER_PLATFORM_WIN32_NT ) && ( os.dwMajorVersion >= 5 ) ;
  334. }
  335. //***************************************************************************
  336. //
  337. // bool IsAuthenticated
  338. //
  339. // DESCRIPTION:
  340. //
  341. // This routine is used by clients in check if an interface pointer is using
  342. // authentication.
  343. //
  344. // PARAMETERS:
  345. //
  346. // pFrom the interface to be tested.
  347. //
  348. // RETURN VALUE:
  349. //
  350. // S_OK all is well
  351. // else error listed in WBEMSVC.H
  352. //
  353. //***************************************************************************
  354. bool WINAPI IsAuthenticated(IUnknown * pFrom)
  355. {
  356. bool bAuthenticate = true;
  357. if(pFrom == NULL)
  358. return true;
  359. IClientSecurity * pFromSec = NULL;
  360. SCODE sc = pFrom->QueryInterface(IID_IClientSecurity, (void **) &pFromSec);
  361. if(sc == S_OK)
  362. {
  363. DWORD dwAuthnSvc, dwAuthzSvc, dwAuthnLevel, dwImpLevel, dwCapabilities;
  364. sc = pFromSec->QueryBlanket(pFrom, &dwAuthnSvc, &dwAuthzSvc,
  365. NULL,
  366. &dwAuthnLevel, &dwImpLevel,
  367. NULL, &dwCapabilities);
  368. if (sc == 0x800706d2 || (sc == S_OK && dwAuthnLevel == RPC_C_AUTHN_LEVEL_NONE))
  369. bAuthenticate = false;
  370. pFromSec->Release();
  371. }
  372. return bAuthenticate;
  373. }
  374. //***************************************************************************
  375. //
  376. // SCODE GetAuthImp
  377. //
  378. // DESCRIPTION:
  379. //
  380. // Gets the authentication and impersonation levels for a current interface.
  381. //
  382. // PARAMETERS:
  383. //
  384. // pFrom the interface to be tested.
  385. // pdwAuthLevel
  386. //
  387. // RETURN VALUE:
  388. //
  389. // S_OK all is well
  390. // else error listed in WBEMSVC.H
  391. //
  392. //***************************************************************************
  393. SCODE WINAPI GetAuthImp(IUnknown * pFrom, DWORD * pdwAuthLevel, DWORD * pdwImpLevel)
  394. {
  395. if(pFrom == NULL || pdwAuthLevel == NULL || pdwImpLevel == NULL)
  396. return WBEM_E_INVALID_PARAMETER;
  397. IClientSecurity * pFromSec = NULL;
  398. SCODE sc = pFrom->QueryInterface(IID_IClientSecurity, (void **) &pFromSec);
  399. if(sc == S_OK)
  400. {
  401. DWORD dwAuthnSvc, dwAuthzSvc, dwCapabilities;
  402. sc = pFromSec->QueryBlanket(pFrom, &dwAuthnSvc, &dwAuthzSvc,
  403. NULL,
  404. pdwAuthLevel, pdwImpLevel,
  405. NULL, &dwCapabilities);
  406. // Special case of going to a win9x share level box
  407. if (sc == 0x800706d2)
  408. {
  409. *pdwAuthLevel = RPC_C_AUTHN_LEVEL_NONE;
  410. *pdwImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
  411. sc = S_OK;
  412. }
  413. pFromSec->Release();
  414. }
  415. return sc;
  416. }
  417. void GetCurrentValue(IUnknown * pFrom,DWORD & dwAuthnSvc, DWORD & dwAuthzSvc)
  418. {
  419. if(pFrom == NULL)
  420. return;
  421. IClientSecurity * pFromSec = NULL;
  422. SCODE sc = pFrom->QueryInterface(IID_IClientSecurity, (void **) &pFromSec);
  423. if(sc == S_OK)
  424. {
  425. sc = pFromSec->QueryBlanket(pFrom,
  426. &dwAuthnSvc,
  427. &dwAuthzSvc,
  428. NULL,NULL, NULL,NULL, NULL);
  429. pFromSec->Release();
  430. }
  431. }
  432. //***************************************************************************
  433. //
  434. // SCODE SetInterfaceSecurity
  435. //
  436. // DESCRIPTION:
  437. //
  438. // This routine is used by clients in order to set the identity to be used by a connection.
  439. //
  440. // PARAMETERS:
  441. //
  442. // pInterface Interface to be set
  443. // pDomain Input, domain
  444. // pUser Input, user name
  445. // pPassword Input, password.
  446. // pFrom Input, if not NULL, then the authentication level of this interface
  447. // is used
  448. // bAuthArg If pFrom is NULL, then this is the authentication level
  449. // RETURN VALUE:
  450. //
  451. // S_OK all is well
  452. // else error listed in WBEMSVC.H
  453. //
  454. //***************************************************************************
  455. HRESULT WINAPI SetInterfaceSecurity(IUnknown * pInterface,
  456. LPWSTR pAuthority, LPWSTR pUser, LPWSTR pPassword,
  457. IUnknown * pFrom, bool bAuthArg /*=true*/)
  458. {
  459. SCODE sc;
  460. if(pInterface == NULL)
  461. return WBEM_E_INVALID_PARAMETER;
  462. // Check the source pointer to determine if we are running in a non authenticated mode which
  463. // would be the case when connected to a Win9X box which is using share level security
  464. bool bAuthenticate = true;
  465. if(pFrom)
  466. bAuthenticate = IsAuthenticated(pFrom);
  467. else
  468. bAuthenticate = bAuthArg;
  469. // If we are doing trivial case, just pass in a null authenication structure which is used
  470. // if the current logged in user's credentials are OK.
  471. if((pAuthority == NULL || wcslen(pAuthority) < 1) &&
  472. (pUser == NULL || wcslen(pUser) < 1) &&
  473. (pPassword == NULL || wcslen(pPassword) < 1))
  474. return SetInterfaceSecurityAuth(pInterface, NULL, bAuthenticate);
  475. // If user, or Authority was passed in, the we need to create an authority argument for the login
  476. BSTR AuthArg = NULL, UserArg = NULL;
  477. BSTR bstrPrincipal = NULL;
  478. sc = DetermineLoginTypeEx(AuthArg, UserArg, bstrPrincipal, pAuthority, pUser);
  479. if(sc != S_OK)
  480. return sc;
  481. COAUTHIDENTITY authident;
  482. memset((void *)&authident,0,sizeof(COAUTHIDENTITY));
  483. if(UserArg)
  484. {
  485. authident.UserLength = wcslen(UserArg);
  486. authident.User = (LPWSTR)UserArg;
  487. }
  488. if(AuthArg)
  489. {
  490. authident.DomainLength = wcslen(AuthArg);
  491. authident.Domain = (LPWSTR)AuthArg;
  492. }
  493. if(pPassword)
  494. {
  495. authident.PasswordLength = wcslen(pPassword);
  496. authident.Password = (LPWSTR)pPassword;
  497. }
  498. authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  499. sc = SetInterfaceSecurityAuth(pInterface, &authident, bAuthenticate);
  500. SysFreeString(UserArg);
  501. SysFreeString(AuthArg);
  502. SysFreeString(bstrPrincipal);
  503. return sc;
  504. }
  505. //***************************************************************************
  506. //
  507. // SCODE SetInterfaceSecurity
  508. //
  509. // DESCRIPTION:
  510. //
  511. // This routine is used by clients in order to set the identity to be used by a connection.
  512. //
  513. // PARAMETERS:
  514. //
  515. // pInterface Interface to be set
  516. // pAuthority Authentication Authority
  517. // pDomain Input, domain
  518. // pUser Input, user name
  519. // pPassword Input, password.
  520. //
  521. // RETURN VALUE:
  522. //
  523. // S_OK all is well
  524. // else error listed in WBEMSVC.H
  525. //
  526. //***************************************************************************
  527. HRESULT WINAPI SetInterfaceSecurity(IUnknown * pInterface,
  528. LPWSTR pAuthority, LPWSTR pUser, LPWSTR pPassword,
  529. DWORD dwAuthLevel, DWORD dwImpLevel, DWORD dwCapabilities)
  530. {
  531. SCODE sc;
  532. if(pInterface == NULL)
  533. return WBEM_E_INVALID_PARAMETER;
  534. DWORD AuthnSvc = RPC_C_AUTHN_WINNT;
  535. DWORD AuthzSvc = RPC_C_AUTHZ_NONE;
  536. GetCurrentValue(pInterface,AuthnSvc,AuthzSvc);
  537. // If we are doing trivial case, just pass in a null authenication structure which is used
  538. // if the current logged in user's credentials are OK.
  539. if((pAuthority == NULL || wcslen(pAuthority) < 1) &&
  540. (pUser == NULL || wcslen(pUser) < 1) &&
  541. (pPassword == NULL || wcslen(pPassword) < 1))
  542. {
  543. sc = WbemSetProxyBlanket(pInterface,
  544. AuthnSvc ,
  545. RPC_C_AUTHZ_NONE, NULL,
  546. dwAuthLevel, dwImpLevel,
  547. NULL,
  548. dwCapabilities);
  549. return sc;
  550. }
  551. // If user, or Authority was passed in, the we need to create an authority argument for the login
  552. BSTR AuthArg = NULL;
  553. BSTR UserArg = NULL;
  554. BSTR PrincipalArg = NULL;
  555. sc = DetermineLoginTypeEx(AuthArg, UserArg, PrincipalArg, pAuthority, pUser);
  556. if(sc != S_OK)
  557. return sc;
  558. COAUTHIDENTITY authident;
  559. memset((void *)&authident,0,sizeof(COAUTHIDENTITY));
  560. if(UserArg)
  561. {
  562. authident.UserLength = wcslen(UserArg);
  563. authident.User = (LPWSTR)UserArg;
  564. }
  565. if(AuthArg)
  566. {
  567. authident.DomainLength = wcslen(AuthArg);
  568. authident.Domain = (LPWSTR)AuthArg;
  569. }
  570. if(pPassword)
  571. {
  572. authident.PasswordLength = wcslen(pPassword);
  573. authident.Password = (LPWSTR)pPassword;
  574. }
  575. authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  576. sc = WbemSetProxyBlanket(pInterface,
  577. (PrincipalArg) ? RPC_C_AUTHN_GSS_KERBEROS : AuthnSvc,
  578. RPC_C_AUTHZ_NONE,
  579. PrincipalArg,
  580. dwAuthLevel, dwImpLevel,
  581. ((dwAuthLevel == RPC_C_AUTHN_LEVEL_DEFAULT) ||
  582. (dwAuthLevel >= RPC_C_AUTHN_LEVEL_CONNECT)) ? &authident : NULL,
  583. dwCapabilities);
  584. SysFreeString(UserArg);
  585. SysFreeString(AuthArg);
  586. SysFreeString(PrincipalArg);
  587. return sc;
  588. }
  589. //***************************************************************************
  590. //
  591. // SCODE SetInterfaceSecurity
  592. //
  593. // DESCRIPTION:
  594. //
  595. // This routine is used by clients in order to set the identity to be used by a connection.
  596. //
  597. // PARAMETERS:
  598. //
  599. // pInterface Interface to be set
  600. // pauthident Structure with the identity info already set.
  601. //
  602. // RETURN VALUE:
  603. //
  604. // S_OK all is well
  605. //
  606. //***************************************************************************
  607. HRESULT WINAPI SetInterfaceSecurityAuth(IUnknown * pInterface, COAUTHIDENTITY * pauthident, bool bAuthenticate)
  608. {
  609. return SetInterfaceSecurityEx(pInterface,(bAuthenticate) ? pauthident : NULL,
  610. NULL,
  611. (bAuthenticate) ? RPC_C_AUTHN_LEVEL_DEFAULT : RPC_C_AUTHN_LEVEL_NONE,
  612. RPC_C_IMP_LEVEL_IDENTIFY,
  613. EOAC_NONE);
  614. }
  615. //***************************************************************************
  616. //
  617. // SCODE SetInterfaceSecurityEx
  618. //
  619. // DESCRIPTION:
  620. //
  621. // This routine is used by clients in order to set the identity to be used by a connection.
  622. //
  623. // PARAMETERS:
  624. //
  625. // pInterface Interface to be set
  626. // pAuthority Input, authority
  627. // pUser Input, user name
  628. // pPassword Input, password.
  629. // dwAuthLevel Input, Authorization Level
  630. // dwImpLevel Input, Impersonation Level
  631. // dwCapabilities Input, Capability settings
  632. // ppAuthIdent Output, Allocated AuthIdentity if applicable, caller must free
  633. // manually (can use the FreeAuthInfo function).
  634. // pPrincipal Output, Principal calculated from supplied data Caller must
  635. // free using SysFreeString.
  636. //
  637. // RETURN VALUE:
  638. //
  639. // S_OK all is well
  640. // else error listed in WBEMSVC.H
  641. //
  642. //***************************************************************************
  643. HRESULT WINAPI SetInterfaceSecurityEx(IUnknown * pInterface, LPWSTR pAuthority, LPWSTR pUser, LPWSTR pPassword,
  644. DWORD dwAuthLevel, DWORD dwImpLevel, DWORD dwCapabilities,
  645. COAUTHIDENTITY** ppAuthIdent, BSTR* pPrincipal, bool GetInfoFirst)
  646. {
  647. SCODE sc;
  648. DWORD dwAuthenticationArg = RPC_C_AUTHN_GSS_NEGOTIATE;
  649. DWORD dwAuthorizationArg = RPC_C_AUTHZ_NONE;
  650. if( pInterface == NULL || NULL == ppAuthIdent || NULL == pPrincipal )
  651. return WBEM_E_INVALID_PARAMETER;
  652. if(GetInfoFirst)
  653. GetCurrentValue(pInterface, dwAuthenticationArg, dwAuthorizationArg);
  654. // If we are doing trivial case, just pass in a null authenication structure which is used
  655. // if the current logged in user's credentials are OK.
  656. if((pAuthority == NULL || wcslen(pAuthority) < 1) &&
  657. (pUser == NULL || wcslen(pUser) < 1) &&
  658. (pPassword == NULL || wcslen(pPassword) < 1))
  659. {
  660. DWORD dwCorrectedAuth = (RPC_C_AUTHN_GSS_KERBEROS == dwAuthenticationArg)?RPC_C_AUTHN_GSS_NEGOTIATE:dwAuthenticationArg;
  661. sc = WbemSetProxyBlanket(pInterface,
  662. dwCorrectedAuth,
  663. dwAuthorizationArg,
  664. NULL, // no principal,
  665. dwAuthLevel,
  666. dwImpLevel,
  667. NULL,
  668. dwCapabilities);
  669. return sc;
  670. }
  671. // If user, or Authority was passed in, the we need to create an authority argument for the login
  672. BSTR AuthArg = NULL, UserArg = NULL, PrincipalArg = NULL;
  673. sc = DetermineLoginTypeEx(AuthArg, UserArg, PrincipalArg, pAuthority, pUser);
  674. if(sc != S_OK)
  675. {
  676. return sc;
  677. }
  678. // Handle an allocation failure
  679. COAUTHIDENTITY* pAuthIdent = NULL;
  680. // We will only need this structure if we are not cloaking and we want at least
  681. // connect level authorization
  682. if ( !( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) )
  683. && ((RPC_C_AUTHN_LEVEL_DEFAULT == dwAuthLevel) || (dwAuthLevel >= RPC_C_AUTHN_LEVEL_CONNECT)) )
  684. {
  685. sc = WbemAllocAuthIdentity( UserArg, pPassword, AuthArg, &pAuthIdent );
  686. }
  687. if ( SUCCEEDED( sc ) )
  688. {
  689. DWORD dwCorrectedAuth = (PrincipalArg) ? RPC_C_AUTHN_GSS_KERBEROS : dwAuthenticationArg;
  690. dwCorrectedAuth = (NULL == PrincipalArg && RPC_C_AUTHN_GSS_KERBEROS == dwCorrectedAuth)?RPC_C_AUTHN_GSS_NEGOTIATE:dwCorrectedAuth;
  691. sc = WbemSetProxyBlanket(pInterface,
  692. dwCorrectedAuth,
  693. dwAuthorizationArg,
  694. PrincipalArg,
  695. dwAuthLevel, dwImpLevel,
  696. pAuthIdent,
  697. dwCapabilities);
  698. // We will store relevant values as necessary
  699. if ( SUCCEEDED( sc ) )
  700. {
  701. *ppAuthIdent = pAuthIdent;
  702. *pPrincipal = PrincipalArg;
  703. PrincipalArg = NULL;
  704. }
  705. else
  706. {
  707. WbemFreeAuthIdentity( pAuthIdent );
  708. }
  709. }
  710. SysFreeString(UserArg);
  711. SysFreeString(AuthArg);
  712. SysFreeString(PrincipalArg);
  713. return sc;
  714. }
  715. //***************************************************************************
  716. //
  717. // SCODE SetInterfaceSecurityEx
  718. //
  719. // DESCRIPTION:
  720. //
  721. // This routine is used by clients in order to set the identity to be used by a connection.
  722. //
  723. // PARAMETERS:
  724. //
  725. // pInterface Interface to be set
  726. // pAuthIdent Input, Preset COAUTHIDENTITY structure pointer.
  727. // pPrincipal Input, Preset principal argument
  728. // dwAuthLevel Input, Authorization Level
  729. // dwImpLevel Input, Impersonation Level
  730. // dwCapabilities Input, Capability settings
  731. // GetInfoFirst if true, the authentication and authorization are retrived via
  732. // QueryBlanket.
  733. // RETURN VALUE:
  734. //
  735. // S_OK all is well
  736. // else error listed in WBEMSVC.H
  737. //
  738. //***************************************************************************
  739. HRESULT WINAPI SetInterfaceSecurityEx(IUnknown * pInterface, COAUTHIDENTITY* pAuthIdent, BSTR pPrincipal,
  740. DWORD dwAuthLevel, DWORD dwImpLevel,
  741. DWORD dwCapabilities, bool GetInfoFirst)
  742. {
  743. DWORD dwAuthenticationArg = RPC_C_AUTHN_GSS_NEGOTIATE;
  744. DWORD dwAuthorizationArg = RPC_C_AUTHZ_NONE;
  745. if(pInterface == NULL)
  746. return WBEM_E_INVALID_PARAMETER;
  747. if(GetInfoFirst)
  748. GetCurrentValue(pInterface, dwAuthenticationArg, dwAuthorizationArg);
  749. // The complicated values should have already been precalced.
  750. // Note : For auth level, we have to check for the 'RPC_C_AUTHN_LEVEL_DEFAULT' (=0) value as well,
  751. // as after negotiation with the server it might result in something high that does need
  752. // the identity structure !!
  753. DWORD dwCorrectedAuth = (pPrincipal) ? RPC_C_AUTHN_GSS_KERBEROS : dwAuthenticationArg;
  754. dwCorrectedAuth = (NULL == pPrincipal && RPC_C_AUTHN_GSS_KERBEROS == dwCorrectedAuth)?RPC_C_AUTHN_GSS_NEGOTIATE:dwCorrectedAuth;
  755. return WbemSetProxyBlanket(pInterface,
  756. dwCorrectedAuth,
  757. dwAuthorizationArg,
  758. pPrincipal,
  759. dwAuthLevel,
  760. dwImpLevel,
  761. ((dwAuthLevel == RPC_C_AUTHN_LEVEL_DEFAULT) ||
  762. (dwAuthLevel >= RPC_C_AUTHN_LEVEL_CONNECT)) ? pAuthIdent : NULL,
  763. dwCapabilities);
  764. }
  765. //***************************************************************************
  766. //
  767. // HRESULT WbemAllocAuthIdentity
  768. //
  769. // DESCRIPTION:
  770. //
  771. // Walks a COAUTHIDENTITY structure and CoTaskMemAllocs the member data and the
  772. // structure.
  773. //
  774. // PARAMETERS:
  775. //
  776. // pUser Input
  777. // pPassword Input
  778. // pDomain Input
  779. // ppAuthInfo Output, Newly allocated structure
  780. //
  781. // RETURN VALUE:
  782. //
  783. // S_OK all is well
  784. //
  785. //***************************************************************************
  786. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pUser, LPCWSTR pPassword, LPCWSTR pDomain,
  787. COAUTHIDENTITY** ppAuthIdent )
  788. {
  789. if ( NULL == ppAuthIdent ) return WBEM_E_INVALID_PARAMETER;
  790. // Handle an allocation failure
  791. COAUTHIDENTITY* pAuthIdent = (COAUTHIDENTITY*) CoTaskMemAlloc( sizeof(COAUTHIDENTITY) );
  792. if (NULL == pAuthIdent) return WBEM_E_OUT_OF_MEMORY;
  793. OnDeleteIf<PVOID,void(*)(PVOID),CoTaskMemFree> fmAuth(pAuthIdent);
  794. memset((void *)pAuthIdent,0,sizeof(COAUTHIDENTITY));
  795. WCHAR * pCopyUser = NULL;
  796. WCHAR * pCopyDomain = NULL;
  797. WCHAR * pCopyPassword = NULL;
  798. // Allocate needed memory and copy in data. Cleanup if anything goes wrong
  799. if ( pUser )
  800. {
  801. size_t cchTmp = wcslen(pUser) + 1;
  802. pCopyUser = (WCHAR *) CoTaskMemAlloc( cchTmp * sizeof( WCHAR ) );
  803. if ( NULL == pCopyUser ) return WBEM_E_OUT_OF_MEMORY;
  804. StringCchCopyW(pCopyUser,cchTmp, pUser );
  805. pAuthIdent->UserLength = cchTmp -1;
  806. }
  807. OnDeleteIf<PVOID,void(*)(PVOID),CoTaskMemFree> fmUser(pCopyUser);
  808. if ( pDomain )
  809. {
  810. size_t cchTmp = wcslen(pDomain) + 1;
  811. pCopyDomain = (WCHAR *) CoTaskMemAlloc( cchTmp * sizeof( WCHAR ) );
  812. if ( NULL == pCopyDomain ) return WBEM_E_OUT_OF_MEMORY;
  813. StringCchCopyW(pCopyDomain,cchTmp, pDomain );
  814. pAuthIdent->DomainLength = cchTmp -1;
  815. }
  816. OnDeleteIf<PVOID,void(*)(PVOID),CoTaskMemFree> fmDomain(pCopyDomain);
  817. if ( pPassword )
  818. {
  819. size_t cchTmp = wcslen(pPassword) + 1;
  820. pCopyPassword = (WCHAR *) CoTaskMemAlloc( cchTmp * sizeof( WCHAR ) );
  821. if ( NULL == pCopyPassword ) return WBEM_E_OUT_OF_MEMORY;
  822. StringCchCopyW(pCopyPassword,cchTmp, pPassword );
  823. pAuthIdent->PasswordLength = cchTmp -1;
  824. }
  825. OnDeleteIf<PVOID,void(*)(PVOID),CoTaskMemFree> fmPassword(pCopyPassword);
  826. fmUser.dismiss();
  827. pAuthIdent->User = pCopyUser;
  828. fmDomain.dismiss();
  829. pAuthIdent->Domain = pCopyDomain;
  830. fmPassword.dismiss();
  831. pAuthIdent->Password = pCopyPassword;
  832. pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  833. fmAuth.dismiss();
  834. *ppAuthIdent = pAuthIdent;
  835. return S_OK;
  836. }
  837. //***************************************************************************
  838. //
  839. // HRESULT WbemFreeAuthIdentity
  840. //
  841. // DESCRIPTION:
  842. //
  843. // Walks a COAUTHIDENTITY structure and CoTaskMemFrees the member data and the
  844. // structure.
  845. //
  846. // PARAMETERS:
  847. //
  848. // pAuthInfo Structure to free
  849. //
  850. // RETURN VALUE:
  851. //
  852. // S_OK all is well
  853. //
  854. //***************************************************************************
  855. HRESULT WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY* pAuthIdentity )
  856. {
  857. if ( pAuthIdentity )
  858. {
  859. CoTaskMemFree( pAuthIdentity->Password );
  860. CoTaskMemFree( pAuthIdentity->Domain );
  861. CoTaskMemFree( pAuthIdentity->User );
  862. CoTaskMemFree( pAuthIdentity );
  863. }
  864. return S_OK;
  865. }
  866. //***************************************************************************
  867. //
  868. // HRESULT WbemCoQueryClientBlanket
  869. // HRESULT WbemCoImpersonateClient( void)
  870. // HRESULT WbemCoRevertToSelf( void)
  871. //
  872. // PARAMETERS:
  873. //
  874. // pInterface Interface to be set
  875. // pauthident Structure with the identity info already set.
  876. //
  877. // RETURN VALUE:
  878. //
  879. // S_OK all is well
  880. //
  881. //***************************************************************************
  882. HRESULT WINAPI WbemCoQueryClientBlanket(
  883. /* [out] */ DWORD __RPC_FAR *pAuthnSvc,
  884. /* [out] */ DWORD __RPC_FAR *pAuthzSvc,
  885. /* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *pServerPrincName,
  886. /* [out] */ DWORD __RPC_FAR *pAuthnLevel,
  887. /* [out] */ DWORD __RPC_FAR *pImpLevel,
  888. /* [out] */ void __RPC_FAR *__RPC_FAR *pPrivs,
  889. /* [out] */ DWORD __RPC_FAR *pCapabilities)
  890. {
  891. IServerSecurity * pss = NULL;
  892. SCODE sc = CoGetCallContext(IID_IServerSecurity, (void**)&pss);
  893. if(S_OK == sc)
  894. {
  895. sc = pss->QueryBlanket(pAuthnSvc, pAuthzSvc, pServerPrincName,
  896. pAuthnLevel, pImpLevel, pPrivs, pCapabilities);
  897. pss->Release();
  898. }
  899. return sc;
  900. }
  901. HRESULT WINAPI WbemCoImpersonateClient( void)
  902. {
  903. IServerSecurity * pss = NULL;
  904. SCODE sc = CoGetCallContext(IID_IServerSecurity, (void**)&pss);
  905. if(S_OK == sc)
  906. {
  907. sc = pss->ImpersonateClient();
  908. pss->Release();
  909. }
  910. return sc;
  911. }
  912. bool WINAPI WbemIsImpersonating(void)
  913. {
  914. bool bRet = false;
  915. IServerSecurity * pss = NULL;
  916. SCODE sc = CoGetCallContext(IID_IServerSecurity, (void**)&pss);
  917. if(S_OK == sc)
  918. {
  919. bRet = (pss->IsImpersonating() == TRUE);
  920. pss->Release();
  921. }
  922. return bRet;
  923. }
  924. HRESULT WINAPI WbemCoRevertToSelf( void)
  925. {
  926. IServerSecurity * pss = NULL;
  927. SCODE sc = CoGetCallContext(IID_IServerSecurity, (void**)&pss);
  928. if(S_OK == sc)
  929. {
  930. sc = pss->RevertToSelf();
  931. pss->Release();
  932. }
  933. return sc;
  934. }
  935. //***************************************************************************
  936. //
  937. //***************************************************************************
  938. HRESULT WINAPI EncryptCredentials( COAUTHIDENTITY* pAuthIdent )
  939. {
  940. // nop iplementation
  941. return S_OK;
  942. }
  943. //***************************************************************************
  944. //
  945. //***************************************************************************
  946. HRESULT WINAPI DecryptCredentials( COAUTHIDENTITY* pAuthIdent )
  947. {
  948. // nop iplementation
  949. return S_OK;
  950. }
  951. //***************************************************************************
  952. //
  953. // SCODE SetInterfaceSecurityEncrypt
  954. //
  955. // DESCRIPTION:
  956. //
  957. // This routine is used by clients in order to set the identity to be used by a connection.
  958. // The returned AuthIdentity structure will be encrypted before returning.
  959. //
  960. // PARAMETERS:
  961. //
  962. // pInterface Interface to be set
  963. // pAuthority Input, authority
  964. // pUser Input, user name
  965. // pPassword Input, password.
  966. // dwAuthLevel Input, Authorization Level
  967. // dwImpLevel Input, Impersonation Level
  968. // dwCapabilities Input, Capability settings
  969. // ppAuthIdent Output, Allocated AuthIdentity if applicable, caller must free
  970. // manually (can use the FreeAuthInfo function).
  971. // pPrincipal Output, Principal calculated from supplied data Caller must
  972. // free using SysFreeString.
  973. // GetInfoFirst if true, the authentication and authorization are retrived via
  974. // QueryBlanket.
  975. //
  976. // RETURN VALUE:
  977. //
  978. // S_OK all is well
  979. // else error listed in WBEMSVC.H
  980. //
  981. //***************************************************************************
  982. HRESULT WINAPI SetInterfaceSecurityEncrypt(IUnknown * pInterface, LPWSTR pDomain, LPWSTR pUser, LPWSTR pPassword, DWORD dwAuthLevel, DWORD dwImpLevel, DWORD dwCapabilities,
  983. COAUTHIDENTITY** ppAuthIdent, BSTR* ppPrinciple, bool GetInfoFirst )
  984. {
  985. //_DBG_ASSERT(FALSE);
  986. HRESULT hr = SetInterfaceSecurityEx( pInterface, pDomain, pUser, pPassword, dwAuthLevel, dwImpLevel, dwCapabilities,
  987. ppAuthIdent, ppPrinciple, GetInfoFirst );
  988. if ( SUCCEEDED( hr ) )
  989. {
  990. if ( NULL != ppAuthIdent )
  991. {
  992. hr = EncryptCredentials( *ppAuthIdent );
  993. }
  994. }
  995. return hr;
  996. }
  997. //***************************************************************************
  998. //
  999. // SCODE SetInterfaceSecurityDecrypt
  1000. //
  1001. // DESCRIPTION:
  1002. //
  1003. // This routine is used by clients in order to set the identity to be used by a connection.
  1004. // It will unencrypt and reencrypt the auth identity structure in place.
  1005. //
  1006. // PARAMETERS:
  1007. //
  1008. // pInterface Interface to be set
  1009. // pAuthIdent Input, Preset COAUTHIDENTITY structure pointer.
  1010. // pPrincipal Input, Preset principal argument
  1011. // dwAuthLevel Input, Authorization Level
  1012. // dwImpLevel Input, Impersonation Level
  1013. // dwCapabilities Input, Capability settings
  1014. // GetInfoFirst if true, the authentication and authorization are retrived via
  1015. // QueryBlanket.
  1016. // RETURN VALUE:
  1017. //
  1018. // S_OK all is well
  1019. // else error listed in WBEMSVC.H
  1020. //
  1021. //***************************************************************************
  1022. HRESULT WINAPI SetInterfaceSecurityDecrypt(IUnknown * pInterface, COAUTHIDENTITY* pAuthIdent, BSTR pPrincipal,
  1023. DWORD dwAuthLevel, DWORD dwImpLevel,
  1024. DWORD dwCapabilities, bool GetInfoFirst )
  1025. {
  1026. //_DBG_ASSERT(FALSE);
  1027. // Decrypt first
  1028. HRESULT hr = DecryptCredentials( pAuthIdent );
  1029. if ( SUCCEEDED( hr ) )
  1030. {
  1031. hr = SetInterfaceSecurityEx( pInterface, pAuthIdent, pPrincipal, dwAuthLevel, dwImpLevel,
  1032. dwCapabilities, GetInfoFirst );
  1033. hr = EncryptCredentials( pAuthIdent );
  1034. }
  1035. return hr;
  1036. }