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?
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:
Using two BIOs (one for SSL, one for buffering) should solve your problem.