URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7829
[ Назад ]

Исходное сообщение
"Программирование openssl"

Отправлено Towellie , 14-Янв-09 07:06 
Надо организовать клиент сервер с шифрованием средством openssl.
server.c
//----------------------------------------------------
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include <stdio.h>
#include <string.h>

main()
{
    BIO *sbio, *bbio, *acpt, *out;
    int len;
    char tmpbuf[1024];
    SSL_CTX *ctx;
    SSL *ssl;
    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();
    SSL_library_init();  
    /* Might seed PRNG here */
    ctx=SSL_CTX_new(SSLv23_server_method());
        if(ctx == NULL)
    {
        printf("CTX is null\n");
        return;
    }
        
    printf("After Cert Load\n");
    if (!SSL_CTX_use_certificate_file(ctx,"certfiles/cacert.pem", SSL_FILETYPE_PEM)
        || SSL_CTX_use_PrivateKey_file(ctx,"certfiles/rsa_private_key.pem", SSL_FILETYPE_PEM)
        || SSL_CTX_check_private_key(ctx))
    {
        fprintf(stderr, "Error setting up SSL_CTX\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    printf("After Cert Load\n    ");
    /* Might do other things here like setting verify locations and
    * DH and/or RSA temporary key callbacks
    */
    /* New SSL BIO setup as server */
    sbio=BIO_new_ssl(ctx,0);
    BIO_get_ssl(sbio, &ssl);
    if(!ssl) {
        fprintf(stderr, "Can't locate SSL pointer\n");
        /* whatever ... */
    }
    /* Don't want any retries */
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    /* Create the buffering BIO */
    bbio = BIO_new(BIO_f_buffer());
    /* Add to chain */
    sbio = BIO_push(bbio, sbio);
    acpt=BIO_new_accept("1332");
    /* By doing this when a new connection is established
    * we automatically have sbio inserted into it. The
    * BIO chain is now 'swallowed' by the accept BIO and
    * will be freed when the accept BIO is freed.
    */
    
    BIO_set_accept_bios(acpt,sbio);
    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    /* Setup accept BIO */
    if(BIO_do_accept(acpt) <= 0) {
        fprintf(stderr, "Error setting up accept BIO\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    /* Now wait for incoming connection */
    if(BIO_do_accept(acpt) <= 0) {
        fprintf(stderr, "Error in connection\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    /* We only want one connection so remove and free
    * accept BIO
    */
    sbio = BIO_pop(acpt);
    BIO_free_all(acpt);
    if(BIO_do_handshake(sbio) <= 0)
    {
        fprintf(stderr, "Error in SSL handshake\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    BIO_puts(sbio, "HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n");
    BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n");
    BIO_puts(sbio, "--------------------------------------------------\r\n");
    for(;;) {
        len = BIO_gets(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        BIO_write(sbio, tmpbuf, len);
        BIO_write(out, tmpbuf, len);
        /* Look for blank line signifying end of headers*/
        if((tmpbuf[0] == '\r') || (tmpbuf[0] == '\n')) break;
    }
    BIO_puts(sbio, "--------------------------------------------------\r\n");
    BIO_puts(sbio, "\r\n");
    /* Since there is a buffering BIO present we had better flush it */
    BIO_flush(sbio);
    BIO_free_all(sbio);
}
//----------------------------------------------------
client.c
//----------------------------------------------------
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include <stdio.h>
#include <string.h>

main()
{
    BIO *sbio, *out;
    int len;
    char tmpbuf[1024];
    SSL_CTX *ctx;
    SSL *ssl;
    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();
    SSL_library_init();
    /* We would seed the PRNG here if the platform didn't
    * do it automatically
    */
    ctx = SSL_CTX_new(SSLv23_client_method());
    /* We'd normally set some stuff like the verify paths and
    * mode here because as things stand this will connect to
    * any server whose certificate is signed by any CA.
    */
    sbio = BIO_new_ssl_connect(ctx);
    BIO_get_ssl(sbio, &ssl);
    if(!ssl) {
        fprintf(stderr, "Can't locate SSL pointer\n");
        /* whatever ... */
    }
    /* Don't want any retries */
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    /* We might want to do other things with ssl here */
    BIO_set_conn_hostname(sbio, "localhost:1332");
    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    if(BIO_do_connect(sbio) <= 0) {
        fprintf(stderr, "Error connecting to server\n");
        ERR_print_errors_fp(stderr);
        /* whatever ... */
    }
    if(BIO_do_handshake(sbio) <= 0) {
        fprintf(stderr, "Error establishing SSL connection\n");
        ERR_print_errors_fp(stderr);
        /* whatever ... */
    }
    /* Could examine ssl here to get      info */
    BIO_puts(sbio, "GET / HTTP/1.0\n\n");
    for(;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        BIO_write(out, tmpbuf, len);
    }
    BIO_free_all(sbio);
    BIO_free(out);
}

//----------------------------------------------------

Когда клиент коннектится сервер вылетает со следующим текстом:
$ ./recv
After Cert Load
Enter PEM pass phrase:
After Cert Load
Error in SSL handshake
23749:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:/usr/src/secure/lib/libssl/../../../crypto/openssl/ssl/s3_srvr.c:974:
А клиент с таким:
$ ./send
Error connecting to server
24080:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/usr/src/secure/lib/libssl/../../../crypto/openssl/ssl/s23_clnt.c:562:
Error establishing SSL connection
24080:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/usr/src/secure/lib/libssl/../../../crypto/openssl/ssl/s23_clnt.c:562:
Вот собственно и проблема.
Заранее спасибо


Содержание

Сообщения в этом обсуждении
"Программирование openssl"
Отправлено angra , 14-Янв-09 07:11 
Студентам здесь не подают. Если уж стырил код, то напряги то, что замещает у тебя мозг, и почитай хотя бы лекции.

"граммиро вание"
Отправлено Andrey Mitrofanov , 14-Янв-09 08:57 
>то напряги то, что замещает у тебя мозг

Он и напрягает -- форум. %)

>, и почитай хотя бы лекции.

Осторожно, а то вдруг и это оно только ч/з форум умеет??! |))


"Программирование openssl"
Отправлено from_mars , 14-Янв-09 07:18 
вот здесь ошибка:

main()
{
    BIO *sbio, *bbio, *acpt, *out;
    int len;
    char tmpbuf[1024];
    SSL_CTX *ctx;
    SSL *ssl;
    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();
    SSL_library_init();  
    /* Might seed PRNG here */
    ctx=SSL_CTX_new(SSLv23_server_method());
        if(ctx == NULL)
    {
        printf("CTX is null\n");
        return;
    }
        
    printf("After Cert Load\n");
    if (!SSL_CTX_use_certificate_file(ctx,"certfiles/cacert.pem", SSL_FILETYPE_PEM)
        || SSL_CTX_use_PrivateKey_file(ctx,"certfiles/rsa_private_key.pem", SSL_FILETYPE_PEM)
        || SSL_CTX_check_private_key(ctx))
    {
        fprintf(stderr, "Error setting up SSL_CTX\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    printf("After Cert Load\n    ");
    /* Might do other things here like setting verify locations and
    * DH and/or RSA temporary key callbacks
    */
    /* New SSL BIO setup as server */
    sbio=BIO_new_ssl(ctx,0);
    BIO_get_ssl(sbio, &ssl);
    if(!ssl) {
        fprintf(stderr, "Can't locate SSL pointer\n");
        /* whatever ... */
    }
    /* Don't want any retries */
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    /* Create the buffering BIO */
    bbio = BIO_new(BIO_f_buffer());
    /* Add to chain */
    sbio = BIO_push(bbio, sbio);
    acpt=BIO_new_accept("1332");
    /* By doing this when a new connection is established
    * we automatically have sbio inserted into it. The
    * BIO chain is now 'swallowed' by the accept BIO and
    * will be freed when the accept BIO is freed.
    */
    
    BIO_set_accept_bios(acpt,sbio);
    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    /* Setup accept BIO */
    if(BIO_do_accept(acpt) <= 0) {
        fprintf(stderr, "Error setting up accept BIO\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    /* Now wait for incoming connection */
    if(BIO_do_accept(acpt) <= 0) {
        fprintf(stderr, "Error in connection\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    /* We only want one connection so remove and free
    * accept BIO
    */
    sbio = BIO_pop(acpt);
    BIO_free_all(acpt);
    if(BIO_do_handshake(sbio) <= 0)
    {
        fprintf(stderr, "Error in SSL handshake\n");
        ERR_print_errors_fp(stderr);
        return 0;
    }
    BIO_puts(sbio, "HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n");
    BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n");
    BIO_puts(sbio, "--------------------------------------------------\r\n");
    for(;;) {
        len = BIO_gets(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        BIO_write(sbio, tmpbuf, len);
        BIO_write(out, tmpbuf, len);
        /* Look for blank line signifying end of headers*/
        if((tmpbuf[0] == '\r') || (tmpbuf[0] == '\n')) break;
    }
    BIO_puts(sbio, "--------------------------------------------------\r\n");
    BIO_puts(sbio, "\r\n");
    /* Since there is a buffering BIO present we had better flush it */
    BIO_flush(sbio);
    BIO_free_all(sbio);
}
//----------------------------------------------------
client.c
//----------------------------------------------------
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include <stdio.h>
#include <string.h>

main()
{
    BIO *sbio, *out;
    int len;
    char tmpbuf[1024];
    SSL_CTX *ctx;
    SSL *ssl;
    ERR_load_crypto_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();
    SSL_library_init();
    /* We would seed the PRNG here if the platform didn't
    * do it automatically
    */
    ctx = SSL_CTX_new(SSLv23_client_method());
    /* We'd normally set some stuff like the verify paths and
    * mode here because as things stand this will connect to
    * any server whose certificate is signed by any CA.
    */
    sbio = BIO_new_ssl_connect(ctx);
    BIO_get_ssl(sbio, &ssl);
    if(!ssl) {
        fprintf(stderr, "Can't locate SSL pointer\n");
        /* whatever ... */
    }
    /* Don't want any retries */
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    /* We might want to do other things with ssl here */
    BIO_set_conn_hostname(sbio, "localhost:1332");
    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    if(BIO_do_connect(sbio) <= 0) {
        fprintf(stderr, "Error connecting to server\n");
        ERR_print_errors_fp(stderr);
        /* whatever ... */
    }
    if(BIO_do_handshake(sbio) <= 0) {
        fprintf(stderr, "Error establishing SSL connection\n");
        ERR_print_errors_fp(stderr);
        /* whatever ... */
    }
    /* Could examine ssl here to get      info */
    BIO_puts(sbio, "GET / HTTP/1.0\n\n");
    for(;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        BIO_write(out, tmpbuf, len);
    }
    BIO_free_all(sbio);
    BIO_free(out);
}


"Программирование openssl"
Отправлено Towellie , 14-Янв-09 15:03 
Проблема преобразилась в другую
server.c
//-------------
#include "stdio.h"
#include "string.h"

#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

int password_callback(char *buf, int size, int rwflag, void *userdata)
{
    /* For the purposes of this demonstration, the password is "ibmdw" */

    printf("*** Callback function called\n");
    strcpy(buf, "ibmdw");
    return 1;
}

int main()
{
    SSL_CTX *ctx;
    SSL *ssl;
    BIO *bio, *abio, *out, *sbio;
    char tmpbuf[1024];
    int len;

    int (*callback)(char *, int, int, void *) = &password_callback;

    printf("Secure Programming with the OpenSSL API, Part 4:\n");
    printf("Serving it up in a secure manner\n\n");

    SSL_load_error_strings();
    ERR_load_BIO_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();
    SSL_library_init();

    printf("Attempting to create SSL context... ");
    ctx = SSL_CTX_new(SSLv23_server_method());
    if(ctx == NULL)
    {
        printf("Failed. Aborting.\n");
        return 0;
    }

    printf("\nLoading certificates...\n");
    SSL_CTX_set_default_passwd_cb(ctx, callback);
    if(!SSL_CTX_use_certificate_file(ctx, "certificate.pem", SSL_FILETYPE_PEM))
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }
    if(!SSL_CTX_use_PrivateKey_file(ctx, "private.key", SSL_FILETYPE_PEM))
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }

    printf("Attempting to create BIO object... ");
    bio = BIO_new_ssl(ctx, 0);
    if(bio == NULL)
    {
        printf("Failed. Aborting.\n");
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }

    printf("\nAttempting to set up BIO for SSL...\n");
    BIO_get_ssl(bio, &ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    
    abio = BIO_new_accept("4422");
    BIO_set_accept_bios(abio, bio);

    printf("Waiting for incoming connection...\n");

    if(BIO_do_accept(abio) <= 0)
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
        BIO_free_all(abio);
        return;
    }

    if(BIO_do_accept(abio) <= 0)
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
        BIO_free_all(abio);
        return;
    }

    out = BIO_pop(abio);

    if(BIO_do_handshake(out) <= 0)
    {
        printf("Handshake failed.\n");
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
        BIO_free_all(abio);
        return;
    }

    BIO_puts(out, "Hello\n");
    
    //Read end
    for(;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        tmpbuf[len]='\0';
    }
    printf("%s", tmpbuf);
    //Read end
    if(strcmp(tmpbuf,"Hello\n")==0)
    {
        printf("Hello received sending user request\n");
        BIO_puts(out, "Hello\n");
    }
//----------
client.c
//--------
#include "stdio.h"
#include "string.h"

#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

int password_callback(char *buf, int size, int rwflag, void *userdata)
{
    /* For the purposes of this demonstration, the password is "ibmdw" */

    printf("*** Callback function called\n");
    strcpy(buf, "ibmdw");
    return 1;
}

int main()
{
    SSL_CTX *ctx;
    SSL *ssl;
    BIO *bio, *abio, *out, *sbio;
    char tmpbuf[1024];
    int len;

    int (*callback)(char *, int, int, void *) = &password_callback;

    printf("Secure Programming with the OpenSSL API, Part 4:\n");
    printf("Serving it up in a secure manner\n\n");

    SSL_load_error_strings();
    ERR_load_BIO_strings();
    ERR_load_SSL_strings();
    OpenSSL_add_all_algorithms();
    SSL_library_init();

    printf("Attempting to create SSL context... ");
    ctx = SSL_CTX_new(SSLv23_server_method());
    if(ctx == NULL)
    {
        printf("Failed. Aborting.\n");
        return 0;
    }

    printf("\nLoading certificates...\n");
    SSL_CTX_set_default_passwd_cb(ctx, callback);
    if(!SSL_CTX_use_certificate_file(ctx, "certificate.pem", SSL_FILETYPE_PEM))
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }
    if(!SSL_CTX_use_PrivateKey_file(ctx, "private.key", SSL_FILETYPE_PEM))
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }

    printf("Attempting to create BIO object... ");
    bio = BIO_new_ssl(ctx, 0);
    if(bio == NULL)
    {
        printf("Failed. Aborting.\n");
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }

    printf("\nAttempting to set up BIO for SSL...\n");
    BIO_get_ssl(bio, &ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    
    abio = BIO_new_accept("4422");
    BIO_set_accept_bios(abio, bio);

    printf("Waiting for incoming connection...\n");

    if(BIO_do_accept(abio) <= 0)
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
        BIO_free_all(abio);
        return;
    }

    if(BIO_do_accept(abio) <= 0)
    {
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
        BIO_free_all(abio);
        return;
    }

    out = BIO_pop(abio);

    if(BIO_do_handshake(out) <= 0)
    {
        printf("Handshake failed.\n");
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        BIO_free_all(bio);
        BIO_free_all(abio);
        return;
    }

    BIO_puts(out, "Hello\n");
    
    //Read end
    for(;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        tmpbuf[len]='\0';
    }
    printf("%s", tmpbuf);
    //Read end
    if(strcmp(tmpbuf,"Hello\n")==0)
    {
        printf("Hello received sending user request\n");
        BIO_puts(out, "Hello\n");
    }
//-------    
    BIO_flush(out);
    BIO_free_all(out);
    BIO_free_all(bio);
    BIO_free_all(abio);

    SSL_CTX_free(ctx);
}

    
    BIO_flush(out);
    BIO_free_all(out);
    BIO_free_all(bio);
    BIO_free_all(abio);

    SSL_CTX_free(ctx);
}
//-------
Проблема в том что со стороны клиента Hello получается принять и опознать
А со стороны сервера len = BIO_read(sbio, tmpbuf, 1024); возвращает ноль - тоесть на клиенте засовываю в out
буфер а он не а на сервере он просто не приходит.
Та конструкция которая в мануале вообще в буфер ничего не записывает ни на каких этапах вообще (( ни на сервере ни на клиенте.
http://openssl.org/docs/crypto/BIO_read.html
Вот описания функций - я не могу понять какие именно функции нужно использовать. (Сижу перевожу дальше)


"Программирование openssl"
Отправлено Towellie , 15-Янв-09 09:20 
Вобщем судя по всему надо переделывать кусок кода для чтения
//Read end
    for(;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        if(len <= 0) break;
        tmpbuf[len]='\0';
    }
    printf("%s", tmpbuf);
//Read end
Если добавить
//Read end
    for(;;) {
        len = BIO_read(sbio, tmpbuf, 1024);
        printf("%d <------ should\n", BIO_should_retry(sbio));<---- Это
        if(len <= 0) break;
        tmpbuf[len]='\0';
    }
    printf("%s", tmpbuf);
//Read end
Возвращается 0 на обоих функциях(на сервере)
For example if a call to BIO_read() on a socket BIO returns 0 and BIO_should_retry() is false then the cause will be that the connection closed.
Значит соединение закрыто? Оно должно быть открыто может я как то не так использую BIO_should_retry()?

"Программирование openssl"
Отправлено Towellie , 15-Янв-09 10:04 
>так использую BIO_should_retry()?

Дело еще например в том что логично предположить, что при удачном приеме (Если len > 0) - (Это на клиенте где прием удается)  то функция
BIO_should_retry должна вернуть true(потому что соединение еще не закрыто) и ошибиться в том что это именно sbio(потому, что мы же все таки с него считываем) тоже сложно.(Хотя я пробовал и bio) один фиг возврящяется 0.
:S


"Программирование openssl"
Отправлено Towellie , 15-Янв-09 12:41 
Вобщем в итоге все упирается в то, что BIO_read на сервере возвращает -2 по документации If the return value is -2 then the operation is not implemented in the specific BIO type.
И вот тут тупик. На клиенте функция отрабатывает.

P.S. Если я опять по вашему мнению спираю всю мысленную работу на вас - вы хоть отпишите(Даже сообщения ты студент, ты пень, кури маны только приветвтвуются)


"Программирование openssl"
Отправлено NuINu , 15-Янв-09 16:34 
>Вобщем в итоге все упирается в то, что BIO_read на сервере возвращает
>-2 по документации If the return value is -2 then the
>operation is not implemented in the specific BIO type.
>И вот тут тупик. На клиенте функция отрабатывает.
>
>P.S. Если я опять по вашему мнению спираю всю мысленную работу на
>вас - вы хоть отпишите(Даже сообщения ты студент, ты пень, кури
>маны только приветвтвуются)

почитай:
http://www.linuxjournal.com/article/4822
http://www.linuxjournal.com/article/5487

на ibm.com есть 3 статьи по программированию.



"Программирование openssl"
Отправлено Towellie , 16-Янв-09 06:46 
Спасибо за ответ - хороший материал.
Прочитал первую статью с горем пополам(С английским все плохо) Интересно но много букв и другой подход нежели на ibm.com - (В том числе и то, что например в этих статьях они вообще не используют bio_read).
Я их конечно дочитаю эти статьи чтобы понять в чем может быть проблема, но код я их использовать не буду. Тот код что выше это код взятый с openssl.org и исправленный немного(В первоначальном варианте он нерабочий) - сейчас уже почти все работает за исключением того что я не могу прочитать на сервере входящее сообщение.  И проанализированный со статьями на ibm.com (Очень доступные статьи) я с этих статей стырил код чтения - записи - с анализом ошибки и с повтором. - В коде с openssl.org он прекрасно себя чувствует при передаче с сервера на клиент а наоборот - нет - такая же в общем история.
//Write begin
printf("Sending Hello server\n");
strcpy(tmpbuf, "Hello server\n");
for(;;)
{
if(BIO_write(out, tmpbuf, strlen(tmpbuf)) <= 0)
{
  if(! BIO_should_retry(out))
  {
   printf("Write is crashed\n");
   return 0;
  }
  continue;
  }
break;
}
// Write end
//Read begin
for(;;)
{
len = BIO_read(sbio, tmpbuf, sizeof(tmpbuf));
if(len == 0)
{
  printf("Server is close connection\n");
  return 0;
}
else if(len < 0)
{
  if(! BIO_should_retry(sbio))
   {
   printf("Read is crashed %d\n",len);
   return 0;
   }
   continue;
}
break;
}    
printf("[%s] --- [%d] \n",tmpbuf, strlen(tmpbuf));
//Read end

"Программирование openssl"
Отправлено NuINu , 16-Янв-09 12:36 
>Спасибо за ответ - хороший материал.
>Прочитал первую статью с горем пополам(С английским все плохо) Интересно но много
>букв и другой подход нежели на ibm.com - (В том числе
>и то, что например в этих статьях они вообще не используют
>bio_read).
>Я их конечно дочитаю эти статьи чтобы понять в чем может быть
>проблема, но код я их использовать не буду. Тот код что
>выше это код взятый с openssl.org и исправленный немного(В первоначальном варианте
>он нерабочий) - сейчас уже почти все работает за исключением того

собственно не понятно как он у вас работает, потому как в вашем клиенте нет главного, а именно попытки соединиться с сервером.



"Программирование openssl"
Отправлено Towellie , 18-Янв-09 07:10 
Прошу прощения я не правильно вставил код.
Вобщем почитал я тут поэксперементировал немного - некоторые вещи прояснились переделал код - в общем я в обе стороны могу передавать, но возникла следующая трудность:
Код подкючения и тд и тп я писать не буду - он рабочий осталость только понять как работают BIO_read + BIO_write вобщем
Идея следующая - код записи и чтения везде одинаковый на одной стороне считать а потом записать а на втором конце соответственно наоборот.
Получается следующая картина:
./send
Sending Hello server
End writing
lets reading
Before read

./recv
Before read

Это означает то, что функция write отработала программа пошла дальше читать, а на другом конце read не получила ничего. - Но прикол в следующем если убрать код чтения из send. - Он будет отмечен внизу, read
получит свой Hello server.
$./recv
Before read
[13]<-----
[Hello client
] --- [13]
End reading
lets writing
Sending Hello server
End writing

$ ./send
Sending Hello server
End writing
lets reading

- И еще один момент - read отрабатывает после sleep на send. Это блин почему так может получиться? Складыавется такое чувство что данные передаются когда соединение завершается. - Странно не правда ли?


Код на одном конце:(recv.c)
    //Read begin
    for(;;)
    {
    printf("Before read\n");
    len = BIO_read(sbio, tmpbuf, sizeof(tmpbuf));
    printf("[%d]<-----\n",len);
    if(len == 0)
    {
      printf("Server is close connection\n");
      return 0;
    }
    else if(len < 0)
    {
      if(! BIO_should_retry(sbio))
       {
       printf("Read is crashed %d\n",len);
       return 0;
       }
       continue;
    }
    tmpbuf[len]=0;
    break;
    }    
    printf("[%s] --- [%d] \n",tmpbuf, strlen(tmpbuf));
    //Read end
    printf("End reading\n");
    BIO_flush(sbio);
    sleep(5);
    printf("lets writing\n");
    
    //Write begin
    printf("Sending Hello server\n");
    strcpy(tmpbuf, "Hello client\n");
    for(;;)
    {
    if(BIO_write(sbio, tmpbuf, strlen(tmpbuf)) <= 0)
    {
      if(! BIO_should_retry(sbio))
      {
       printf("Write is crashed\n");
       return 0;
      }
      continue;
      }
    break;
       }
    // Write end
    printf("End writing\n");
___________________________А вот на другом__________________________________________(send.c)

    //Write begin
    printf("Sending Hello server\n");
    strcpy(tmpbuf, "Hello client\n");
    for(;;)
    {
    if(BIO_write(sbio, tmpbuf, strlen(tmpbuf)) <= 0)
    {
      if(! BIO_should_retry(sbio))
      {
       printf("Write is crashed\n");
       return 0;
      }
      continue;
      }
    break;
    }
    // Write end
    printf("End writing\n");
    sleep(5);
    printf("lets reading\n");
    
    //Read begin <-----------------------
    for(;;)
    {
    printf("Before read\n");
    len = BIO_read(sbio, tmpbuf, sizeof(tmpbuf));
    printf("[%d]<-----\n",len);
    if(len == 0)
    {
      printf("Server is close connection\n");
      return 0;
    }
    else if(len < 0)
    {
      if(! BIO_should_retry(sbio))
       {
       printf("Read is crashed %d\n",len);
       return 0;
       }
       continue;
    }
    tmpbuf[len]=0;
    break;
    }    
    printf("[%s] --- [%d] \n",tmpbuf, strlen(tmpbuf));
    //Read end
    printf("End reading\n");
    BIO_flush(sbio);<--------------------------------------
    


"Программирование openssl"
Отправлено Towellie , 19-Янв-09 07:35 
Ну вот я уже можно сказать скурил все маны оказалось что
int BIO_read(BIO *b, void *buf, int len);
Пытается прочесть из объекта b len байт данных в буфер buf. Возвращает количество
прочитанных байт.
- И будет пытаться пока соединение не завершится(Поэтому данные передавались в конце соединения - соединение рвется BIO_read выходит из цикла и показывает что получла) в отличие от
int BIO_gets(BIO *b, char *buf, int size);
Для большинства типов BIO выполняет операцию, аналогичную fgets — читает из b в buf
до ближайшего конца строки, но не более size байт.
Тоесть функция read ждет а gets не ждет. - Поскольку я не знаю сколько мне должно придти (параметр len мне узнать не откуда) функция gets выглядит более предпочтительно - НО! Функция BIO_set_conn_hostname которая определяет объект ввода вывода не поддерживает BIO_gets
Connect BIOs support BIO_puts() but not BIO_gets().
Как мне быть? Куда смотреть теперь?


"Программирование openssl"
Отправлено angra , 19-Янв-09 08:17 
Много несколько вариантов.
1. изменить свой протокол добавив туда посылку размера сообщения
2. использовать буферизованный ввод при помощи BIO_f_buffer
3. использовать nonblocking io  на основе select в комбинации с BIO_should_retry