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

Reply via email to