The Google Chrome Agenda breaks this SSL_read. Does anyone have code that works?

I need a minimal SSL server and came up with the following:

confirm(WSAStartup(MakeWord(1,1), WData) = 0); SSL_library_init; SSL_load_error_strings; ctx := SSL_CTX_new(SSLv23_server_method); confirm(ctx <> nil); confirm(SSL_CTX_use_certificate_chain_file(ctx, 'cert.pem') > 0); confirm(SSL_CTX_use_PrivateKey_file(ctx, 'key.pem', SSL_FILETYPE_PEM) > 0); confirm(SSL_CTX_check_private_key(ctx)); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); listen_socket := socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); confirm(listen_socket <> 0); sa_serv.sin_family := AF_INET; sa_serv.sin_port := htons(DEFAULTPORT); sa_serv.sin_addr.s_addr := INADDR_ANY; confirm(bind(listen_socket, sa_serv, SizeOf(sa_serv)) = 0); while TRUE do begin if listen(listen_socket, 100) <> 0 then continue; client_len := SizeOf(sa_cli); sock := accept(listen_socket, @sa_cli, @client_len); if sock = INVALID_SOCKET then continue; ssl := SSL_new(ctx); if ssl = nil then continue; SSL_set_fd(ssl, sock); if SSL_accept(ssl) = 1 then begin bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1); if bytesin > 0 then begin buffer[bytesin] := #0; response := getresponse(buffer); SSL_write(ssl, pchar(response)^, length(response)); end; end; SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN or SSL_RECEIVED_SHUTDOWN); CloseSocket(sock); SSL_free(ssl); end; 

A single SSL_read will capture the entire GET or POST request from Firefox, and everything works fine. On the other hand, Chrome GET will call the first few SSL_read calls to return null bytes, but eventually SSL_read will grab the entire GET request, and the code still works.

But when Chrome sends a POST, the first few calls to SSL_read pick up the null bytes, and the next SSL_read will grab ONLY HEADERS . The getresponse () routine cannot understand POST because another SSL_read is needed to capture the contents of the POST.

SSL_MODE_AUTO_RETRY was set, hoping that SSL_read would not be present until the entire request was completed, but this did not work. SSL_pending always returns zero, before or after each SSL_read, so no help either.

As this question answers , non-blocking SSL seems to contain a lot of torture and heartburn. I played with SSL_reads executing in a separate thread and killed the thread after shutting down on a verified read, but this seems dangerous because it is not known what state SSL is in (or how to reset it) when the thread is killed.

Does anyone have code for a minimal loop similar to the one above, but it will not hang on Chrome POST or SSL_read, which is simple and fairly vanilla easy to convert to Delphi 6?

+2
source share
2 answers

I modified OpenSSL s_server.c , which now does the trick and posted it as an answer to question 7080958 .

0
source

You need to remember that TCP is flow-based, and a single Read call can return any piece of data that it can, and it can be, for example, half the header or the header + data bit of the message or something in between. You cannot expect a single read to return full data.

Therefore, your only option is the following algorithm:

  • read something.
  • check if you have the full title inside.
  • If you have a header, check if it contains Content-Length (some messages may not contain it)
  • If you have Content-length, continue reading from the socket to the length of the content, and then process the full request.
  • If you do not have Content-length, you need to deal with encoded encoding. This is a complicated thing to handle that goes far beyond the scope of the SO issue.

If I were you, I would take some existing HTTP / HTTPS server implementation. The obvious options are the Indy + SSL layer or the HTTPBlackbox server package of our SecureBlackbox.

+3
source

All Articles