msrpc-server.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. #if _WIN32 && !defined(NO_PRIVATE_IP_DETECT)
  10. #include <winsock2.h>
  11. #endif
  12. #include "msrpc-server.h"
  13. #include "output.h"
  14. #include "kms.h"
  15. #include "helpers.h"
  16. #include "shared_globals.h"
  17. #include "ntservice.h"
  18. #include "endian.h"
  19. #include "types.h"
  20. #if __amd64 || defined(_M_AMD64) // 64-bit
  21. #ifndef _M_AMD64
  22. #define _M_AMD64
  23. #endif // _M_AMD64
  24. #include "KMSServer_s2_x64_mingw_gcc.c"
  25. #else // 32-bit
  26. #include "KMSServer_s2_mingw_gcc.c"
  27. #endif // 32-bit
  28. #if !defined(NO_LIMIT)
  29. #define MAXCALLS MaxTasks
  30. #else // defined(NO_LIMIT)
  31. #define MAXCALLS RPC_C_LISTEN_MAX_CALLS_DEFAULT
  32. #endif
  33. /*
  34. * This is the main run loop for the KMS server
  35. * We actually just setup things (must be after Cygwin fork) and then sleep
  36. */
  37. int runServer()
  38. {
  39. # if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
  40. // The RPC setup survives a Cygwin exec without problems but no daemonizing
  41. // SIGHUP is currently disabled for Cygwin. So this code should never compile
  42. if (IsRestarted)
  43. {
  44. # ifndef NO_LOG
  45. logger("vlmcsd %s started successfully\n", Version);
  46. # endif // NO_LOG
  47. }
  48. else
  49. # endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
  50. {
  51. RPC_STATUS status;
  52. // Endpoint is actually a TCP port for "ncacn_ip_tcp"
  53. status = RpcServerUseProtseqEpA
  54. (
  55. (RPC_CSTR)"ncacn_ip_tcp",
  56. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  57. (RPC_CSTR)defaultport,
  58. NULL
  59. );
  60. if (status)
  61. {
  62. printerrorf("Fatal: Cannot bind to port %s: %s\n", defaultport, win_strerror(status));
  63. return status;
  64. }
  65. # ifndef NO_LOG
  66. logger("Listening on port %s\n", defaultport);
  67. # endif // NO_LOG
  68. // Registers the KMSServer interface.
  69. status = RpcServerRegisterIf2
  70. (
  71. KMSServer_v1_0_s_ifspec,
  72. NULL,
  73. NULL,
  74. RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH | RPC_IF_AUTOLISTEN,
  75. MAXCALLS,
  76. MAX_RESPONSE_SIZE, // currently set to sizeof(RESPONSE_V6)
  77. NULL
  78. );
  79. if (status)
  80. {
  81. printerrorf("Fatal: Cannot register RPC interface: %s\n", win_strerror(status));
  82. return status;
  83. }
  84. # ifndef NO_LOG
  85. logger("vlmcsd %s started successfully\n", Version);
  86. # endif // NO_LOG
  87. if (IsNTService) ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 200);
  88. }
  89. // We could run RpcServerListen here but we need something
  90. // that can be signaled from Cygwin. So we just sleep 24h (POSIX sleep, no Windows Sleep),
  91. // wake up for some nanoseconds and sleep again.
  92. while(TRUE) sleep(86400); // Sleep one day
  93. }
  94. /*
  95. * Get's the IP address from an RPC_BINDING_HANDLE. Caller must call RpcStringFreeA to
  96. * release memory allocated in *ipAddress
  97. */
  98. #ifndef NO_LOG
  99. RPC_STATUS getClientIp(const RPC_BINDING_HANDLE clientBinding, RPC_CSTR *ipAddress)
  100. {
  101. RPC_STATUS result;
  102. RPC_CSTR stringBinding;
  103. RPC_BINDING_HANDLE serverBinding;
  104. // Fix for wine (disabled by default, because vlmcsd runs natively on all platforms where wine runs)
  105. // Feel free to #define SUPPORT_WINE if you really want to run the Windows version with MS RPC (Wine RPC in this case)
  106. #ifdef SUPPORT_WINE
  107. HMODULE h = GetModuleHandleA("kernel32.dll");
  108. if (h)
  109. {
  110. // Since wine simply terminates the thread when RpcBindingServerFromClient is called, we exit with an error
  111. if (GetProcAddress(h, "wine_get_unix_file_name")) return RPC_S_CANNOT_SUPPORT;
  112. }
  113. #endif // SUPPORT_WINE
  114. if ((result = RpcBindingServerFromClient(clientBinding, &serverBinding)) != RPC_S_OK) return result;
  115. if ((result = RpcBindingToStringBindingA(serverBinding, &stringBinding)) != RPC_S_OK)
  116. {
  117. RpcBindingFree(&serverBinding);
  118. return result;
  119. }
  120. result = RpcStringBindingParseA(stringBinding, NULL, NULL, ipAddress, NULL, NULL);
  121. RpcStringFreeA(&stringBinding);
  122. RpcBindingFree(&serverBinding);
  123. return result;
  124. }
  125. #endif // NO_LOG
  126. #ifndef NO_PRIVATE_IP_DETECT
  127. static int_fast8_t IsPrivateIPAddress(char* ipAddress)
  128. {
  129. int family = strchr(ipAddress,'.') ? AF_INET : AF_INET6;
  130. switch(family)
  131. {
  132. case AF_INET:
  133. {
  134. int i;
  135. char* current;
  136. char* next;
  137. uint32_t ip;
  138. for (ip = 0, i = 0, current = ipAddress; i < 4; i++, current = next + 1)
  139. {
  140. ip = (ip << 8) | strtoul(current, &next, 10);
  141. if (*next != '.') break;
  142. }
  143. if
  144. (
  145. (ip & 0xff000000) == 0x7f000000 || // 127.x.x.x localhost
  146. (ip & 0xffff0000) == 0xc0a80000 || // 192.168.x.x private routeable
  147. (ip & 0xffff0000) == 0xa9fe0000 || // 169.254.x.x link local
  148. (ip & 0xff000000) == 0x0a000000 || // 10.x.x.x private routeable
  149. (ip & 0xfff00000) == 0xac100000 // 172.16-31.x.x private routeable
  150. )
  151. {
  152. return TRUE;
  153. }
  154. break;
  155. }
  156. case AF_INET6:
  157. {
  158. if (!strcmp(ipAddress, "::1")) return TRUE;
  159. if (strchr(ipAddress, ':') - ipAddress != 4) break;
  160. int16_t firstWord;
  161. hex2bin((BYTE*)&firstWord, ipAddress, 2);
  162. if ((BE16(firstWord) & 0xe000) != 0x2000) return TRUE;
  163. }
  164. }
  165. return FALSE;
  166. }
  167. #endif // NO_PRIVATE_IP_DETECT
  168. /*
  169. * This is the callback function for the RPC request as defined in KMSServer.idl
  170. * Output from the MIDL compiler has been modified manually to support gcc (and compatible compilers)
  171. * as well as Cygwin and MingW-w64 toolchains.
  172. */
  173. int ProcessActivationRequest(handle_t IDL_handle, int requestSize, unsigned char *request, int *responseSize, unsigned char **response)
  174. {
  175. RPC_CSTR clientIpAddress;
  176. RPC_STATUS result;
  177. int status = RPC_S_OK;
  178. result = getClientIp(IDL_handle, &clientIpAddress);
  179. # ifndef NO_LOG
  180. logger("RPC connection accepted: %s\n", !result ? (const char*)clientIpAddress : "Unknown IP");
  181. # endif // NO_LOG
  182. # ifndef NO_PRIVATE_IP_DETECT
  183. if (result && (PublicIPProtectionLevel & 2))
  184. {
  185. # ifndef NO_LOG
  186. logger ("Cannot verify that client has a private IP address\n");
  187. # endif
  188. return RPC_S_ACCESS_DENIED;
  189. }
  190. if (!result && (PublicIPProtectionLevel & 2) && !IsPrivateIPAddress((char*)clientIpAddress))
  191. {
  192. # ifndef NO_LOG
  193. logger("Client with public IP address rejected\n");
  194. # endif
  195. RpcStringFreeA(&clientIpAddress);
  196. return RPC_S_ACCESS_DENIED;
  197. }
  198. # endif // NO_PRIVATE_IP_DETECT
  199. // Discard any packet smaller than a v4 request
  200. if (requestSize < (int)sizeof(REQUEST_V4))
  201. {
  202. if (!result) RpcStringFreeA(&clientIpAddress);
  203. return RPC_S_CANNOT_SUPPORT;
  204. }
  205. *response = (uint8_t *)midl_user_allocate(MAX_RESPONSE_SIZE);
  206. switch(LE16(((REQUEST*)(request))->MajorVer))
  207. {
  208. case 4:
  209. *responseSize = CreateResponseV4((REQUEST_V4 *)request, *response, (char*)clientIpAddress);
  210. break;
  211. case 5:
  212. case 6:
  213. *responseSize = CreateResponseV6((REQUEST_V6 *) request, *response, (char*)clientIpAddress);
  214. break;
  215. default:
  216. status = RPC_S_INVALID_ARG;
  217. break;
  218. }
  219. if (!result) RpcStringFreeA(&clientIpAddress);
  220. return status;
  221. }
  222. // Memory allocation function for RPC.
  223. void *__RPC_USER midl_user_allocate(SIZE_T len)
  224. {
  225. return vlmcsd_malloc(len);
  226. }
  227. // Memory deallocation function for RPC.
  228. void __RPC_USER midl_user_free(void __RPC_FAR *ptr)
  229. {
  230. if (ptr) free(ptr);
  231. ptr = NULL;
  232. }
  233. #endif // USE_MSRPC