在指定端口上与 OpenSSL 建立 SSL 连接

发布于 2024-11-26 17:39:04 字数 3370 浏览 1 评论 0原文

我必须使用 SSL 连接到 URL host/getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy 的某个服务器。

我正在使用下面显示的代码片段,但无法从服务器获取任何数据。

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”时,我得到了与应用程序中一样的空响应。不幸的是,我无法在 BIO_set_conn_hostname() 函数中添加“http”。 有些想法有什么问题?

I have to connect to some server with URL host/getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy using SSL.

I'm using code snippet shown below but I can't get any data from server.

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);

I've checked connection with CURL.
When using command
curl --insecure 'https://localhost:8888/getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy'
everything works, but when I remove 'http' from command, I get empty response as in the application. Unfortunately I can't add 'http' in BIO_set_conn_hostname() function.
Some ideas what is wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

标点 2024-12-03 17:39:04

Duskwuff 是对的,因为您显然是通过 https 连接,所以使用更高级别的 cURL 会更容易(您可以使用 libcurl 以编程方式使用它)。否则,您将必须自己处理协议的 HTTP 部分。

如果这对你来说可以接受,那么我认为问题在于你的 BIO 没有缓冲,这就是为什么你没有使用 BIO_puts 从服务器获取任何数据。另请参阅这个精彩的教程

您可以通过调用BIO_puts()和BIO_gets()以及BIO_write()和BIO_read()来传输数据,而不是使用SSL_write()和SSL_read(),前提是创建并设置了缓冲区BIO如下:...

使用两个 BIO(一个用于 SSL,一个用于缓冲)应该可以解决您的问题。

Duskwuff is right, since you are apparently connecting via https, it would be much easier for you to use something higher level as cURL (you can use it programmatically using libcurl). Otherwise you'll have to handle the HTTP part of the protocol all by yourself.

If that's acceptable for you, then I think the problem is that your BIO is not buffered, and that's why you don't get any data from the server using BIO_puts. See also this excellent turorial:

Instead of using SSL_write() and SSL_read(), you can transmit data by calling BIO_puts() and BIO_gets(), and BIO_write() and BIO_read(), provided that a buffer BIO is created and set up as follows: ...

Using two BIOs (one for SSL, one for buffering) should solve your problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文