1

I am looking to download or read a file from a server over HTTPS, and I'm using openSSL for it.

I see the connection succeeds, however SSL_read() returns 0. SSL_get_error() returns 6 which refers to SSL_ERROR_ZERO_RETURN macro and seems to be a normal behavior but I'm not sure why was the connection shutdown while something was being read? And this might be why it's reading 0 bytes?

#define CHECK_NULL(x) if ((x)==NULL) exit (1)
#define CHECK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHECK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

void ServerConnectAndRcv(uint8_t *str)
{
    int err;
    int sd;
    struct sockaddr_in sa;
    SSL_CTX* ctx;
    SSL*     ssl;
    char*    str;
    char     buf [4096];
    const SSL_METHOD *meth;
    
    SSLeay_add_ssl_algorithms();
    meth = TLSv1_2_client_method();
    SSL_load_error_strings();
    ctx = SSL_CTX_new (meth);
    
    SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 
    
    // create a socket and connect to the server 
    sd = socket (AF_INET, SOCK_STREAM, 0);       
    CHK_ERR(sd, "socket");
    
    memset (&sa, '\0', sizeof(sa));
    sa.sin_family      = AF_INET;
    sa.sin_addr.s_addr = inet_addr (<SERVER-IP>);           /* Server IP */
    sa.sin_port        = htons     (<SERVER-PORT>);          /* Server Port number */
    
    ssl = SSL_new (ctx);                        
    CHECK_NULL(ssl);    
    
    SSL_set_fd (ssl, sd);
    
    err = SSL_connect (ssl);                     
    CHECK_SSL(err);
    
    // read from the server
    err = SSL_read (ssl, buf, sizeof(buf) - 1);                     
    CHECK_SSL(err);
    
    if (err <= 0)
    {
        printf ("Error reading: %d\n", SSL_get_error(ssl, err));
    }
    
    buf[err] = '\0';
    printf ("Received % bytes\n", err); // Received 0 bytes
    SSL_shutdown (ssl);  
}
xyf
  • 664
  • 1
  • 6
  • 16
  • 1
    You say you want to download 'over HTTPS' but **you're not implementing HTTPS**, only TLS. Many HTTPS (and HTTP) servers can only handle a limited number of client connections, and connecting to such a server and not sending an HTTP[S] request is used as a denial-of-service attack, so many such servers disconnect such connections to prevent such an attack. Aside: you also don't provide the hostname for SNI, and many HTTPS servers today require SNI to implement virtual hosting, although apparently not the one you are using. – dave_thompson_085 Nov 30 '21 at 23:00
  • shouldn't I be able to read from a server with this approach? the examples i've seen online are fairly similar – xyf Nov 30 '21 at 23:43
  • You can read once you send an appropriate HTTP request, like GET, POST, etc. It's HTTP, the client goes first. – President James K. Polk Dec 01 '21 at 01:10
  • @PresidentJamesK.Polk that's the sort of approach I'm taking: https://stackoverflow.com/a/16255486/12497236 – xyf Dec 01 '21 at 03:14

1 Answers1

0

As one of the commenters pointed out, I needed to send a GET request to be able to receive a response back from the server. I sent pszResourcePath via SSL_write() and SSL_read() read the entire response just fine.

char pszRequest[100]= {0};
char pszResourcePath[]="<resourcePath>";
char pszHostAddress[]="<serverIP>";
sprintf(pszRequest, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Keep-Alive\r\n\r\n", pszResourcePath, pszHostAddress);

xyf
  • 664
  • 1
  • 6
  • 16