1
0

msrpc-server.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #ifndef CONFIG
  2. #define CONFIG "config.h"
  3. #endif // CONFIG
  4. #include CONFIG
  5. #ifdef USE_MSRPC
  6. #if !defined(_WIN32) && !defined(__CYGWIN__)
  7. #error MSRPC is only available with native Windows or Cygwin
  8. #endif
  9. #include "msrpc-server.h"
  10. #include "output.h"
  11. #include "kms.h"
  12. #include "helpers.h"
  13. #include "shared_globals.h"
  14. #include "ntservice.h"
  15. #include "endian.h"
  16. #include "types.h"
  17. #if __amd64 || defined(_M_AMD64) // 64-bit
  18. #ifndef _M_AMD64
  19. #define _M_AMD64
  20. #endif // _M_AMD64
  21. #include "KMSServer_s2_x64_mingw_gcc.c"
  22. #else // 32-bit
  23. #include "KMSServer_s2_mingw_gcc.c"
  24. #endif // 32-bit
  25. #if !defined(NO_LIMIT)
  26. #define MAXCALLS MaxTasks
  27. #else // defined(NO_LIMIT)
  28. #define MAXCALLS RPC_C_LISTEN_MAX_CALLS_DEFAULT
  29. #endif
  30. /*
  31. * This is the main run loop for the KMS server
  32. * We actually just setup things (must be after Cygwin fork) and then sleep
  33. */
  34. int runServer()
  35. {
  36. # if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
  37. // The RPC setup survives a Cygwin exec without problems but no daemonizing
  38. // SIGHUP is currently disabled for Cygwin. So this code should never compile
  39. if (IsRestarted)
  40. {
  41. # ifndef NO_LOG
  42. logger("vlmcsd %s started successfully\n", Version);
  43. # endif // NO_LOG
  44. }
  45. else
  46. # endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
  47. {
  48. RPC_STATUS status;
  49. // Endpoint is actually a TCP port for "ncacn_ip_tcp"
  50. status = RpcServerUseProtseqEpA
  51. (
  52. (RPC_CSTR)"ncacn_ip_tcp",
  53. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  54. (RPC_CSTR)defaultport,
  55. NULL
  56. );
  57. if (status)
  58. {
  59. printerrorf("Fatal: Cannot bind to port %s: %s\n", defaultport, win_strerror(status));
  60. return status;
  61. }
  62. # ifndef NO_LOG
  63. logger("Listening on port %s\n", defaultport);
  64. # endif // NO_LOG
  65. // Registers the KMSServer interface.
  66. status = RpcServerRegisterIf2
  67. (
  68. KMSServer_v1_0_s_ifspec,
  69. NULL,
  70. NULL,
  71. RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH | RPC_IF_AUTOLISTEN,
  72. MAXCALLS,
  73. MAX_RESPONSE_SIZE, // currently set to sizeof(RESPONSE_V6)
  74. NULL
  75. );
  76. if (status)
  77. {
  78. printerrorf("Fatal: Cannot register RPC interface: %s\n", win_strerror(status));
  79. return status;
  80. }
  81. # ifndef NO_LOG
  82. logger("vlmcsd %s started successfully\n", Version);
  83. # endif // NO_LOG
  84. if (IsNTService) ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 200);
  85. }
  86. // We could run RpcServerListen here but we need something
  87. // that can be signaled from Cygwin. So we just sleep 24h (POSIX sleep, no Windows Sleep),
  88. // wake up for some nanoseconds and sleep again.
  89. while(TRUE) sleep(86400); // Sleep one day
  90. }
  91. /*
  92. * Get's the IP address from an RPC_BINDING_HANDLE. Caller must call RpcStringFreeA to
  93. * release memory allocated in *ipAddress
  94. */
  95. #ifndef NO_LOG
  96. RPC_STATUS getClientIp(const RPC_BINDING_HANDLE clientBinding, RPC_CSTR *ipAddress)
  97. {
  98. RPC_STATUS result;
  99. RPC_CSTR stringBinding;
  100. RPC_BINDING_HANDLE serverBinding;
  101. // Fix for wine (disabled by default, because vlmcsd runs natively on all platforms where wine runs)
  102. // Feel free to #define SUPPORT_WINE if you really want to run the Windows version with MS RPC (Wine RPC in this case)
  103. #ifdef SUPPORT_WINE
  104. HMODULE h = GetModuleHandleA("kernel32.dll");
  105. if (h)
  106. {
  107. // Since wine simply terminates the thread when RpcBindingServerFromClient is called, we exit with an error
  108. if (GetProcAddress(h, "wine_get_unix_file_name")) return RPC_S_CANNOT_SUPPORT;
  109. }
  110. #endif // SUPPORT_WINE
  111. if ((result = RpcBindingServerFromClient(clientBinding, &serverBinding)) != RPC_S_OK) return result;
  112. if ((result = RpcBindingToStringBindingA(serverBinding, &stringBinding)) != RPC_S_OK)
  113. {
  114. RpcBindingFree(&serverBinding);
  115. return result;
  116. }
  117. result = RpcStringBindingParseA(stringBinding, NULL, NULL, ipAddress, NULL, NULL);
  118. RpcStringFreeA(&stringBinding);
  119. RpcBindingFree(&serverBinding);
  120. return result;
  121. }
  122. #endif // NO_LOG
  123. /*
  124. * This is the callback function for the RPC request as defined in KMSServer.idl
  125. * Output from the MIDL compiler has been modified manually to support gcc (and compatible compilers)
  126. * as well as Cygwin and MingW-w64 toolchains.
  127. */
  128. int ProcessActivationRequest(handle_t IDL_handle, int requestSize, unsigned char *request, int *responseSize, unsigned char **response)
  129. {
  130. RPC_CSTR clientIpAddress;
  131. RPC_STATUS result;
  132. int status = RPC_S_OK;
  133. result = getClientIp(IDL_handle, &clientIpAddress);
  134. # ifndef NO_LOG
  135. logger("RPC connection accepted: %s\n", !result ? (const char*)clientIpAddress : "Unknown IP");
  136. # endif // NO_LOG
  137. // Discard any packet smaller than a v4 request
  138. if (requestSize < (int)sizeof(REQUEST_V4))
  139. {
  140. if (!result) RpcStringFreeA(&clientIpAddress);
  141. return RPC_S_CANNOT_SUPPORT;
  142. }
  143. *response = (uint8_t *)midl_user_allocate(MAX_RESPONSE_SIZE);
  144. switch(LE16(((REQUEST*)(request))->MajorVer))
  145. {
  146. case 4:
  147. *responseSize = CreateResponseV4((REQUEST_V4 *)request, *response, (char*)clientIpAddress);
  148. break;
  149. case 5:
  150. case 6:
  151. *responseSize = CreateResponseV6((REQUEST_V6 *) request, *response, (char*)clientIpAddress);
  152. break;
  153. default:
  154. status = RPC_S_INVALID_ARG;
  155. break;
  156. }
  157. if (!result) RpcStringFreeA(&clientIpAddress);
  158. return status;
  159. }
  160. // Memory allocation function for RPC.
  161. void *__RPC_USER midl_user_allocate(SIZE_T len)
  162. {
  163. return vlmcsd_malloc(len);
  164. }
  165. // Memory deallocation function for RPC.
  166. void __RPC_USER midl_user_free(void __RPC_FAR *ptr)
  167. {
  168. if (ptr) free(ptr);
  169. ptr = NULL;
  170. }
  171. #endif // USE_MSRPC