2016-12-19 4 views
0

Я написал сценарий, который может создать подключение к HTTP-серверу и отображать содержимое веб-сайта в консоли. Очень легко.OpenSSL в соединении Socket Socket (клиент HTTPS)

Но я хочу подключиться к серверу https и выполнять те же процедуры. Я искал в google и не нашел то, что искал.

Пожалуйста, помогите мне и дайте мне учебник, который я могу использовать в библиотеке openssl.

Я попробовал себя в библиотеке openssl, но библиотека очень сложная и трудная для понимания.

Вот мой код клиента HTTP:

#include <iostream> 
#include <ctype.h> 
#include <cstring> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <unistd.h> 
#include <sstream> 
#include <fstream> 
#include <string> 
#include <arpa/inet.h> 
#include <openssl/ssl.h> 

using namespace std; 

int sock; 
struct sockaddr_in client; 
int PORT = 80; 

int main(int argc, char const *argv[]) 
{ 
    bzero(&client, sizeof(client)); 
    client.sin_family = AF_INET; 
    client.sin_port = htons(PORT); 
    client.sin_addr.s_addr = inet_addr("172.16.0.6"); 

    sock = socket(AF_INET, SOCK_STREAM, 0); 

    if (sock < 0) { 
     cout << "Error creating socket." << endl; 
     exit(1); 
    } 

    if (connect(sock, (struct sockaddr *)&client, sizeof(client)) < 0) { 
     close(sock); 
     cout << "Could not connect" << endl; 
     exit(1); 
    } 

    stringstream ss; 
    ss << "GET /" << "\r\n" 
    << "Host: 172.16.1.4\r\n" 
    << "Accept: application/json\r\n" 
    << "Connection: close" 
    << "\r\n\r\n"; 
    string request = ss.str(); 

    if (send(sock, request.c_str(), request.length(), 0) != (int)request.length()) { 
     cout << "Error sending request." << endl; 
     exit(1); 
    } 

    char cur; 
    while (read(sock, &cur, 1) > 0) { 
     cout << cur; 
    } 

    return 0; 
} 
+3

Да, библиотека OpenSSL выше средней, с точки зрения сложности и сложности использования. Вам не только нужно выяснить, как использовать его, но также иметь хорошие рабочие знания о технологии SSL/TLS. Начните читать свою документацию. Получите книгу по внедрению приложений SSL и начните читать эту книгу. Нет, нет ярлыков и никаких волшебных палочек, которые можно отменить, и сделать клиенту SSL-клиента из воздуха. Нет альтернативы инвестированию значительного времени и усилий в изучение и изучение способов использования библиотеки. –

+0

Да, я знаю. существует небольшое знание TLS/SSL. Но мне нужно «быстрое» решение для C++-программы. Теперь я нашел хороший способ: я использую библиотеку libcurl. Вот уже реализация HTTPS. Большое спасибо! – Hball

+0

Используя OpenSSL, самым простым подходом было бы заменить слова 'connect()', 'read()' и 'send()' на 'ssl_connect()', 'ssl_read()' и 'ssl_write()' соответственно. Это означает повторную запись существующей логики сокетов, поскольку HTTP и HTTPS будут использовать разные коды кода. Если вы хотите повторно использовать существующий код сокета и просто добавить OpenSSL поверх него, вы можете использовать API-интерфейс OpenSSL 'BIO', который позволяет вам продолжать использовать' connect() ',' read() 'и' send() ' , вы просто связываете некоторые выделенные буферы памяти для обработки зашифрованных данных взад и вперед. Есть ** тонны ** примеров, если вы посмотрите вокруг. –

ответ

1

Вот пример SSL-клиент, который подключается к https://google.ru и печатает загружал страницу: SSLClient.cpp

//============================================================================ 
// Name  : SSLClient.cpp 
// Compiling : g++ -c -o SSLClient.o SSLClient.cpp 
       g++ -o SSLClient SSLClient.o -lssl -lcrypto 
//============================================================================ 
#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <openssl/ssl.h> 
#include <openssl/err.h> 
using namespace std; 

SSL *ssl; 
int sock; 

int RecvPacket() 
{ 
    int len=100; 
    char buf[1000000]; 
    do { 
     len=SSL_read(ssl, buf, 100); 
     buf[len]=0; 
     printf(buf); 
    } while (len > 0); 
    if (len < 0) { 
     int err = SSL_get_error(ssl, len); 
     if (err == SSL_ERROR_WANT_READ) 
      return 0; 
     if (err == SSL_ERROR_WANT_WRITE) 
      return 0; 
     if (err == SSL_ERROR_ZERO_RETURN || err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL) 
      return -1; 
    } 
} 

int SendPacket(const char *buf) 
{ 
    int len = SSL_write(ssl, buf, strlen(buf)); 
    if (len < 0) { 
     int err = SSL_get_error(ssl, len); 
     switch (err) { 
     case SSL_ERROR_WANT_WRITE: 
      return 0; 
     case SSL_ERROR_WANT_READ: 
      return 0; 
     case SSL_ERROR_ZERO_RETURN: 
     case SSL_ERROR_SYSCALL: 
     case SSL_ERROR_SSL: 
     default: 
      return -1; 
     } 
    } 
} 


void log_ssl() 
{ 
    int err; 
    while (err = ERR_get_error()) { 
     char *str = ERR_error_string(err, 0); 
     if (!str) 
      return; 
     printf(str); 
     printf("\n"); 
     fflush(stdout); 
    } 
} 


int main(int argc, char *argv[]) 
{ 
    int s; 
    s = socket(AF_INET, SOCK_STREAM, 0); 
    if (!s) { 
     printf("Error creating socket.\n"); 
     return -1; 
    } 
    struct sockaddr_in sa; 
    memset (&sa, 0, sizeof(sa)); 
    sa.sin_family  = AF_INET; 
    sa.sin_addr.s_addr = inet_addr("74.125.232.247"); // address of google.ru 
    sa.sin_port  = htons (443); 
    socklen_t socklen = sizeof(sa); 
    if (connect(s, (struct sockaddr *)&sa, socklen)) { 
     printf("Error connecting to server.\n"); 
     return -1; 
    } 
    SSL_library_init(); 
    SSLeay_add_ssl_algorithms(); 
    SSL_load_error_strings(); 
    const SSL_METHOD *meth = TLSv1_2_client_method(); 
    SSL_CTX *ctx = SSL_CTX_new (meth); 
    ssl = SSL_new (ctx); 
    if (!ssl) { 
     printf("Error creating SSL.\n"); 
     log_ssl(); 
     return -1; 
    } 
    sock = SSL_get_fd(ssl); 
    SSL_set_fd(ssl, s); 
    int err = SSL_connect(ssl); 
    if (err <= 0) { 
     printf("Error creating SSL connection. err=%x\n", err); 
     log_ssl(); 
     fflush(stdout); 
     return -1; 
    } 
    printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); 

    char *request = "GET https://www.google.ru/intl/en/about/company/facts/ HTTP/1.1\r\n\r\n"; 
    SendPacket(request); 
    RecvPacket(); 
    return 0; 
} 

Обратите внимание, что если вы хотите обмен данными между клиентом и сервером с помощью openssl, вам может потребоваться обработать коды ошибок SSL_ERROR_WANT_READ и SSL_ERROR_WANT_WRITE, как описано в документации. Но его не нужно здесь, как протокол HTTPS, является серийным.