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.

428 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. rpcsvr.c
  5. Abstract:
  6. This file contains routines for starting and stopping RPC servers.
  7. StartRpcServerListen
  8. StopRpcServerListen
  9. Author:
  10. Vlad Sadovsky (vlads) 10-Jan-1997
  11. Environment:
  12. User Mode - Win32
  13. Revision History:
  14. 26-Jan-1997 VladS created
  15. --*/
  16. #include "precomp.h"
  17. //#define NOMINMAX
  18. #include "stiexe.h"
  19. #include <apiutil.h>
  20. #include <stirpc.h>
  21. #ifndef stirpc_ServerIfHandle
  22. #define stirpc_ServerIfHandle stirpc_v2_0_s_ifspec
  23. #endif
  24. HANDLE g_hWiaServiceStarted = NULL;
  25. RPC_STATUS RPC_ENTRY StiRpcSecurityCallBack(
  26. RPC_IF_HANDLE hIF,
  27. void *Context)
  28. {
  29. RPC_STATUS rpcStatus = RPC_S_ACCESS_DENIED;
  30. WCHAR *pBinding = NULL;
  31. WCHAR *pProtSeq = NULL;
  32. RPC_AUTHZ_HANDLE hPrivs;
  33. DWORD dwAuthenticationLevel;
  34. rpcStatus = RpcBindingInqAuthClient(Context,
  35. &hPrivs,
  36. NULL,
  37. &dwAuthenticationLevel,
  38. NULL,
  39. NULL);
  40. if (rpcStatus != RPC_S_OK)
  41. {
  42. DBG_ERR(("STI Security: Error calling RpcBindingInqAuthClient"));
  43. goto CleanUp;
  44. }
  45. //
  46. // We require at least packet-level authentication with integrity checking
  47. //
  48. if (dwAuthenticationLevel < RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
  49. {
  50. DBG_ERR(("STI Security: Error, client attempting to use weak authentication."));
  51. rpcStatus = RPC_S_ACCESS_DENIED;
  52. goto CleanUp;
  53. }
  54. //
  55. // Also, we only accept LRPC requests i.e. we only process requests from this machine,
  56. // and we disallow any remote calls to us.
  57. //
  58. rpcStatus = RpcBindingToStringBindingW(Context, &pBinding);
  59. if (rpcStatus == RPC_S_OK)
  60. {
  61. rpcStatus = RpcStringBindingParseW(pBinding,
  62. NULL,
  63. &pProtSeq,
  64. NULL,
  65. NULL,
  66. NULL);
  67. if (rpcStatus == RPC_S_OK)
  68. {
  69. if (lstrcmpiW(pProtSeq, L"ncalrpc") == 0)
  70. {
  71. DBG_TRC(("STI Security: We have a local client"));
  72. rpcStatus = RPC_S_OK;
  73. }
  74. else
  75. {
  76. DBG_ERR(("STI Security: Error, remote client attempting to connect to STI RPC server"));
  77. rpcStatus = RPC_S_ACCESS_DENIED;
  78. }
  79. }
  80. else
  81. {
  82. DBG_ERR(("STI Security: Error 0x%08X calling RpcStringBindingParse", rpcStatus));
  83. goto CleanUp;
  84. }
  85. }
  86. else
  87. {
  88. DBG_ERR(("STI Security: Error 0x%08X calling RpcBindingToStringBinding", rpcStatus));
  89. goto CleanUp;
  90. }
  91. CleanUp:
  92. if (pBinding)
  93. {
  94. RpcStringFree(&pBinding);
  95. pBinding = NULL;
  96. }
  97. if (pProtSeq)
  98. {
  99. RpcStringFree(&pProtSeq);
  100. pProtSeq = NULL;
  101. }
  102. return rpcStatus;
  103. }
  104. RPC_STATUS
  105. PrepareStiAcl(
  106. ACL **ppAcl)
  107. /*++
  108. Routine Description:
  109. This function prepares appropriate ACL for our RPC endpoint
  110. Arguments:
  111. ppAcl - points to ACL pointer we allocate and fill in.
  112. The ACL is allocated from the process heap and stays allocated for the
  113. lifetime of the process
  114. Return Value:
  115. NOERROR, or any GetLastError() codes.
  116. --*/
  117. {
  118. RPC_STATUS RpcStatus = NOERROR;
  119. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  120. PSID AuthenticatedUsers = NULL;
  121. PSID BuiltinAdministrators = NULL;
  122. ULONG AclSize;
  123. if(!AllocateAndInitializeSid(&NtAuthority,
  124. 2,
  125. SECURITY_BUILTIN_DOMAIN_RID,
  126. DOMAIN_ALIAS_RID_ADMINS,
  127. 0,0,0,0,0,0,
  128. &BuiltinAdministrators))
  129. {
  130. RpcStatus = GetLastError();
  131. DBG_ERR(("PrepareStiAcl: failed to allocate SID for BuiltinAdministrators, RpcStatus = %d",
  132. RpcStatus));
  133. goto Cleanup;
  134. }
  135. if(!AllocateAndInitializeSid(&NtAuthority,
  136. 1,
  137. SECURITY_AUTHENTICATED_USER_RID,
  138. 0,0,0,0,0,0, 0,
  139. &AuthenticatedUsers))
  140. {
  141. RpcStatus = GetLastError();
  142. DBG_ERR(("PrepareStiAcl: failed to allocate SID for AuthenticatedUsers, RpcStatus = %d",
  143. RpcStatus));
  144. goto Cleanup;
  145. }
  146. AclSize = sizeof(ACL) +
  147. 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG)) +
  148. GetLengthSid(AuthenticatedUsers) +
  149. GetLengthSid(BuiltinAdministrators);
  150. *ppAcl = (ACL *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AclSize);
  151. if(*ppAcl == NULL)
  152. {
  153. RpcStatus = GetLastError();
  154. DBG_ERR(("PrepareStiAcl: failed to allocate ACL (LastError = %d)",
  155. RpcStatus));
  156. goto Cleanup;
  157. }
  158. if(!InitializeAcl(*ppAcl, AclSize, ACL_REVISION))
  159. {
  160. RpcStatus = GetLastError();
  161. DBG_ERR(("PrepareStiAcl: failed to initialize ACL (LastError = %d)",
  162. RpcStatus));
  163. goto Cleanup;
  164. }
  165. if(!AddAccessAllowedAce(*ppAcl, ACL_REVISION,
  166. SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
  167. AuthenticatedUsers))
  168. {
  169. RpcStatus = GetLastError();
  170. DBG_ERR(("PrepareStiAcl: failed to allow AuthenticatedUsers (LastError = %d)",
  171. RpcStatus));
  172. goto Cleanup;
  173. }
  174. if(!AddAccessAllowedAce(*ppAcl, ACL_REVISION,
  175. GENERIC_ALL,
  176. BuiltinAdministrators))
  177. {
  178. RpcStatus = GetLastError();
  179. DBG_ERR(("PrepareStiAcl: failed to allow BuiltinAdministrators (LastError = %d)",
  180. RpcStatus));
  181. goto Cleanup;
  182. }
  183. Cleanup:
  184. if(RpcStatus != NOERROR)
  185. {
  186. if(AuthenticatedUsers)
  187. {
  188. FreeSid(AuthenticatedUsers);
  189. }
  190. if(BuiltinAdministrators)
  191. {
  192. FreeSid(BuiltinAdministrators);
  193. }
  194. if(*ppAcl)
  195. {
  196. HeapFree(GetProcessHeap(), 0, *ppAcl);
  197. *ppAcl = NULL;
  198. }
  199. }
  200. return RpcStatus;
  201. }
  202. RPC_STATUS
  203. StartRpcServerListen(
  204. VOID)
  205. /*++
  206. Routine Description:
  207. This function starts RpcServerListen for this process.
  208. RPC server only binds to LRPC transport , if STI becomes remotable
  209. it will need to bind to named pipe and/or tcp/ip ( or netbios) transports
  210. Shouldn't happen though, since WIA will be the remotable part, while STI will
  211. be local to the machine.
  212. Arguments:
  213. Return Value:
  214. NERR_Success, or any RPC error codes that can be returned from
  215. RpcServerUnregisterIf.
  216. --*/
  217. {
  218. DBG_FN(StartRpcServerListen);
  219. RPC_STATUS RpcStatus;
  220. SECURITY_DESCRIPTOR SecurityDescriptor;
  221. ACL *pAcl = NULL;
  222. // prepare our ACL
  223. RpcStatus = PrepareStiAcl(&pAcl);
  224. if(pAcl == NULL) {
  225. DBG_ERR(("StartRpcServerListen: PrepareStiAcl() returned RpcStatus=0x%X", RpcStatus));
  226. return RpcStatus;
  227. }
  228. // Give access to everybody
  229. InitializeSecurityDescriptor(&SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
  230. SetSecurityDescriptorDacl(&SecurityDescriptor, TRUE, pAcl, FALSE);
  231. //
  232. // For now, ignore the second argument.
  233. //
  234. RpcStatus = RpcServerUseProtseqEp((RPC_STRING)STI_LRPC_SEQ,
  235. STI_LRPC_MAX_REQS,
  236. (RPC_STRING)STI_LRPC_ENDPOINT,
  237. &SecurityDescriptor);
  238. if ( NOERROR != RpcStatus) {
  239. DBG_ERR(("StartRpcServerListen: RpcServerUseProtseqEp returned RpcStatus=0x%X",RpcStatus));
  240. return RpcStatus;
  241. }
  242. //
  243. // Add interface by using implicit handle, generated by MIDL
  244. //
  245. RpcStatus = RpcServerRegisterIfEx(stirpc_ServerIfHandle, //RpcInterface
  246. 0, //MgrUuid
  247. 0, //MgrEpv
  248. RPC_IF_ALLOW_SECURE_ONLY,
  249. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  250. StiRpcSecurityCallBack);
  251. if ( NOERROR != RpcStatus) {
  252. DBG_ERR(("StartRpcServerListen: RpcServerRegisterIf returned RpcStatus=0x%X",RpcStatus));
  253. return RpcStatus;
  254. }
  255. //
  256. // Now initiate servicing
  257. //
  258. RpcStatus = RpcServerListen(STI_LRPC_THREADS, // Minimum # of listen threads
  259. STI_LRPC_MAX_REQS, // Concurrency
  260. TRUE); // Immediate return
  261. if ( NOERROR != RpcStatus) {
  262. DBG_ERR(("StartRpcServerListen: RpcServerListen returned RpcStatus=0x%X",RpcStatus));
  263. return RpcStatus;
  264. }
  265. //
  266. //
  267. //
  268. SECURITY_ATTRIBUTES sa = { sizeof(sa), FALSE, NULL };
  269. // allocate appropriate security attributes for the named event we
  270. // use to learn about WIA service startup
  271. if(!ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("D:(A;;0x1f0003;;;SY)(A;;0x1f0003;;;LS)(A;;0x1f0003;;;LA)"),
  272. SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL))
  273. {
  274. DBG_ERR(("StartRpcServerListen failed to produce event security descriptor (Error %d)", GetLastError()));
  275. return GetLastError();
  276. }
  277. g_hWiaServiceStarted = CreateEvent(&sa, FALSE, FALSE, TEXT("Global\\WiaServiceStarted"));
  278. if(!g_hWiaServiceStarted) {
  279. DBG_ERR(("StartRpcServerListen failed to produce event security descriptor (Error %d)", GetLastError()));
  280. if(sa.lpSecurityDescriptor) LocalFree(sa.lpSecurityDescriptor);
  281. return GetLastError();
  282. }
  283. if(!SetEvent(g_hWiaServiceStarted)) {
  284. DBG_ERR(("StartRpcServerListen failed to set event (Error %d)", GetLastError()));
  285. }
  286. return (RpcStatus);
  287. }
  288. RPC_STATUS
  289. StopRpcServerListen(
  290. VOID
  291. )
  292. /*++
  293. Routine Description:
  294. Deletes the interface.
  295. Arguments:
  296. Return Value:
  297. RPC_S_OK or any RPC error codes that can be returned from
  298. RpcServerUnregisterIf.
  299. --*/
  300. {
  301. RPC_STATUS RpcStatus;
  302. EnterCriticalSection(&g_RpcEvent.cs);
  303. if(g_RpcEvent.pAsync) {
  304. RPC_STATUS status;
  305. status = RpcAsyncAbortCall(g_RpcEvent.pAsync, RPC_S_CALL_CANCELLED);
  306. if(status) {
  307. DBG_ERR(("RpcAsyncAbortCall failed with error 0x%x", status));
  308. }
  309. g_RpcEvent.pAsync = NULL;
  310. }
  311. LeaveCriticalSection(&g_RpcEvent.cs);
  312. RpcStatus = RpcServerUnregisterIf(stirpc_ServerIfHandle,
  313. NULL, // MgrUuid
  314. TRUE); // wait for calls to complete
  315. // BUGBUG RPC server should stop only after all interfaces are unregistered. For now we
  316. // only have one, so this is non-issue. When adding new interfaces to this RPC server, keep
  317. // ref count on register/unregister
  318. RpcStatus = RpcMgmtStopServerListening(0);
  319. //
  320. // wait for all RPC threads to go away.
  321. //
  322. if( RpcStatus == RPC_S_OK) {
  323. RpcStatus = RpcMgmtWaitServerListen();
  324. }
  325. return (RpcStatus);
  326. }