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

时间:2011-07-27 13:56:03

标签: c openssl

我必须使用SSL连接到某个服务器,其中包含URL主机/ 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'。 有些想法有什么不对?

1 个答案:

答案 0 :(得分:2)

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

如果这对您来说是可以接受的,那么我认为问题在于您的BIO没有缓冲,这就是为什么您不使用BIO_puts从服务器获取任何数据的原因。另见这篇优秀的turorial

  

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

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