rkd77 / elinks

Fork of elinks
Other
349 stars 38 forks source link

[ ssl ] question: is the ssl get error called correctly? #158

Closed mtatton closed 2 years ago

mtatton commented 2 years ago

Hello rkd77,

I'm currently trying to compile the elinks on mingw. I'm just wondering. This:

define ssl_do_connect(socket) SSL_get_error((SSL )socket->ssl, SSL_connect((SSL )socket->ssl))

in src/network/ssl/socket.c

According to this: OpenSSL error handling

SSL_get_error() returns a result code (suitable for the C "switch" statement) for a preceding call to SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or SSL_write() on ssl. The value returned by that TLS/SSL I/O function must be passed to SSL_get_error() in parameter ret.

I guess the SSL_get_error has to be called AFTER the call of SSL_connect. I just spent some time trying to figure out what error does the SSL_connect returns. Because if this is called prior to the SSL_connect it would corrupt the stack in the connect thread on it's next call. In my opinion. The SSL_connect thread wasn't debuggable and returned error 0 and SYSCALL error.

So I guess the SSL_get_error shouldn't be called prior to the SSL_connect.

BTW: now I'm finally getting to the error messages and I'm getting:

DEBUG MESSAGE at socket.c:516:
ssl error syscall error:00000005:lib(0):func(0):DH lib
DEBUG MESSAGE at socket.c:517:
ws err 10009
DEBUG MESSAGE at socket.c:518:
os err 0
ELinks: SSL error

I'm unsure what is the error telling me. The DH lib is very cryptic and winsock error code 10009 is:

WSAEBADF10009 | File handle is not valid. The file handle supplied is not valid.

https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2

I just hope I'm retrieving the error codes correctly.

Would You have any educated guess on what could be possibly wrong?

Thank You and have a nice day

rkd77 commented 2 years ago

See how it is done in links browser (connect.c). If such changes don't help, change to a few instructions: something like: int ret = SSL_connect((SSL *)socket_ssl);

// debug here

int ret2 = SSL_get_error((SSL *)socket_ssl, ret);

// debug here

mtatton commented 2 years ago

Thank You very much. I'm slowly starting to be desperate. My current DEBUG messages looks like this:

DEBUG MESSAGE at ssl.c:92: ssl.c:init_openssl DEBUG MESSAGE at socket.c:145: socket.c:init_socket DEBUG MESSAGE at socket.c:145: socket.c:init_socket DEBUG MESSAGE at socket.c:271: socket.c:make_connection DEBUG MESSAGE at socket.c:112: socket.c:init_connection_info DEBUG MESSAGE at socket.c:235: socket.c:dns_found DEBUG MESSAGE at socket.c:595: socket.c:connect_socket DEBUG MESSAGE at socket.c:563: socket.c:init_bind_address DEBUG MESSAGE at socket.c:567: socket.c:init_bind_address INIT BIND ADDRESS PTON DEBUG MESSAGE at socket.c:683: socket.c:connect_socket CREATE SOCKET O.K. DEBUG MESSAGE at socket.c:472: socket.c:complete_connect_socket DEBUG MESSAGE at ssl_socket.c:435: ssl_socket.c:ssl_connect DEBUG MESSAGE at ssl_socket.c:442: Connectiong to 127.0.0.1 with ssl DEBUG MESSAGE at ssl.c:421: ssl.c:init_ssl_connection DEBUG MESSAGE at ssl.c:513: INIT SSL CONNECTION OK ssl.c:init_ssl_connection DEBUG MESSAGE at ssl_socket.c:459: INIT SSL CONNECTION O.K. DEBUG MESSAGE at ssl_socket.c:469: SSL attach to socket O.K. DEBUG MESSAGE at ssl_socket.c:555: SSL_state_string TWCH DEBUG MESSAGE at ssl_socket.c:556: SSL_state_string SSLv3/TLS write client hello DEBUG MESSAGE at ssl_socket.c:557: ssl error syscall error:00000005:lib(0):func(0):DH lib DEBUG MESSAGE at ssl_socket.c:558: winsock errror 10009 DEBUG MESSAGE at socket.c:595: socket.c:connect_socket DEBUG MESSAGE at socket.c:181: socket.c:close_socket DEBUG MESSAGE at ssl_socket.c:682: ssl_socket.c:ssl_close

DEBUG MESSAGE at ssl.c:520: ssl.c:done_ssl_connection DEBUG MESSAGE at socket.c:161: socket.c:done_socket DEBUG MESSAGE at socket.c:181: socket.c:close_socket DEBUG MESSAGE at socket.c:130: socket.c:done_connection_info DEBUG MESSAGE at socket.c:161: socket.c:done_socket DEBUG MESSAGE at socket.c:181: socket.c:close_socket ELinks: SSL error DEBUG MESSAGE at ssl.c:184: ssl.c:done_openssl

This is the problematic part:

    ret = SSL_connect(socket->ssl);                                                                                        

    int ssl_errno = SSL_get_error(socket->ssl, ret);                                                                       
    int err_WSAGetLastError = WSAGetLastError();                                                                           
    DBG("SSL_state_string %s", SSL_state_string(socket->ssl));                                                             
    DBG("SSL_state_string %s", SSL_state_string_long(socket->ssl));                                                        
    DBG("ssl error syscall %s", ERR_error_string(ssl_errno, NULL));                                                        
    DBG("winsock errror %d", err_WSAGetLastError,NULL);      

I did compile my own openssl under mingw for win64 for static linking as this:

$ cat build_win64.sh CFLAGS="-g -ggdb -DDEBUG_SAFESTACK" \ CPPFLAGS="-g -ggdb -DDEBUG_SAFESTACK" \ CXXFLAGS="-g -ggdb -DDEBUG_SAFESTACK" \ ./Configure \ no-ssl3 \ mingw64 \ --cross-compile-prefix=x86_64-w64-mingw32- \ --prefix=/usr/local && \ make && make install_runtime_libs

Tis does link, it has debuggin information but it fails somwhere deep inside the openssl library... I'm not sure if the problem is in the context initialization. I'm trying different settings like: //method = SSLv23_client_method(); method = TLSv1_method(); //SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); context = SSL_CTX_new(method); SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_2); SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_3);

Nothins really works.

Neither for the server from ./test/server/https.py nor 1.1.1.1 ... nothing.

From these messages: DEBUG MESSAGE at ssl_socket.c:555: SSL_state_string TWCH DEBUG MESSAGE at ssl_socket.c:556: SSL_state_string SSLv3/TLS write client hello DEBUG MESSAGE at ssl_socket.c:557: ssl error syscall error:00000005:lib(0):func(0):DH lib DEBUG MESSAGE at ssl_socket.c:558: winsock errror 10009

I'd say it ends up somehwere during the Diffie-Hellman key exchange.

The server (./test/server.py) uses:

Following protocols: SSL/TLS Protocols: SSLv2 disabled SSLv3 disabled TLSv1.0 disabled TLSv1.1 disabled TLSv1.2 enabled TLSv1.3 enabled

Thank You fro Your advice.

rkd77 commented 2 years ago

I don't know other method than adding debug statements to openssl and recompile it.

mtatton commented 2 years ago

I came up with this (below). Gonna try to test different scenarios and configurations. It has to work. While I used gdb on openssl I still cannot find the solution. The same code does work when compiled under gcc on linux. The state machine in openssl is hell. And the elinks code is not readable too much too. The preprocessor directives for GNU and OPENSSL are quite making it harder to read. But I found interesting note in TODO. Regarding the possibility to use faster and more straightforward cryptolib. What could I do if I would like to make test from the ssl-connect? I found a test for string matching in ssl.

// gcc -o ssl-connect ssl-connect.c -pedantic -Wall -std=c99 -lssl -lcrypto

#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <openssl/ssl.h>

char hostname[] = "127.0.0.1";
int port = 443;

void ssl_do_connect() {

  struct sockaddr_in addr;
  const SSL_METHOD* client_method;
  SSL_CTX *context;
  SSL *ssl;
  int sock = -1;
  int sd;

  OpenSSL_add_all_algorithms();
  client_method = SSLv23_client_method();
  context = SSL_CTX_new(client_method);

  sd = socket(PF_INET, SOCK_STREAM, 0);

  bzero(&addr, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = inet_addr(hostname);
  connect(sd, (struct sockaddr*)&addr, sizeof(addr));

  ssl = SSL_new(context);
  SSL_set_fd(ssl, sock);
  SSL_connect(ssl);

  SSL_free(ssl);
  close(sock);
  SSL_CTX_free(context);

}

int main(int argc, char *argv[]) {
  ssl_do_connect();
}
mtatton commented 2 years ago

Update 20220429:

This probably won't seem like a huge progress. But for me it is. There is a file in osdep directory with overrides.c. And that's where all the portability magick is made. In the code it just appear You're calling standard socket functions like connect, write, read, close. But in the fact You're calling it's redefined equivalent like win32_connect etc.

The win32 function has totally different definitions, using different parameters and when You just look at the code it seems like the code is quite pretty standard GNU like code.

Whatever. I just found what the dh lib problem was about. When the socket number is sent to the overrides it just differentiate between socket, file and keyboard event description by it's number. And when the new socket is opened it add SOCK_SHIFT to it (1024). When someone contributed with the openssl extension he / she didn't know that and used standard file description number.

With that in mind if You call SSL functions on socket You have to shift the fd number by 1024 lower.

Now I'm in different kind of error. And that's SSL 0002 and that's: DEBUG MESSAGE at socket.c:524: ssl error error:00000002:lib(0):func(0):system lib A small step forward.

And winsock error 10035 that would hint something about socket blocking WSAEWOULDBLOCK (could be something similar to the plaintext http requests).

20220429_elinks_ssl_errno_002

mtatton commented 2 years ago

Update 20220429: Handshake problem solved.

Now it seems like there is trouble with read / write or select. The connection timeouts without receiving / sending data.

20220430_elinks_err_000

mtatton commented 2 years ago

There was problem with the select in the term of errno setting to 0. In win32_select function, errno = 0 caused crash of the select loop thread. In my opinion errno is defined somewhere else for some different reason.

I'll complete and cleanup my code and try to prepare patch.

Thank You for listening and advises.

20220430_elinks_win64_ok

mtatton commented 2 years ago

Thank You very much. I'm closing this.