SSL-соединение с OpenSSL по указанному порту - PullRequest
1 голос
/ 27 июля 2011

Мне нужно подключиться к какому-либо серверу с URL-адресом host / getdata? Reqtype = generate & login = xxx & pass = xxx & dest = yyy с использованием SSL.

Я использую фрагмент кода, показанный ниже, но не могу получить данныес сервера.

CRYPTO_malloc_init();
SSL_library_init();
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();

SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
SSL* ssl;
BIO* bio = BIO_new_ssl_connect(ctx);

char *host = "host:8888";
char *con_protocol = "";

const char *REQUEST_PROTO = "GET /getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy HTTP/1.1\nHost: %s\nAccept: */*\nConnection: keep-alive\n\n";

char *con_string = (char*)calloc((strlen(host)+strlen(con_protocol))+1, sizeof(char));

strcat(con_string, host);
strcat(con_string, con_protocol);

// Failure?
if (bio == NULL) {
   printf("Error creating BIO!\n");
        ERR_print_errors_fp(stderr);
   // We need to free up the SSL_CTX before we leave.
        SSL_CTX_free(ctx);
        return;
}
// Makes ssl point to bio's SSL object.
BIO_get_ssl(bio, &ssl);
// Set the SSL to automatically retry on failure.
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
printf("connection string : %s\n", con_string);
BIO_set_conn_hostname(bio, con_string);

// Same as before, try to connect.
int y = BIO_do_connect(bio);
if (y <= 0) {
   printf("Failed to connect!\nError code : %d\n", y);
   BIO_free_all(bio);
   SSL_CTX_free(ctx);
   return;
}

// Now we need to do the SSL handshake, so we can communicate.
if (BIO_do_handshake(bio) <= 0) {
   printf("Failed to do SSL handshake!\n");
   BIO_free_all(bio);
   SSL_CTX_free(ctx);
   return;
}

// Create a buffer for grabbing information from the page.
char buf[1024];
memset(buf, 0, sizeof(buf));
// Create a buffer for the reqest we'll send to the server
char send[1024];
memset(send, 0, sizeof(send));


size_t total_size = strlen(REQUEST_PROTO)+strlen(host);
int t_size = (int)total_size+1;
    char *my_buf = malloc(t_size*sizeof(char));

    snprintf(my_buf, t_size, REQUEST_PROTO, host);

    printf("my_buf : %s\n", my_buf);

    BIO_puts(bio, my_buf);
    int temp = 0;
    int begin = 0;
    char *key_buff = (char *)calloc(32, sizeof(char));

    while (1) {
    int bytes_read = BIO_read(bio, buf, sizeof(buf) - 1);
        printf("bytes_read == %d\n", bytes_read);

        if (bytes_read == 0) {
            break;
        }
        else if (bytes_read < 0) {
            if (!BIO_should_retry(bio)) {
                printf("\nRead Failed!\n");
                BIO_free_all(bio);
                SSL_CTX_free(ctx);
                return;
            }
        }
        // We actually got some data, without errors!
        else {
            // Null-terminate our buffer, just in case
            buf[bytes_read] = 0;
            if ((bytes_read != 0) && (temp)) {
                for (begin; begin<(bytes_read+begin); begin++) {
                    key_buff[begin] = buf[begin];
                }
            }
            if (!temp) {
                temp = bytes_read;
            }

        }
    }

    BIO_free_all(bio);
    SSL_CTX_free(ctx);
    printf("key : %s\n\n", buf);

Я проверил соединение с CURL.При использовании команды curl --insecure 'https://localhost:8888/getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy' все работает, но когда я удаляю http из команды, я получаю пустой ответ, как в приложении.К сожалению, я не могу добавить 'http' в функцию BIO_set_conn_hostname ().Некоторые идеи, что не так?

1 Ответ

2 голосов
/ 28 июля 2011

Duskwuff прав, так как вы, очевидно, подключаетесь через https, вам было бы намного проще использовать что-то более высокого уровня, например cURL (вы можете использовать это программно, используя libcurl). В противном случае вам придется обрабатывать часть протокола HTTP самостоятельно.

Если это приемлемо для вас, то, я думаю, проблема в том, что ваша BIO не буферизуется, и поэтому вы не получаете никаких данных с сервера, используя BIO_puts. Смотрите также этот превосходный турориал :

Вместо использования SSL_write () и SSL_read () вы можете передавать данные, вызывая BIO_puts () и BIO_gets (), а также BIO_write () и BIO_read (), при условии, что буфер BIO создан и настроен следующим образом : ...

Использование двух BIO (один для SSL, другой для буферизации) должен решить вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...