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.

333 lines
8.2 KiB

  1. //
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-2001
  5. //
  6. // Author: AdamEd
  7. // Date: January 2000
  8. //
  9. // Abstractions for directory service layer
  10. //
  11. //
  12. //---------------------------------------------------------------------
  13. #include "cstore.hxx"
  14. CServerContext::CServerContext() :
  15. _wszServerName( NULL )
  16. {
  17. }
  18. CServerContext::~CServerContext()
  19. {
  20. delete [] _wszServerName;
  21. }
  22. HRESULT
  23. CServerContext::Initialize(
  24. CServerContext* pServerContext )
  25. {
  26. return Initialize(
  27. pServerContext->GetServerName() );
  28. }
  29. HRESULT
  30. CServerContext::Initialize(
  31. WCHAR* wszServerName )
  32. {
  33. if ( wszServerName )
  34. {
  35. _wszServerName = StringDuplicate( wszServerName );
  36. if ( ! _wszServerName )
  37. {
  38. return E_OUTOFMEMORY;
  39. }
  40. }
  41. return S_OK;
  42. }
  43. BOOL
  44. CServerContext::Compare( CServerContext* pServerContext )
  45. {
  46. //
  47. // If the caller doesn't specify a context, this is equivalent to the
  48. // case where our context has no state
  49. //
  50. if ( ! pServerContext )
  51. {
  52. if ( ! _wszServerName )
  53. {
  54. return TRUE;
  55. }
  56. return FALSE;
  57. }
  58. //
  59. // The caller specified the context, so we ensure they both have state
  60. // or they both don't -- if there is a difference, they are not equivalent
  61. //
  62. if ( ( NULL == _wszServerName ) != ( NULL == pServerContext->_wszServerName ) )
  63. {
  64. return FALSE;
  65. }
  66. //
  67. // We now compare all state specified in this context and the specified context
  68. //
  69. if ( _wszServerName )
  70. {
  71. if ( CSTR_EQUAL != CompareString(
  72. LOCALE_INVARIANT,
  73. NORM_IGNORECASE,
  74. _wszServerName,
  75. wcslen( _wszServerName ),
  76. pServerContext->_wszServerName,
  77. wcslen( pServerContext->_wszServerName ) ) )
  78. {
  79. return FALSE;
  80. }
  81. }
  82. return TRUE;
  83. }
  84. WCHAR*
  85. CServerContext::GetServerName()
  86. {
  87. return _wszServerName;
  88. }
  89. //*************************************************************
  90. //
  91. // DoesPathContainAServerName()
  92. //
  93. // Purpose: Checks the given ADSI path to see if it
  94. // contains a server name
  95. //
  96. // Parameters: lpPath - ADSI path
  97. //
  98. // Return: True if the path contains a server name
  99. // FALSE if not
  100. //
  101. //*************************************************************
  102. BOOL DoesPathContainAServerName (LPTSTR lpPath)
  103. {
  104. BOOL bResult = FALSE;
  105. //
  106. // Skip over LDAP:// if found
  107. //
  108. if ( CompareString( LOCALE_INVARIANT, NORM_IGNORECASE,
  109. lpPath, 7, L"LDAP://", 7 ) == CSTR_EQUAL )
  110. {
  111. lpPath += 7;
  112. }
  113. //
  114. // Check if the 3rd character in the path is an equal sign.
  115. // If so, this path does not contain a server name
  116. //
  117. if ((lstrlen(lpPath) > 2) && (*(lpPath + 2) != TEXT('=')))
  118. {
  119. bResult = TRUE;
  120. }
  121. return bResult;
  122. }
  123. HRESULT
  124. DSGetAndValidateColumn(
  125. HANDLE hDSObject,
  126. ADS_SEARCH_HANDLE hSearchHandle,
  127. ADSTYPE ADsType,
  128. LPWSTR pszColumnName,
  129. PADS_SEARCH_COLUMN pColumn
  130. )
  131. {
  132. HRESULT hr;
  133. //
  134. // First, instruct adsi to unmarshal the data into
  135. // the column
  136. //
  137. hr = ADSIGetColumn(
  138. hDSObject,
  139. hSearchHandle,
  140. pszColumnName,
  141. pColumn);
  142. //
  143. // Validate the returned data
  144. //
  145. if ( SUCCEEDED(hr) )
  146. {
  147. //
  148. // Verify that the type information is correct --
  149. // if it is not, we cannot safely interpret the data.
  150. // Incorrect type information is most likely to happen
  151. // when adsi is unable to download the schema, possibly
  152. // due to kerberos errors
  153. //
  154. if ( ADsType != pColumn->dwADsType )
  155. {
  156. //
  157. // We need to free the column, since the caller is not
  158. // expected to free it if we return a failure
  159. //
  160. ADSIFreeColumn( hDSObject, pColumn );
  161. hr = CS_E_SCHEMA_MISMATCH;
  162. }
  163. }
  164. return hr;
  165. }
  166. HRESULT DSAccessCheck(
  167. PSECURITY_DESCRIPTOR pSD,
  168. PRSOPTOKEN pRsopUserToken,
  169. BOOL* pbAccessAllowed
  170. )
  171. {
  172. GENERIC_MAPPING DS_GENERIC_MAPPING = {
  173. GENERIC_READ_MAPPING,
  174. GENERIC_WRITE_MAPPING,
  175. GENERIC_EXECUTE_MAPPING,
  176. GENERIC_ALL_MAPPING };
  177. DWORD dwAccessMask;
  178. HRESULT hr;
  179. hr = S_OK;
  180. if ( pRsopUserToken )
  181. {
  182. hr = RsopAccessCheckByType(pSD,
  183. 0,
  184. pRsopUserToken,
  185. GENERIC_READ,
  186. NULL,
  187. 0,
  188. &DS_GENERIC_MAPPING,
  189. NULL,
  190. NULL,
  191. &dwAccessMask,
  192. pbAccessAllowed );
  193. }
  194. else
  195. {
  196. //
  197. // A null user token means we are running in
  198. // reporting mode where we are trying to dump the
  199. // contents of the gpo rather than simulate what
  200. // apps the target might receive,
  201. // so we should not try to perform
  202. // an access check (we are running as some user, not
  203. // as the system). Instead, if we retrieved the app,
  204. // we have access, so we always return TRUE in this case
  205. //
  206. *pbAccessAllowed = TRUE;
  207. }
  208. return hr;
  209. }
  210. HRESULT
  211. DSServerOpenDSObject(
  212. CServerContext* pServerContext,
  213. LPWSTR pszDNName,
  214. LONG lFlags,
  215. PHANDLE phDSObject
  216. )
  217. {
  218. WCHAR* wszServerBasedPath = NULL;
  219. WCHAR* wszServerName = pServerContext ? pServerContext->GetServerName() : NULL;
  220. WCHAR* wszPath = pszDNName;
  221. BOOL bServerName = FALSE;
  222. //
  223. // Check to see if there's a server name in the path -- only do this
  224. // if the caller is specifying a server name -- otherwise, we assume
  225. // that there is no server name in the path (a domain name may be specified,
  226. // but that is not the same as a server).
  227. //
  228. if ( wszServerName && DoesPathContainAServerName( wszPath ) )
  229. {
  230. lFlags |= ADS_SERVER_BIND;
  231. bServerName = TRUE;
  232. }
  233. //
  234. // If a server is specified and the path doesn't already have a server, we need to create a server based LDAP path
  235. // to pass to adsi
  236. //
  237. if ( ! bServerName && wszServerName )
  238. {
  239. //
  240. // The DN passed to this function is a serverless path of the form
  241. //
  242. // LDAP://<DN>
  243. //
  244. // We need to transform it to a path of the form
  245. //
  246. // LDAP://<Server>/<DN>
  247. //
  248. // We first allocate space for the transformation
  249. //
  250. DWORD cchServerBasedPath = wcslen( wszServerName ) + 1 + wcslen( pszDNName ) + 1;
  251. wszServerBasedPath = new WCHAR [ cchServerBasedPath ];
  252. if ( NULL == wszServerBasedPath )
  253. {
  254. return E_OUTOFMEMORY;
  255. }
  256. //
  257. // Perform the transformation
  258. //
  259. (void) StringCchCopy( wszServerBasedPath, cchServerBasedPath, LDAPPREFIX );
  260. (void) StringCchCat( wszServerBasedPath, cchServerBasedPath, wszServerName );
  261. (void) StringCchCat( wszServerBasedPath, cchServerBasedPath, L"/" );
  262. (void) StringCchCat( wszServerBasedPath, cchServerBasedPath, pszDNName + sizeof( LDAPPREFIX ) / sizeof(WCHAR) - 1 );
  263. wszPath = wszServerBasedPath;
  264. //
  265. // Since we are binding to a server, add the flag that gives
  266. // the hint to ldap to bind
  267. //
  268. lFlags |= ADS_SERVER_BIND;
  269. }
  270. HRESULT hr;
  271. hr = ADSIOpenDSObject(
  272. wszPath,
  273. NULL,
  274. NULL,
  275. lFlags,
  276. phDSObject);
  277. if ( wszServerBasedPath )
  278. {
  279. delete [] wszServerBasedPath;
  280. }
  281. return hr;
  282. }