LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-09-2021, 01:07 PM   #1
Mackyboy123
Member
 
Registered: Feb 2020
Distribution: Slackware
Posts: 92

Rep: Reputation: Disabled
Openssl library returning cert as null.


I have an openssl library, which connects to google, checks for a cert, and tries to send a request:
Code:
#include <iostream>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <sstream>
#include <sys/types.h>
#include <sys/socket.h>

#include <netdb.h>
#include <string.h>
#include <unistd.h>

#include <vector>
#include <string>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/conf.h>

class Website
{
    int status, sock;
    struct addrinfo hints;
    struct addrinfo *servinfo;
    SSL_CTX* ctx = NULL;
    BIO *web = NULL, *out = NULL;
    SSL *ssl = NULL;
    long res = 1;
 
    struct URL
    {
        std::string host;
        std::string port;
        std::string protocol;
    };
    URL url;
    public:
      Website(std::string url){
          parseUrl(url);
          if(Website::url.protocol == "http"){
            establishConn();
          } else if(Website::url.protocol == "https"){
            initSSL();
            initCTX();
            if((web = BIO_new_ssl_connect(ctx)) == NULL) throw "Error in bio ssl";
            if(BIO_set_conn_hostname(web, Website::url.host.c_str()) != 1) throw "BIO hostname error"; 
            if(BIO_set_conn_port(web, Website::url.port.c_str()) != 1) throw "BIO port error";
            BIO_get_ssl(web, &ssl);
            if(ssl == NULL) throw "Error in ssl";
            const char* const PREFERED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
            if(SSL_set_cipher_list(ssl, PREFERED_CIPHERS) != 1) throw "Cipher error";
            if(SSL_set_tlsext_host_name(ssl, Website::url.host.c_str()) != 1) throw "Hostname error";
            if((out= BIO_new_fp(stdout,BIO_NOCLOSE)) == NULL) throw "Error with out";
            if(BIO_do_connect(web) == 0) throw "Error connecting";
            if(BIO_do_handshake(web) == 0) throw "Error handshake";
            X509* cert = SSL_get_peer_certificate(ssl);
            if(cert) X509_free(cert);
            if(cert == NULL) {throw "Error with cert"; ERR_print_errors_fp(stderr);}
            if(SSL_get_verify_result(ssl) != X509_V_OK) throw "Error verifying cert";
           /* establishConn();
            if(SSL_set_fd(ssl, sock) == 0) throw "Error setting fd";
            int SSL_status = SSL_connect(ssl);
            switch(SSL_get_error(ssl,SSL_status)){
                case SSL_ERROR_NONE:
                    //No error, do nothing
                    break;
                case SSL_ERROR_ZERO_RETURN:
                    throw "Peer has closed connection";
                    break;
                case SSL_ERROR_SSL:
                    ERR_print_errors_fp(stderr);
                    SSL_shutdown(ssl);

                    throw "Error in SSL library";
                    break;
                 default:
                    throw "Unknown error";
                    break;
            }*/ 

          }
      }
     
      std::string get(std::string loc, int maxsize){
        std::string request = "GET "+ loc + "\r\n\r\n";
        char *recvBuf = new char[maxsize];
        memset(recvBuf, 0, strlen(recvBuf));
        Website::sendToSite(request);
        Website::recvFromSite(recvBuf, maxsize);
        std::string reply(recvBuf);
        return reply;
      }
    ~Website(){
      if(Website::url.protocol =="http"){
        close(sock);
        freeaddrinfo(servinfo);
      }else if(Website::url.protocol == "https"){
        SSL_free(ssl);
        SSL_CTX_free(ctx);
      }
     }

    private:
      void sendToSite(std::string request){
        if(Website::url.protocol == "http"){
            if (send(sock, request.c_str(), strlen(request.c_str()), 0)  == -1) throw "Error sending message";
        } else if(Website::url.protocol == "https"){
            BIO_puts(web, request.c_str());
            BIO_puts(out, "\n");
        }
      }

      void recvFromSite(char buf[], int maxsize){
        if(Website::url.protocol == "http"){
            if (recv(sock, buf, maxsize, 0) == -1) throw "Error receving message";
        } else if(Website::url.protocol == "https"){
            int len = 0;
           do
           {
            len = BIO_read(web, buf, strlen(buf));
            if(len > 0) BIO_write(out, buf,len);

           } while(len > 0 || BIO_should_retry(web));
        }
      }
      //Setting up the SSL
      void initSSL(void){
        SSL_library_init();

      }
      void initCTX(){
        const SSL_METHOD* method = TLS_method();
        if((ctx = SSL_CTX_new(method)) == NULL) throw "Could not create CTX";
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        SSL_CTX_set_verify_depth(ctx, 4);
        if((ssl = SSL_new(ctx)) == NULL) throw "Couldn't create SSL";

 
  
      }
      void establishConn(){
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        if((status = getaddrinfo(Website::url.host.c_str(), Website::url.port.c_str(), &hints, &servinfo)) != 0) throw "Something wrong with getaddrinfo";
        if((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) throw "Something wrong with creating socket";
        if((connect(sock, servinfo->ai_addr, servinfo->ai_addrlen)) != 0) throw "Error in connecting to website";       
      }
//Filles struct Website::url  with host as first argument and path as second
  void parseUrl(std::string url){
    // Check wether url is http or https
    if(url.rfind("http://", 0) == 0){
        Website::url.port = "80";
        Website::url.host = url.substr(7);
        Website::url.protocol = "http";  
    } else if (url.rfind("https://", 0) == 0){
        Website::url.port = "443";
        Website::url.host = url.substr(8);
        Website::url.protocol = "https";
    } else {
        throw "Invalid url, must start with http:// or https://";
    }
  }
};
When I try connecting to google.com using this library, it returns a null certificate and throws the error "Error with cert"
 
Old 02-09-2021, 02:13 PM   #2
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206
As you have not asked a question it is difficult to understand the purpose of your post. I might assume that you think your code is not working correctly, but that might also send us both, and anyone else who reads this thread down the wrong path, so let's not do that!

Please review the Site FAQ for guidance in posting your questions and general forum usage. Especially, read the link in that page, How To Ask Questions The Smart Way. The more effort you put into understanding your problem and framing your questions, the better others can help!

Posting whole code and asking others to first understand how it should work, then to figure out why it may not be working in your specific case is not often a good way to approach a problem.

If you think the message being returned is not correct please explain why and include any steps you have taken to figure out why that may be.

Last edited by astrogeek; 02-09-2021 at 02:33 PM. Reason: Almost proved my own point! Never assume...
 
Old 02-10-2021, 06:27 AM   #3
Mackyboy123
Member
 
Registered: Feb 2020
Distribution: Slackware
Posts: 92

Original Poster
Rep: Reputation: Disabled
Website refusing to return cert openssl c++

I am developing an application that connects to a website and tries to verify if it provided a cert. Here is the(incomplete) code:
Code:
#include <iostream>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <sstream>
#include <sys/types.h>
#include <sys/socket.h>

#include <netdb.h>
#include <string.h>
#include <unistd.h>

#include <vector>
#include <string>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/conf.h>

class Website
{
    int status, sock;
    struct addrinfo hints;
    struct addrinfo *servinfo;
    SSL_CTX* ctx = NULL;
    BIO *web = NULL, *out = NULL;
    SSL *ssl = NULL;
    long res = 1;
 
    struct URL
    {
        std::string host;
        std::string port;
        std::string protocol;
    };
    URL url;
    public:
      Website(std::string url){
          parseUrl(url);
          if(Website::url.protocol == "http"){
            establishConn();
          } else if(Website::url.protocol == "https"){
            initSSL();
            initCTX();
            if((web = BIO_new_ssl_connect(ctx)) == NULL) throw "Error in bio ssl";
            if(BIO_set_conn_hostname(web, Website::url.host.c_str()) != 1) throw "BIO hostname error"; 
            if(BIO_set_conn_port(web, Website::url.port.c_str()) != 1) throw "BIO port error";
            BIO_get_ssl(web, &ssl);
            if(ssl == NULL) throw "Error in ssl";
            const char* const PREFERED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
            if(SSL_set_cipher_list(ssl, PREFERED_CIPHERS) != 1) throw "Cipher error";
            if(SSL_set_tlsext_host_name(ssl, Website::url.host.c_str()) != 1) throw "Hostname error";
            if((out= BIO_new_fp(stdout,BIO_NOCLOSE)) == NULL) throw "Error with out";
            if(BIO_do_connect(web) == 0) throw "Error connecting";
            if(BIO_do_handshake(web) == 0) throw "Error handshake";
            X509* cert = SSL_get_peer_certificate(ssl);
            if(cert) X509_free(cert);
            if(cert == NULL) {throw "Error with cert"; ERR_print_errors_fp(stderr);}
            if(SSL_get_verify_result(ssl) != X509_V_OK) throw "Error verifying cert";
           /* establishConn();
            if(SSL_set_fd(ssl, sock) == 0) throw "Error setting fd";
            int SSL_status = SSL_connect(ssl);
            switch(SSL_get_error(ssl,SSL_status)){
                case SSL_ERROR_NONE:
                    //No error, do nothing
                    break;
                case SSL_ERROR_ZERO_RETURN:
                    throw "Peer has closed connection";
                    break;
                case SSL_ERROR_SSL:
                    ERR_print_errors_fp(stderr);
                    SSL_shutdown(ssl);

                    throw "Error in SSL library";
                    break;
                 default:
                    throw "Unknown error";
                    break;
            }*/ 

          }
      }
     

    ~Website(){
      if(Website::url.protocol =="http"){
        close(sock);
        freeaddrinfo(servinfo);
      }else if(Website::url.protocol == "https"){
        SSL_free(ssl);
        SSL_CTX_free(ctx);
      }
     }

    private:

      //Setting up the SSL
      void initSSL(void){
        SSL_library_init();

      }
      void initCTX(){
        const SSL_METHOD* method = TLS_method();
        if((ctx = SSL_CTX_new(method)) == NULL) throw "Could not create CTX";
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        SSL_CTX_set_verify_depth(ctx, 4);
        if((ssl = SSL_new(ctx)) == NULL) throw "Couldn't create SSL";

 
  
      }

};/*
When an external program calls the constructor, using google.com for the url, It runs without error until it gets to this line of code:
Code:
X509* cert = SSL_get_peer_certificate(ssl);
if(cert) X509_free(cert);
if(cert == NULL) {ERR_print_errors_fp(stderr); throw "Error with cert";}
This checks if the server has provided a certificate and throws an error and prints the SSL error stack. When I run my program, the server refuses to provide a certificate, which means that cert == NULL and the program exits after printing the error queue, which is:

Code:
140014272479040:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1913:
Why is the server refusing to provide a certificate?
I am using Arch Linux.
 
Old 02-10-2021, 06:29 AM   #4
Mackyboy123
Member
 
Registered: Feb 2020
Distribution: Slackware
Posts: 92

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by astrogeek View Post
As you have not asked a question it is difficult to understand the purpose of your post. I might assume that you think your code is not working correctly, but that might also send us both, and anyone else who reads this thread down the wrong path, so let's not do that!

Please review the Site FAQ for guidance in posting your questions and general forum usage. Especially, read the link in that page, How To Ask Questions The Smart Way. The more effort you put into understanding your problem and framing your questions, the better others can help!

Posting whole code and asking others to first understand how it should work, then to figure out why it may not be working in your specific case is not often a good way to approach a problem.

If you think the message being returned is not correct please explain why and include any steps you have taken to figure out why that may be.
I improved my post https://www.linuxquestions.org/quest....php?p=6218626
 
Old 02-10-2021, 09:30 AM   #5
Mackyboy123
Member
 
Registered: Feb 2020
Distribution: Slackware
Posts: 92

Original Poster
Rep: Reputation: Disabled
It seems that I've solved my own problem. Openssl automatically verifies and then frees the certificates, so I only need the verification code when I'm trying to create my own verification function.
 
1 members found this post helpful.
Old 02-10-2021, 02:06 PM   #6
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206
Please post your thread only once. Posting a single thread in the most relevant forum will make it easier for members to help you and will keep the discussion in one place. When improving on a question please do so in the original thread to make it easier for others to follow the discussion.

Your threads have been merged.
 
  


Reply

Tags
c++, library, linux, openssl, ssl



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
httpd + openssl : compilation issues while using shared openssl library vlrk Programming 4 10-07-2019 10:43 AM
how to configure Apache with one SSL cert for primary domain, another wildcard cert for subdomains? sneakyimp Linux - Server 5 05-08-2018 12:36 AM
concat server SSL cert and chain cert LYC Linux - Newbie 2 07-20-2015 07:08 AM
Error: Can't read cert file /etc/pki/tls/certs/cert.pem in Twiki jsaravana87 Linux - Server 1 09-09-2011 06:01 PM
OpenSSL / Sendmail verifies both "TLS cert" and "x509 cert" in client mode, why? fast-reflexes Linux - Server 0 09-12-2010 11:32 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:15 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration