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.

322 lines
10 KiB

  1. //***************************************************************************
  2. //
  3. // WBEMSEC.CPP
  4. //
  5. // Purpose: Provides some security helper functions.
  6. //
  7. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  8. //
  9. //***************************************************************************
  10. //#undef _WIN32_WINNT
  11. //#define _WIN32_WINNT 0x0400
  12. #include "precomp.h"
  13. #include <wbemidl.h>
  14. #include "wbemsec.h"
  15. //***************************************************************************
  16. //
  17. // InitializeSecurity(DWORD dwAuthLevel, DWORD dwImpLevel)
  18. //
  19. // DESCRIPTION:
  20. //
  21. // Initialize DCOM security. The authentication level is typically
  22. // RPC_C_AUTHN_LEVEL_CONNECT, and the impersonation level is typically
  23. // RPC_C_IMP_LEVEL_IMPERSONATE. When using asynchronous call backs, an
  24. // authentication level of RPC_C_AUTHN_LEVEL_NONE is useful
  25. //
  26. // RETURN VALUE:
  27. //
  28. // see description.
  29. //
  30. //***************************************************************************
  31. HRESULT InitializeSecurity(DWORD dwAuthLevel, DWORD dwImpLevel)
  32. {
  33. // Initialize security
  34. // ===================
  35. return CoInitializeSecurity(NULL, -1, NULL, NULL,
  36. dwAuthLevel, dwImpLevel,
  37. NULL, EOAC_NONE, 0);
  38. }
  39. //***************************************************************************
  40. //
  41. // bool bIsNT
  42. //
  43. // DESCRIPTION:
  44. //
  45. // Returns true if running windows NT.
  46. //
  47. // RETURN VALUE:
  48. //
  49. // see description.
  50. //
  51. //***************************************************************************
  52. bool bIsNT(void)
  53. {
  54. OSVERSIONINFO os;
  55. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  56. if(!GetVersionEx(&os))
  57. return FALSE; // should never happen
  58. return os.dwPlatformId == VER_PLATFORM_WIN32_NT;
  59. }
  60. //***************************************************************************
  61. //
  62. // SCODE ParseAuthorityUserArgs
  63. //
  64. // DESCRIPTION:
  65. //
  66. // Examines the Authority and User argument and determines the authentication
  67. // type and possibly extracts the domain name from the user arugment in the
  68. // NTLM case. For NTLM, the domain can be at the end of the authentication
  69. // string, or in the front of the user name, ex; "redmond\a-davj"
  70. //
  71. // PARAMETERS:
  72. //
  73. // ConnType Returned with the connection type, ie wbem, ntlm
  74. // AuthArg Output, contains the domain name
  75. // UserArg Output, user name
  76. // Authority Input
  77. // User Input
  78. //
  79. // RETURN VALUE:
  80. //
  81. // S_OK all is well
  82. // else error listed in WBEMSVC.H
  83. //
  84. //***************************************************************************
  85. SCODE ParseAuthorityUserArgs(BSTR & AuthArg, BSTR & UserArg,BSTR & Authority,BSTR & User)
  86. {
  87. // Determine the connection type by examining the Authority string
  88. if(!(Authority == NULL || wcslen(Authority) == 0 || !_wcsnicmp(Authority, L"NTLMDOMAIN:",11)))
  89. return E_INVALIDARG;
  90. // The ntlm case is more complex. There are four cases
  91. // 1) Authority = NTLMDOMAIN:name" and User = "User"
  92. // 2) Authority = NULL and User = "User"
  93. // 3) Authority = "NTLMDOMAIN:" User = "domain\user"
  94. // 4) Authority = NULL and User = "domain\user"
  95. // first step is to determine if there is a backslash in the user name somewhere between the
  96. // second and second to last character
  97. WCHAR * pSlashInUser = NULL;
  98. if(User)
  99. {
  100. WCHAR * pEnd = User + wcslen(User) - 1;
  101. for(pSlashInUser = User; pSlashInUser <= pEnd; pSlashInUser++)
  102. if(*pSlashInUser == L'\\') // dont think forward slash is allowed!
  103. break;
  104. if(pSlashInUser > pEnd)
  105. pSlashInUser = NULL;
  106. }
  107. if(Authority && wcslen(Authority) > 11)
  108. {
  109. if(pSlashInUser)
  110. return E_INVALIDARG;
  111. AuthArg = SysAllocString(Authority + 11);
  112. if(User) UserArg = SysAllocString(User);
  113. return S_OK;
  114. }
  115. else if(pSlashInUser)
  116. {
  117. INT_PTR iDomLen = min(MAX_PATH-1, pSlashInUser-User);
  118. WCHAR cTemp[MAX_PATH];
  119. wcsncpy(cTemp, User, iDomLen);
  120. cTemp[iDomLen] = 0;
  121. AuthArg = SysAllocString(cTemp);
  122. if(wcslen(pSlashInUser+1))
  123. UserArg = SysAllocString(pSlashInUser+1);
  124. }
  125. else
  126. if(User) UserArg = SysAllocString(User);
  127. return S_OK;
  128. }
  129. //***************************************************************************
  130. //
  131. // SCODE GetAuthImp
  132. //
  133. // DESCRIPTION:
  134. //
  135. // Gets the authentication and impersonation levels for a current interface.
  136. //
  137. // PARAMETERS:
  138. //
  139. // pFrom the interface to be tested.
  140. // pdwAuthLevel Set to the authentication level
  141. // pdwImpLevel Set to the impersonation level
  142. // RETURN VALUE:
  143. //
  144. // S_OK all is well
  145. // else error listed in WBEMSVC.H
  146. //
  147. //***************************************************************************
  148. SCODE GetAuthImp(IUnknown * pFrom, DWORD * pdwAuthLevel, DWORD * pdwImpLevel)
  149. {
  150. if(pFrom == NULL || pdwAuthLevel == NULL || pdwImpLevel == NULL)
  151. return WBEM_E_INVALID_PARAMETER;
  152. IClientSecurity * pFromSec = NULL;
  153. SCODE sc = pFrom->QueryInterface(IID_IClientSecurity, (void **) &pFromSec);
  154. if(sc == S_OK)
  155. {
  156. DWORD dwAuthnSvc, dwAuthzSvc, dwCapabilities;
  157. sc = pFromSec->QueryBlanket(pFrom, &dwAuthnSvc, &dwAuthzSvc,
  158. NULL,
  159. pdwAuthLevel, pdwImpLevel,
  160. NULL, &dwCapabilities);
  161. // Special case of going to a win9x share level box
  162. if (sc == 0x800706d2)
  163. {
  164. *pdwAuthLevel = RPC_C_AUTHN_LEVEL_NONE;
  165. *pdwImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
  166. sc = S_OK;
  167. }
  168. pFromSec->Release();
  169. }
  170. return sc;
  171. }
  172. //***************************************************************************
  173. //
  174. // SCODE SetInterfaceSecurity
  175. //
  176. // DESCRIPTION:
  177. //
  178. // This routine is used by clients in order to set the identity to be used by a connection.
  179. // NOTE that setting the security blanket on the interface is not recommended.
  180. // The clients should typically just call CoInitializeSecurity( NULL, -1, NULL, NULL,
  181. // RPC_C_AUTHN_LEVEL_DEFAULT,
  182. // RPC_C_IMP_LEVEL_IMPERSONATE,
  183. // NULL,
  184. // EOAC_NONE,
  185. // NULL );
  186. // before calling out to WMI.
  187. //
  188. //
  189. // PARAMETERS:
  190. //
  191. // pInterface Interface to be set
  192. // pDomain Input, domain
  193. // pUser Input, user name
  194. // pPassword Input, password.
  195. // pFrom Input, if not NULL, then the authentication level of this interface
  196. // is used
  197. // bAuthArg If pFrom is NULL, then this is the authentication level
  198. // RETURN VALUE:
  199. //
  200. // S_OK all is well
  201. // else error listed in WBEMSVC.H
  202. //
  203. //***************************************************************************
  204. HRESULT SetInterfaceSecurity(IUnknown * pInterface, LPWSTR pAuthority, LPWSTR pUser,
  205. LPWSTR pPassword, DWORD dwAuthLevel, DWORD dwImpLevel)
  206. {
  207. SCODE sc;
  208. if(pInterface == NULL)
  209. return E_INVALIDARG;
  210. // If we are lowering the security, no need to deal with the identification info
  211. if(dwAuthLevel == RPC_C_AUTHN_LEVEL_NONE)
  212. return CoSetProxyBlanket(pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
  213. RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
  214. // If we are doing trivial case, just pass in a null authentication structure which is used
  215. // if the current logged in user's credentials are OK.
  216. if((pAuthority == NULL || wcslen(pAuthority) < 1) &&
  217. (pUser == NULL || wcslen(pUser) < 1) &&
  218. (pPassword == NULL || wcslen(pPassword) < 1))
  219. return CoSetProxyBlanket(pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
  220. dwAuthLevel, dwImpLevel, NULL, EOAC_NONE);
  221. // If user, or Authority was passed in, the we need to create an authority argument for the login
  222. COAUTHIDENTITY authident;
  223. BSTR AuthArg = NULL, UserArg = NULL;
  224. sc = ParseAuthorityUserArgs(AuthArg, UserArg, pAuthority, pUser);
  225. if(sc != S_OK)
  226. return sc;
  227. memset((void *)&authident,0,sizeof(COAUTHIDENTITY));
  228. if(bIsNT())
  229. {
  230. if(UserArg)
  231. {
  232. authident.UserLength = (ULONG)wcslen(UserArg);
  233. authident.User = (LPWSTR)UserArg;
  234. }
  235. if(AuthArg)
  236. {
  237. authident.DomainLength = (ULONG)wcslen(AuthArg);
  238. authident.Domain = (LPWSTR)AuthArg;
  239. }
  240. if(pPassword)
  241. {
  242. authident.PasswordLength = (ULONG)wcslen(pPassword);
  243. authident.Password = (LPWSTR)pPassword;
  244. }
  245. authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  246. }
  247. else
  248. {
  249. char szUser[MAX_PATH], szAuthority[MAX_PATH], szPassword[MAX_PATH];
  250. // Fill in the indentity structure
  251. if(UserArg)
  252. {
  253. wcstombs(szUser, UserArg, MAX_PATH);
  254. authident.UserLength = (ULONG)strlen(szUser);
  255. authident.User = (LPWSTR)szUser;
  256. }
  257. if(AuthArg)
  258. {
  259. wcstombs(szAuthority, AuthArg, MAX_PATH);
  260. authident.DomainLength = (ULONG)strlen(szAuthority);
  261. authident.Domain = (LPWSTR)szAuthority;
  262. }
  263. if(pPassword)
  264. {
  265. wcstombs(szPassword, pPassword, MAX_PATH);
  266. authident.PasswordLength = (ULONG)strlen(szPassword);
  267. authident.Password = (LPWSTR)szPassword;
  268. }
  269. authident.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
  270. }
  271. sc = CoSetProxyBlanket(pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
  272. dwAuthLevel, dwImpLevel, &authident, EOAC_NONE);
  273. if(UserArg)
  274. SysFreeString(UserArg);
  275. if(AuthArg)
  276. SysFreeString(AuthArg);
  277. return sc;
  278. }