I've not been through your code properly, but this line grabbed my eye as I skimmed over it:
> len = SSL_read(ctx->ssl, buffer + buf_offset, sizeof(BUFFER_SIZE) - buf_offset); You don't show the definition of BUFFER_SIZE anywhere, but sizeof(BUFFER_SIZE) is likely to be 4 or 8 or similar; are you sure that's what you mean? Regards, jjf > From: Mario [mailto:m...@kernelobjects.org] > > I have an issue with a try of my implementation of a secure > communication software. > > I´m compiling everything on Debian 6.0.7 (openssl 0.9.8o-4squeeze14 and > its dev package). > > For the application I´m dealing with non-blocking IO for the socket. I > can communicate a few bytes between server and client. However when my > server answers too much, the conneciton will be closed for both sides > when I try to read (SSL_read() returns 0 and the SSL-Error is 5 but the > systems errno is 0 all the time). The last SSL_write will always return > the amount of bytes I have to send, but ins this setup only 4 Bytes are > transmitted to the client. I case I send more than those 4 Bytes the > connection will be closed as described. > > Here is my SSL relevant code of my server part: > --- SNIP > /* setup our crypto environment */ > SSL_load_error_strings(); > SSL_library_init(); > OpenSSL_add_all_ciphers(); > if((ctx->ssl_ctx = SSL_CTX_new(TLSv1_server_method())) == NULL) { > tproxy_error_die("unable to initialize SSLv3 methods", 1); > } > SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_ALL); > SSL_CTX_set_timeout(ctx->ssl_ctx, 300); > if(!SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, ctx->cert_bundle)) > { > tproxy_error_die("unable to read certificate bundle file", 1); > } > if(strlen(ctx->key_file_pw)) { > SSL_CTX_set_default_passwd_cb(ctx->ssl_ctx, > private_key_pass_callback); > SSL_CTX_set_default_passwd_cb_userdata(ctx->ssl_ctx, (void *)ctx); > } > if(!SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx, ctx->key_file, > SSL_FILETYPE_PEM)) { > tproxy_error_die("unable to read key file", 1); > } > SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL); > SSL_CTX_set_info_callback(ctx->ssl_ctx, apps_ssl_info_callback); > [...] > con->sock = accept(ctx->socket[i], (struct sockaddr *)&in_socket, > &s_size); > /* make the accepted socket non-blocking */ > if(ioctl(con->sock, FIONBIO, (char *)&enable) < 0) { > tproxy_error_die("cannot set socket flags", 1); > } > /* create a new SSL context to handle the connection with the peer */ > con->ssl = SSL_new(ctx->ssl_ctx); > SSL_set_mode(con->ssl, SSL_MODE_AUTO_RETRY | > SSL_MODE_ENABLE_PARTIAL_WRITE); > > /* complete ssl connection */ > con->sbio = BIO_new_socket(con->sock, BIO_NOCLOSE); > SSL_set_bio(con->ssl, con->sbio, con->sbio); > /* set chipher */ > if (SSL_set_cipher_list(con->ssl,"AES128-SHA") <= 0) { > tproxy_error_die("unable to set chipher", 1); > } > /* do not require a valid client certificate */ > SSL_set_verify(con->ssl, SSL_VERIFY_NONE, NULL); > add_connection(ctx, con); > [...] > > /* later in the connection worker thread */ > > [...] > while(cur) { > switch(cur->state) { > case CSTATE_SSL_HANDSHAKE: > /* wait for the client to accept */ > if(1 != SSL_accept(cur->ssl)) { > if(SSL_get_error(cur->ssl, -1) != SSL_ERROR_WANT_READ && > SSL_get_error(cur->ssl, -1) != SSL_ERROR_WANT_WRITE) { > /* an SSL error occured */ > cur->state = CSTATE_TERMINATING; > } > } else { > cur->state = CSTATE_T_SETUP; > } > break; > case CSTATE_T_SETUP: > len = SSL_read(cur->ssl, cur->data + cur->data_offset, > TPROXY_BUFFER_SIZE - cur->data_offset); > if(len > 0) { > cur->data_offset += len; > } else if(len == 0){ > cur->state = CSTATE_TERMINATING; > } else { > if(SSL_get_error(cur->ssl, -1) != SSL_ERROR_WANT_READ && > SSL_get_error(cur->ssl, -1) != SSL_ERROR_WANT_WRITE) { > cur->state = CSTATE_TERMINATING; > } else { > if(cur->data_offset) { > [... do something with the data for application handshake...] > } > } > break; > case CSTATE_CONNECTED: > if(SSL_want(cur->ssl) == SSL_NOTHING) { > [...] check if something is in the pipe to send [...] > if(proto_data->len != SSL_write(cur->ssl, proto_data, > proto_data->len)) { > [...handle the partial send (never notices)...] > } > } > len = SSL_read(cur->ssl, cur->data + cur->data_offset, > TPROXY_BUFFER_SIZE - cur->data_offset); > if(len > 0) { > cur->data_offset += len; > } else if(len == 0){ > [...here is the actual error I´m talking about...] > } else { > if(SSL_get_error(cur->ssl, -1) != SSL_ERROR_WANT_READ && > SSL_get_error(cur->ssl, -1) != SSL_ERROR_WANT_WRITE) { > cur->state = CSTATE_TERMINATING; > } else { > if(cur->data_offset) { > [... do something with the data for application ...] > } > } > break; > [...] > ----SNIP > > I guess there was nothing special about it. The client is almost equal > - except that it do not handle multiple connections in a structure > (cur) > as it only has one ssl connection a time to the server: > > ----SNIP > /* setup ssl stuff */ > SSL_load_error_strings(); > SSL_library_init(); > OpenSSL_add_all_ciphers(); > if(NULL == (ctx->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) { > tproxy_error_die("unable to initialize ssl environment", 1); > } > SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL); > SSL_CTX_set_info_callback(ctx->ssl_ctx, apps_ssl_info_callback); > [...] > if(connect(ctx->proxy_socket, (struct sockaddr *)&addr, > sizeof(struct > sockaddr_in)) < 0) { > close(ctx->proxy_socket); > tproxy_error_die("unable to connect", 1); > } > if(ioctl(ctx->proxy_socket, FIONBIO, (char *)&enable) < 0) { > tproxy_error_die("cannot modify socket", 1); > } > SSL_CTX_set_timeout(ctx->ssl_ctx, 300); > ctx->ssl = SSL_new(ctx->ssl_ctx); > if (SSL_set_cipher_list(ctx->ssl, "AES128-SHA") <= 0) { > tproxy_error_die("unable to set chipher", 1); > } > ctx->bio = BIO_new_socket(ctx->proxy_socket, BIO_NOCLOSE); > SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio); > SSL_set_mode(ctx->ssl, SSL_MODE_AUTO_RETRY); > while(1 != (len = SSL_connect(ctx->ssl))) { > switch(SSL_get_error(ctx->ssl, len)) { > case SSL_ERROR_WANT_WRITE: > case SSL_ERROR_WANT_READ: > usleep(10000); > /* everything went fine (->non-blocking connect) */ > break; > default: > tproxy_error_die("unable to connect", 1); > } > } > > peer = SSL_get_peer_certificate(ctx->ssl); > X509_NAME_get_text_by_NID(X509_get_subject_name(peer), > NID_commonName, common_name, sizeof(common_name)); > printf("cn of peer: %s\n", common_name); > [... prepare application handshake ...] > if(len != SSL_write(ctx->ssl, init_data_out, len)) { > [... handle it (program was never here)...] > } > /* getting the configuration of the server */ > while(buf_offset < sizeof(struct proxy_proto_init_resp)) { > len = SSL_read(ctx->ssl, buffer + buf_offset, BUFFER_SIZE - > buf_offset); > if(len <= 0) { > switch(SSL_get_error(ctx->ssl, len)) { > case SSL_ERROR_WANT_WRITE: > case SSL_ERROR_WANT_READ: > usleep(10000); > /* everything went fine (->non-blocking connect) */ > break; > default: > tproxy_error_die("did not receive configuration", 1); > } > } else { > buf_offset += len; > } > } > [...setup application for user...] > while(1) { > /***** recv from ssl link *****/ > ERR_print_errors(ctx->bio); > len = SSL_read(ctx->ssl, buffer + buf_offset, sizeof(BUFFER_SIZE) > - > buf_offset); > t_err = errno; > if(len > 0) { > printf("%d bytes recvd %.*s\n", len, len, buffer + buf_offset); > // debugging > buf_offset += len; > } else if(len == 0) { > ERR_print_errors(ctx->bio); > if(SSL_ERROR_SYSCALL == SSL_get_error(ctx->ssl, len)) { > printf("fatal:%s\n", strerror(t_err)); > } > ERR_print_errors(ctx->bio); > tproxy_error_die("connection broken 1", SSL_get_error(ctx->ssl, > len)); > } else { > if(SSL_get_error(ctx->ssl, -1) != SSL_ERROR_WANT_READ && > SSL_get_error(ctx->ssl, -1) != SSL_ERROR_WANT_WRITE) { > tproxy_error_die("connection broken 2", 1); > } else { > [... do something with the date in the application ...] > } > } > } > [...] > ----SNIP > > Sending application data to the server is currently not implementet as > the server is not able to send the first application related message > (>4 > bytes) to the client. However the application handshake proceeds > without > any problems. > > The msg-callback and my debugging writes the following information into > the stdout: > CLIENT: > SSL_connect:before/connect initialization > SSL_connect:SSLv3 write client hello A > SSL_connect:error in SSLv3 read server hello A > SSL_connect:SSLv3 read server hello A > SSL_connect:SSLv3 read server certificate A > SSL_connect:SSLv3 read server done A > SSL_connect:SSLv3 write client key exchange A > SSL_connect:SSLv3 write change cipher spec A > SSL_connect:SSLv3 write finished A > SSL_connect:SSLv3 flush data > SSL_connect:error in SSLv3 read server session ticket A > SSL_connect:SSLv3 read server session ticket A > SSL_connect:SSLv3 read finished A > fatal:Success > fatal:connection broken 1 > Error: error:00000000:lib(0):func(0):reason(0) > > SERVER: > SSL_accept:before/accept initialization > SSL_accept:error in SSLv3 read client hello B > SSL_accept:SSLv3 read client hello B > SSL_accept:SSLv3 write server hello A > SSL_accept:SSLv3 write certificate A > SSL_accept:SSLv3 write server done A > SSL_accept:SSLv3 flush data > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:error in SSLv3 read client certificate A > SSL_accept:SSLv3 read client key exchange A > SSL_accept:SSLv3 read finished A > SSL_accept:SSLv3 write session ticket A > SSL_accept:SSLv3 write change cipher spec A > SSL_accept:SSLv3 write finished A > SSL_accept:SSLv3 flush data > > > I´m happy about any hint and any idea! Is there anything I can do for > deeper debugging openssl? > > Thank you. ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org