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