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.

452 lines
11 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. sspiserv.cxx
  6. Abstract:
  7. sspiserv
  8. Author:
  9. Larry Zhu (LZhu) Januray 1, 2002
  10. Revision History:
  11. --*/
  12. #include <stdlib.h>
  13. #include <windows.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <rpc.h> // RPC data structures and APIs
  18. #include <hresult.hxx>
  19. #include <ntsecapi.h>
  20. #include <output.hxx>
  21. #include <lsasspi.hxx>
  22. #include "sspitest.h" // header file generated by MIDL compiler
  23. void Usage(char * pszProgramName)
  24. {
  25. fprintf(stderr, "Usage: %s\n", pszProgramName);
  26. fprintf(stderr, " -p protocol_sequence\n");
  27. fprintf(stderr, " -e endpoint\n");
  28. fprintf(stderr, " -o options\n");
  29. fprintf(stderr, " -s authn service\n");
  30. fprintf(stderr, " -t target service principal name\n");
  31. exit(1);
  32. }
  33. HANDLE TerminateEvent;
  34. ULONG AuthnService = RPC_C_AUTHN_GSS_NEGOTIATE;
  35. INT __cdecl
  36. main(
  37. INT argc,
  38. PSTR argv[]
  39. )
  40. {
  41. RPC_STATUS status;
  42. PSTR pszProtocolSequence = "ncacn_ip_tcp";
  43. PSTR pszEndpoint = "10";
  44. PSTR pszOptions = NULL;
  45. PSTR pszStringBinding = NULL;
  46. PSTR PrincipalName = NULL;
  47. int i;
  48. DWORD WaitStatus;
  49. // allow the user to override settings with command line switches
  50. for (i = 1; i < argc; i++)
  51. {
  52. if ((*argv[i] == '-') || (*argv[i] == '/'))
  53. {
  54. switch (tolower(*(argv[i]+1)))
  55. {
  56. case 'p': // protocol sequence
  57. pszProtocolSequence = argv[++i];
  58. break;
  59. case 'e':
  60. pszEndpoint = argv[++i];
  61. break;
  62. case 'o':
  63. pszOptions = argv[++i];
  64. break;
  65. case 's':
  66. AuthnService = strtol(argv[++i], NULL, 0);
  67. break;
  68. case 't':
  69. PrincipalName = argv[++i];
  70. break;
  71. case 'h':
  72. case '?':
  73. default:
  74. Usage(argv[0]);
  75. }
  76. }
  77. else
  78. {
  79. Usage(argv[0]);
  80. }
  81. }
  82. //
  83. // Create an event to wait on
  84. //
  85. TerminateEvent = CreateEventA(
  86. NULL, // No security attributes
  87. TRUE, // Must be manually reset
  88. FALSE, // Initially not signaled
  89. NULL // No name
  90. );
  91. if (TerminateEvent == NULL)
  92. {
  93. printf( "Couldn't CreateEvent %ld\n", GetLastError() );
  94. return 2;
  95. }
  96. printf("Server using protseq %s endpoint %s\n", pszProtocolSequence, pszEndpoint);
  97. status = RpcServerUseProtseqEpA(
  98. (UCHAR*) pszProtocolSequence,
  99. 3, // maximum concurrent calls
  100. (UCHAR*)pszEndpoint,
  101. 0
  102. );
  103. if (status)
  104. {
  105. printf("RpcServerUseProtseqEp returned 0x%x\n", status);
  106. exit(2);
  107. }
  108. status = RpcServerRegisterIf(srv_sspitest_ServerIfHandle, 0, 0);
  109. if (status)
  110. {
  111. printf("RpcServerRegisterIf returned 0x%x\n", status);
  112. exit(2);
  113. }
  114. printf("RpcServerRegisterAuthInfoA AuthnService %#x, PrincipalName %s\n", AuthnService, PrincipalName);
  115. status = RpcServerRegisterAuthInfoA(
  116. (UCHAR*) PrincipalName,
  117. AuthnService,
  118. NULL, // GetKeyFn
  119. NULL // Arg to GetKeyFn
  120. );
  121. if (status)
  122. {
  123. printf("RpcServerRegisterAuthInfo returned 0x%x\n", status);
  124. exit(2);
  125. }
  126. status = RpcServerInqDefaultPrincNameA(
  127. AuthnService,
  128. (UCHAR**)&PrincipalName
  129. );
  130. if (status)
  131. {
  132. printf("RpcServerInqDefaultPrincName returned %d\n", status);
  133. exit(2);
  134. }
  135. printf("RpcServerInqDefaultPrincNameA obtained AuthnService %#x, PrincipalName %s\n", AuthnService, PrincipalName);
  136. printf("Calling RpcServerListen\n");
  137. status = RpcServerListen(
  138. 1, //MinimumCallThreads
  139. 12345, // MaxCalls
  140. TRUE // DontWait
  141. );
  142. if (status)
  143. {
  144. printf("RpcServerListen returned: 0x%x\n", status);
  145. exit(2);
  146. }
  147. WaitStatus = WaitForSingleObject(TerminateEvent, INFINITE);
  148. if ( WaitStatus != WAIT_OBJECT_0)
  149. {
  150. printf("Couldn't WaitForSingleObject %ld %ld\n", WaitStatus, GetLastError());
  151. return 2;
  152. }
  153. return ERROR_SUCCESS;
  154. } /* end main() */
  155. // ====================================================================
  156. // MIDL allocate and free
  157. // ====================================================================
  158. void __RPC_FAR * __RPC_API
  159. MIDL_user_allocate(size_t len)
  160. {
  161. return(malloc(len));
  162. }
  163. void __RPC_API
  164. MIDL_user_free(void __RPC_FAR * ptr)
  165. {
  166. free(ptr);
  167. }
  168. ULONG
  169. RecurseRemoteCall(
  170. ULONG Options,
  171. PSTR RemoteAddress,
  172. PSTR RemoteProtocol,
  173. PSTR RemoteEndpoint,
  174. PSTR Principal,
  175. PSTR Address,
  176. ULONG AuthnLevel,
  177. ULONG AuthnSvc,
  178. ULONG RecursionLevel
  179. )
  180. {
  181. PSTR pszStringBinding = NULL;
  182. RPC_STATUS status;
  183. handle_t BindingHandle;
  184. // Use a convenience function to concatenate the elements of
  185. // the string binding into the proper sequence.
  186. status = RpcStringBindingComposeA(NULL,
  187. (UCHAR*) RemoteProtocol,
  188. (UCHAR*) RemoteAddress,
  189. (UCHAR*) RemoteEndpoint,
  190. NULL, // no network options
  191. (UCHAR**) &pszStringBinding);
  192. if (status)
  193. {
  194. printf("RpcStringBindingCompose returned %d\n", status);
  195. return(status);
  196. }
  197. printf("pszStringBinding = %s\n", pszStringBinding);
  198. //
  199. // Set the binding handle that will be used to bind to the server.
  200. //
  201. status = RpcBindingFromStringBindingA((UCHAR*) pszStringBinding,
  202. &BindingHandle);
  203. RpcStringFree((UCHAR**) &pszStringBinding);
  204. if (status)
  205. {
  206. printf("RpcBindingFromStringBinding returned %d\n", status);
  207. return (status);
  208. }
  209. //
  210. // Tell RPC to do the security thing.
  211. //
  212. printf("Binding auth info set to level %d, service %d, principal %s\n",
  213. AuthnLevel, AuthnService, Principal);
  214. status = RpcBindingSetAuthInfoA(
  215. BindingHandle,
  216. (UCHAR*)Principal,
  217. AuthnLevel,
  218. AuthnService,
  219. NULL, // no SID
  220. RPC_C_AUTHZ_NAME);
  221. if (status)
  222. {
  223. printf("RpcBindingSetAuthInfo returned %ld\n", status);
  224. return( status );
  225. }
  226. //
  227. // Do the actual RPC calls to the server.
  228. //
  229. RpcTryExcept
  230. {
  231. status = RemoteCall(
  232. BindingHandle,
  233. Options,
  234. (UCHAR*) Address,
  235. (UCHAR*) RemoteProtocol,
  236. (UCHAR*) RemoteEndpoint,
  237. (UCHAR*) Principal,
  238. (UCHAR*) RemoteAddress,
  239. AuthnLevel,
  240. AuthnService,
  241. RecursionLevel
  242. );
  243. if (status != ERROR_SUCCESS)
  244. {
  245. printf("RemoteCall failed: 0x%x\n",status);
  246. }
  247. }
  248. RpcExcept(EXCEPTION_EXECUTE_HANDLER)
  249. {
  250. printf("Runtime library reported an exception %d\n", RpcExceptionCode());
  251. } RpcEndExcept
  252. // The calls to the remote procedures are complete.
  253. // Free the binding handle
  254. status = RpcBindingFree(&BindingHandle); // remote calls done; unbind
  255. if (status)
  256. {
  257. printf("RpcBindingFree returned %d\n", status);
  258. exit(2);
  259. }
  260. return status;
  261. }
  262. ULONG
  263. srv_RemoteCall(
  264. handle_t BindingHandle,
  265. ULONG Options,
  266. UCHAR* RemoteAddress,
  267. UCHAR* RemoteProtocol,
  268. UCHAR* RemoteEndpoint,
  269. UCHAR* Principal,
  270. UCHAR* Address,
  271. ULONG AuthnLevel,
  272. ULONG AuthnSvc,
  273. ULONG RecursionLevel
  274. )
  275. {
  276. RPC_STATUS RpcStatus;
  277. CHAR ClientName[100];
  278. ULONG NameLen = sizeof(ClientName);
  279. RpcStatus = RpcImpersonateClient( NULL );
  280. if ( RpcStatus != RPC_S_OK )
  281. {
  282. printf( "RpcImpersonateClient Failed %ld\n", RpcStatus );
  283. goto Cleanup;
  284. }
  285. GetUserName(ClientName,&NameLen);
  286. printf("Recursion %d: Client called: name = %s\n", RecursionLevel, ClientName);
  287. if (RecursionLevel != 0)
  288. {
  289. RpcStatus = RecurseRemoteCall(
  290. Options,
  291. (PSTR) RemoteAddress,
  292. (PSTR) RemoteProtocol,
  293. (PSTR) RemoteEndpoint,
  294. (PSTR) Principal,
  295. (PSTR) Address,
  296. AuthnLevel,
  297. AuthnSvc,
  298. RecursionLevel - 1
  299. );
  300. }
  301. (void) RpcRevertToSelf(); // could fail?
  302. Cleanup:
  303. return(RpcStatus);
  304. }
  305. void
  306. srv_Shutdown(
  307. handle_t BindingHandle
  308. )
  309. {
  310. RPC_STATUS status;
  311. status = RpcMgmtStopServerListening(NULL);
  312. if (status)
  313. {
  314. printf("RpcMgmtStopServerListening returned: 0x%x\n", status);
  315. exit(2);
  316. }
  317. status = RpcServerUnregisterIf(NULL, NULL, FALSE);
  318. if (status)
  319. {
  320. printf("RpcServerUnregisterIf returned 0x%x\n", status);
  321. exit(2);
  322. }
  323. if ( !SetEvent( TerminateEvent) )
  324. {
  325. printf("Couldn't SetEvent %ld\n", GetLastError());
  326. }
  327. }
  328. unsigned long srv_ReadRegistryValueData(
  329. /* [in] */ handle_t BindingHandle,
  330. /* [in] */ unsigned long RootKeyLower,
  331. /* [unique][string][in] */ unsigned char *pszRegistryKey,
  332. /* [unique][string][in] */ unsigned char *pszRegistryValue,
  333. /* [in] */ unsigned long cbBuf,
  334. /* [size_is][unique][out][in] */ unsigned char *pBuf,
  335. /* [out] */ unsigned long *pDataType,
  336. /* [out] */ unsigned long *pcbReturned)
  337. {
  338. THResult hRetval;
  339. HKEY KeyRoot = ( HKEY ) (ULONG_PTR)((LONG)(0x80000000 | RootKeyLower)); // open registry key to Lsa\MSV1_0
  340. HKEY KeyHandle = NULL;
  341. ULONG RegValueType = 0;
  342. ULONG RegValue = 0;
  343. ULONG RegValueSize = 0;
  344. hRetval DBGCHK = HResultFromWin32(RpcImpersonateClient(BindingHandle));
  345. if (SUCCEEDED(hRetval))
  346. {
  347. DebugPrintf(SSPI_LOG, "*********srv_ReadRegistryValueData checking client user data************\n");
  348. hRetval DBGCHK = CheckUserData();
  349. }
  350. if (SUCCEEDED(hRetval))
  351. {
  352. hRetval DBGCHK = HResultFromWin32(RegOpenKey(KeyRoot, (PSTR) pszRegistryKey, &KeyHandle));
  353. }
  354. if (SUCCEEDED(hRetval))
  355. {
  356. RegValueSize = sizeof(RegValue);
  357. hRetval DBGCHK = HResultFromWin32(
  358. RegQueryValueExA(
  359. KeyHandle,
  360. (PSTR) pszRegistryValue,
  361. 0, // reserved
  362. &RegValueType,
  363. pBuf,
  364. &cbBuf
  365. ));
  366. }
  367. if (SUCCEEDED(hRetval))
  368. {
  369. DebugPrintf(SSPI_LOG, "srv_ReadRegistryValueData KeyRoot %#x, Key %s, Value %s, type %#x\n", KeyRoot, pszRegistryKey, pszRegistryValue, RegValueType);
  370. DebugPrintHex(SSPI_LOG, "ValueData", cbBuf, pBuf);
  371. *pcbReturned = cbBuf;
  372. }
  373. (void) RpcRevertToSelf(); // could fail?
  374. return HRESULT_CODE(hRetval);
  375. }