LCOV - code coverage report
Current view: top level - src - clustercon.c (source / functions) Hit Total Coverage
Test: mkernel.info Lines: 0 109 0.0 %
Date: 2024-12-05 21:00:54 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /**
       2             :  *    @file  clustercon.c
       3             :  *   @brief
       4             :  *
       5             :  *  <+DETAILED+>
       6             :  *
       7             :  *  @author  François Cerbelle (Fanfan), francois@cerbelle.net
       8             :  *
       9             :  *  @internal
      10             :  *       Created:  25/10/2024
      11             :  *      Revision:  none
      12             :  * Last modified:  2024-11-13 21:40
      13             :  *      Compiler:  gcc
      14             :  *  Organization:  Cerbelle.net
      15             :  *     Copyright:  Copyright (c) 2024, François Cerbelle
      16             :  *
      17             :  *  This source code is released for free distribution under the terms of the
      18             :  *  GNU General Public License as published by the Free Software Foundation.
      19             :  */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include "clustercon.h"
      26             : #include "base64.h"                             /* Base64 encoder and decoder */
      27             : 
      28             : #include <unistd.h>
      29             : #include <string.h>
      30             : #ifdef _WIN32
      31             : #include <winsock2.h>
      32             : #include <ws2tcpip.h>
      33             : #else
      34             : #include <arpa/inet.h>
      35             : #endif
      36             : #include <openssl/err.h>
      37             : 
      38             : typedef struct rsclustercon_s {
      39             :     char*              host;
      40             :     char*              user;
      41             :     char*              pass;
      42             :     unsigned short int insecure;
      43             :     char*              cacert;
      44             :     int                sock;
      45             :     SSL_CTX*           ctx;
      46             :     SSL*               ssl;
      47             : } rsclustercon_t;
      48             : 
      49           0 : rsclustercon_t*    cluster_new(const cluster_t* cluster) {
      50           0 :     rsclustercon_t* rsclustercon = NULL;
      51             : 
      52           0 :     if (NULL==(rsclustercon=malloc(sizeof(struct rsclustercon_s)))) {
      53           0 :         perror("cluster_new");
      54           0 :         return NULL;
      55             :     }
      56           0 :     if (NULL==(rsclustercon->host=strdup(cluster->host))) {
      57           0 :         perror("cluster_new host");
      58           0 :         free(rsclustercon);
      59           0 :         return NULL;
      60             :     }
      61           0 :     if (NULL==(rsclustercon->user=strdup(cluster->user))) {
      62           0 :         perror("cluster_new user");
      63           0 :         free(rsclustercon->host);
      64           0 :         free(rsclustercon);
      65           0 :         return NULL;
      66             :     }
      67           0 :     if (NULL==(rsclustercon->pass=strdup(cluster->pass))) {
      68           0 :         perror("cluster_new pass");
      69           0 :         free(rsclustercon->user);
      70           0 :         free(rsclustercon->host);
      71           0 :         free(rsclustercon);
      72           0 :         return NULL;
      73             :     }
      74           0 :     if (NULL==(rsclustercon->cacert=strdup(cluster->cacert))) {
      75           0 :         perror("cluster_new cacert");
      76           0 :         free(rsclustercon->pass);
      77           0 :         free(rsclustercon->user);
      78           0 :         free(rsclustercon->host);
      79           0 :         free(rsclustercon);
      80           0 :         return NULL;
      81             :     }
      82           0 :     rsclustercon->insecure = strcmp(cluster->insecure,"false");
      83           0 :     return rsclustercon;
      84             : }
      85             : 
      86           0 : int   cluster_open(rsclustercon_t* rsclustercon) {
      87             :     struct sockaddr_in server_addr;
      88             : 
      89             :     /* Socket creation */
      90           0 :     rsclustercon->sock = socket(AF_INET, SOCK_STREAM, 0);
      91           0 :     if (rsclustercon->sock < 0) {
      92           0 :         perror("Socket creation error");
      93           0 :         return 1;
      94             :     }
      95             : 
      96           0 :     server_addr.sin_family = AF_INET;
      97           0 :     server_addr.sin_port = htons(9443);
      98           0 :     if (inet_pton(AF_INET, rsclustercon->host, &server_addr.sin_addr) <= 0) {
      99           0 :         perror("Invalid address");
     100           0 :         return 2;
     101             :     }
     102             : 
     103             :     /* Server connection */
     104           0 :     if (connect(rsclustercon->sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
     105           0 :         perror("Connection failed");
     106           0 :         return 3;
     107             :     }
     108             : 
     109             :     /* OpenSSL initialization */
     110           0 :     SSL_library_init();
     111             :     /* OpenSSL_add_all_algorithms(); */
     112           0 :     OpenSSL_add_ssl_algorithms();
     113           0 :     SSL_load_error_strings();
     114             : 
     115             :     /* Initialize OpenSSL context */
     116           0 :     rsclustercon->ctx = SSL_CTX_new(SSLv23_client_method());
     117           0 :     if (!rsclustercon->ctx) {
     118           0 :         ERR_print_errors_fp(stderr);
     119           0 :         return 4;
     120             :     }
     121             : 
     122             :     /* Load server certificate or certificate from a certification authority (CA) */
     123           0 :     if (strcmp("",rsclustercon->cacert)&&rsclustercon->insecure==0)
     124           0 :         if (SSL_CTX_load_verify_locations(rsclustercon->ctx, rsclustercon->cacert, NULL) != 1) {
     125           0 :             ERR_print_errors_fp(stderr);
     126           0 :             return 5;
     127             :         }
     128             : 
     129           0 :     if (rsclustercon->insecure)
     130             :         /* Disable certificat check */
     131           0 :         SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_NONE, NULL);
     132             :     else
     133             :         /* Enable certificat check */
     134           0 :         SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_PEER, NULL);
     135             : 
     136             : 
     137             :     /* Link SSL configuration to the socket */
     138           0 :     rsclustercon->ssl = SSL_new(rsclustercon->ctx);
     139           0 :     SSL_set_fd(rsclustercon->ssl, rsclustercon->sock);
     140             : 
     141             :     /* Initiate SSL connection */
     142           0 :     if (SSL_connect(rsclustercon->ssl) <= 0) {
     143           0 :         ERR_print_errors_fp(stderr);
     144           0 :         return 6;
     145             :     }
     146             : 
     147           0 :     return 0;
     148             : }
     149             : 
     150           0 : cJSON* cluster_queryget(const rsclustercon_t* rsclustercon, const char* endpoint) {
     151             :     char buf[1024];
     152             : 
     153             :     /* Prepare basic authentication */
     154             :     char* auth_encoded;
     155             :     {
     156             :         char* auth_clear;
     157           0 :         if (NULL==(auth_clear = (char*)malloc(strlen(rsclustercon->user)+1+strlen(rsclustercon->pass)+1))) {
     158           0 :             perror("cluster_queryget malloc(auth)");
     159           0 :             return NULL;
     160             :         };
     161           0 :         strcpy(auth_clear,rsclustercon->user);
     162           0 :         strcat(auth_clear,":");
     163           0 :         strcat(auth_clear,rsclustercon->pass);
     164           0 :         auth_encoded=base64_encode(auth_clear);
     165           0 :         free(auth_clear);
     166             :     }
     167             : 
     168             :     /* Prepare query */
     169             :     char http_request[512];
     170           0 :     snprintf(http_request, sizeof(http_request),
     171             :              "GET %s HTTP/1.1\r\n"
     172             :              "Host: %s\r\n"
     173             :              "Content-Type: application/json\r\n"
     174             :              "Authorization: Basic %s\r\n"
     175             :              "Connection: close\r\n\r\n",
     176           0 :              endpoint,rsclustercon->host,auth_encoded
     177             :             );
     178           0 :     free(auth_encoded);
     179             : 
     180             :     /* Send query */
     181           0 :     SSL_write(rsclustercon->ssl, http_request, strlen(http_request));
     182             : 
     183             :     /* Read reply */
     184           0 :     int bytes=0;
     185           0 :     char* reply=NULL;
     186           0 :     if (NULL==(reply=strdup(""))) {
     187           0 :         perror("cluster_queryget strdup");
     188           0 :         return NULL;
     189             :     };
     190           0 :     while ((bytes=SSL_read(rsclustercon->ssl, buf, 1024 - 1)) > 0) {
     191           0 :         buf[bytes] = 0;
     192             :         char* newreply;
     193           0 :         if ((newreply=(char*)realloc(reply,strlen(reply)+bytes+1))==NULL) {
     194           0 :             perror("Unable to allocate reply buffer");
     195           0 :             free(reply);
     196           0 :             return NULL;
     197             :         } else
     198           0 :             reply = newreply;
     199           0 :         strcat(reply, buf);
     200             :     }
     201             : 
     202             :     /* Remove HTTP headers */
     203             :     char* http_body;
     204             :     char* retval_txt;
     205           0 :     if (NULL==(http_body = strstr(reply,"\r\n\r\n")))
     206           0 :         retval_txt= NULL;
     207             :     else
     208           0 :         retval_txt=strdup(http_body);
     209           0 :     free(reply);
     210             : 
     211           0 :     cJSON* retval_json = cJSON_Parse(retval_txt);
     212           0 :     free(retval_txt);
     213             : 
     214           0 :     return retval_json;
     215             : }
     216             : 
     217           0 : void  cluster_close(rsclustercon_t* rsclustercon) {
     218           0 :     SSL_shutdown(rsclustercon->ssl);
     219           0 :     SSL_free(rsclustercon->ssl);
     220           0 :     close(rsclustercon->sock);
     221           0 :     SSL_CTX_free(rsclustercon->ctx);
     222           0 :     EVP_cleanup();
     223           0 : }
     224             : 
     225           0 : void  cluster_del(rsclustercon_t* rsclustercon) {
     226           0 :     free(rsclustercon->cacert);
     227           0 :     free(rsclustercon->pass);
     228           0 :     free(rsclustercon->user);
     229           0 :     free(rsclustercon->host);
     230           0 :     free(rsclustercon);
     231           0 : }
     232             : 
     233             : /* vim: set tw=80: */

Generated by: LCOV version 1.16