-
Notifications
You must be signed in to change notification settings - Fork 37
/
msrpc-client.c
191 lines (145 loc) · 4.12 KB
/
msrpc-client.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#ifndef CONFIG
#define CONFIG "config.h"
#endif // CONFIG
#include CONFIG
#ifdef USE_MSRPC
#if !defined(_WIN32) && !defined(__CYGWIN__)
#error MSRPC is only available with native Windows or Cygwin
#endif
#include "msrpc-client.h"
#include <stdio.h>
#include "output.h"
#include "helpers.h"
#if __amd64 || defined(_M_AMD64) // 64-bit
#ifndef _M_AMD64
#define _M_AMD64
#endif // _M_AMD64
#include "KMSServer_c_x64_mingw_gcc.c"
#else // 32-bit
#include "KMSServer_c_mingw_gcc.c"
#endif // 32-bit
static RPC_CSTR stringBinding;
jmp_buf jmp;
RPC_STATUS PreviousRpcCallFailed = RPC_S_OK;
/*
* Creates an RPC string binding that is used to connect to the server.
* Input is host:port, e.g. "[::1]:1688" or "127.0.0.1:1688"
* Output is for example "ncacn_ip_tcp:127.0.0.1[endpoint=1688]"
*/
#if !__amd64
#pragma GCC optimize("O0") ////TODO: Find out why gcc needs -O0 for RPC handling
#endif
static RPC_STATUS createStringBinding(char *const addr, RPC_CSTR* stringBinding)
{
char *szHost, *szPort;
parseAddress(addr, &szHost, &szPort);
return RpcStringBindingComposeA
(
NULL, /* UUID */
(RPC_CSTR)"ncacn_ip_tcp", /* use TCP */
(RPC_CSTR)szHost, /* host name or IP address */
(RPC_CSTR)szPort, /* endpoint (TCP port here) */
NULL, /* options */
stringBinding /* resulting string binding */
);
}
/*
* This does not actually connect to a TCP port because MS RPC doesn't connect
* before the actual RPC call is made. So this a stub
*/
RpcCtx connectToAddress(char *const addr, const int AddressFamily_unused, int_fast8_t showHostName_unused)
{
RPC_STATUS status;
printf("Connecting to %s ... ", addr);
if ((status = createStringBinding(addr, &stringBinding)) != RPC_S_OK)
{
errorout("%s\n", win_strerror(status));
return !0;
}
if (PreviousRpcCallFailed)
{
errorout("%s\n", win_strerror(PreviousRpcCallFailed));
return !0;
}
printf("successful\n");
return 0;
}
/*
* Does not do RPC binding on the wire. Just initializes the interface
*/
RpcStatus rpcBindClient(const RpcCtx handle, const int_fast8_t verbose)
{
RPC_STATUS status;
if ((status = RpcBindingFromStringBindingA(stringBinding, &KMSServer_v1_0_c_ifspec)) != RPC_S_OK)
{
errorout("\n%s\n", win_strerror(status));
}
return status;
}
/*
* You never know if you have a TCP connection or not
* This returns true if the previous RPC call failed
*/
int_fast8_t isDisconnected(const RpcCtx handle)
{
return PreviousRpcCallFailed;
}
/*
* This is the exception handler because the RPC call may
* throw an SEH exception and gcc does not support
* __try / __except as MSVC does.
*/
static LONG WINAPI rpcException (LPEXCEPTION_POINTERS exception_pointers)
{
DWORD exception = exception_pointers->ExceptionRecord->ExceptionCode;
if (!exception) exception = (DWORD)~0;
longjmp(jmp, exception_pointers->ExceptionRecord->ExceptionCode);
return EXCEPTION_EXECUTE_HANDLER;
}
/*
* This actually calls the RPC server
*/
#define try SetUnhandledExceptionFilter(rpcException); RPC_STATUS exception = setjmp(jmp); if (!exception)
#define catch else
RpcStatus rpcSendRequest(const RpcCtx handle, BYTE* KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t* responseSize)
{
*KmsResponse = NULL; // Let midl_user_allocate do the job
try
{
exception = RequestActivation(KMSServer_v1_0_c_ifspec, (int)requestSize, KmsRequest, (int*)responseSize, KmsResponse);
}
catch
{
errorout("\n%s", win_strerror(exception));
}
PreviousRpcCallFailed = exception;
SetUnhandledExceptionFilter(NULL);
return exception;
}
#undef catch
#undef try
/*
* Only frees local handles. Cannot close the TCP connection
*/
RpcStatus closeRpc(const RpcCtx handle)
{
RPC_STATUS status;
if ((status = RpcBindingFree(&KMSServer_v1_0_c_ifspec)) != RPC_S_OK) return status;
status = RpcStringFreeA(&stringBinding);
//Ctx = INVALID_RPCCTX;
return status;
}
#if !MULTI_CALL_BINARY
// Memory allocation function for RPC.
void *__RPC_USER midl_user_allocate(SIZE_T len)
{
return vlmcsd_malloc(len);
}
// Memory deallocation function for RPC.
void __RPC_USER midl_user_free(void __RPC_FAR *ptr)
{
if (ptr) free(ptr);
ptr = NULL;
}
#endif // !MULTI_CALL_BINARY
#endif // USE_MSRPC