Master-X
Форум | Новости | Статьи
Главная » Форум » Программинг, Скрипты, Софт, Сервисы » 
Тема: С++ вопрос
цитата
12/06/18 в 21:44
 S_Flash
Есть скрипт:

a) /lib/bill.cc
в нём:
Код:
#include "bill.hh"
и вызов метода
Код:
ssl = open_ssl_sock(host, TIMEOUT);

б) Единственное где нашёл упоминаниние open_ssl_sock, это /include/bill.hh
Код:
#include <openssl/ssl.h>
#include <openssl/err.h>
и единственная строка хоть как-то связанная с вышеупомянутым медотом:
Код:
SSL* open_ssl_sock(string host, int timeout = 30);


1) Хуййознает, обясните пожалуйста, где искать реализацию метода open_ssl_sock() и должна ли она быть вобще ???
2) Вызов ssl = open_ssl_sock(host, TIMEOUT); в скомпиленом bill.o даёт ошибку "ERR: Can't connect to host via SSL" (до этого работало, но на той стороне куда смотрит переменная host обновили SSL -> TLS 1.2). Может ли open_ssl_sock() использовать /usr/include/openssl/ssl.h либу?? Как-то можно проверить какую именно либу он использует? Апнул openssl на сервере, перезалил хедеры в /usr/include/openssl/, перекомпилил bill.cc - ошибка SSL при вызове open_ssl_sock не ушла.
цитата
13/06/18 в 14:41
 Alexs
проверь время на серваке и на клиенте , openSSL очень чувствителен ко времени

и на host сертификат живой ?
цитата
13/06/18 в 18:50
 S_Flash
1) host - публичный сервис - там всё норм с с ертификатом, другие не жалуются.
2) На что обратить вснимие во времени сервера (ssl клиента) ? Визуально там всё норм с годом, часом и минута в минуту с GEO временем..
цитата
13/06/18 в 19:29
 S_Flash
Мега проблема для меня лично, что я не знаю, что есть такое open_ssl_sock()
Как её реализовали, куда там порт втыкать?
цитата
13/06/18 в 21:43
 Alexs
давай по порядку попробуй натравить curl на host

curl -I https://127.0.0.1:8081

так мы убедимся что на серваке все гуд


S_Flash писал:
что есть такое open_ssl_sock()

подозреваю что функция в твоих исходниках, иначе бы оно гуглилосьбы

попробуй собрать пример что ли
https://gist.github.com/raschupkin/88a1ff730bcfa1c5a12d5804bbf451c9
цитата
13/06/18 в 22:33
 Mika
Какая ОС и версия openssl?
цитата
13/06/18 в 23:01
 S_Flash
Alexs: Mika:

FreeBSD 8.4-RELEASE-p35
OpenSSL> version
OpenSSL 1.0.2o 27 Mar 2018
(обновил ня днях)

Нашёл реализацию:

Код:

SSL*
open_ssl_sock(string host, int timeout) {
    SSL_METHOD *meth;
    SSL* ssl;
    SSL_CTX* ctx;
    struct hostent* he;
    struct sockaddr_in sa;
    struct timeval tv;
    unsigned char *addr;
    char ip[128];
    int sd;
   
    if ((he = gethostbyname(host.c_str())) != NULL) {
   addr = (unsigned char*)he->h_addr;
   snprintf(ip, sizeof(ip), "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
    }
    else {
   throw string("can't resolve ")+host+" : "+hstrerror(h_errno);
    }

    SSL_load_error_strings();
    SSL_library_init();
    meth = (SSL_METHOD*)SSLv23_client_method();

    if((ctx = SSL_CTX_new(meth)) == NULL) {
   throw "SSL: SSL_CTX_new() failed";
    }

    SSL_CTX_set_timeout(ctx, timeout);

    sd = socket (AF_INET, SOCK_STREAM, 0);
    tv.tv_sec  = timeout;
    tv.tv_usec = 0;
    setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval));

    memset (&sa, '\0', sizeof(sa));
    sa.sin_family      = AF_INET;
    sa.sin_addr.s_addr = inet_addr(ip);
    sa.sin_port        = htons(SSL_PORT);

    if (connect(sd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
   SSL_CTX_free (ctx);
   throw string("SSL: connect() failed : ") + strerror(errno);
    }

    tv.tv_sec = timeout;
    setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval));

    if((ssl = SSL_new(ctx)) == NULL) {
   SSL_CTX_free (ctx);
   close(sd);
   throw "SSL: SSL_new() failed";
    }
    SSL_set_fd(ssl, sd);

    if (SSL_connect (ssl) == -1) {
   SSL_CTX_free(ssl->ctx);
   SSL_free(ssl);
   close(sd);
   throw "Can't connect to host via SSL";
    }
   
    return ssl;
};


Мне кажется проблема в этой строке
Код:
meth = (SSL_METHOD*)SSLv23_client_method();

На сервере откуда тянется SSL API обновили SSL до TLS1.2
цитата
14/06/18 в 13:21
 Mika
S_Flash писал:
Мне кажется проблема в этой строке
Код:
meth = (SSL_METHOD*)SSLv23_client_method();

На сервере откуда тянется SSL API обновили SSL до TLS1.2

Эта функция универсальная.
https://www.openssl.org/docs/man1.0.2/ssl/SSLv23_client_method.html
Цитата:
SSLv23_method(), SSLv23_server_method(), SSLv23_client_method()
These are the general-purpose version-flexible SSL/TLS methods. The actual protocol version used will be negotiated to the highest version mutually supported by the client and the server. The supported protocols are SSLv2, SSLv3, TLSv1, TLSv1.1 and TLSv1.2. Most applications should use these method, and avoid the version specific methods described below.


Что выдает
$ echo | openssl s_client -connect host:port
?
цитата
14/06/18 в 13:54
 S_Flash
Mika писал:
Что выдает
$ echo | openssl s_client -connect host:port
?


Код:

% echo | openssl s_client -connect srs.segpay.com:443

CONNECTED(00000003)
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO ECC Certification Authority
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL Multi-Domain/CN=ssl515380.cloudflaressl.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Certification Authority
2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE/jCCBKWgAwIBAgIRAK6dENhd24crv0piw62fWIIwCgYIKoZIzj0EAwIwgZIx

...
...
...

CCqGSM49BAMCA0cAMEQCICdMjcz4p8ADsbQRL84dfULl04DAR3qQrUgESiFmRbeV
AiAsDFbZxWaqVENWIrqeg8l1KeMKH9jjenkEpvHVG8Zs5Q==
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL Multi-Domain/CN=ssl515380.cloudflaressl.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3683 bytes and written 437 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-...
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES128-GCM-SHA256
    Session-ID: DB4D81C905C4A99F2ABF7902C5970D2D8504F407F593233116B0DF3786218DBA
    Session-ID-ctx:
    Master-Key: 925D55AE12D4E7DD82A89CDAB29857...
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 64800 (seconds)
    TLS session ticket:
    0000 - eb 03 c4 b3 7b a9 70 c4-cc a6 d6 9b 78 29 f8 1c   ....{.p.....x)..
    0010 - 55 48 1d 9a 49 9a 49 84-bd 62 db 85 f0 d6 38 46   UH..I.I..b....8F

    ...
    ...
    ...

    0090 - 75 6d b5 84 b4 96 8d 74-45 7a 3d 4a 21 84 34 f8   um.....tEz=J!.4.
    00a0 - f5 fd ce 40 fe d7 d4 7c-94 03 56 89 89 58 f7 65   ...@...|..V..X.e

    Start Time: 1528973487
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
DONE



ПС Только порт я взял стандартный ибо в open_ssl_sock() нигде порт не упоминается в данных. Возможно порт получает клиент уже в каком-то из первых респонсов хедерами и пытается пересоединиться используюя полученный порт и IP сокетом.
цитата
21/06/18 в 16:46
 S_Flash
Подскажите форум, где поискать спецов по C++, которые могут исправить функцию:

Код:


SSL*
open_ssl_sock(string host, int timeout) {
    SSL_METHOD *meth;
    SSL* ssl;
    SSL_CTX* ctx;
    struct hostent* he;
    struct sockaddr_in sa;
    struct timeval tv;
    unsigned char *addr;
    char ip[128];
    int sd;
   
    if ((he = gethostbyname(host.c_str())) != NULL) {
   addr = (unsigned char*)he->h_addr;
   snprintf(ip, sizeof(ip), "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
    }
    else {
   throw string("can't resolve ")+host+" : "+hstrerror(h_errno);
    }

    SSL_load_error_strings();
    SSL_library_init();
    meth = (SSL_METHOD*)TLSv1_2_client_method();

    if((ctx = SSL_CTX_new(meth)) == NULL) {
   throw "SSL: SSL_CTX_new() failed";
    }

    SSL_CTX_set_timeout(ctx, timeout);

    sd = socket (AF_INET, SOCK_STREAM, 0);
    tv.tv_sec  = timeout;
    tv.tv_usec = 0;
    setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval));

    memset (&sa, '\0', sizeof(sa));
    sa.sin_family      = AF_INET;
    sa.sin_addr.s_addr = inet_addr(ip);
    sa.sin_port        = htons(SSL_PORT);

    if (connect(sd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
   SSL_CTX_free (ctx);
   throw string("SSL: connect() failed : ") + strerror(errno);
    }

    tv.tv_sec = timeout;
    setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval));

    if((ssl = SSL_new(ctx)) == NULL) {
   SSL_CTX_free (ctx);
   close(sd);
   throw "SSL: SSL_new() failed";
    }
    SSL_set_fd(ssl, sd);

    if (SSL_connect (ssl) == -1) {
   SSL_CTX_free(ssl->ctx);
   SSL_free(ssl);
   close(sd);
   throw "Can't connect to host via SSL";
    }
   
    return ssl;
};

цитата
21/06/18 в 17:06
 S_Flash
Вот весь модуль ssl.cc



#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <string>
#include "libstr.h"
#include "bill.hh"

#define TIMEOUT 30
#define SSL_PORT 443

SSL*
open_ssl_sock(string host, int timeout) {
    SSL_METHOD *meth;
    SSL* ssl;
    SSL_CTX* ctx;
    struct hostent* he;
    struct sockaddr_in sa;
    struct timeval tv;
    unsigned char *addr;
    char ip[128];
    int sd;
   
    if ((he = gethostbyname(host.c_str())) != NULL) {
   addr = (unsigned char*)he->h_addr;
   snprintf(ip, sizeof(ip), "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
    }
    else {
   throw string("can't resolve ")+host+" : "+hstrerror(h_errno);
    }

    SSL_load_error_strings();
    SSL_library_init();
    //meth = (SSL_METHOD*)SSLv23_client_method();
    meth = (SSL_METHOD*)TLSv1_2_client_method();

    if((ctx = SSL_CTX_new(meth)) == NULL) {
   throw "SSL: SSL_CTX_new() failed";
    }

    SSL_CTX_set_timeout(ctx, timeout);

    sd = socket (AF_INET, SOCK_STREAM, 0);
    tv.tv_sec  = timeout;
    tv.tv_usec = 0;
    setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval));

    memset (&sa, '\0', sizeof(sa));
    sa.sin_family      = AF_INET;
    sa.sin_addr.s_addr = inet_addr(ip);
    sa.sin_port        = htons(SSL_PORT);

    if (connect(sd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
   SSL_CTX_free (ctx);
   throw string("SSL: connect() failed : ") + strerror(errno);
    }

    tv.tv_sec = timeout;
    setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
    setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(struct timeval));

    if((ssl = SSL_new(ctx)) == NULL) {
   SSL_CTX_free (ctx);
   close(sd);
   throw "SSL: SSL_new() failed";
    }
    SSL_set_fd(ssl, sd);

    if (SSL_connect (ssl) == -1) {
   SSL_CTX_free(ssl->ctx);
   SSL_free(ssl);
   close(sd);
   throw "Can't connect to host via SSL";
    }
   
    return ssl;
};

void
close_ssl_sock(SSL *ssl)
{
    SSL_shutdown(ssl);
    SSL_CTX_free(ssl->ctx);
    close(SSL_get_fd(ssl));
    SSL_free(ssl);
}

string
read_responce(SSL *ssl, bool verbose)
{
    char buff[1024*16];
    string data;
    int r;
    unsigned long n;
   
    // read response
    while ((r = SSL_read(ssl, buff, sizeof(buff)-1))) {
   if (verbose) cout << "read_responce() : " << r << " bytes" << endl;
   if (r < 0) {
       break;
   }
   buff[r] = 0;
   data += buff;
    }

    if ((n = data.find("\r\n")) == string::npos) {
   n = data.find("\n");
    }
    if (n == string::npos || n < 15) {
   cout << "ssl_read_responce(): Read timeout or invalid HTTP response : "+data;
   return "";
    }
//    if (data.substr(0, 15) != "HTTP/1.1 200 OK" && data.substr(0, 15) != "HTTP/1.0 200 OK") {
   if (data.substr(0, 15) != "HTTP/1.1 200 OK" && data.substr(0, 15) != "HTTP/1.0 200 OK" && data.substr(0, 15) != "HTTP/1.0 302 Fo") {
       cout << "ssl_read_responce(): bad HTTP code : "+data;
       return "";
    }

    return data;
}


string
http_get_request(string host, string path, string query, bool verbose, string auth, string method)
{
    int sock, bytes;
    unsigned long n;
    size_t sin_size;
    struct sockaddr_in serv_addr;
    struct timeval timeout;
    struct hostent *he;
    fd_set fds;
    char buff[4096];
    string xml;
   
    string req = method+" "+path+(!query.empty() ? "?"+query : "")+" HTTP/1.1\r\nHost: "+host+"\r\n";
    if (!auth.empty()) {
   req += "Authorization: Basic "+auth+"\r\n";
    }
    req += "\r\n";
    if (verbose) cout << "http_get_request(): " << req;

    // resolve host
    he = gethostbyname(host.c_str());
    if (he == NULL) {
        throw string("can't resolve hostname ")+host+" : "+hstrerror(h_errno);
    }

    // create socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr = * ((struct in_addr *) he->h_addr); ;
    serv_addr.sin_port = htons(80);
    memset(&(serv_addr.sin_zero), '\0', 8);
    sin_size = sizeof(struct sockaddr_in);
    // connect
    if (connect(sock, (struct sockaddr*)&serv_addr, sin_size) != 0) {
        throw string("connect() failed : ")+strerror(errno);
    }
    // send request
    write(sock, req.c_str(), req.length());
    // read response
    while (1) {
        // timeout checking
        FD_ZERO(&fds);
        FD_SET(sock, &fds);
        timeout.tv_sec = TIMEOUT;
        timeout.tv_usec = 0;
        if (select(sock+1, &fds, NULL, NULL, &timeout) == 0) {
       break;
        }

        // read data
        memset(buff, 0, sizeof(buff));
        bytes = read(sock, buff, sizeof(buff)-1);
        xml += buff;
        if (bytes == 0) {
            // no more data
            break;
        }
        if (bytes == -1) {
       throw "http_get_request(): read error - timeout";
        }
    }

    // HEAD - return all response
    if (method == "HEAD") {
   return xml;
    }

    // GET - remove headers and decode
    if ((n = xml.find("\r\n")) == string::npos) {
   n = xml.find("\n");
    }
    if (n == string::npos || n < 15) {
   cout << "http_get_request(): Read timeout or invalid HTTP response : '"+xml+"'";
   return "";
    }
    string code = xml.substr(9, 3);
    if (code != "200" && code != "302") {
   cout << "http_get_request(): bad HTTP code : '"+xml.substr(0, 15)+"'";
   return "";
    }
    xml = chunk_decode(xml);

    return xml;
}

string
http_post_request(string host, string path, string query, bool verbose, string cookie)
{
    string headers, req;
    int sock, bytes;
    unsigned long n;
    size_t sin_size;
    struct sockaddr_in serv_addr;
    struct timeval timeout;
    struct hostent *he;
    fd_set fds;
    char buff[4096];
    string xml;
   
    headers  = "Content-Type: application/x-www-form-urlencoded\r\n";
    headers += "Content-Length: "+itoa(query.size())+"\r\n";
    headers += "Connection: close\r\n";

    req  = "POST "+path+" HTTP/1.1\r\n";
    req += "Host: "+host+"\r\n";
    if (!cookie.empty()) {
   req += "Cookie: "+cookie+";\r\n";
    }
    req += headers;
    req += "\r\n";
    req += query;

    if (verbose) cout << "http_post_request(): " << req << endl;

    // resolve host
    he = gethostbyname(host.c_str());
    if (he == NULL) {
        throw string("can't resolve hostname ")+host+" : "+hstrerror(h_errno);
    }

    // create socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr = * ((struct in_addr *) he->h_addr); ;
    serv_addr.sin_port = htons(80);
    memset(&(serv_addr.sin_zero), '\0', 8);
    sin_size = sizeof(struct sockaddr_in);
    // connect
    if (connect(sock, (struct sockaddr*)&serv_addr, sin_size) != 0) {
        throw string("connect() failed : ")+strerror(errno);
    }
    // send request
    write(sock, req.c_str(), req.length());
    // read response
    while (1) {
        // timeout checking
        FD_ZERO(&fds);
        FD_SET(sock, &fds);
        timeout.tv_sec = TIMEOUT;
        timeout.tv_usec = 0;
        if (select(sock+1, &fds, NULL, NULL, &timeout) == 0) {
       break;
        }

        // read data
        memset(buff, 0, sizeof(buff));
        bytes = read(sock, buff, sizeof(buff)-1);
        xml += buff;
        if (bytes == 0) {
            // no more data
            break;
        }
        if (bytes == -1) {
       throw "http_post_request(): read error - timeout";
        }
    }
   
    if ((n = xml.find("\r\n")) == string::npos) {
   n = xml.find("\n");
    }
    if (n == string::npos || n < 15) {
   cout << "http_post_request(): Read timeout or invalid HTTP response : '"+xml+"'";
   return "";
    }
    string code = xml.substr(9, 3);
    if (code != "200" && code != "302") {
   cout << "http_post_request(): bad HTTP code : '"+xml.substr(0, 15)+"'";
   return "";
    }
    xml = chunk_decode(xml);

    return xml;
}


цитата
22/06/18 в 00:07
 Mika
S_Flash писал:
в скомпиленом bill.o даёт ошибку

S_Flash писал:
перекомпилил bill.cc

Ты уверен, что ты все как надо скомпилировал после обновления openssl?
.o файлы - это object-файлы, эдакое промежуточное звено между исходниками и итоговой прогой, которая может использовать множество различных object-файлов.
цитата
22/06/18 в 00:43
 S_Flash
Mika:
У меня компилится без ошибок.
Вот этот участок в ssl.cc отдаёт исключение

Код:

if (SSL_connect (ssl) == -1) {
   SSL_CTX_free(ssl->ctx);
   SSL_free(ssl);
   close(sd);
   throw "Can't connect to host via SSL";
}


срабатывает условие SSL_connect (ssl) == -1
Пытался выдернуть реальный код ошибки через SSL_get_error() функцию, получил SSL_ERROR_SSL (A failure in the SSL library occurred, usually a protocol error. The OpenSSL error queue contains more information on the error.). Но это не точно.
цитата
22/06/18 в 23:58
 Mika
Есть такое чувство, что ты компилишь не так как надо, или не с тем чем надо.
Поясни что значит это?
S_Flash писал:
Апнул openssl на сервере, перезалил хедеры в /usr/include/openssl/, перекомпилил bill.cc

A именно, как ты "апал" openssl, зачем хедеры в /usr/include/openssl/ перезаливать, и как итоговую прогу ты создаешь после перекомпиляции bill.cc?
ХЗ как оно там во freebsd, но, например, в debian'е, надо поставить/обновить libssl-dev, который содержит хедеры и бинарник либы. Никакие хедеры перезаливать вручную не надо, они вообще вполне возможно могут быть и не затронуты, а изменения содержит лишь бинарник либы.
Ну и после того как object-файлы скомпилишь, нужно еще саму прогу слинковать из них.


Эта страница в полной версии