28#define MAX_STR_LEN 128
77 URL_COMPONENTS c = {0};
78 c.dwStructSize =
sizeof(c);
79 c.dwSchemeLength = -1;
80 c.dwHostNameLength = -1;
81 c.dwUrlPathLength = -1;
83 if (WinHttpCrackUrl(wUrl,
len, 0, &c) !=
TRUE) {
87 if (c.nScheme == INTERNET_SCHEME_HTTPS) {
88 components->
https =
true;
90 components->
https =
false;
98 c.lpszHostName, c.dwHostNameLength);
99 wcsncpy_s(components->
path,
100 sizeof(components->
path) /
sizeof(components->
path[0]),
101 c.lpszUrlPath, c.dwUrlPathLength);
102 components->
port = c.nPort;
106static void CALLBACK http_callback(HINTERNET internet
__attribute__((unused)),
107 DWORD_PTR
context, DWORD status,
108 LPVOID statusInfo, DWORD statusInfoLen) {
111 EnterCriticalSection(&c->
mtx);
113 case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
117 case WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED:
121 case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE:
125 case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
128 c->
len = statusInfoLen;
130 case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: {
131 WINHTTP_ASYNC_RESULT *result = (WINHTTP_ASYNC_RESULT *) statusInfo;
132 DBG_ERR(
"Request error: %lu %lu", (
long unsigned) result->dwResult,
136 case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING:
141 if (new_stage > c->
stage) {
142 c->
stage = new_stage;
144 LeaveCriticalSection(&c->
mtx);
147static void backend_set_verbosity(
uint8_t verbosity, FILE *output) {
152static yh_rc backend_init(
uint8_t verbosity, FILE *output) {
153 backend_set_verbosity(verbosity, output);
157static void backend_cleanup(
void) {}
163 WinHttpOpen(L
"YubiHSM WinHttp/" VERSION, WINHTTP_ACCESS_TYPE_NO_PROXY,
164 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS,
167 InitializeCriticalSection(&backend->
context->mtx);
168 WinHttpSetOption(backend->
internet, WINHTTP_OPTION_CONTEXT_VALUE,
170 WinHttpSetStatusCallback(backend->
internet, http_callback,
171 WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0);
175static void backend_disconnect(
yh_backend *connection) {
176 WinHttpCloseHandle(connection->
con);
177 WinHttpCloseHandle(connection->
internet);
179 EnterCriticalSection(&connection->
context->mtx);
180 DeleteCriticalSection(&connection->
context->mtx);
200 if (parseUrl(connector->
status_url, &components) ==
false) {
209 WinHttpOpenRequest(backend->
con, L
"GET", components.
path, NULL, NULL,
210 WINHTTP_DEFAULT_ACCEPT_TYPES,
211 components.
https ? WINHTTP_FLAG_SECURE : 0);
213 WinHttpSetTimeouts(backend->
context->req, timeout * 1000, timeout * 1000,
214 timeout * 1000, timeout * 1000);
216 WinHttpSendRequest(backend->
context->req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
217 WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
219 DWORD dwStatusCode = 0;
220 DWORD dwSize =
sizeof(dwStatusCode);
221 bool complete =
false;
224 enum stage new_stage = 0;
225 EnterCriticalSection(&backend->
context->mtx);
226 switch (backend->
context->stage) {
229 WinHttpReceiveResponse(backend->
context->req, NULL);
234 WinHttpQueryDataAvailable(backend->
context->req, NULL);
240 DBG_ERR(
"Failed request for new data: %lu", GetLastError());
248 WinHttpQueryHeaders(backend->
context->req,
249 WINHTTP_QUERY_STATUS_CODE |
250 WINHTTP_QUERY_FLAG_NUMBER,
251 WINHTTP_HEADER_NAME_BY_INDEX, &dwStatusCode,
252 &dwSize, WINHTTP_NO_HEADER_INDEX);
254 WinHttpCloseHandle(backend->
context->req);
255 if (dwStatusCode != HTTP_STATUS_OK) {
256 DBG_ERR(
"Got HTTP error from server: %lu", dwStatusCode);
274 if (new_stage > backend->
context->stage) {
275 backend->
context->stage = new_stage;
277 LeaveCriticalSection(&backend->
context->mtx);
285 bool complete =
false;
288 DWORD dwStatusCode = 0;
289 DWORD dwSize =
sizeof(dwStatusCode);
297 msg->
st.len = htons(msg->
st.len);
302 WinHttpOpenRequest(connection->
con, L
"POST", components.
path, NULL, NULL,
303 WINHTTP_DEFAULT_ACCEPT_TYPES,
304 components.
https ? WINHTTP_FLAG_SECURE : 0);
308 WinHttpSetTimeouts(connection->
context->req, 30 * 1000, 30 * 1000, 250 * 1000,
311 WinHttpSendRequest(connection->
context->req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
312 msg->
raw, raw_len, raw_len, 0);
315 enum stage new_stage = 0;
316 EnterCriticalSection(&connection->
context->mtx);
317 switch (connection->
context->stage) {
320 WinHttpReceiveResponse(connection->
context->req, NULL);
325 WinHttpQueryDataAvailable(connection->
context->req, NULL);
329 if (WinHttpReadData(connection->
context->req, response->raw,
331 DBG_ERR(
"Failed request for new data: %lu", GetLastError());
339 if (connection->
context->len == 0) {
343 "Got a 0 length response, hoping there's more on the wire for us.");
348 WinHttpQueryHeaders(connection->
context->req,
349 WINHTTP_QUERY_STATUS_CODE |
350 WINHTTP_QUERY_FLAG_NUMBER,
351 WINHTTP_HEADER_NAME_BY_INDEX, &dwStatusCode,
352 &dwSize, WINHTTP_NO_HEADER_INDEX);
354 if (dwStatusCode != HTTP_STATUS_OK) {
355 DBG_ERR(
"Got HTTP error from server: %lu", dwStatusCode);
359 WinHttpCloseHandle(connection->
context->req);
360 response->st.len = ntohs(response->st.len);
361 if (response->st.len + 3 == connection->
context->len) {
365 DBG_ERR(
"Wrong length received, %d vs %d", response->st.len + 3,
375 WinHttpCloseHandle(connection->
context->req);
383 if (new_stage > connection->
context->stage) {
384 connection->
context->stage = new_stage;
386 LeaveCriticalSection(&connection->
context->mtx);
390 msg->
st.len = ntohs(msg->
st.len);
401 DBG_ERR(
"Backend options not (yet?) supported with winhttp");
void YH_INTERNAL parse_status_data(char *data, yh_connector *connector)
struct sysio::chain::eosvmoc::code_cache_header __attribute__((packed))
yh_rc(* backend_init)(uint8_t verbosity, FILE *output)
void(* backend_set_verbosity)(uint8_t verbosity, FILE *output)
void(* backend_disconnect)(yh_backend *connection)
yh_rc(* backend_send_msg)(yh_backend *connection, Msg *msg, Msg *response)
yh_rc(* backend_option)(yh_backend *connection, yh_connector_option opt, const void *val)
yh_backend *(* backend_create)(void)
void(* backend_cleanup)(void)
yh_rc(* backend_connect)(yh_connector *connector, int timeout)
wchar_t hostname[MAX_STR_LEN+1]
wchar_t path[MAX_STR_LEN+1]
uint8_t raw[3+SCP_MSG_BUF_SIZE]
@ YHR_SUCCESS
Returned value when function was successful.
@ YHR_INVALID_PARAMETERS
Returned value when an argument to a function is invalid.
@ YHR_CONNECTOR_NOT_FOUND
Returned value when failing to find a suitable connector.
@ YHR_CONNECTOR_ERROR
Return value when connector operation failed.
yh_backend * backend_create(void)
FILE YH_INTERNAL * _yh_output
struct backend_functions * backend_functions(void)
uint8_t YH_INTERNAL _yh_verbosity