static void handshake_cb(SoupSession *session, SoupMessage *message, void *user_data) { sr_session_t *s = user_data; struct sr_session_priv *priv = s->priv; const char *data, *end; if (!SOUP_STATUS_IS_SUCCESSFUL(message->status_code)) { handshake_failure(s); return; } data = message->response_body->data; end = strchr(data, '\n'); if (!end) /* really bad */ return; if (strncmp(data, "OK", end - data) == 0) { priv->handshake_delay = 1; parse_handshake(s, data); sr_session_submit(s); } else if (strncmp(data, "BANNED", end - data) == 0) fatal_error(s, "Client is banned"); else if (strncmp(data, "BADAUTH", end - data) == 0) fatal_error(s, "Bad authorization"); else if (strncmp(data, "BADTIME", end - data) == 0) fatal_error(s, "Wrong system time"); else handshake_failure(s); }
/** \brief Parse a bt_cmdtype_t::UTMSG_PAYL received by the attached bt_swarm_full_t * * @return a tokeep for the bt_swarm_full_t */ bool bt_swarm_full_utmsg_t::parse_utmsg_payl(pkt_t &pkt) throw() { uint8_t recved_opcode; bt_utmsgtype_t recved_utmsgtype; // log to debug KLOG_DBG("enter pkt="<< pkt); // parse the bt_utmsgtype_t try { pkt >> recved_opcode; }catch(serial_except_t &e){ return bt_err_t::ERROR; } // log to debug KLOG_DBG("recved_opcode=" << (int)recved_opcode); // convert the recved_opcode with the convtable_db_t convtable_db_t::const_iterator iter; for(iter = convtable_db.begin(); iter != convtable_db.end(); iter++){ const bt_utmsgtype_t & local_utmsgtype = iter->first; const uint8_t & remote_opcode = iter->second; // if the remote_opcode is not the recved_opcode, goto the next if( recved_opcode != remote_opcode ) continue; // set the recved_utmsgtype and leave the loop recved_utmsgtype = local_utmsgtype; break; } // if the recved_opcode has not been found in the convtable_db, return an error if( iter == convtable_db.end() ) return parsing_error("received opcode not in convtable_db from a " + swarm_full->remote_peerid().peerid_progfull()); // if the recved_utmsgtype is a HANDSHAKE, parse it internally if( recved_utmsgtype == bt_utmsgtype_t::HANDSHAKE ) return parse_handshake(pkt); // sanity check - the cnx_vapi_db MUST contain the bt_utmsgtype_t too DBG_ASSERT( cnx_vapi_db.find(recved_utmsgtype) != cnx_vapi_db.end() ); // send the packet to parse to the bt_utmsg_cnx_vapi_t bt_utmsg_cnx_vapi_t * cnx_vapi = cnx_vapi_db.find(recved_utmsgtype)->second; return cnx_vapi->parse_pkt(recved_utmsgtype, pkt); }
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; }
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; }