Esempio n. 1
0
ws_ctx_t *do_handshake(int sock) {
    char handshake[4096], response[4096], sha1[29], trailer[17];
    char *scheme, *pre;
    headers_t *headers;
    int len, ret, i, offset;
    ws_ctx_t * ws_ctx;

    // Peek, but don't read the data
    len = recv(sock, handshake, 1024, MSG_PEEK);
    handshake[len] = 0;
    if (len == 0) {
        handler_msg("ignoring empty handshake\n");
        return NULL;
    } else if (bcmp(handshake, "<policy-file-request/>", 22) == 0) {
        len = recv(sock, handshake, 1024, 0);
        handshake[len] = 0;
        handler_msg("sending flash policy response\n");
        send(sock, POLICY_RESPONSE, sizeof(POLICY_RESPONSE), 0);
        return NULL;
    } else if ((bcmp(handshake, "\x16", 1) == 0) ||
               (bcmp(handshake, "\x80", 1) == 0)) {
        // SSL
        if (!settings.cert) {
            handler_msg("SSL connection but no cert specified\n");
            return NULL;
        } else if (access(settings.cert, R_OK) != 0) {
            handler_msg("SSL connection but '%s' not found\n",
                        settings.cert);
            return NULL;
        }
        ws_ctx = alloc_ws_ctx();
        ws_socket_ssl(ws_ctx, sock, settings.cert, settings.key);
        if (! ws_ctx) { return NULL; }
        scheme = "wss";
        handler_msg("using SSL socket\n");
    } else if (settings.ssl_only) {
        handler_msg("non-SSL connection disallowed\n");
        return NULL;
    } else {
        ws_ctx = alloc_ws_ctx();
        ws_socket(ws_ctx, sock);
        if (! ws_ctx) { return NULL; }
        scheme = "ws";
        handler_msg("using plain (not SSL) socket\n");
    }
    offset = 0;
    for (i = 0; i < 10; i++) {
        len = ws_recv(ws_ctx, handshake+offset, 4096);
        if (len == 0) {
            handler_emsg("Client closed during handshake\n");
            return NULL;
        }
        offset += len;
        handshake[offset] = 0;
        if (strstr(handshake, "\r\n\r\n")) {
            break;
        }
        usleep(10);
    }

    //handler_msg("handshake: %s\n", handshake);
    if (!parse_handshake(ws_ctx, handshake)) {
        handler_emsg("Invalid WS request\n");
        return NULL;
    }

    headers = ws_ctx->headers;
    if (ws_ctx->hybi > 0) {
        handler_msg("using protocol HyBi/IETF 6455 %d\n", ws_ctx->hybi);
        gen_sha1(headers, sha1);
        sprintf(response, SERVER_HANDSHAKE_HYBI, sha1, "base64");
    } else {
        if (ws_ctx->hixie == 76) {
            handler_msg("using protocol Hixie 76\n");
            gen_md5(headers, trailer);
            pre = "Sec-";
        } else {
            handler_msg("using protocol Hixie 75\n");
            trailer[0] = '\0';
            pre = "";
        }
        sprintf(response, SERVER_HANDSHAKE_HIXIE, pre, headers->origin, pre, scheme,
                headers->host, headers->path, pre, "base64", trailer);
    }
    
    //handler_msg("response: %s\n", response);
    ws_send(ws_ctx, response, strlen(response));

    return ws_ctx;
}
Esempio n. 2
0
ws_ctx_t *do_handshake(int sock, bool* useHixie) {
   char handshake[4096], response[4096], trailer[17], hashDataB64[256];
   char *scheme, *pre;
   headers_t headers;
   int len, i;
   u_char hashTemp[5];
   ws_ctx_t * ws_ctx;
   SHA1Context sha1context;
   
   ws_ctx = ws_socket(sock);
   // Peek, but don't read the data
   len = ws_recv(ws_ctx, handshake, 1024);
   if (len < 1)
   {
      handler_msg("recv error %d in do_handshake\n", WSAGetLastError());
   }
   handshake[len] = 0;
   if (len == 0) {
      handler_msg("ignoring empty handshake\n");
      return NULL;
   } else if (bcmp(handshake, "<policy-file-request/>", 22) == 0) {
      handshake[len] = 0;
      handler_msg("sending flash policy response\n");
      send(sock, policy_response, sizeof(policy_response) - 1, 0);
      return NULL;
   } else if ((bcmp(handshake, "\x16", 1) == 0) ||
      (bcmp(handshake, "\x80", 1) == 0)) {
         // SSL
         if (!settings.cert) {
            handler_msg("SSL connection but no cert specified\n");
            return NULL;
         } else if (access(settings.cert, R_OK) != 0) {
            handler_msg("SSL connection but '%s' not found\n",
               settings.cert);
            return NULL;
         }
         //ws_ctx = ws_socket_ssl(sock, settings.cert, settings.key);
         if (! ws_ctx) { return NULL; }
         scheme = "wss";
         handler_msg("using SSL socket\n");
   } else if (settings.ssl_only) {
      handler_msg("non-SSL connection disallowed\n");
      return NULL;
   } else {
      ws_ctx = ws_socket(sock);
      if (! ws_ctx) { return NULL; }
      scheme = "ws";
      handler_msg("using plain (not SSL) socket\n");
   }
   //len = ws_recv(ws_ctx, handshake, 4096);
   if (len == 0) {
      handler_emsg("Client closed during handshake\n");
      return NULL;
   }
   else if (len == -1)
   {
      return ws_ctx;
   }
   handshake[len] = 0;

   if (!parse_handshake(handshake, &headers)) {
      handler_emsg("Invalid WS request\n");
      return NULL;
   }

   if (headers.version[0] != '\0')
   {
      //strcpy((char*)headers.key1, (const char *)"dGhlIHNhbXBsZSBub25jZQ==");
      strncat(headers.key1, websocket_GUID, strlen(websocket_GUID));   
      SHA1Reset(&sha1context);
      //sha1context.Length_High = 0;
      //sha1context.Length_Low = strlen(headers.key1);
      SHA1Input(&sha1context, (const unsigned char*)&(headers.key1), strlen(headers.key1));
      SHA1Result(&sha1context);
      for (i = 0; i < 5; i++)
      {
         hashTemp[i * 4] = ((u_char*)sha1context.Message_Digest)[i * 4 + 3];
         hashTemp[i * 4 + 1] = ((u_char*)sha1context.Message_Digest)[i * 4 + 2];
         hashTemp[i * 4 + 2] = ((u_char*)sha1context.Message_Digest)[i * 4 + 1];
         hashTemp[i * 4 + 3] = ((u_char*)sha1context.Message_Digest)[i * 4];
      }
      b64_ntop((const u_char*)&hashTemp, 5 * sizeof(int), (char*)&hashDataB64, 256);
      //b64_pton((const char*)sha1context.Message_Digest, (u_char*)&hashDataB64, 256);
      sprintf(response, server_handshake_hybi, headers.upgrade, headers.connection, hashDataB64);
      handler_msg("response: %s\n", response);
      ws_send(ws_ctx, response, strlen(response));
      *useHixie = FALSE;
      return ws_ctx;
   }

   if (headers.key3[0] != '\0') {
      gen_md5(&headers, trailer);
      pre = "Sec-";
      handler_msg("using protocol version 76\n");
   } else {
      trailer[0] = '\0';
      pre = "";
      handler_msg("using protocol version 75\n");
   }

   sprintf(response, server_handshake, pre, headers.origin, pre, scheme,
      headers.host, headers.path, "", trailer);
   handler_msg("response: %s\n", response);
   ws_send(ws_ctx, response, strlen(response));

   return ws_ctx;
}